SimpleNetworkWrapper 服务端插件和客户端模组通讯报错
Your CleanroomMC Discord Username
No response
Cleanroom Version
0.3.21
Java Version
Java 21
Graphics Card Vendor
NVidia
Bug Report
[09:13:40] [Client thread/ERROR]: FMLIndexedMessageCodec exception caught io.netty.handler.codec.EncoderException: java.lang.RuntimeException: Undefined discriminator for message type eos.moe.celestialepic.MessageHandlerToServer in channel celestial:channel at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:107) at io.netty.handler.codec.MessageToMessageCodec.write(MessageToMessageCodec.java:130) at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:825) at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:804) at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:869) at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1046) at io.netty.channel.Channel.writeAndFlush(Channel.java:257) at io.netty.channel.embedded.EmbeddedChannel.writeAndFlush(EmbeddedChannel.java:797) at net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper.sendToServer(SimpleNetworkWrapper.java:321) at eos.moe.celestialepic.ClientPacketSender.sendPacket(ClientPacketSender.java:131) at net.minecraft.client.network.NetHandlerPlayClient.handler$zzj000$unknown_owner$onJoinGame(NetHandlerPlayClient.java:2289) at net.minecraft.client.network.NetHandlerPlayClient.func_147282_a(NetHandlerPlayClient.java:309) at net.minecraft.network.play.server.SPacketJoinGame.func_148833_a(SourceFile:76) at net.minecraft.network.play.server.SPacketJoinGame.func_148833_a(SourceFile:13) at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:22) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) at net.minecraft.util.Util.func_181617_a(Util.java:47) at net.minecraft.client.Minecraft.func_71411_J(Minecraft.java:1068) at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:398) at net.minecraft.client.main.Main.main(SourceFile:123) at top.outlands.foundation.LaunchHandler.launch(LaunchHandler.java:125) at top.outlands.foundation.boot.Foundation.main(Foundation.java:39) Caused by: java.lang.RuntimeException: Undefined discriminator for message type eos.moe.celestialepic.MessageHandlerToServer in channel celestial:channel at net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec.encode(FMLIndexedMessageToMessageCodec.java:76) at io.netty.handler.codec.MessageToMessageCodec$2.encode(MessageToMessageCodec.java:85) at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:90) ... 22 more [09:13:40] [Client thread/INFO]: [CHAT] 曼德拉草 joined the game
以下是我的代码,他们在Forge上可以正常工作,和服务器通讯等。
public class ClientPacketSender {
/** 与服务端通信的主信道 */
public static SimpleNetworkWrapper simpleNetworkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel("celestial:channel");
/**
* 注册消息处理器
*/
public static void register() {
//取值范围:0 ~ 255(单字节)
// simpleNetworkWrapper.registerMessage(MessageHandlerToServer.class, MessageHandlerToServer.class, 111, Side.CLIENT);
simpleNetworkWrapper.registerMessage(MessageHandlerToServer.class, MessageHandlerToServer.class, 111, Side.SERVER);
simpleNetworkWrapper.registerMessage(MessageHandlerToClient.class, MessageHandlerToClient.class, 112, Side.CLIENT);
}
}
Mod List
Optifine 我自己的模组 Fugue
Final Checklist
- [x] I have searched the issues and haven't found a similar issue.
- [x] I have read the readme and know that what is action build.
- [x] I have installed Fugue and it didn't fix my issue.
- [x] I have installed Scalar Legacy and it didn't fix my issue.
- [x] I have switched my Forgelin and LibrarianLib to continuous versions(check readme for more detail).
- [x] I am running a test build from Cleanroom Github Actions. (Or, if I've compiled it myself I plan to fix the issue)
- [x] I did not use PCL/PCLCE or other unsupported launchers. 我没有使用 PCL/PCLCE 等其他未被支持的启动器。
有无完整源码
package eos.moe.celestialepic;
import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.zip.GZIPOutputStream; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraftforge.fml.common.network.NetworkRegistry; import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; import net.minecraftforge.fml.relauncher.Side;
/**
-
客户端发送数据包到服务端的工具类
-
封装了各种不同类型的数据传输方法 */ public class ClientPacketSender {
/** 与服务端通信的主信道 */ public static SimpleNetworkWrapper simpleNetworkWrapper = NetworkRegistry.INSTANCE.newSimpleChannel("celestial:channel");
/**
- 注册消息处理器 */ public static void register() { //取值范围:0 ~ 255(单字节) // simpleNetworkWrapper.registerMessage(MessageHandlerToServer.class, MessageHandlerToServer.class, 111, Side.CLIENT); simpleNetworkWrapper.registerMessage(MessageHandlerToServer.class, MessageHandlerToServer.class, 111, Side.SERVER); simpleNetworkWrapper.registerMessage(MessageHandlerToClient.class, MessageHandlerToClient.class, 112, Side.CLIENT); }
/**
- 通知实体进入世界 */ public static void sendEntityJoin(UUID entityId) { simpleNetworkWrapper.sendToServer(new MessageHandlerToServer(4, buf -> buf.writeUniqueId(entityId))); }
/**
-
压缩并分片发送大数据 */ public static void sendLargeData(Map<String, String> map) throws Throwable { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : map.entrySet()) { sb.append(entry.getKey()).append(",").append(entry.getValue()).append("|"); } byte[] compressed = compressData(sb.toString().getBytes(StandardCharsets.UTF_8)); if (compressed == null) return;
List<byte[]> parts = splitData(compressed, 30000); if (parts.isEmpty()) { sendDataPart(new byte[0], true); return; } for (int i = 0; i < parts.size(); i++) { sendDataPart(parts.get(i), i == parts.size() - 1); } }
/**
- 发送数据分片 */ private static void sendDataPart(byte[] data, boolean isLast) { simpleNetworkWrapper.sendToServer(new MessageHandlerToServer(13, buf -> { buf.writeBoolean(isLast); buf.writeInt(data.length); buf.writeBytes(data); })); }
/**
- 按指定大小切分字节数组 */ public static List<byte[]> splitData(byte[] data, int size) { List<byte[]> parts = new ArrayList<>(); int pos = 0; while (pos < data.length) { int end = Math.min(pos + size, data.length); parts.add(Arrays.copyOfRange(data, pos, end)); pos = end; } return parts; }
/**
- 使用 GZIP 压缩字节数组 */ public static byte[] compressData(byte[] data) throws Throwable { ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream gzip = null; try { gzip = new GZIPOutputStream(out); gzip.write(data); gzip.close(); closeQuietly(out); closeQuietly(gzip); return out.toByteArray(); } catch (IOException e) { DragonCore.logHelper.sendError("数据压缩失败", e); closeQuietly(out); closeQuietly(gzip); return null; } }
/**
- 安全关闭流 */ public static void closeQuietly(Closeable closeable) throws IOException { if (closeable != null) { try { closeable.close(); } catch (IOException ignored) { } } } } package eos.moe.celestialepic;
import com.google.common.primitives.Bytes; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.zip.GZIPInputStream; import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; import org.apache.commons.io.IOUtils;
public class MessageHandlerToClient implements IMessage, IMessageHandler<MessageHandlerToClient, IMessage> { private static final Map<Integer, Method> packetHandlerMethods = new HashMap<>(); private static final ConcurrentHashMap<Integer, byte[]> packetCache;
static {
registerPacketHandlers(CoreMessageHandler.class);
packetCache = new ConcurrentHashMap<>();
}
private static void registerPacketHandlers(Class<?> cls) throws SecurityException {
for (Method method : cls.getDeclaredMethods()) {
if (Modifier.isStatic(method.getModifiers()) && method.isAnnotationPresent(PacketPackHandler.class)) {
method.setAccessible(true);
PacketPackHandler annotation = method.getAnnotation(PacketPackHandler.class);
if (packetHandlerMethods.containsKey(annotation.Index())) {
throw new RuntimeException("重复id" + cls.getSimpleName() + " :" + method.getName());
}
packetHandlerMethods.put(annotation.Index(), method);
}
}
}
@Override
public void fromBytes(ByteBuf byteBuf) {
boolean z = byteBuf.readBoolean();
byte[] bArrMethod182 = readBytes(byteBuf);
if (z) {
bArrMethod182 = decompress(bArrMethod182);
}
if (bArrMethod182 == null) {
return;
}
PacketBuffer packetBuffer = new PacketBuffer(Unpooled.wrappedBuffer(bArrMethod182));
int i = packetBuffer.readInt();
if (packetBuffer.readInt() == 1) {
byte[] bArrRemove = packetCache.remove(i);
if (bArrRemove != null) {
packetBuffer = new PacketBuffer(Unpooled.wrappedBuffer(bArrRemove));
}
PacketBuffer finalPacketBuffer = packetBuffer;
Minecraft.getMinecraft().addScheduledTask(() -> {
handlePacket(i, finalPacketBuffer);
});
return;
}
packetCache.put(i, Bytes.concat(packetCache.getOrDefault(i, new byte[0]), readBytes(packetBuffer)));
}
public static byte[] readBytes(ByteBuf buf) {
byte[] bytes = new byte[buf.readableBytes()];
buf.getBytes(buf.readerIndex(), bytes);
return bytes;
}
@Override
public void toBytes(ByteBuf buf) {
// 这里暂时为空
}
private static byte[] decompress(byte[] compressed) {
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
IOUtils.copy(new GZIPInputStream(new ByteArrayInputStream(compressed)), output);
IOUtils.closeQuietly((InputStream) null);
IOUtils.closeQuietly(output);
return output.toByteArray();
} catch (IOException e) {
IOUtils.closeQuietly((InputStream) null);
IOUtils.closeQuietly(output);
return null;
} catch (Throwable t) {
IOUtils.closeQuietly((InputStream) null);
IOUtils.closeQuietly(output);
throw t;
}
}
/* renamed from: Method2495 */
@Override
public IMessage onMessage(MessageHandlerToClient message, MessageContext context) {
return null;
}
private void handlePacket(int packetId, PacketBuffer buffer) {
try {
Method handler = packetHandlerMethods.get(packetId);
if (handler == null) {return;}
Class<?>[] paramTypes = handler.getParameterTypes();
Object[] args = new Object[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
Class<?> type = paramTypes[i];
if (type == String.class) {
args[i] = buffer.readStringUnlimited();
} else if (type == int.class) {
args[i] = buffer.readInt();
} else if (type == float.class) {
args[i] = buffer.readFloat();
} else if (type == double.class) {
args[i] = buffer.readDouble();
} else if (type == boolean.class) {
args[i] = buffer.readBoolean();
} else if (type == long.class) {
args[i] = buffer.readLong();
} else if (type == UUID.class) {
args[i] = buffer.readUniqueId();
} else if (type == PacketBuffer.class) {
args[i] = buffer;
} else if (type == ItemStack.class) {
args[i] = buffer.readItemStack();
} else if (type == BlockPos.class) {
args[i] = BlockPos.fromLong(buffer.readLong());
} else if (type == NBTTagCompound.class) {
args[i] = NBTHelper.readNBT(buffer);
}
}
handler.invoke(null, args);
} catch (Throwable t) {
t.printStackTrace();
} finally {
buffer.release();
}
}
}
Undefined message for discriminator 112 in channel celestial:channel
Please send your mod, I need to see it up close. I'm not sure if it actually works on the forge. reproduce is needed.
And....Your are trying to handle the packet at fromBytes ?