网络管线

基本信息

属性 值
管线类 PacketPipeline(MessageToMessageCodec<FMLProxyPacket, AbstractPacket>)
通道名 TMechWorks(大写 W,与 modid TMechworks 大小写不一致)
基类 mantle.common.network.AbstractPacket
已注册包 1(PacketDrawbridge)
discriminator 0(自动分配,逻辑排序)
数据格式 13 字节(3×writeInt + writeByte)
初始化 TMechworks.preInit → packetPipeline.initalise()(TMechworks.java:74)
后初始化 TMechworks.postInit → packetPipeline.postInitialise()
编码风格 NIO(ByteBuf),非 1.7.10 常见的 Packet250CustomPayload

PacketDrawbridge

network/packet/PacketDrawbridge.java —— 唯一的数据包,单向 S2C→C2S,用于在 GUI 中设置 Drawbridge 的放置方向。

字段 类型 编码 字节
x int buffer.writeInt(x) 4
y int buffer.writeInt(y) 4
z int buffer.writeInt(z) 4
direction byte buffer.writeByte(direction) 1
合计 13

处理

handleServerSide(EntityPlayer)(:53-66):

World world = player.worldObj;
TileEntity te = world.getTileEntity(x, y, z);
if (te instanceof DrawbridgeLogic) {
    ((DrawbridgeLogic) te).setPlacementDirection(direction);
    te.markDirty();
} else if (te instanceof AdvancedDrawbridgeLogic) {
    ((AdvancedDrawbridgeLogic) te).setPlacementDirection(direction);
}

handleClientSide(EntityPlayer) 是空方法 —— 该包纯上行(C2S),客户端不发也不处理。

发送方:DrawbridgeGui.updateServer(byte) / AdvDrawbridgeGui.updateServer(byte) → TMechworks.packetPipeline.sendToServer(new PacketDrawbridge(...))(client/gui/DrawbridgeGui.java:91-92)。

数值

数值 值
通道名 TMechWorks(大写 W,非 modid TMechworks)
包数量 1
discriminator 0
数据长度 13 字节
方向 C2S 单向(handleClientSide 空)
容量上限 256(registerPacket 的 size() > 256 检查)
重复注册检查 有(packets.contains(clazz))
postInit 后注册 拒绝(isPostInitialised)

源码缺陷

  • 通道名与 modid 大小写不一致:modid 是 TMechworks,而 NetworkRegistry.INSTANCE.newChannel 传入 "TMechWorks"(network/packet/PacketPipeline.java:119)。FML 会把通道名转小写做内部匹配,当前可用;但若与其他 mod 的通道名仅大小写不同会发生冲突。源码无注释说明。
  • registerPacket 的 3 处失败路径全部不记日志(:49-65):三段 // You should log here!! 注释后直接 return false。若注册失败,discriminator 会错位导致客户端与服务端解码错包,但无任何日志可查。这是从 CPW 模板复制来的已知缺陷。
  • 容量检查是 > 256 而非 >= 256(:50):允许注册到 257 个包,此时第 257 个包的 discriminator 会溢出 byte。边界 off-by-one。
  • handleServerSide 的两个分支重复代码(:58-65):DrawbridgeLogic 与 AdvancedDrawbridgeLogic 各写一遍 setPlacementDirection,可用共同父接口 IDrawbridgeLogicBase 消除(该接口确实存在)。
  • AdvancedDrawbridgeLogic 分支缺 markDirty():DrawbridgeLogic 分支调了 te.markDirty(),Advanced 分支没有 —— 改方向后服务端可能不及时持久化该 TE。
  • 两个 updateServer 内保留 8 行注释掉的 Packet250CustomPayload 旧实现(client/gui/DrawbridgeGui.java:81-89、client/gui/AdvDrawbridgeGui.java:145-153):两处完全相同的 9 行死代码。
  • PacketDrawbridge 有两个构造器但只有 1 个包:PacketDrawbridge() 无参(供解码用)+ PacketDrawbridge(x, y, z, direction)(供编码用),这是标准做法,非缺陷。
  • packets 是 LinkedList 而非 ArrayList:包数量为 1,无性能影响。
  • 无任何包用于同步 Drawbridge 的 extension / active 状态:GUI 界面不显示伸展进度,玩家只能靠观察方块判断。

相关条目