封包编解码

基本信息

属性 值
编解码器 net.bdew.lib.network.SerializedMessageCodec[T <: NetChannel]
Netty 基类 MessageToMessageCodec[FMLProxyPacket, BaseMessage[T]]
通道封装 net.bdew.lib.network.NetChannel
消息基类 net.bdew.lib.network.BaseMessage
序列化格式 Java 原生序列化(ObjectOutputStream / ObjectInputStream)
载体封包 cpw.mods.fml.common.network.internal.FMLProxyPacket
network/ Scala 文件数 7

功能

BD lib 的网络层允许下游模组用普通的 Scala case class 定义封包,无需手写字节读写。它把消息用 Java 原生序列化写入一个 Netty ByteBuf,再包进 FML 的 FMLProxyPacket 发出。

编解码流程

SerializedMessageCodec(network/SerializedMessageCodec.scala:35)标注了 Netty 的 @Sharable,同时实现 encode 与 decode:

  • encode(:37-51)— 分配 Unpooled.buffer(),包一层 ObjectOutputStream(new ByteBufOutputStream(buff)),writeObject(msg) 后连同 ctx.channel.attr(NetworkRegistry.FML_CHANNEL).get 构造 FMLProxyPacket 发出。
  • decode(:53-)— 包一层 ObjectInputStream(new ByteBufInputStream(msg.payload())),并覆写 resolveClass 加入白名单校验(见 封包白名单)。

NetChannel

NetChannel(name)(network/NetChannel.scala:29)封装了 FML 的 FMLEmbeddedChannel,按 Side 维护一份通道表。它定义了两个内部 Netty handler:

  • ServerHandler(SimpleChannelInboundHandler[Message])— 从 NetworkRegistry.NET_HANDLER 取出 EntityPlayerMP,在 serverChain 中查找处理器;找不到时只记一条警告(Unable to handle message from user %s)而不抛异常;整个处理体包在 try/catch 中,异常记为 Error handling packet。
  • ClientHandler — 客户端对应实现。

内置通道

本模组自身只注册了一条通道:

通道名 类 用途
bdew.multiblock multiblock/network/NetHandler.scala:16 多方块输出面配置(MsgOutputCfg、MsgOutputCfgSlot)

预注册的封包类

preInit 阶段向 SerializedMessageCodec 登记 4 个允许反序列化的类(BdLib.scala:65-68):BaseMessage、MsgOutputCfgRSMode、MsgOutputCfg、MsgOutputCfgSlot。

数值

数值名 值
network/ Scala 文件数 7
本模组自建网络通道数 1(bdew.multiblock)
预初始化登记的封包类数 4
序列化方式 Java 原生序列化(writeObject / readObject)
内部 Netty handler 数 2(ServerHandler / ClientHandler)

交互

玩家无法直接触发封包。以下为框架对使用者的可见行为:

触发 行为
下游模组发送封包 消息被序列化为字节并以 FMLProxyPacket 走 FML 通道
客户端发来未注册类型的封包 decode 中 resolveClass 拒绝该类,记录 Received disallowed message component class 警告并中止反序列化
消息类型已注册但无处理器 服务端记 Unable to handle message from user %s 警告,游戏不崩
消息处理器抛出异常 记为 Error handling packet 错误日志,不影响服务端继续运行

相关条目