网络封包(Network Messages)
基本信息
| 属性 | 值 |
|---|---|
| 通道 | net/NetworkHandler.java 的 NetworkHandler.instance |
| 类型 | cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper |
| 通道名 | Hodgepodge.MODID = hodgepodge(NetworkHandler.java:12) |
| 注册时机 | Hodgepodge.java:81 —— NetworkHandler.init()(FMLPreInitEvent 阶段) |
| 封包总数 | 3(ID 0、1、2),全部单向:S2C |
| 关联 | Speedups 配置、Coremod 引导 |
功能
Hodgepodge 只有 3 个自研封包,且都走 FML 的 SimpleNetworkWrapper(registerMessage(消息类, 处理类, id, side))。三者全部注册为 Side.CLIENT —— 即服务端发、客户端收,没有反向通道。
Hodgepodge 不注册方块 / 物品 / TileEntity,因此没有方块实体同步封包。第 1 号封包虽然是实体描述封包,但它是批量转发原版
S35PacketUpdateTileEntity的透传容器,不新增实体类型。
明细
ID 0 —— MessageConfigSync(配置同步)
| 属性 | 值 |
|---|---|
| 源文件 | net/MessageConfigSync.java |
| 载荷 | 2 个 boolean,共 2 字节 |
| 发送时机 | 玩家登录时,HodgepodgeEventHandler.java:50 |
| 触发 | @SubscribeEvent onPlayerLogin(PlayerEvent.PlayerLoggedInEvent) |
同步两个由服务端决定、客户端不能自行开启的开关:
| 字段 | 源配置 | 客户端行为 |
|---|---|---|
longerSentMessages |
TweaksConfig.longerSentMessages |
直接覆盖客户端值 |
fastBlockPlacingServerSide |
TweaksConfig.fastBlockPlacingServerSide |
为 false 时才强制关闭 fastBlockPlacing 与 fastBlockPlacingServerSide |
处理端逻辑(MessageConfigSync.java:47-56):
TweaksConfig.longerSentMessages = message.isLongerSentMessages();
if (!message.isFastBlockPlacingServerSide()) {
TweaksConfig.fastBlockPlacing = false;
TweaksConfig.fastBlockPlacingServerSide = false;
}
注意单向覆盖:fastBlockPlacingServerSide 为 true 时客户端值不变(保留玩家自己的本地设置)。
向后兼容的读法
fromBytes 对第二个布尔做了容错(:20-30):
longerSentMessages = buf.readBoolean();
if (buf.readableBytes() < 1) {
fastBlockPlacingServerSide = true; // 旧服务端只发 1 字节
} else {
fastBlockPlacingServerSide = buf.readBoolean();
}
源码注释:«Ensures clients with the setting can still join servers without the setting (servers running older versions of the mod)»。即第二个字段是后加的,用剩余可读字节数判断对端是否为旧版。
ID 1 —— BatchedDescriptionPacket / BatchedDescriptionHandler(方块实体描述批处理)
| 属性 | 值 |
|---|---|
| 源文件 | hax/TileEntityDescriptionBatcher.java:122-137(封包)、:139-174(处理) |
| 载荷 | 拼接后的 ByteBuf(多个原版 S35PacketUpdateTileEntity 的字节流) |
| 发送时机 | 服务端 tick END 阶段 flushMessages(TickEvent.ServerTickEvent)(:100-109) |
| 门控 | SpeedupsConfig.batchDescriptionPacketsMixins(Mixin 侧,需重启)+ batchDescriptionPacketsCode(代码侧,不需重启) |
send()(:111-120)把该玩家本 tick 累积的 ByteBuf 拷进新缓冲再发出并清空原缓冲。
处理端有两条路径,由 SpeedupsConfig.asyncBatchedNBTParsing 决定:
| 路径 | 行为 |
|---|---|
| 关闭(默认) | parseAndHandle(message.data, client) —— 同线程直接解析并逐个 client.handleUpdateTileEntity(packet) |
| 打开 | 先把字节拷进 byte[](注释:原缓冲可能被复用),提交 AsyncNBTParser,解析完再 Minecraft.func_152344_a(...) 回主线程逐个处理 |
非客户端连接时打 ERROR 后忽略(:143-149):Received BatchedDescriptionPacket while not playing: ignoring it。
ID 2 —— MessageChangeDifficulty(难度同步)
| 属性 | 值 |
|---|---|
| 源文件 | net/MessageChangeDifficulty.java(37 行,全文) |
| 载荷 | 1 个 byte(EnumDifficulty 的 id) |
| 发送时机 | 服务端难度变化时 |
| 发送方 | mixins/early/minecraft/MixinMinecraftServer_UpdateClientDifficulty.java:28 |
| 发送范围 | sendToDimension(...) —— 只发给该维度的玩家 |
| 门控 | FixesConfig.updateClientDifficultyOnServer |
onMessage 只有一行(:32-36):Minecraft.getMinecraft().theWorld.difficultySetting = message.difficulty;
对应 FixesConfig.updateClientDifficultyOnServer 的描述:«Updates the difficulty on every connected client when the difficulty of the server changes via /difficulty or the difficulty button.» —— 原版 1.7.10 中客户端难度不随服务端更新。
数值
| 项 | 值 |
|---|---|
| 封包 ID 范围 | 0 – 2(3 个) |
| 方向 | 全部 S2C |
SimpleNetworkWrapper 实例数 |
1(NetworkHandler.instance) |
| 通道名 | hodgepodge |
相关条目
- Speedups 配置 - 封包 1 的三个门控开关
- Fixes 配置 - 封包 0 与 2 的门控开关
- Tweaks 配置 - 封包 0 同步的两个字段
- Coremod 引导 - 混淆状态下 SRG 字段名选择