网络消息

SignPostsNetworkHelper 用 Forge 1.7.10 的 SimpleNetworkWrapper(FMLEmptyPacket 时代的 cpw.mods.fml.common.network.simpleimpl)注册 2 个消息,通道名等于 SignPostsMod.ID = signposts。

⚠️ 本模组只有 2 个自定义消息,不是 4 个。 network/ 目录下共 4 个文件 = 2 个消息类 + 2 个 Handler 类。源码中没有 S→C(服务端到客户端)方向的自定义消息。

通道注册

public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel(SignPostsMod.ID);

SignPostsMod 里另外定义了 CHANNEL = ID 常量,但从未被使用(helper 直接传 SignPostsMod.ID)。

消息对照表

判别号 消息类 Handler 方向 载荷字段(字节序) 何时发送
0 CreateJumpTargetMessage CreateJumpTargetMessageHandler C→S int signX、int signY、int signZ、double jumpX、double jumpY、double jumpZ、String label(UTF8) 玩家在 铭文输入界面 点「完成」按钮
1 JumpMessage JumpMessageHandler C→S int markerId、String paymentHandler(UTF8) 玩家在 Atlas 界面上点击一个 signPost 类型的全局标记

方向由 registerMessage(handler, msg, id, Side.SERVER) 明确指定为 Side.SERVER,两个发送方法都走 INSTANCE.sendToServer(msg)。

判别号与注册顺序

INSTANCE.registerMessage(CreateJumpTargetMessageHandler.class, CreateJumpTargetMessage.class, 0, Side.SERVER);
INSTANCE.registerMessage(JumpMessageHandler.class,  JumpMessage.class,  1, Side.SERVER);

判别号 0 / 1 是硬编码的,顺序不可调换(两个消息都需要无参构造器,Netty 靠反射实例化)。

CreateJumpTargetMessage

字段 类型 说明
signX int 目标路牌 X
signY int 目标路牌 Y(下半格)
signZ int 目标路牌 Z
jumpX double 传送目标 X(玩家坐标,浮点)
jumpY double 传送目标 Y
jumpZ double 传送目标 Z
label String 铭文文本,经 ByteBufUtils.writeUTF8String 编码

Handler 直接转发,不做任何服务端校验:

SignPostsMod.addJumpTarget(message.getSignX(), message.getSignY(), message.getSignZ(),
                           message.getJumpX(), message.getJumpY(), message.getJumpZ(),
                           message.getLabel(), ctx.getServerHandler().playerEntity);

6 个坐标与铭文全部来自客户端,服务端既不检查玩家是否手持 魔法路牌标记、不检查距离、不检查权限(源码无任何 OP/权限判定,已 grep 确认)。唯一的服务端约束来自 addJumpTarget 内部:目标方块位置必须确实是 SignPostTileEntity,否则整段逻辑被跳过。

JumpMessage

字段 类型 说明
markerId int Atlas 全局标记 ID
paymentHandler String 支付处理器注册键:signposts 或 signpost

Handler 同样直接转发:

SignPostsMod.playerJump(msg.getMarkerId(), ctx.getServerHandler().playerEntity, msg.getPaymentHandler());

paymentHandler 键由客户端提供。服务端 paymentHandlers.get(key) 若返回 null(例如客户端发送了未注册的键),在非创造模式玩家身上会触发 NullPointerException——源码没有 null 检查。

本模组之外的数据包

客户端 → 服务端还会经由 Antique Atlas 发送 BrowsingPositionPacket(关闭 Atlas 界面时记录浏览位置,SignPostsAtlasGui.onGuiClosed)。服务端 → 客户端则使用 Antique Atlas 的 MarkersPacket(新增标记时 PacketDispatcher.sendToAll)与原版 S35PacketUpdateTileEntity(路牌 TileEntity 同步)。这些都不是 signposts 通道的消息。

相关条目