560 words
3 minutes
HunterGame 队伍发光功能修复总结
Glow功能修复总结
问题分析
根据服务器日志,我们遇到了以下错误:
[20:09:01 WARN]: [CatHunterGame] 设置玩家发光效果失败: You cannot register objects without a watcher object![20:09:01 WARN]: java.lang.IllegalArgumentException: You cannot register objects without a watcher object![20:09:01 WARN]: at ProtocolLib.jar//com.comphenix.protocol.wrappers.WrappedDataWatcher.setObject(WrappedDataWatcher.java:514)根本原因
问题在于我们使用了空的WrappedDataWatcher对象,但ProtocolLib要求使用watcher对象来注册数据。在ProtocolLib中,WrappedDataWatcher需要先注册字段才能设置值。
修复方案
1. 避免使用WrappedDataWatcher.toDataValueCollection()
问题: 使用WrappedDataWatcher.toDataValueCollection()方法时出现NullPointerException,因为serializer为null。
修复方案: 直接创建WrappedDataValue列表,避免使用WrappedDataWatcher的转换方法。
2. 完整的修复代码
// 创建数据值列表List<WrappedDataValue> dataValues = new ArrayList<>();
// 设置实体标志byte entityFlags = 0;if (shouldGlow) { entityFlags |= 0x40; // 设置发光标志位}
// 添加实体标志数据值dataValues.add(new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), entityFlags));
// 如果支持队伍颜色发光,添加颜色效果if (shouldGlow && target.isGlowing()) { Color glowColor = getPlayerGlowColor(target); if (glowColor != null) { dataValues.add(new WrappedDataValue(1, WrappedDataWatcher.Registry.get(Integer.class), glowColor.asRGB())); }}关键改进点
- 使用实体构造函数:使用
new WrappedDataWatcher(target)而不是空的构造函数 - 自动字段注册:实体构造函数会自动注册必要的字段,避免”watcher object”错误
- 类型安全:使用正确的数据类型设置实体元数据
实体元数据字段说明
- 索引0:实体标志(Entity Flags)
- 类型:
Byte - 位6 (0x40):发光效果标志位
- 类型:
- 索引1:发光颜色(Glow Color)
- 类型:
Integer - RGB颜色值
- 类型:
预期效果
修复后,TeamGlowManager应该能够:
- 正确设置玩家的发光效果
- 支持队伍专属颜色(猎物绿色,猎人红色)
- 实现距离控制(10格内不显示发光)
- 旁观者能看到所有队伍的发光效果
- 性能优化(数据包缓存、状态缓存)
测试建议
- 启动服务器并加载插件
- 开始游戏,检查是否还有错误日志
- 验证同队玩家之间是否能看到发光效果
- 验证不同队伍玩家之间是否看不到发光效果
- 验证旁观者是否能看到所有队伍的发光效果
- 验证距离控制功能是否正常工作
参考资料
HunterGame 队伍发光功能修复总结
https://mizuki.mysqil.com/posts/glow-fix-summary/