一些工具
# 一些工具
PluginBase 附带了一些好用的工具。基本都在包 top.mrxiaom.pluginbase.util 里面,有较完整的 javadoc 可查阅。
# AdventureUtil
作为老旧的 ColorHelper 的替代品,用于处理 MiniMessage、新旧颜色代码转换、处理本地平台实现等等。
在不对 adventure 进行 relocate 操作的情况下,可以与 Paper 服务端无缝兼容。
# ColorHelper
用于替换彩色字、十六进制颜色、渐变色。
用法为 ColorHelper.parseColor("");
更建议使用 AdventureUtil 作为替代。
# AdventureItemStack
对于 adventure 的 Component,与 Bukkit 的 ItemStack 的操作交互工具。
主要是对物品名称和物品Lore进行操作,并将这两项操作抽象到了 ItemEditor 接口,可修改为内置的 PaperItemEditor,与 Paper 服务端无缝兼容。(模块 paper 已实现 PaperItemEditor,可直接引用依赖添加)
可替代 ItemStackUtil 的部分功能。
# ItemStackUtil
物品管理器,可以做到
- 序列化、反序列化物品
- 快速构造一个物品
- 以特定格式解析物品,支持 1.12 及以下的旧版物品
itemsadder-物品名使用 ItemsAdder 物品,如itemsadder-example
物品#CMD使用原版物品并添加 CustomModelData,如DIAMOND_SWORD#10001
head-base64-头颅值使用 base64 格式头颅物品,可以从 Minecraft Heads (opens new window) 获取头颅 (For Developers: Value) - 快捷修改物品名、Lore
- 快捷获取附魔书物品 (同时避免把附魔存错位置)
- 快捷给予玩家物品,背包满时掉落到玩家附近
等
# depend.PAPI
PlaceholderAPI 兼容接口,在服务器安装了 PlaceholderAPI 时正常替换变量;未安装时直接替换 %player_name% 为玩家名
# Util
大杂烩工具集合。
- 将 stackTrace 打印到字符串,跟 kotlin 用法类似
- Location 的快捷序列化与反序列化,格式为
x,y,z,yaw,pitch,保留两位小数 - 提前储存玩家列表,快捷高效获取 OfflinePlayer (离线玩家) 与 Player (在线玩家) 实例,避免同步频繁获取离线玩家 (读取文件进行IO操作) 时卡服
- 字符串反序列化为
Optional<数字类型>(double,float,long,int) - 字符串反序列化为枚举 带默认值 (
valueOr(Material.class, "PAPER", null)为读取Material.PAPER(不分大小写),读不到就返回默认值null) - 检查类是否存在
isPresent(String)
等
# ConfigUtils
配置读取、写入相关工具。
- 从文件加载配置
load(File, Charset),可以自行指定编码,默认UTF_8。还有load(FileConfiguration, File, Charset)可以将文件内容加载到指定配置实例里。 - 保存配置到文件
save(FileConfiguration, File, Charset),可以自行指定编码,默认UTF_8。 - 读取对象列表
getSectionList(ConfigurationSection, String),对象列表的示例格式如下。此前,只能用.getMapList(String)来读取,很不方便。需要注意的是,读出来的 List 跟原来的配置不存在引用关系,改了要手动写回去。写回去很简单,直接section-list: - text: 'foo' level: 1 - text: 'bar' level: 11
2
3
4
5.set(String, List<ConfigurationSection>)就行了。 - 获取允许空值的数字
getDouble/getInt。原本是基本类型,不允许空值,现在改为引用类型,允许空值。 - 获取百分比数字
getPercentAsDouble/getPercentAsFloat,读取一个带小数点的实数,当配置值以百分号%结尾时,数值除以100。简单来说,就是获取1.0 = 100%的百分数。
# CollectionUtils
集合(Collection)、键值对(Map)操作相关工具。
- 键值对获取
getOrPut(Map<K, V>, K, Supplier<V>),键存在的时候,正常返回值,键不存在的时候,调用Supplier获取值,写进Map里,再返回值。 - 列表分割
chunk(List<T>, int),将一个列表分割成多个长度一样的子列表,与 kotlin 用法类似,最后一个列表可能长度不够 - 快捷正则表达式分割字符串
split(Pattern, String, Consumer<RegexResult>),在 ColorHelper 中有使用示例 - 重新实现的分割字符串
split(String, char, int),与String.split功能几乎一致,仅仅是没有正则表达式支持 - 筛选出列表中开头匹配的字符串
startsWith(String, Iterable<String>),用于onTabComplete命令补全,只要return startsWith(args[1], "foo", "bar");即可为第二个参数添加候选foo和bar。
# Bytes
BungeeCord 消息构建轮子。
需要模块:misc
// 发送到所有子服
void foo() {
Bytes.sendByWhoeverOrNot("BungeeCord", Bytes.build(out -> {
out.writeUTF(Bukkit.getVersion());
out.writeUTF("Hello World!");
}, /*subChannel:*/"Forward", /*arguments:*/"ALL", "MyChannel"));
}
2
3
4
5
6
7
// 使用模块接收
// 要在模块的构造函数里写 registerBungee();
@Override
public void receiveBungee(String subChannel, DataInputStream in) throws IOException {
if (subChannel.equals("MyChannel")) {
String bukkitVersion = in.readUTF();
String message = in.readUTF();
info("收到了 MyChannel 消息: " + bukkitVersion + ", " + message);
}
}
2
3
4
5
6
7
8
9
10
注意:BungeeCord 消息是不可靠的,必须要有玩家在子服中,才能发送或接收。以及发送出去的消息,只有相同名字的插件才能接收。
对于我目前写插件的情况来说,用到 BungeeCord 消息的大多数用途,是发送“缓存已过期”提醒,让插件清掉,或更新某人的缓存,以便下次进入子服时数据同步。
建议在发送时在最前面添加
out.writeLong(System.currentTimeMillis() + 3000L);
接收时在判断 subChannel 后,在最前面判定
if (System.currentTimeMillis() > in.readLong()) return;
以防止一个没人在线的子服,突然有人上线时,之前堆积的 BungeeCord 消息频繁涌入导致性能问题。