本帖最后由 914554688wyt 于 2016-8-19 19:48 编辑
6.关于"数据包".
本章内容在bukkit javadoc中无涉及,
需查看NMS包.
服务端与客户端之间的通讯,全部以数据包来往的方式进行.然而Bukkit并提供没有收发包的API,具体原因嘛...自己脑补一下我也不知道.
这里暂且不涉及到具体通讯方法(Socket,暂时不打算搞)
每一种数据包都被封装为一个类,这个类在net.minecraft.server.版本包中,类名格式为Packet + 类型 + (Out/In) +内容.
类型有四种
Login - 加入服务器时.(与登录插件无关)
Status - Ping与MOTD等
Play - 游戏内容
Handshake - 握手包
Out 是指 传出,即发送给客户端的包
In 是指 收到,即从客户端传出的包
如何不使用别的工具(ProtocolLib说的就是你!)发包
(需要一定的反射知识)
[以下是本人口胡时间]
首先我们想,给玩家发包,应该是在Player类下
然后我们又发现,Player是个抽象类,于是我们找到他的实现类CraftPlayer.
我们发现一个很有可能的成员 playerConnection,但这个成员在CraftPlayer.getHandle()下,
继续顺藤摸瓜,找到getHandle的返回类型EntityPlayer,打开PlayerConnection类,
然后就可以看到在PlayerConnection类下的sendPacket方法!
[以下为正文]
通过不懈的探索与寻找(其实就是强行查找),我们找到了一个发包(至少是名字像)方法
public void sendPacket(final Packet packet)
但在Player类中没有包含getHandle这个方法,只在他的实现类CraftPlayer中有.但所有Player实例实际上也是一个CraftPlayer实例
假设有Player p;
1.这时候就要用到我们的反射大法,首先获取Class<CraftPlayer>实例,然后再获取他的"getHandle"方法,再执行获取EntityPlayer实例
Object entityPlayer = p.getClass().getMethod("getHandle", new Class[0]).invoke(p, new Object[0]);
可能有人会说,可以强转CraftPlayer然后直接调用getHandle啊
.. 如果出现导入,那么服务端换了版本就会抛ClassNotFound异常,因为
所以说, 你强转CraftPlayer类不需要导入吗?
2.再获取他的playerConnection 字段
Object playerConnection = craftPlayer.getClass().getField("playerConnection").get(craftPlayer);
3.最后获取他的sendPacket方法
playerConnection .getClass().getMethod("sendPacket", new Class[] { getNMSClass("Packet") })
这个getNMSClass,是因为NMS居心险恶的每个版本的包名不一样,而这个包名的格式是
net.minecraft.server.vX_X_RX
然后bukkit的实现类都在craftbukkit包里,这个包名的格式是
org.bukkit.craftbukkit.vX_X_RX
这个好办,我们随便获取一个nms或者cb Class,然后取他的包名然后再处理就可以了,就像这样
version = Bukkit.getServer().getClass().getPackage().getName()
.substring(Bukkit.getServer().getClass().getPackage().getName().lastIndexOf('.') + 1);
*这里的getServer()返回的是CraftServer实例
得到版本后,就直接Class.forName(net.minecraft.server.版本.类名)获取NMS类就可以了.
得到sendPacket方法后,我们还需要处理他的参数Packet.
通过反射获取我们需要的包的构造器, 假如我要发PacketPlayOutTitle包
Object packetTitle = getNmsClass("PacketPlayOutTitle").getConstructor(new Class[] {有序的构造器参数类型的Class实例})
.newInstance(new Object[] { 有序的构造器参数 });
现在来完成最后一步, 执行sendPacket方法
playerConnection .getClass().
getMethod("sendPacket", new Class[] { getNMSClass("Packet") }).invoke(playerConnection , new Object[] { packetTitle });
大功告成,这样你就成功的给玩家发送了一个Packet.
另外,我们还可以使用ProtocolLib进行收发包,监听包的收发等等....
梨子的ProtocolLib教程:
[Ni]ProtocolLib怎么玩|使用ProtocolLib发包或收包|突破Bukkit限制|只有想不到系列
http://www.mcbbs.net/thread-568714-1-1.html
番外
NMS包是不是有混淆? 有些包的字段是不是看不懂?
你需要这个
http://wiki.vg/Protocol
完整的描述了mc数据包每个字段的意义.
6.关于"数据包".
本章内容在bukkit javadoc中无涉及,
需查看NMS包.
服务端与客户端之间的通讯,全部以数据包来往的方式进行.然而Bukkit并提供没有收发包的API,具体原因嘛...自己脑补一下
这里暂且不涉及到具体通讯方法(Socket,暂时不打算搞)
每一种数据包都被封装为一个类,这个类在net.minecraft.server.版本包中,类名格式为Packet + 类型 + (Out/In) +内容.
类型有四种
Login - 加入服务器时.(与登录插件无关)
Status - Ping与MOTD等
Play - 游戏内容
Handshake - 握手包
Out 是指 传出,即发送给客户端的包
In 是指 收到,即从客户端传出的包
如何不使用别的工具(ProtocolLib说的就是你!)发包
(需要一定的反射知识)
[以下是本人口胡时间]
首先我们想,给玩家发包,应该是在Player类下
然后我们又发现,Player是个抽象类,于是我们找到他的实现类CraftPlayer.
我们发现一个很有可能的成员 playerConnection,但这个成员在CraftPlayer.getHandle()下,
继续顺藤摸瓜,找到getHandle的返回类型EntityPlayer,打开PlayerConnection类,
然后就可以看到在PlayerConnection类下的sendPacket方法!
[以下为正文]
通过不懈的探索与寻找(其实就是强行查找),我们找到了一个发包(至少是名字像)方法
public void sendPacket(final Packet packet)
但在Player类中没有包含getHandle这个方法,只在他的实现类CraftPlayer中有.但所有Player实例实际上也是一个CraftPlayer实例
假设有Player p;
1.这时候就要用到我们的反射大法,首先获取Class<CraftPlayer>实例,然后再获取他的"getHandle"方法,再执行获取EntityPlayer实例
Object entityPlayer = p.getClass().getMethod("getHandle", new Class[0]).invoke(p, new Object[0]);
可能有人会说,可以强转CraftPlayer然后直接调用getHandle啊
.. 如果出现导入,那么服务端换了版本就会抛ClassNotFound异常,因为
NMS与CraftBukkit包居心险恶的每个版本的包名不一样
所以说, 你强转CraftPlayer类不需要导入吗?
2.再获取他的playerConnection 字段
Object playerConnection = craftPlayer.getClass().getField("playerConnection").get(craftPlayer);
3.最后获取他的sendPacket方法
playerConnection .getClass().getMethod("sendPacket", new Class[] { getNMSClass("Packet") })
这个getNMSClass,是因为NMS
net.minecraft.server.vX_X_RX
然后bukkit的实现类都在craftbukkit包里,这个包名的格式是
org.bukkit.craftbukkit.vX_X_RX
这个好办,我们随便获取一个nms或者cb Class,然后取他的包名然后再处理就可以了,就像这样
version = Bukkit.getServer().getClass().getPackage().getName()
.substring(Bukkit.getServer().getClass().getPackage().getName().lastIndexOf('.') + 1);
*这里的getServer()返回的是CraftServer实例
得到版本后,就直接Class.forName(net.minecraft.server.版本.类名)获取NMS类就可以了.
得到sendPacket方法后,我们还需要处理他的参数Packet.
通过反射获取我们需要的包的构造器, 假如我要发PacketPlayOutTitle包
Object packetTitle = getNmsClass("PacketPlayOutTitle").getConstructor(new Class[] {有序的构造器参数类型的Class实例})
.newInstance(new Object[] { 有序的构造器参数 });
现在来完成最后一步, 执行sendPacket方法
playerConnection .getClass().
getMethod("sendPacket", new Class[] { getNMSClass("Packet") }).invoke(playerConnection , new Object[] { packetTitle });
大功告成,这样你就成功的给玩家发送了一个Packet.
另外,我们还可以使用ProtocolLib进行收发包,监听包的收发等等....
梨子的ProtocolLib教程:
[Ni]ProtocolLib怎么玩|使用ProtocolLib发包或收包|突破Bukkit限制|只有想不到系列
http://www.mcbbs.net/thread-568714-1-1.html
番外
NMS包是不是有混淆? 有些包的字段是不是看不懂?
你需要这个
http://wiki.vg/Protocol
完整的描述了mc数据包每个字段的意义.
914554688wyt 发表于 2016-8-7 16:21
6.关于"数据包".
本章内容在bukkit javadoc中无涉及,
需查看NMS包.
反射大法2333
那个bukkit的javadoc链接 404了
hsk001ufo 发表于 2016-8-10 18:03
那个bukkit的javadoc链接 404了
https://hub.spigotmc.org/javadocs/spigot/,可以尝试一下spigotAPI,与BukkitAPI98%基本相同
等等..容器(container)?不是集合(collection)吗?
请问楼主,用骨粉催熟作物的绿色粒子在Bukkit1.7.10没有吗?Effect找了一圈没看到{:10_493:}
hsk001ufo 发表于 2016-8-10 18:03
那个bukkit的javadoc链接 404了
Bukkit:https://hub.spigotmc.org/javadocs/bukkit
Spigot:https://hub.spigotmc.org/javadocs/spigot
914554688wyt 发表于 2016-8-4 16:41
2.创建命令
论如何创建一个安全,优雅的命令
1.无报错,正常运行.
关于plugin.yml中的
command:部分没有解释到位 还有很多节点没有说明
914554688wyt 发表于 2016-8-6 15:15
4.监听事件
事件是什么
顾名思义,一件事,如: 玩家传送,实体死亡,交互等等等等..
请问@Override的作用是什么?必须要加吗?不加会怎么样?
黄总 发表于 2016-8-13 20:46
请问@Override的作用是什么?必须要加吗?不加会怎么样?
复写父类方法
这个东西我们称其为注解
不加就是super.onEnable()
还有这是java基础写插件要基础的
很好啊qwq 我要收藏起来慢慢看
楼主我编插件有个问题能问下么QQ上
tallmoon 发表于 2016-8-15 12:19
楼主我编插件有个问题能问下么QQ上
可以私聊哦,不需要QQ
LZ,教程很棒哦~
a390807154 发表于 2016-8-13 17:04
关于plugin.yml中的
command:部分没有解释到位 还有很多节点没有说明
觉得拥有自己探索的能力才是最重要的,所以我仅仅讲了重要部分
914554688wyt 发表于 2016-8-7 16:21
6.关于"数据包".
本章内容在bukkit javadoc中无涉及,
需查看NMS包.
额...我这样直接获得的...好像不用反射..
PlayerConnection conn=((CraftPlayer)p).getHandle().playerConnection;
asdfg25855 发表于 2016-8-19 18:49
额...我这样直接获得的...好像不用反射..
PlayerConnection conn=((CraftPlayer)p).getHandle().playerCo ...
我里面有说这样做的弊端
syn614211648 发表于 2016-8-13 12:12
请问楼主,用骨粉催熟作物的绿色粒子在Bukkit1.7.10没有吗?Effect找了一圈没看到 ...
辣个是happyvillager
gooding300 发表于 2016-8-10 21:09
等等..容器(container)?不是集合(collection)吗?
????难道我被C++带跑了??
syn614211648 发表于 2016-8-13 12:12
请问楼主,用骨粉催熟作物的绿色粒子在Bukkit1.7.10没有吗?Effect找了一圈没看到 ...
1.7.10没有粒子效果的API,需要自行发包.
[题外话:我就是半吊子从其他语言边写插件边转过来的,然后现在还得恶补一番.]
讲道理你从什么语言转的?
我正在从C++转..
而且我是学算法搞竞赛的..
SYS_TEM 发表于 2016-8-23 09:45
讲道理你从什么语言转的?
我正在从C++转..
而且我是学算法搞竞赛的..
pascal -> c++ ->java
{:10_510:}又遇OI狗..
楼主的教程跟论坛里的其他教程差不多.
对于这种教程我有一种看法就是,能看懂API的不会来看这教程,看这教程的基本上是看不懂API的.
很多内容楼主都是一笔带过,对于已经懂了这种方法是什么意思的人不会学到什么,之前不懂的人看了你的教程还是不懂这个方法是什么意思.
其实我觉的,如果花那么多时间写一个已经有点泛滥的教程不如把API整理翻译一下,顺便告诉大家用法,要注意些什么比较来的有用些.
我说这个并不是针对楼主,只是觉的如果有能力的话不如把时间用来写更有用的教程上面去,这是给楼主说的也是给以后打算写插件教程的人说的.
对于这种教程我有一种看法就是,能看懂API的不会来看这教程,看这教程的基本上是看不懂API的.
很多内容楼主都是一笔带过,对于已经懂了这种方法是什么意思的人不会学到什么,之前不懂的人看了你的教程还是不懂这个方法是什么意思.
其实我觉的,如果花那么多时间写一个已经有点泛滥的教程不如把API整理翻译一下,顺便告诉大家用法,要注意些什么比较来的有用些.
我说这个并不是针对楼主,只是觉的如果有能力的话不如把时间用来写更有用的教程上面去,这是给楼主说的也是给以后打算写插件教程的人说的.
shtsoul 发表于 2016-8-23 15:40
楼主的教程跟论坛里的其他教程差不多.
对于这种教程我有一种看法就是,能看懂API的不会来看这教程,看这教程 ...
之所以发教程,是想给不知道从哪入手写插件的人点亮一条道路,该讲的其他教程里有讲,其他教程里没讲的我也讲了部分,懂了的没有必要来看,不懂的的确看不懂,如果这么容易能懂那为什么能开发的人基于总数这么少,
API翻译早就有在进行,
何况我觉得这种东西可以自己尝试,没有必要做伸手党
前面有什么必须注意的,我都已经写得很清楚了,那些不那么重要的地方就没有说,因为没有必要说.
开发永远也没有捷径,伸手党永远也成不了dalao,唯实践出真知
其实吧,论坛教程的确泛滥,现在已经有5页了,我个人觉得价值最高几个之一的就是
突破org限制,运用nms给插件升*格
http://www.mcbbs.net/thread-622936-1-1.html
本帖最后由 shtsoul 于 2016-8-23 19:04 编辑
可能我没表达明白.
我也恨伸手党,但是谁又不是从伸手党走过来的呢?
作为寻找答案得到结果最快的方法就是做伸手党.
拿汉化API来说,当有一种东西不是你的母语的时候大多数人肯定会先找下有没有自己语言的版本.
会英语的可以直接去阅读,但是有多少人能完全看的懂呢,这本身就做了一个网过滤掉了很多想开发插件但是看不懂API的人.
就算是可以找各种翻译软件去翻译但是翻译出来的东西往往还需要花些时间去理解,这又会过滤掉一大部分人.
其实很多人会说,你不会英文学什么编程呀,但是我觉的会英语可以帮助学编程,但是不会英语并不一定就不会编程,就像跑步需要双腿,但是没有了双腿并不影响你用辅助工具帮助你跑,就像刀锋战士一样.
我说的这种情况在咱们国家很普遍,说到这里可能扯的有点远了.
API的汉化之前有在论坛里听说过,但是过去这么久了也没出一想就可能是坑了.
有些时候人多并不一定好办事,懒惰是会传染的,有一个人懒就会传染给另一个人,之后大家都懒的做事.
如果真的有心去汉化,一天汉化一个方法都可以,今天你在论坛发一点汉化,明天其他人汉化一点,大家到时候一整合一个完整的API就出来了,就像论坛里现在的搬运一样,今天你搬,等你搬累了不想搬了我接下去继续搬.
还有就是,有些人写教程其实并没有想教别人的想法,可能是他们想展示一下自己的技术满足一下自己的虚荣心,也可能是想水一水贴.
914554688wyt 发表于 2016-8-23 17:09
之所以发教程,是想给不知道从哪入手写插件的人点亮一条道路,该讲的其他教程里有讲,其他教程里没讲的我也 ...
可能我没表达明白.
我也恨伸手党,但是谁又不是从伸手党走过来的呢?
作为寻找答案得到结果最快的方法就是做伸手党.
拿汉化API来说,当有一种东西不是你的母语的时候大多数人肯定会先找下有没有自己语言的版本.
会英语的可以直接去阅读,但是有多少人能完全看的懂呢,这本身就做了一个网过滤掉了很多想开发插件但是看不懂API的人.
就算是可以找各种翻译软件去翻译但是翻译出来的东西往往还需要花些时间去理解,这又会过滤掉一大部分人.
其实很多人会说,你不会英文学什么编程呀,但是我觉的会英语可以帮助学编程,但是不会英语并不一定就不会编程,就像跑步需要双腿,但是没有了双腿并不影响你用辅助工具帮助你跑,就像刀锋战士一样.
我说的这种情况在咱们国家很普遍,说到这里可能扯的有点远了.
API的汉化之前有在论坛里听说过,但是过去这么久了也没出一想就可能是坑了.
有些时候人多并不一定好办事,懒惰是会传染的,有一个人懒就会传染给另一个人,之后大家都懒的做事.
如果真的有心去汉化,一天汉化一个方法都可以,今天你在论坛发一点汉化,明天其他人汉化一点,大家到时候一整合一个完整的API就出来了,就像论坛里现在的搬运一样,今天你搬,等你搬累了不想搬了我接下去继续搬.
还有就是,有些人写教程其实并没有想教别人的想法,可能是他们想展示一下自己的技术满足一下自己的虚荣心,也可能是想水一水贴.
我是一枚小白,我遇到点问题:
我想集中在主类读取配置,可在处理指令类里不能声明对象,onCommand()方法也不能写"FileConfiguration config = getConfig();" 所以我被迫将指令处理区写在了主类里..
求大佬帮助


我想集中在主类读取配置,可在处理指令类里不能声明对象,onCommand()方法也不能写"FileConfiguration config = getConfig();" 所以我被迫将指令处理区写在了主类里..
求大佬帮助



983341575 发表于 2017-5-20 21:56
我是一枚小白,我遇到点问题:
我想集中在主类读取配置,可在处理指令类里不能声明对象,onCommand()方法也不 ...
插件主类中 {
public static 插件主类 INSTANCE;
onEnable() += INSTANCE = this;
}
CommandExecutor {
插件主类.INSTANCE.getConfig()
}
另外吐槽下这篇教程很多地方是错的
为了混积分,给萌萌哒的lz赞一个QwQ
楼主,希望帮我解决一个问题=-=
楼主求解决!
楼主求解决!
914554688wyt 发表于 2016-8-4 16:41
2.创建命令
论如何创建一个安全,优雅的命令
1.无报错,正常运行.
就因为你这command没加s,浪费了我十几分钟=。=
s8566597s 发表于 2018-2-8 19:32
就因为你这command没加s,浪费了我十几分钟=。=
同上,蒙了半天,机智跑隔壁看了看,对比了下才走出来
教教我们插件重载失效怎么解决
914554688wyt 发表于 2016-8-6 22:26
5.物品(ItemStack)类与背包(Inventory)类
先说ItemStack类(Material或ID + 数量 + damage(附加值,比如不同 ...
所以怎么利用物品类和背包类
小白表示看不懂………………
感谢非常感谢
神乎其技,不服不行!!
914554688wyt 发表于 2016-8-3 16:44
1.创建一个空白插件
安装好jdk和IDE之后,我们就可以准备写第一个插件了.
请问,第一步中 "JavaPlugin类未导入" 这个为什么我的没提示。。。或者说这个对应版本的bukkit api该怎么获得。。。
如何像用config.yml一样用xxxxxx.yml?
emmm,前来翻贴
第一步,点击搜藏,第二步,关掉界面。
很棒 很详细一遍懂
实例不就是对象吗,实例这个词听起来一点都不顺畅
66666666666666666
66666666666666666
虽然我没有看懂哈哈哈哈哈哈哈
所以,怎么样整彩色字体啊楼主
谢谢大佬,非常有用!