PacketHandler(网络通道与注册表)
事实基准:
harvestcraft-1.3.14-GTNH.jar(MC 1.7.10 / Forge 10.13.4.1614)CFR 0.152 反编译源码。
概览
Pam’s HarvestCraft 的整个网络层是 FML SimpleNetworkWrapper(cpw.mods.fml.common.network.simpleimpl),没有使用旧版 FMLEmbeddedChannel / 自定义 payload。
| 属性 | 值 | 来源 |
|---|---|---|
| 通道实现 | NetworkRegistry.INSTANCE.newSimpleChannel(...) → SimpleNetworkWrapper |
PacketHandler.java:14 |
| 通道名 | "harvestcraft" |
PacketHandler.java:14 |
| 字段 | PacketHandler.INSTANCE(public static final) |
PacketHandler.java:14 |
| 初始化时机 | HarvestCraft.preInit() 第 92 行调用 PacketHandler.init() |
HarvestCraft.java:92 |
| 已注册包数 | 3 | PacketHandler.java:17-19 |
| 判别器占用 | 0、1、2(连续,无空洞) |
PacketHandler.java:17-19 |
注册表(权威来源:PacketHandler.init())
init() 的全部内容就是下面三行 registerMessage 调用——PacketHandler.java:17-19:
| 判别器 | 包类 | 目标侧 | Handler |
|---|---|---|---|
0 |
MessageMarketBrowse |
Side.SERVER |
自身(IMessageHandler<MessageMarketBrowse, IMessage>) |
1 |
MessageMarketBuy |
Side.SERVER |
自身 |
2 |
MessageMarketClosed |
Side.SERVER |
自身 |
三个包全部是客户端 → 服务端(Side.SERVER 表示"在服务端处理")。本模组没有任何注册为 Side.CLIENT 的包:服务端从不主动向客户端推送本模组自定义数据,市场 UI 的同步完全靠原版方块实体 / GUI 同步机制。
三个包都使用自处理模式(implements IMessage, IMessageHandler<自身, IMessage>),不经过 SimpleNetworkWrapper.registerMessage(handler, requestMessageType, discriminator, side) 的四参分离写法。
方向与调用点
| 方向 | 触发点 | 来源 |
|---|---|---|
| 客户端 → 服务端 | GuiMarket.java:80、:82、:85 发送 MessageMarketBuy |
PacketHandler.INSTANCE.sendToServer(...) |
| 客户端 → 服务端 | GuiMarket.java:93 发送 MessageMarketClosed |
PacketHandler.INSTANCE.sendToServer(...) |
全部 4 个发送点都在 GuiMarket 里,即只有打开市场 GUI 时才会产生本模组的网络流量。
缺陷:注册了但没有发送方的包
MessageMarketBrowse(判别器 0)在 PacketHandler 里注册、在自身 onMessage 里实现了完整的服务端处理逻辑,但客户端没有任何一处构造并发送它——全模组对 MessageMarketBrowse 的引用只有 PacketHandler.java:6(import)、PacketHandler.java:17(注册)和它自己的类定义。
- 处理器逻辑:
MessageMarketBrowse.java:46-55(定位TileEntityMarket→setBrowsingInfo(itemNum)→ 刷新 GUI)。 - 实际可达性:不可达。市场翻页功能实际由
TileEntityMarket自身的方块实体同步承担。
缺陷:同名通道被创建了两次
| 位置 | 代码 | 后果 |
|---|---|---|
PacketHandler.java:14 |
NetworkRegistry.INSTANCE.newSimpleChannel("harvestcraft") → PacketHandler.INSTANCE |
承载全部 3 个包注册 |
HarvestCraft.java:162 |
NetworkRegistry.INSTANCE.newSimpleChannel(modid) → HarvestCraft.INSTANCE |
完全未被使用 |
HarvestCraft.java:59 声明了 public static final SimpleNetworkWrapper INSTANCE,静态初始化块 HarvestCraft.java:162 用同一个 modid(= "harvestcraft",见 HarvestCraft.java:59)又建了一个通道。
HarvestCraft.INSTANCE在全模组没有任何读取点(除声明与赋值外无引用),因此没有包注册到它上面。- 两个 wrapper 用了相同的通道名字符串。本机没有 FML 1.7.10 的源码,无法从本仓库判定
NetworkRegistry.INSTANCE.newSameChannel对重名通道的处理(是复用、覆盖还是抛异常),因此不断言这会在运行时抛错;只记录"同名通道被创建两次"这一源码事实。
另一套未使用的抽象:AbstractPacket
AbstractPacket(encodeInto / decodeInto / handleClientSide / handleServerSide)是旧版自定义 payload 方案的基类,共有 5 个子类,全部是空方法。详见 AbstractPacket 与 旧版空壳包。