网络封包

基本信息

属性 值
频道名 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 同步。

相关条目