Add in a simple(ish) event driven network handling system. Register using newEventDrivenChannel

and you'll get a simple network handler that will fire events at the subscriber(s) of your
choice, whenever a packet is received. You'll also get some convenience methods for sending
to things.
This commit is contained in:
Christian 2014-01-12 13:20:41 -05:00
parent 7a8eda46c4
commit 670f76accd
7 changed files with 212 additions and 11 deletions

View file

@ -0,0 +1,88 @@
package cpw.mods.fml.common.network;
import io.netty.channel.ChannelHandlerContext;
import java.util.EnumMap;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
import cpw.mods.fml.common.eventhandler.EventBus;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import cpw.mods.fml.relauncher.Side;
public class FMLEventChannel {
private EnumMap<Side, FMLEmbeddedChannel> channels;
private EventBus eventBus;
FMLEventChannel(String name)
{
this.channels = NetworkRegistry.INSTANCE.newChannel(name, new NetworkEventFiringHandler(this));
this.eventBus = new EventBus();
}
public void register(Object object)
{
this.eventBus.register(object);
}
public void unregister(Object object)
{
this.eventBus.unregister(object);
}
void fireRead(FMLProxyPacket msg, ChannelHandlerContext ctx)
{
FMLNetworkEvent.CustomPacketEvent<?> event = null;
if (msg.handler() instanceof NetHandlerPlayClient)
{
NetHandlerPlayClient client = (NetHandlerPlayClient) msg.handler();
event = new FMLNetworkEvent.ClientCustomPacketEvent(client.func_147298_b(), msg);
}
else if (msg.handler() instanceof NetHandlerPlayServer)
{
NetHandlerPlayServer server = (NetHandlerPlayServer) msg.handler();
event = new FMLNetworkEvent.ServerCustomPacketEvent(server.func_147362_b(), msg);
}
if (event != null)
{
this.eventBus.post(event);
if (event.reply != null)
{
ctx.channel().attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.REPLY);
ctx.writeAndFlush(event.reply);
}
}
}
public void sendToAll(FMLProxyPacket pkt)
{
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL);
channels.get(Side.SERVER).writeAndFlush(pkt);
}
public void sendTo(FMLProxyPacket pkt, EntityPlayerMP player)
{
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player);
channels.get(Side.SERVER).writeAndFlush(pkt);
}
public void sendToAllAround(FMLProxyPacket pkt, NetworkRegistry.TargetPoint point)
{
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point);
channels.get(Side.SERVER).writeAndFlush(pkt);
}
public void sendToDimension(FMLProxyPacket pkt, int dimensionId)
{
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION);
channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimensionId);
channels.get(Side.SERVER).writeAndFlush(pkt);
}
public void sendToServer(FMLProxyPacket pkt)
{
channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER);
channels.get(Side.CLIENT).writeAndFlush(pkt);
}
}

View file

@ -5,6 +5,8 @@ import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.INetHandlerPlayClient;
import net.minecraft.network.play.INetHandlerPlayServer;
import cpw.mods.fml.common.eventhandler.Event;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import cpw.mods.fml.relauncher.Side;
public class FMLNetworkEvent<T extends INetHandler> extends Event {
public final T handler;
@ -49,4 +51,49 @@ public class FMLNetworkEvent<T extends INetHandler> extends Event {
super((INetHandlerPlayClient) manager.func_150729_e(), INetHandlerPlayClient.class, manager);
}
}
public static abstract class CustomPacketEvent<S extends INetHandler> extends FMLNetworkEvent<S> {
/**
* The packet that generated the event
*/
public final FMLProxyPacket packet;
/**
* Set this packet to reply to the originator
*/
public FMLProxyPacket reply;
CustomPacketEvent(S thing, Class<S> type, NetworkManager manager, FMLProxyPacket packet)
{
super(thing, type, manager);
this.packet = packet;
}
public abstract Side side();
}
public static class ClientCustomPacketEvent extends CustomPacketEvent<INetHandlerPlayClient> {
public ClientCustomPacketEvent(NetworkManager manager, FMLProxyPacket packet)
{
super((INetHandlerPlayClient) manager.func_150729_e(), INetHandlerPlayClient.class, manager, packet);
}
@Override
public Side side()
{
return Side.CLIENT;
}
}
public static class ServerCustomPacketEvent extends CustomPacketEvent<INetHandlerPlayServer> {
public ServerCustomPacketEvent(NetworkManager manager, FMLProxyPacket packet)
{
super((INetHandlerPlayServer) manager.func_150729_e(), INetHandlerPlayServer.class, manager, packet);
}
@Override
public Side side()
{
return Side.SERVER;
}
}
}

View file

@ -31,12 +31,26 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
}
@Override
public List<NetworkDispatcher> selectNetworks(Object args)
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
return null;
}
},
REPLY
{
@Override
public void validateArgs(Object args)
{
// NOOP
}
@Override
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
return ImmutableList.of(packet.getDispatcher());
}
},
PLAYER
{
@Override
@ -48,7 +62,7 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
}
}
@Override
public List<NetworkDispatcher> selectNetworks(Object args)
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
EntityPlayerMP player = (EntityPlayerMP) args;
NetworkDispatcher dispatcher = player.field_71135_a.field_147371_a.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
@ -63,7 +77,7 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
}
@SuppressWarnings("unchecked")
@Override
public List<NetworkDispatcher> selectNetworks(Object args)
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.<NetworkDispatcher>builder();
for (EntityPlayerMP player : (List<EntityPlayerMP>)FMLCommonHandler.instance().getMinecraftServerInstance().func_71203_ab().field_72404_b)
@ -86,7 +100,7 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
}
@SuppressWarnings("unchecked")
@Override
public List<NetworkDispatcher> selectNetworks(Object args)
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
int dimension = (Integer)args;
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.<NetworkDispatcher>builder();
@ -114,7 +128,7 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
@SuppressWarnings("unchecked")
@Override
public List<NetworkDispatcher> selectNetworks(Object args)
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
TargetPoint tp = (TargetPoint)args;
ImmutableList.Builder<NetworkDispatcher> builder = ImmutableList.<NetworkDispatcher>builder();
@ -144,7 +158,7 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
throw new RuntimeException("Cannot set TOSERVER as a target on the server");
}
@Override
public List<NetworkDispatcher> selectNetworks(Object args)
public List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet)
{
NetworkManager clientConnection = FMLCommonHandler.instance().getClientToServerNetworkManager();
return clientConnection == null ? ImmutableList.<NetworkDispatcher>of() : ImmutableList.of(clientConnection.channel().attr(NetworkDispatcher.FML_DISPATCHER).get());
@ -152,7 +166,7 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
};
public abstract void validateArgs(Object args);
public abstract List<NetworkDispatcher> selectNetworks(Object args);
public abstract List<NetworkDispatcher> selectNetworks(Object args, ChannelHandlerContext context, FMLProxyPacket packet);
}
@Override
@ -162,6 +176,7 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
{
return;
}
FMLProxyPacket pkt = (FMLProxyPacket) msg;
OutboundTarget outboundTarget;
Object args = null;
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
@ -182,7 +197,7 @@ public class FMLOutboundHandler extends ChannelOutboundHandlerAdapter {
outboundTarget.validateArgs(args);
}
List<NetworkDispatcher> dispatchers = outboundTarget.selectNetworks(args);
List<NetworkDispatcher> dispatchers = outboundTarget.selectNetworks(args, ctx, pkt);
// This will drop the messages into the output queue at the embedded channel
if (dispatchers == null)

View file

@ -0,0 +1,29 @@
package cpw.mods.fml.common.network;
import cpw.mods.fml.common.network.internal.FMLProxyPacket;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
* Use this handler as the only thing in your channel, to receive network events
* whenever your channel receives a message.
* Note: it will not forward on to other handlers.
*
* @author cpw
*
*/
public class NetworkEventFiringHandler extends SimpleChannelInboundHandler<FMLProxyPacket> {
private FMLEventChannel eventChannel;
NetworkEventFiringHandler(FMLEventChannel fmlEventChannel)
{
this.eventChannel = fmlEventChannel;
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception
{
eventChannel.fireRead(msg,ctx);
}
}

View file

@ -127,6 +127,10 @@ public enum NetworkRegistry
return result;
}
public FMLEventChannel newEventDrivenChannel(String name)
{
return new FMLEventChannel(name);
}
/**
* INTERNAL Create a new channel pair with the specified name and channel handlers.
* This is used internally in forge and FML

View file

@ -67,7 +67,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
public static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = new AttributeKey<NetworkDispatcher>("fml:dispatcher");
public static final AttributeKey<Boolean> IS_LOCAL = new AttributeKey<Boolean>("fml:isLocal");
private final NetworkManager manager;
public final NetworkManager manager;
private final ServerConfigurationManager scm;
private EntityPlayerMP player;
private ConnectionState state;
@ -259,6 +259,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
else if (NetworkRegistry.INSTANCE.hasChannel(channelName, Side.CLIENT))
{
FMLProxyPacket proxy = new FMLProxyPacket(msg);
proxy.setDispatcher(this);
context.fireChannelRead(proxy);
return true;
}
@ -293,6 +294,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> imple
else if (NetworkRegistry.INSTANCE.hasChannel(channelName, Side.SERVER))
{
FMLProxyPacket proxy = new FMLProxyPacket(msg);
proxy.setDispatcher(this);
context.fireChannelRead(proxy);
return true;
}

View file

@ -3,15 +3,15 @@ package cpw.mods.fml.common.network.internal;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
import java.io.IOException;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.network.handshake.NetworkDispatcher;
import cpw.mods.fml.relauncher.Side;
public class FMLProxyPacket extends Packet {
@ -19,6 +19,7 @@ public class FMLProxyPacket extends Packet {
private Side target;
private final ByteBuf payload;
private INetHandler netHandler;
private NetworkDispatcher dispatcher;
private FMLProxyPacket(byte[] payload, String channel)
{
@ -92,4 +93,19 @@ public class FMLProxyPacket extends Packet {
{
this.target = target;
}
public void setDispatcher(NetworkDispatcher networkDispatcher)
{
this.dispatcher = networkDispatcher;
}
public NetworkManager getOrigin()
{
return this.dispatcher != null ? this.dispatcher.manager : null;
}
public NetworkDispatcher getDispatcher()
{
return this.dispatcher;
}
}