But that would not explain why they work at the first login on a server with the client.
Anyway i am no longer using the SimpleNetworkWrapper. I implemented my own PluginChannel handler. Its code is based on the SimpleNetworkWrapper, but it doesnt converts the FMLProxyPacket to an IMessage, because i dont need it anyway. I just need the byte[] payload. My Channel works fine, but it still only works on the first login. Maybe this is actually a forge bug?! If you are interested here is the code:
package de.sirati97.oilmod.forge;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import net.minecraft.network.INetHandler;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.common.network.FMLEmbeddedChannel;
import net.minecraftforge.fml.common.network.FMLOutboundHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
import net.minecraftforge.fml.relauncher.Side;
import java.util.EnumMap;
/**
* Created by sirati97 on 16.03.2016.
*/
public abstract class PluginChannel {
private String name;
private EnumMap<Side, FMLEmbeddedChannel> channels;
private PluginChannelInboundHandler handler = new PluginChannelInboundHandler(this);
public PluginChannel(String name) {
this.name = name;
channels = NetworkRegistry.INSTANCE.newChannel(name, handler);
}
public void sendToServer(byte[] out) {
FMLProxyPacket message = encode(out);
channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER);
channels.get(Side.CLIENT).writeAndFlush(message).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
public String getName() {
return name;
}
public abstract byte[] onMessage(byte[] in, INetHandler netHandler);
public FMLProxyPacket encode(byte[] out) {
PacketBuffer buffer = new PacketBuffer(Unpooled.buffer());
buffer.writeBytes(out);
FMLProxyPacket proxy = new FMLProxyPacket(buffer, getName());
return proxy;
}
public byte[] decode(FMLProxyPacket msg) {
ByteBuf buf = msg.payload().copy();
byte[] stream = new byte[buf.array().length-buf.arrayOffset()];
buf.readBytes(stream);
return stream;
}
}
and the imbound handler:
package de.sirati97.oilmod.forge;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.minecraft.network.INetHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.network.FMLOutboundHandler;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.internal.FMLProxyPacket;
import org.apache.logging.log4j.Level;
/**
* Created by sirati97 on 16.03.2016.
*/
@ChannelHandler.Sharable
public class PluginChannelInboundHandler extends SimpleChannelInboundHandler<FMLProxyPacket> {
private final PluginChannel pluginChannel;
public PluginChannelInboundHandler(PluginChannel pluginChannel) {
this.pluginChannel = pluginChannel;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception {
INetHandler iNetHandler = ctx.channel().attr(NetworkRegistry.NET_HANDLER).get();
byte[] out = pluginChannel.onMessage(pluginChannel.decode(msg), iNetHandler);
if (out != null) {
FMLProxyPacket result = pluginChannel.encode(out);
ctx.channel().attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.REPLY);
ctx.writeAndFlush(result).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
FMLLog.log(Level.ERROR, cause, "PluginChannelInboundHandler exception");
super.exceptionCaught(ctx, cause);
}
}
That should not be an issue because NetworkRegistry.INSTANCE.newChannel(String name, ChannelHandler... handlers) puts them in there map on both sides:
public EnumMap<Side,FMLEmbeddedChannel> newChannel(String name, ChannelHandler... handlers)
{
if (channels.get(Side.CLIENT).containsKey(name) || channels.get(Side.SERVER).containsKey(name) || name.startsWith("MC|") || name.startsWith("\u0001") || name.startsWith("FML"))
{
throw new RuntimeException("That channel is already registered");
}
EnumMap<Side,FMLEmbeddedChannel> result = Maps.newEnumMap(Side.class);
for (Side side : Side.values())
{
FMLEmbeddedChannel channel = new FMLEmbeddedChannel(name, side, handlers);
channels.get(side).put(name,channel);
result.put(side, channel);
}
return result;
}