William_Shi
本教程系PVPIN教程复刻系列
索引见https://www.mcbbs.net/thread-1034477-1-1.html
本教程不做排版,如果你觉得不舒服,可以选择退出本页面
本教程所有代码全部在coding开源,详见索引
本教程可能存在一定吞代码问题,总体上以开源地址的代码为准

不知道你们有没有试过System out println 玩家对象,亦或者是输出玩家对象的getClass、getSimpleName
如果试过,那么你们应该清楚实现了Player接口的类是CraftPlayer
在Bukkit中有非常多的接口,而且我们在多数情况下都直接Bukkit的接口中规定的方法,而这些方法的具体实现类则不被关心
但我也写了那么多NMS的相关教程了,或多或少大家应该也自己探究过了
大部分接口的实现类都在OBC包中,也就是org.bukkit.craftbukkit.v1_x_Rx
比如说Player的实现类是CraftPlayer、Server的实现类是CraftServer
当然也有例外,比如说Enchantment有一个Wrap,比如说PluginManager由SimplePluginManager实现等等
但总体而言,OBC包实现了Bukkit的接口
我们知道Bukkit服务端并不是Minecraft的源码,Minecraft的源码另有NMS包
其包名是类似的,net.minecraft.server.v1_x_Rx
这个包没有任何层次架构,一个包装了所有的Minecraft源码的所有类
为什么?因为MC是混淆的,你的Spigot等SDK都是CraftBukkit反混淆
如果你拆开看过Vanilla端的源码,那里面不存在“包”,所有的文件就叫abc.class这样的混淆,
那么forge为什么有包?forge反混淆和CraftBukkit不同,forge的反混淆很彻底,包括方法名 、变量名都反混淆了
但CraftBukkit的反混淆并非如此,全都是Notch名,类似于int a,void b 这样的都是Notch名

那么既然有了NMS,要OBC何用?
OBC本身并不规定游戏的逻辑,比如僵尸瞄准玩家,这些都有NMS去实现
OBC负责提供接口给我们,修改游戏的内容
就比如说物品堆的DisplayName是在NBT内的,涉及到display混合数据包,再在其中留有物品名的数据键供定义,但是Bukkit给我们ItemMeta方便修改
再比如,给玩家发Title(就是在屏幕正中央显示一行大字一行小字),这本身是数据包的操作,但是使用Bukkit,你只需要调用sendTitle一行方法就可以了
但很多时候我们需要获取NMS中的对象,此时我们使用getHandle方法
因为OBC对象是对于NMS对象的一个封装,提供接口,这就注定OBC对象不脱离于NMS对象存在

注:getHandle方法一般是把OBC对象转换为NMS对象的方法,但并不是每个OBC对象都可以这样
比如说方块CraftBlock,就没有什么getHandle方法
通过例如((CraftPlayer)Bukkit.getPlayer("William_Shi")).getHandle(),我们就可以获取到NMS中的Player对象

那么方块为什么那么特殊呢?因为并不是每一个方块在任何时候都有对象的
假如任何一个方块都有对象,那么玩家这1个区块就会存在16x16x256个对象,如果加载附近区块呢?如果有几个玩家都在线呢?玩家移动16格,服务器是不是就要新加载65536个对象到内存然后再销毁掉旧的65536个对象?那你稍微跑一下图,游戏估计就会卡死
因此可以理解为,方块对象是在你需要使用的时候存在,不用的时候,只需要记录哪里的方块是什么材质就可以了
当然有例外,TileEntity,因为有一些方块并不只是有材质,比如说箱子有物品栏,就采用TileEntity保存数据

方块在获取上是分版本的,一般来说1.12和1.15采用两种不同的方法
1.12:方法getNMSBlock返回NMS中的Block对象(private方法)
1.15:方法getNMS返回NMS中的IBlockData,再通过IBlockData#getBlock得到NMS中的Block对象

为什么这期教程缩水了?因为最近在做PVPINCore的本地化键获取部分,下次考虑写一篇本地化键的获取
(并不是对原版本地化键的枚举,或者强行拼接xxx.minecraft.xxx的那种,当然是全部通过NMS来获取)

Pan$brother
感谢大大的教程

many先生
感谢楼主教程,顶

洞穴夜莺
没有本质不同吧
Entity也是用到时才创建CraftEntity对象,平时只有NMS对象

第一页 上一页 下一页 最后一页