package openmods.network; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import cpw.mods.fml.common.network.FMLEmbeddedChannel; import cpw.mods.fml.common.network.FMLOutboundHandler; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.network.handshake.NetworkDispatcher; import cpw.mods.fml.common.network.internal.FMLProxyPacket; import cpw.mods.fml.relauncher.Side; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelPromise; import io.netty.util.AttributeKey; import java.util.Collection; import java.util.Map; public class ExtendedOutboundHandler extends ChannelOutboundHandlerAdapter { public static final AttributeKey<IPacketTargetSelector<?>> MESSAGETARGET = new AttributeKey<IPacketTargetSelector<?>>("om:outboundTarget"); private static <T> Collection<NetworkDispatcher> getDispatchers(IPacketTargetSelector<T> target, Object arg) { final Collection<NetworkDispatcher> output = Lists.newArrayList(); target.listDispatchers(target.castArg(arg), output); return output; } @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { if (!(msg instanceof FMLProxyPacket)) { ctx.write(msg); return; } final Channel channel = ctx.channel(); final IPacketTargetSelector<?> target = channel.attr(MESSAGETARGET).get(); if (target == null) { ctx.write(msg); return; } final FMLProxyPacket pkt = (FMLProxyPacket)msg; final Side channelSide = channel.attr(NetworkRegistry.CHANNEL_SOURCE).get(); Preconditions.checkState(target.isAllowedOnSide(channelSide), "Packet not allowed on side"); final String channelName = channel.attr(NetworkRegistry.FML_CHANNEL).get(); Object arg = channel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).get(); try { final Collection<NetworkDispatcher> dispatchers = getDispatchers(target, arg); for (NetworkDispatcher dispatcher : dispatchers) dispatcher.sendProxy(pkt); } catch (Throwable t) { throw new IllegalStateException(String.format( "Failed to select and send message (selector %s, arg: %s, channel: %s, side: %s)", target, arg, channelName, channelSide), t); } } public static void install(Map<Side, FMLEmbeddedChannel> channels) { for (Side side : Side.values()) install(channels.get(side)); } public static void install(FMLEmbeddedChannel fmlEmbeddedChannel) { fmlEmbeddedChannel.pipeline().addAfter("fml:outbound", "om:outbound", new ExtendedOutboundHandler()); } }