本帖最后由 trychen 于 2017-7-15 08:34 编辑
基本实现原理:
准备工作:
初始化变量:
复制代码组为了让大家看的更清晰,代码尽量拆分的更短!下面开始创建 BLOCK_CHANGE 包:
复制代码这样,ProtocolLib 就会创建一个 BLOCK_CHANGE 包,并修改里面的 BlockPosition 等变量为我们需要的内容,达到伪造一个牌子的效果。接着我们要创建 UPDATE_SIGN 包来更新我们需要的内容:
复制代码这个包需要注意的是,版本差异较大,旧版本(1.8 || Older)可能是通过NBT来修改,这就需要以下方法:
复制代码然后我们发送一个打开Sign GUI的包即可完成创建包了:
复制代码最后我们就可以把上述包都发送给玩家:
复制代码这样我们就完成了打开牌子的UI
监听关闭我们打开的牌子
如果你是想通过牌子来修改某些东西,那我们就需要读取牌子修改后的内容,这时我们就需要通过监听包。
一般的实现原理:
开始监听
复制代码以上代码纯手撸(这编辑器还吞格式,恶心),可能有写错,欢迎提出。
总结
这样你就使用 ProtocolLib 打开了 Sign GUI,本教程更希望你能掌握 ProtocolLib 的基本使用。
本文未仔细校验
来自群组: Unknown Domain
用处:
- 通过 Sign 作为输入密码的方式
- 作为高级的输入方式
- 显示提示
知识前提:
- 掌握 Bukkit API
- 知道关于“包”的基本概念
- ProtocolLib 的基本使用
基本实现原理:
- 创建包 (BLOCK_CHANGE),让客户端把玩家的最底下 (new Location(player.getLocation().getX(), 0, player.getLocation().getZ())) 基岩误设置为一个牌子;
- 创建包 (UPDATE_SIGN),更新牌子的内容为我们想显示的内容;
- 创建包 (OPEN_SIGN_ENTITY),让服务器打开牌子的UI
- 发送上面的全部包,完成打开 Sign GUI
准备工作:
- 创建一个 Bukkit 的项目,并导入 ProtocolLib 插件作为依赖库
- 创建一个类用于存储我们生成的 Sign 归属者 (signLocation2Player)
- 在上述类中创建方法 public boolean openSignGUI(Player player, String[] lines) 或 fun Player.openSignGUI():boolean
- Go!
初始化变量:
- ProtocolManager manager = ProtocolLibrary.getProtocolManager();
- PacketContainer blockChange = manager.createPacket(PacketType.Play.Server.BLOCK_CHANGE);
- blockChange.getBlockPositionModifier().write(0, blockPosition);
- blockChange.getBlockData().write(0, WrappedBlockData.createData(Material.SIGN_POST));
- PacketContainer updateSign = manager.createPacket(UPDATE_SIGN);
- updateSign.getBlockPositionModifier().write(0, blockPosition);
- updateSign.getChatComponentArrays().write(0, new WrappedChatComponent[]{WrappedChatComponent.fromText(lines[0]), WrappedChatComponent.fromText(lines[1]), WrappedChatComponent.fromText(lines[2]), WrappedChatComponent.fromText(lines[3])});
- PacketContainer updateSign = manager.createPacket(UPDATE_SIGN);
- updateSign.getBlockPositionModifier().write(0, blockPosition);
- PacketContainer open = manager.createPacket(OPEN_SIGN_ENTITY);
- open.getBlockPositionModifier().write(0, blockPosition);
- manager.sendServerPacket(player, blockChange);
监听关闭我们打开的牌子
如果你是想通过牌子来修改某些东西,那我们就需要读取牌子修改后的内容,这时我们就需要通过监听包。
一般的实现原理:
- 如果你不想监听,也要把客户端发过来的属于你打开的牌子的 UPDATE_SIGN 取消掉,否则服务器会发现对应方块不是一个牌子
- 玩家在完成修改任意一个牌子后,客户端会发送包 (UPDATE_SIGN) 给服务器,其中包含了牌子修改后的数据(ESC 或 完成 都将发送)
- 客户端发送的 UPDATE_SIGN 包 (PlayInUpdateSign) 中,包含了牌子的坐标,我们可以通过牌子的坐标和玩家确定是否是我们创建的牌子
开始监听
- 在发送牌子后,存储玩家和坐标到一个 Map<Player, BlockPosition> map = new HashMap<>() ; //留意线程是否安全
- 通过以下代码在 onEnable 中注册监听 UPDATE_SIGN
- <blockquote>manager.addPacketListener(this.packetListener = new PacketAdapter(plugin, new PacketType[]{PacketType.Play.Client.UPDATE_SIGN}) {
总结
这样你就使用 ProtocolLib 打开了 Sign GUI,本教程更希望你能掌握 ProtocolLib 的基本使用。
本文未仔细校验
来自群组: Unknown Domain
支持 最近正好在研究这方面东西 遇到了一些小问题 ~
顺便来一顶 混乱帽

顺便来一顶 混乱帽


支持 最近正好在研究这方面东西 遇到了一些小问题 ~
顺便来一顶 混乱帽
顺便来一顶 混乱帽
自从梨子的ProtocolLib的教程贴子开始就感受到了发包的神奇,直到现在发包也是我的一个心梗 [捂脸]
打开牌子一定要有个Block牌子?我咋记得不用的啊
感谢楼主分享,希望以后有多多此类教程,论坛上的教程真的太少了,国内的开发环境真的是艰难
包...真是个可怕的东西 心塞....
