好久没动过bukkit了,很久没玩过mc了....前几天一个需求所以折腾了一下bukkit,使用bukkitapi向玩家发送sign的open和Update包也就是打开sign和修改sign的信息,然后我找了一些插件研究.
最后2种方法,1.使用ProtocolLib发包,2.艹nms
bukkitapi貌似就是不能发...据我所知,,我就用过bukkitapi修改过sign木牌信息..让玩家打开sigin到没怎么做过
最后当然是选择用ProtocolLib发包咯,nms太麻烦了(nms发包见最下面)
上图是之前插件一张图片...懒得开游戏弄一张...无视木牌内容就行....
先自行下载protocolib的插件吧:https://www.spigotmc.org/resources/protocollib.1997/
自行在plugin.yml里面添加
depend: [ProtocolLib]
先获取ProtocolManager
ProtocolManager pm = ProtocolLibrary.getProtocolManager();
注意:v1_8_3的核心及以上的版本和v1_8_3以下的核心版本发包是不同的所以需要区分一下
另外,游戏版本1.10以上的PacketPlayOutUpdateSign这个包没有了,所以无法在游戏1.10及以上使用
public static void send17Pack(Player p,String[] lines){ ProtocolManager pm = ProtocolLibrary.getProtocolManager(); try { int x = p.getLocation().getBlockX(); int z = p.getLocation().getBlockZ(); PacketContainer change = pm.createPacket(PacketType.Play.Server.BLOCK_CHANGE); change.getIntegers().write(0,x); change.getIntegers().write(1,0); change.getIntegers().write(2,z); change.getIntegers().write(3,0); change.getBlocks().write(0, Material.SIGN_POST); pm.sendServerPacket(p, change); PacketContainer update = pm.createPacket(PacketType.Play.Server.UPDATE_SIGN); update.getIntegers().write(0,x); update.getIntegers().write(1,0); update.getIntegers().write(2,z); update.getStringArrays().write(0,lines); pm.sendServerPacket(p, update); PacketContainer open = pm.createPacket(PacketType.Play.Server.OPEN_SIGN_ENTITY); open.getIntegers().write(0,x); open.getIntegers().write(1,0); open.getIntegers().write(2,z); pm.sendServerPacket(p, open); } catch (Exception e) { e.printStackTrace(); } }
public static void send18Pack(Player p,String[] lines){ ProtocolManager pm = ProtocolLibrary.getProtocolManager(); try { int x = p.getLocation().getBlockX(); int z = p.getLocation().getBlockZ(); PacketContainer change = pm.createPacket(PacketType.Play.Server.BLOCK_CHANGE); change.getBlockPositionModifier().write(0, new BlockPosition(x, 0, z)); change.getBlockData().write(0, WrappedBlockData.createData(Material.SIGN_POST)); pm.sendServerPacket(p, change); PacketContainer update = pm.createPacket(PacketType.Play.Server.UPDATE_SIGN); update.getBlockPositionModifier().write(0, new BlockPosition(x, 0, z)); update.getChatComponentArrays().write(0, new WrappedChatComponent[] { WrappedChatComponent.fromText(lines[0]), WrappedChatComponent.fromText(lines[1]), WrappedChatComponent.fromText(lines[2]), WrappedChatComponent.fromText(lines[3]) }); pm.sendServerPacket(p, update); PacketContainer open = pm.createPacket(PacketType.Play.Server.OPEN_SIGN_ENTITY); open.getBlockPositionModifier().write(0, new BlockPosition(x, 0, z)); pm.sendServerPacket(p, open); } catch (Exception e) { e.printStackTrace(); } }
上面的代码是发了3个包,一个修改方块,一个修改sign,一个发送sign
对应sign的2个包在nms里面是PacketPlayOutUpdateSign 和PacketPlayOutOpenSignEditor
对应的参数可以反编译查看(写这篇的时候我是linux,,,,无奈jd-gui一直下载不下来...)
捕捉sign修改的包也可以用protocolib捕捉,先创建一个类用于监听
//自行导包(纯手打...) public class SignUpdate extends PacketAdapter implements PacketListener{ public SignUpdate(Plugin plugin, PacketType[] packets) { super(plugin,packets); } public void onPacketReceiving(PacketEvent e){ PacketContainer pack = e.getPacket(); if(pack.getType()==PacketType.Play.Client.UPDATE_SIGN){ //sign修改触发 //如果需要获取修改的内容,那么v1_8_3版本也会有区分 //v1_8_3以下版本 String[] signLine = (String[])pack.getStringArrays().getValues().get(0); //v1_8_3以上版本 WrappedChatComponent[] signLine = (WrappedChatComponent[])pack.getChatComponentArrays().read(0); //然后这个signLine就是木牌修改的值了 //signLine[0] signLine[1] signLine[2] signLine[3] } } }
//主类中添加 ProtocolManager pm = ProtocolLibrary.getProtocolManager(); PacketType[] packs = { PacketType.Play.Client.UPDATE_SIGN }; pm.addPacketListener(new SignUpdateEvent(主类,packs));
String[] lines = {"第一行文字","第二行文字","第三行文字","第四行文字"}; Player p = Bukkit.getServer().getPlayer("xxxx"); this.send18Pack(p,lines);//v1_8_3版本 this.send17Pack(p,lines);//v1_8_3以下版本
如何区分呢?自行判断当前版本号然后比较就ok了
关于nms发包的方法,我这里只写1.8.3以上的发包方法
public void openSign(Player player,String[] lines){ //获取nms和craftbukkit的一些东西 CraftPlayer p = (CraftPlayer)player; CraftWorld cw = (CraftWorld)p.getWorld(); PlayerConnection pc = p.getHandle().playerConnection; //这里的World类是nms里面的World类 net.minecraft.server.v1_8_3.World World nmsWorld = (World)cw.getHandle(); //获取一个方块的坐标 BlockPosition block = new BlockPosition(p.getLocation().getBlockX(),0,p.getLocation().getBlockZ()); //修改方块(因为后面需要修改内容) PacketPlayOutBlockChange change = new PacketPlayOutBlockChange(nmsWorld,block); change.block = Blocks.STANDING_SIGN.getBlockData(); pc.sendPacket(change); //修改木牌 PacketPlayOutUpdateSign update = new PacketPlayOutUpdateSign(nmsWorld,block,new IChatBaseComponent[]{ ChatSerializer.a(lines[0]), ChatSerializer.a(lines[1]), ChatSerializer.a(lines[2]), ChatSerializer.a(lines[3]) }); pc.sendPacket(update); //打开 PacketPlayOutOpenSignEditor open = new PacketPlayOutOpenSignEditor(block); pc.sendPacket(open); }
其实方法和ProtocolLib发包区别不是很大,但是nms每个版本的包名都不同啊,而且有些类的方法名称也是改了的,比如这个版本是v1_8_3另一个版本是v1_8_2那么包名就完全不同的
以上就是ProtocolLib和nms的发包方法
注:因为修改木牌需要修改方块,所以一般都是把木牌放到基岩底层也就是0的位置,如果不放心,可以在修改完成的时候删除这个方块
0条评论登录后可见