我的世界Bukkit服务器插件开发教程(十三)资源包与玩家资料

十三、资源包与玩家资料


1.资源包(Resource Pack)

早期的 Minecraft 并没有资源包一说,而是被叫做材质包。有些服务器为了让玩家拥有更好的游戏体验,一般会在自己特制的客户端中存放一些资源包供玩家加载。

显然,使用资源包的主动权在玩家手中,而且服务器无法检测到玩家是否开启了资源包(在某些场合下,资源包必须开启)。

服务器觉得非常没有面子,于是开始了复仇之路……

复仇个屁啊,server.properties写一行require-resource-pack=true,玩家要是不乖乖下载资源包直接断开连接(小声)


1.1.通通安排

如果你是一名插件制作者,且你的插件需要指定的资源包,必须提供资源包的uri,客户端将会通过该地址下载指定的资源包。

如果你是一名腐竹(插件教程还有腐竹看,ε=(´ο`*))) 唉),你可以打开server.properties文件,找到resource-pack=这一行,填上资源包的uri,建议找到resource-pack-sha1=这一行把它填上(是资源包的SHA-1值),会提高资源包的可靠性缓存的有效性


额外的:

你可以调用Bukkit类中的getResourcePack方法来获取服务器资源包的uri,也可以调用getResourcePackHash获取资源包的SHA-1值。

你也可以获取自定义提示下载资源包时的消息,调用getResourcePackPrompt来实现此功能。

但是,你不可以在插件中更改以上获取到的值,只有通过更改server.properties文件才是有效的。


1.2.获取主动

于是,在之后的版本中,服务器可以请求玩家下载并使用指定的资源包,但是是否下载并使用资源包的主动权依然在玩家手中,在开始下载之前会弹出窗口提示是否下载资源包,如果玩家选择“否”那么也就无能为力了。

Player player = (Player) sender;
player.setResourcePack("<uri>");

如上,填上资源包的uri,这样客户端会弹出窗口请求下载。


1.3.你在干什么?

真是这样吗?

不!当玩家对弹出的窗口采取行动时会触发PlayerResourcePackStatusEvent事件,插件可以获取资源包的状态,必定会是以下四种状态之一:

状态解释
ACCEPTED客户端接受了资源包, 并开始下载
DECLINED客户端拒绝接受资源包
FAILED_DOWNLOAD客户端接受了资源包, 但下载失败
SUCCESSFULLY_LOADED资源包成功地下载并应用到了客户端

如果服务器要求比较苛刻,可以通过这个事件获取资源包状态,要是被拒绝了直接踢出玩家(嘿嘿)。

至于如何监听事件,在上一章已经提到过,这里就不再赘述了。


附:关于插件包资源

插件包中的资源应该位于resource这个文件夹当中,具体如图示:

在这里插入图片描述

可以调用插件主类中getResource方法获取相应的资源:

@Nullable
@Override
public InputStream getResource(@NotNull String filename);
//获取插件相应资源

获取名为filename的资源,返回类型为InputStream


也可以保存内置于插件的.jar文件的某个资源的原始内容。

@Override
public void saveResource(@NotNull String resourcePath, boolean replace);

当参数replacetrue时表示覆盖内置资源的所有内容。第一个参数表示插件.jar文件中查找的内置资源路径。

更多关于资源包的方法或其他请参阅 API文档


2.玩家资料(PlayerProfile)

注:玩家资料在较新版本被引入,旧版本(已知是1.17及以前)没有PlayerProfile

玩家资料,顾名思义,关于某一位玩家的相关资料。想象一下,一摞资料文件放在你的桌前,你尽情翻阅着每位玩家的相关信息,是不是有一种________的感觉。

一份玩家资料(PlayerProfile接口)至少包含玩家唯一ID非空名字,完整的玩家资料除两者外还要有玩家的纹理

PlayerProfile是一个接口,所以你可以放心地使用。


2.1.「打印文件」

我们可以创建一份新的资料,至于是哪个玩家的资料取决于玩家名:

@NotNull
PlayerProfile createPlayerProfile(@Nullable UUID uniqueId, @Nullable String name);

createPlayerProfile方法在Server接口中,可以使用getServer方法来获取:

Bukkit.getServer().createPlayerProfile(UUID.randomUUID(), "<玩家名>");

返回类型是PlayerProfile接口,这就是一份玩家资料。


2.2.「审阅文件」&「核验文件」

我们拿到了一份玩家资料,首先要检查资料是否齐全,即是否是一份完整的玩家资料,我们可以使用isComplete方法来检查资料是否完整。如果不完整,我们还可以调用update方法来更新玩家资料:

@NotNull
CompletableFuture<PlayerProfile> update();

必须注意,返回的类型是CompletableFuture类。因为玩家的相关资料都在官方网站中,所以update方法需要在另外一个线程中发起一个对外连接, 以拉取官方最新资料属性

可以使用如下代码来操作更新完成的玩家资料:

profile.update().thenAcceptAsync(updatedProfile -> {
	//这里操作更新完成的玩家资料
	//...
}, runnable -> Bukkit.getScheduler().runTask(this, runnable));

thenAcceptAsync是指异步对单个处理完的结果进行操作(消费),但它不和父线程使用同一个线程,而是使用自定义的线程池,而在最后一个参数为该方法提供了Executor框架。

关于CompletableFuture<T>,有兴趣可以自行了解,本章不做详细讲解。


玩家的唯一ID及玩家名对我们来说没有一丁点价值,有价值的是玩家的纹理,纹理包括玩家的皮肤(Skin)披风(Cape),我们可以用getSkingetCape分别获取皮肤和披风,注意二者的返回类型均为URL类。

可以用setSkinsetCape方法分别设置玩家的皮肤和披风为指定的URL。但是必须指向 Minecraft 纹理服务器,比如下面的URL就是一个栗子:

http://textures.minecraft.net/texture/b3fbd454b599df593f57101bfca34e67d292a8861213d2202bb575da7fd091ac

PlayerProfile profile = Bukkit.getServer().createPlayerProfile(UUID.randomUUID(), "<玩家名>");
PlayerTextures textures = profile.getTextures();
try {
	textures.setSkin(new URL("http://textures.minecraft.net/texture/b3fbd454b599df593f57101bfca34e67d292a8861213d2202bb575da7fd091ac"));
} catch(Exception e) {
	e.printStackTrace();
	sender.sendMessage("发生异常:" + e.getMessage());
}

这样我们就设置了玩家的皮肤(其实本人没有试过行不行qwq)。

最后,为辨别真假,我们使用isSigned方法来判断这份「文件」是否有效地签名,至此一份资料就审阅完了。


感觉这是自我发布教程以来为数不多的文章了啊,虽然是“简简单单”两个方面但是唠叨了四千多字,实感不容易,也希望读者能够消化消化。

附:Bukkit 和 Spigot 之间的关系

有很多人不明白 Bukkit 和 Spigot 之间有何关系:教程写的是 Bukkit,给的文档确是 Spigot API 文档,让很多人一头雾水。

如果你在翻阅文档时,大致浏览一下 文档 所列出的所有程序包的话,你会发现几乎所有程序包都是以org.开头,只有三个程序包以net.md_5.bungee.开头。这三个程序包在万众之上,所以非常显眼。

在这里插入图片描述

之前提过,Bukkit 是一款开源、免费的项目,但由于种种原因而极其短命。Spigot 项目则继承了 Bukkit,一直存活到现在。它的地位与 Forge 和 Fabric 不相上下。

某种意义上,你可以理解为 Bukkit = Spigot。除此之外还有以org.spigotmc.开头的程序包,这是 Spigot 所特有的。

不难看出 Spigot 是一个大熔炉,用面向对象语言的特性形容 Spigot 就是两个字——继承


上一篇:我的世界Bukkit服务器插件开发教程(十二)物品与监听事件
下一篇:我的世界Bukkit服务器插件开发教程(十四)消息和命令补全器

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值