网络消息
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 通道的消息。
相关条目
- 传送目标流程 - 两条消息在完整链路中的位置
- 铭文输入界面 - 判别号 0 的发送点
- Gollorum 集成 - 判别号 1 的
paymentHandler取值 - Antique Atlas 集成 -
MarkersPacket的来源