仅客户端模组
RecEx 的功能只在客户端存在。专用服务端会装上这个 mod(否则 acceptableRemoteVersions 无法满足连接校验),但只会在日志里打一条警告。
端代理结构
@Mod 类 RecipeExporterMod 用 @SidedProxy 绑定两个实现:
| 端 | 类 |
|---|---|
| 客户端 | com.bigbass.recex.proxy.ClientProxy |
| 服务端 | com.bigbass.recex.proxy.ServerProxy |
两者都继承空的 CommonProxy(其 preInit 与 init 都是空方法体)。
端差异
| 行为 | 客户端 | 服务端 |
|---|---|---|
preInit |
调 super.preInit(空) |
log.warn("This is a clientside only mod!") |
preInit 其余 |
注册 KeyInputEventHandler 到 FML 事件总线 |
无 |
init |
调 super.init(空)+ KeyBindings.getInstance() |
未覆写 → 空 |
即服务端把唯一的 preInit 槽位用来打那条警告;热键注册(ClientProxy.init)与按键事件监听(ClientProxy.preInit)都只发生在客户端。
服务端 ServerProxy 里的这条警告就是判断"你装了个只能在客户端用的 mod"的唯一信号。
客户端独有代码
@SideOnly(Side.CLIENT) 只标注在 gui/GuiMain.java 一个类上。客户端专属的引用还包括:
net.minecraft.client.settings.KeyBinding(KeyBindings.java)net.minecraft.client.Minecraft、net.minecraft.client.gui.GuiScreen(listeners/KeyInputEventHandler.java)org.lwjgl.opengl.GL11、Tessellator、OpenGlHelper(graphics/GraphicsRender.java)
这些类在服务端从未被加载,因为没有任何服务端代码路径会触及它们——ServerProxy.preInit 只打日志。
网络侧
没有任何自定义网络消息。grep -rn "SimpleNetworkWrapper\|IMessage\|NetworkRegistry\|sendToServer\|FMLEmbeddedChannel" src/main/java 零命中——没有自建 channel、没有客户端→服务端包、没有服务端→客户端包。
唯一的网络类使用是 GuiMain 里复用原版聊天包做本地反馈:
mc.getNetHandler().handleChat(new S02PacketChat(new ChatComponentText("Started export")));
S02PacketChat 是原版 net.minecraft.network.play.server 的类,通过 handleChat 直接塞进本地聊天栏显示,并不经过服务器。
联机规则
@Mod(modid = RecipeExporterMod.MODID,
version = Tags.VERSION,
acceptableRemoteVersions = "*")
acceptableRemoteVersions = "*" 表示接受任何远端版本——这是客户端专用 mod 在多人游戏里能连上服务器的前提:服务器若装着这个 mod 也不会因为版本差异拒绝连接,服务器若没装也不影响。
ServerProxy 打的警告不阻止服务器加载该 mod,只提示它无用。
README.md 强调导出必须在已加载的存档/服务器中进行(“the export process happens while in a loaded world/server”),也就是说多人游戏里由客户端本地执行导出,导出的是该客户端自己内存中的配方注册表。
相关条目
- Open Exporter GUI - 客户端独有的热键
- 配方导出流程 - 导出在客户端子线程中执行