网络封包
基本信息
| 属性 | 值 |
|---|---|
| 频道名 | MineTweaker3(MineTweakerMod.java:57,用 MODID 建 SimpleNetworkWrapper) |
| 封包总数 | 3(MineTweakerMod.java:65-81) |
| 方向 | 全部 服务端 → 客户端(3 个都注册为 Side.CLIENT) |
| 载体 | FML SimpleNetworkWrapper(cpw.mods.fml.common.network.simpleimpl) |
| 1.7.10 实现包 | minetweaker/mc1710/network/(6 个文件:3 封包 + 3 handler) |
| 接收方 | 客户端,由 MineTweakerAPI.client(MCClient)所在端接收 |
频道在类初始化时即创建(MineTweakerMod.java:57),3 个 registerMessage 调用紧随其后(:65-81),硬编码 discriminator 0 / 1 / 2。
3 个封包
| discriminator | 封包类 | handler | 方向 | 载荷 | 门控配置 |
|---|---|---|---|---|---|
| 0 | MineTweakerLoadScriptsPacket |
MineTweakerLoadScriptsHandler |
S→C | 脚本字节码 Map<String, byte[]> |
发送:sendLoadScripts / sendScriptsOnReloading;接收:handleLoadScripts |
| 1 | MineTweakerOpenBrowserPacket |
MineTweakerOpenBrowserHandler |
S→C | URL 字符串 | handleDesktopPackets |
| 2 | MineTweakerCopyClipboardPacket |
MineTweakerCopyClipboardHandler |
S→C | 文本字符串 | handleDesktopPackets |
全部 3 个 handler 的 onMessage 都返回 null(无回应封包)。
discriminator 0 —— 脚本下发
本模组唯一的功能性封包,让客户端获得与服务端一致的脚本环境。
发送点
| 时机 | 目标 | 门控 | 源码行 |
|---|---|---|---|
| 玩家登录 | sendTo(单个 EntityPlayerMP) |
sendLoadScripts |
FMLEventHandler.java:43-47 |
| 脚本重载后 | sendToAll(全部在线玩家) |
sendScriptsOnReloading |
MCPlatformFunctions.java:33-36 |
两处都把 MineTweakerAPI.tweaker.getScriptData() 塞进封包 —— 即 MTTweaker.load() 开头用 ScriptProviderMemory.collect(scriptProvider) 抓取的全量脚本文本快照(MTTweaker.java:116)。重载时走 MineTweakerImplementationAPI.reload() 步骤 9(:695-697),且仅当 server != null。
接收逻辑
MineTweakerLoadScriptsHandler.onMessage(network/MineTweakerLoadScriptsHandler.java:21-28):
if (MineTweakerAPI.server == null && MineTweakerConfig.handleLoadScripts) {
MineTweakerImplementationAPI.setScriptProvider(new ScriptProviderMemory(message.getData()));
MineTweakerImplementationAPI.reload();
}
双重门控:
MineTweakerAPI.server == null—— 当前不在单机 / 集成服里。在服务端本机server非 null,直接忽略,避免服务端用客户端脚本覆盖自己的。handleLoadScripts—— 配置项,默认true。
收到后换成内存型 provider 并完整重载一次(回滚 + 重新编译执行)。这也是「服务端改脚本、客户端 /mt reload 后立即生效」的实现方式。
discriminator 1 / 2 —— 桌面操作
两个封包让服务端请求客户端调用 AWT:
| 封包 | 客户端动作 | 源码行 |
|---|---|---|
MineTweakerOpenBrowserPacket |
Desktop.getDesktop().browse(new URI(url)) |
MineTweakerOpenBrowserHandler.java:26-31 |
MineTweakerCopyClipboardPacket |
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(data), null) |
MineTweakerCopyClipboardHandler.java:26-31 |
两者都要求 Desktop.isDesktopSupported() && MineTweakerConfig.handleDesktopPackets(:26),异常(IOException / URISyntaxException)静默吞掉。
脚本侧不可达
如配置项所述,唯一的服务端发送点是 MCPlayer.openBrowser(player/MCPlayer.java:132-137)与 MCPlayer.copyToClipboard(:139-144),二者都要求 player instanceof EntityPlayerMP。而对应的 IPlayer 接口方法刻意未加 @ZenMethod(api/player/IPlayer.java:67-71,注释写明 “not an exposed method. risks abuse”)。因此脚本无法触发这两个封包,handleDesktopPackets(默认 false)实际只对 Java 侧集成有意义。
客户端连接时机
ForgeEventHandler.onPlayerGuiOpen 监听 GuiOpenEvent,当 ev.gui instanceof GuiConnecting 时调 MineTweakerMod.INSTANCE.onClientAboutToConnect()(mc1710/ForgeEventHandler.java:50-54)。该方法受 loadScriptsBeforeConnection 门控(MineTweakerMod.java:181-188):
false(默认):直接return,等登录封包。true:装两级级联 provider(游戏根scripts/+ IMC),并reload();若antiStuck为 true 且已加载过则跳过重载。
这是「连接前加载脚本」配置项的触发点。
无响应封包
3 个 handler 全部 return null,本模组不向服务端发任何封包,也不定义自己的 GUI 同步。