Cleanroom icon indicating copy to clipboard operation
Cleanroom copied to clipboard

SimpleNetworkWrapper 服务端插件和客户端模组通讯报错

Open TLOvO opened this issue 2 months ago • 3 comments

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 等其他未被支持的启动器。

TLOvO avatar Oct 26 '25 01:10 TLOvO

有无完整源码

kappa-maintainer avatar Oct 26 '25 01:10 kappa-maintainer

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

TLOvO avatar Oct 26 '25 01:10 TLOvO

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 ?

Ecdcaeb avatar Oct 26 '25 11:10 Ecdcaeb