网络封包
基本信息
| 属性 | 值 |
|---|---|
| 注册类 | com.github.lunatrius.schematica.network.PacketHandler |
| 封包总数 | 6(discriminator 0–5) |
| 通道名 | Reference.MODID.toLowerCase() = schematica(network/PacketHandler.java:18) |
| 注册时机 | CommonProxy.init → PacketHandler.init()(proxy/CommonProxy.java:54) |
| 网络 API | Forge SimpleNetworkWrapper(1.7.10 FML) |
通道名由 modid 转小写得到,与 modid 本身的大小写不一致——modid 是 Schematica(大写 S,见 reference/Reference.java:8),通道是 schematica。
数值
| ID | 类 | 方向 | 载荷 |
|---|---|---|---|
| 0 | MessageCapabilities |
Side.CLIENT |
boolean isPrinterEnabled / isSaveEnabled / isLoadEnabled |
| 1 | MessageDownloadBegin |
Side.CLIENT |
ItemStack icon / int width / height / length |
| 2 | MessageDownloadBeginAck |
Side.SERVER |
空(无字段) |
| 3 | MessageDownloadChunk |
Side.CLIENT |
int baseX/baseY/baseZ、short[][][] blocks、byte[][][] metadata、List<TileEntity> tileEntities、List<Entity> entities |
| 4 | MessageDownloadChunkAck |
Side.SERVER |
三个 int 坐标 |
| 5 | MessageDownloadEnd |
Side.CLIENT |
String name |
字段定义来源:network/message/MessageCapabilities.java:15-17、MessageDownloadBegin.java:17-20、MessageDownloadChunk.java:28-35、MessageDownloadChunkAck.java:21、MessageDownloadEnd.java:21。
MessageDownloadChunk 静态持有方块注册表引用 BLOCK_REGISTRY = GameData.getBlockRegistry()(network/message/MessageDownloadChunk.java:26),用于把网络传来的方块 ID 还原成 Block 对象。
功能
分块传输协议
下载走五状态握手协议,状态机定义在 network/transfer/SchematicTransfer.State(network/transfer/SchematicTransfer.java:8-28):
BEGIN_WAIT → BEGIN → CHUNK_WAIT → CHUNK → … → END_WAIT → END
标记 waiting = true 的是 BEGIN_WAIT、CHUNK_WAIT、END_WAIT(:10、:12、:14),即服务端等客户端 Ack 的状态。
DownloadHandler.onServerTick(handler/DownloadHandler.java:30-37)在每个服务端 tick 的 END 阶段调 processQueue()(:36)。processQueue(:39-76)每次只处理一名玩家(取 transferMap 的首个 key,:44-47),把该玩家从 map 取出再放回(:47、:75),实现玩家间的轮转。
| 当前状态 | 动作 | 来源 |
|---|---|---|
| 非 waiting 且超时 | 重发当前区块,超出重试上限则丢弃 | :53-65 |
BEGIN_WAIT |
发 MessageDownloadBegin |
:66-67、:78-83 |
CHUNK_WAIT |
发 MessageDownloadChunk |
:68-69、:85-95 |
END_WAIT |
发 MessageDownloadEnd 并结束该传输(先 return,:72) |
:70-72、:97-100 |
setState 每次转移都会把 timeout 与 retries 清零(network/transfer/SchematicTransfer.java:78-82)。
区块推进
SchematicTransfer.confirmChunk(network/transfer/SchematicTransfer.java:54-76)在收到 Ack 且坐标匹配时把 base 坐标推进一格(:57),并在 X/Y/Z 越界时逐层回绕:X 满则 baseX=0 且 baseY += HEIGHT(:59-61);Y 满则 baseY=0 且 baseZ += LENGTH(:63-65);Z 满则转 END_WAIT 并返回 false(:67-69)。
能力同步
MessageCapabilities 把服务端的 printerEnabled / saveEnabled / loadEnabled 三个配置项下发给客户端,字段与三个 ConfigurationHandler 配置项一一对应(network/message/MessageCapabilities.java:15-17 vs handler/ConfigurationHandler.java:83-85)。
⚠️ playerQuotaKilobytes 与 serversideSchematicsEnabled 不在该封包中——它们只在服务端生效,不同步到客户端。
交互
传输超时与重试常量定义在 reference/Constants.java:32-36:
| 常量 | 值 | 含义 |
|---|---|---|
Constants.Network.TIMEOUT |
15 * 20 = 300 tick(15 秒) |
单个状态的等待上限 |
Constants.Network.RETRIES |
5 | 重试次数上限,超过则打 "{}'s download was dropped!" 并放弃(handler/DownloadHandler.java:54-58) |
单个传输区块尺寸(reference/Constants.java:38-43):
| 常量 | 值 |
|---|---|
Constants.SchematicChunk.WIDTH |
16 |
Constants.SchematicChunk.HEIGHT |
16 |
Constants.SchematicChunk.LENGTH |
16 |
⚠️ 区块尺寸是硬编码的 16³,与 SchematicTransfer.confirmChunk 的推进逻辑(network/transfer/SchematicTransfer.java:57-65)共用同一组常量,因此改尺寸会同时影响发包切片与 Ack 推进。