Minecraft(我的世界)中文论坛

 找回密码
 注册(register)
查看: 3847|回复: 6

[插件开发教程] 在插件通过发包(ProtocolLib)打开牌子界面(Sign GUI)

[复制链接]
trychen 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
2443
钻石
性别
保密
注册时间
2013-9-6
查看详细资料
发表于 2017-7-14 22:22:13 | 显示全部楼层 |阅读模式

您尚未登录,立即登录享受更好的浏览体验!

您需要 登录 才可以下载或查看,没有帐号?注册(register)

x
本帖最后由 trychen 于 2017-7-15 08:34 编辑

用处:
  • 通过 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!


初始化变量:
  1. ProtocolManager manager = ProtocolLibrary.getProtocolManager();
复制代码
组为了让大家看的更清晰,代码尽量拆分的更短!下面开始创建 BLOCK_CHANGE 包:
  1. PacketContainer blockChange = manager.createPacket(PacketType.Play.Server.BLOCK_CHANGE);
  2. blockChange.getBlockPositionModifier().write(0, blockPosition);
  3. blockChange.getBlockData().write(0, WrappedBlockData.createData(Material.SIGN_POST));
复制代码
这样,ProtocolLib 就会创建一个 BLOCK_CHANGE 包,并修改里面的 BlockPosition 等变量为我们需要的内容,达到伪造一个牌子的效果。接着我们要创建 UPDATE_SIGN 包来更新我们需要的内容:
  1. PacketContainer updateSign = manager.createPacket(UPDATE_SIGN);
  2. updateSign.getBlockPositionModifier().write(0, blockPosition);
  3. updateSign.getChatComponentArrays().write(0, new WrappedChatComponent[]{WrappedChatComponent.fromText(lines[0]), WrappedChatComponent.fromText(lines[1]), WrappedChatComponent.fromText(lines[2]), WrappedChatComponent.fromText(lines[3])});
  4.                     
复制代码
这个包需要注意的是,版本差异较大,旧版本(1.8 || Older)可能是通过NBT来修改,这就需要以下方法:
  1. PacketContainer updateSign = manager.createPacket(UPDATE_SIGN);
  2. updateSign.getBlockPositionModifier().write(0, blockPosition);
复制代码
然后我们发送一个打开Sign GUI的包即可完成创建包了:
  1. PacketContainer open = manager.createPacket(OPEN_SIGN_ENTITY);
  2. open.getBlockPositionModifier().write(0, blockPosition);
复制代码
最后我们就可以把上述包都发送给玩家:
  1. manager.sendServerPacket(player, blockChange);
复制代码
这样我们就完成了打开牌子的UI

监听关闭我们打开的牌子
如果你是想通过牌子来修改某些东西,那我们就需要读取牌子修改后的内容,这时我们就需要通过监听包。
一般的实现原理:
  • 如果你不想监听,也要把客户端发过来的属于你打开的牌子的 UPDATE_SIGN 取消掉,否则服务器会发现对应方块不是一个牌子
  • 玩家在完成修改任意一个牌子后,客户端会发送包 (UPDATE_SIGN) 给服务器,其中包含了牌子修改后的数据(ESC 或 完成 都将发送)
  • 客户端发送的 UPDATE_SIGN 包 (PlayInUpdateSign) 中,包含了牌子的坐标,我们可以通过牌子的坐标和玩家确定是否是我们创建的牌子

开始监听
  • 在发送牌子后,存储玩家和坐标到一个 Map<Player, BlockPosition> map = new HashMap<>() ; //留意线程是否安全
  • 通过以下代码在 onEnable 中注册监听 UPDATE_SIGN
  1. <blockquote>manager.addPacketListener(this.packetListener = new PacketAdapter(plugin, new PacketType[]{PacketType.Play.Client.UPDATE_SIGN}) {
复制代码
以上代码纯手撸(这编辑器还吞格式,恶心),可能有写错,欢迎提出。

总结
这样你就使用 ProtocolLib 打开了 Sign GUI,本教程更希望你能掌握 ProtocolLib 的基本使用。

本文未仔细校验


来自群组: Unknown Domain

评分

参与人数 5人气 +9 金粒 +40 收起 理由
TONMMY + 1 + 10 MCBBS有你更精彩~
GayaGuoguo + 2 神乎其技,不服不行!
sky015121 + 1 + 10 MCBBS有你更精彩~
syn614211648 + 2 + 20 UD没你不精彩!
810587921 + 3 大触我们做朋友吧!

查看全部评分

小星啊啊啊 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
6593
钻石
性别
保密
注册时间
2013-6-26
查看详细资料
发表于 2017-7-14 22:38:45 | 显示全部楼层
支持 最近正好在研究这方面东西 遇到了一些小问题 ~

顺便来一顶 混乱帽
回复

使用道具 举报

HanMaDaDa 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
18
钻石
性别
保密
注册时间
2017-7-12
查看详细资料
发表于 2017-7-16 08:11:00 | 显示全部楼层
支持 最近正好在研究这方面东西 遇到了一些小问题 ~

顺便来一顶 混乱帽
回复

使用道具 举报

syn614211648 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
1727
钻石
性别
保密
注册时间
2016-3-31
查看详细资料
发表于 2017-7-27 19:51:09 | 显示全部楼层
自从梨子的ProtocolLib的教程贴子开始就感受到了发包的神奇,直到现在发包也是我的一个心梗 [捂脸]
回复

使用道具 举报

JackC92 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
106
钻石
性别
保密
注册时间
2016-8-19
查看详细资料
发表于 2017-7-31 16:49:45 | 显示全部楼层
打开牌子一定要有个Block牌子?我咋记得不用的啊
回复

使用道具 举报

sky015121 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
1038
钻石
性别
保密
注册时间
2012-8-28
查看详细资料
发表于 2017-12-27 12:50:16 | 显示全部楼层
感谢楼主分享,希望以后有多多此类教程,论坛上的教程真的太少了,国内的开发环境真的是艰难
回复

使用道具 举报

RainIFunS 当前离线
帖子
主题
精华
贡献
最后登录
1970-1-1
爱心
积分
1788
钻石
性别
保密
注册时间
2017-12-19
查看详细资料
发表于 2018-8-14 01:38:57 | 显示全部楼层
包...真是个可怕的东西 心塞....
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册(register)

本版积分规则

Archiver|小黑屋|Mcbbs.net ( 京ICP备15023768号-1 ) | 京公网安备 11010502037624号 | 手机版

GMT+8, 2019-8-21 08:20 , Processed in 0.058832 second(s), Total 16, Slave 14 queries , Gzip On, MemCached On.

"Minecraft"以及"我的世界"为Mojang Synergies AB的商标 本站与Mojang以及微软公司没有从属关系

© 2010-2019 我的世界中文论坛 版权所有 本站原创图文内容版权属于原创作者,未经许可不得转载

快速回复 返回顶部 返回列表