The basic network handshaking for FML is done. All scenarios seem to work.
This commit is contained in:
parent
37a00f0158
commit
fadff73489
25 changed files with 625 additions and 612 deletions
|
@ -21,6 +21,7 @@ import java.util.Set;
|
|||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import cpw.mods.fml.common.network.NetworkModHolder;
|
||||
import cpw.mods.fml.common.versioning.ArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
|
@ -140,4 +141,6 @@ public interface ModContainer
|
|||
public Class<?> getCustomResourcePackClass();
|
||||
|
||||
Map<String, String> getSharedModDescriptor();
|
||||
|
||||
NetworkModHolder getNetworkModHolder();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ package cpw.mods.fml.common.network;
|
|||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.EnumConnectionState;
|
||||
import net.minecraft.network.NetHandlerPlayServer;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
|
@ -406,16 +407,20 @@ public class FMLNetworkHandler
|
|||
}
|
||||
}
|
||||
*/
|
||||
public static void fmlHandshake(ServerConfigurationManager scm, NetworkManager manager, EntityPlayerMP player)
|
||||
public static void fmlServerHandshake(ServerConfigurationManager scm, NetworkManager manager, EntityPlayerMP player)
|
||||
{
|
||||
NetHandlerPlayServer nethandler = new NetHandlerPlayServer(scm.func_72365_p(), manager, player);
|
||||
player.field_71135_a = null;
|
||||
scm.func_72355_a(manager, player, nethandler);
|
||||
NetworkDispatcher dispatcher = NetworkDispatcher.allocAndSet(manager, scm);
|
||||
dispatcher.serverToClientHandshake(player);
|
||||
}
|
||||
|
||||
public static void fmlClientHandshake(NetworkManager field_147393_d)
|
||||
{
|
||||
NetworkDispatcher dispatcher = NetworkDispatcher.allocAndSet(field_147393_d);
|
||||
dispatcher.clientToServerHandshake();
|
||||
}
|
||||
|
||||
public static void openGui(EntityPlayer entityPlayer, Object mod, int modGuiId, World world, int x, int y, int z)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
|
@ -430,4 +435,5 @@ public class FMLNetworkHandler
|
|||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package cpw.mods.fml.common.network;
|
||||
|
||||
import net.minecraft.network.INetHandler;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
|
||||
public class FMLPacketHandlerFactory implements IPacketHandlerFactory {
|
||||
private static final String[] CHANNEL = new String[] { "FML" };
|
||||
@Override
|
||||
public String[] channels()
|
||||
{
|
||||
return CHANNEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClientSidePacketHandler makeClientPacketHandler(NetworkMod mod, NetworkManager manager, INetHandler clientPlayHandler, String channel)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IServerSidePacketHandler makeServerPacketHandler(NetworkMod mod, NetworkManager manager, INetHandler serverPlayHandler)
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -20,18 +20,12 @@ public interface IGuiHandler
|
|||
/**
|
||||
* Returns a Server side Container to be displayed to the user.
|
||||
*
|
||||
* @param ID
|
||||
* The Gui ID Number
|
||||
* @param player
|
||||
* The player viewing the Gui
|
||||
* @param world
|
||||
* The current world
|
||||
* @param x
|
||||
* X Position
|
||||
* @param y
|
||||
* Y Position
|
||||
* @param z
|
||||
* Z Position
|
||||
* @param ID The Gui ID Number
|
||||
* @param player The player viewing the Gui
|
||||
* @param world The current world
|
||||
* @param x X Position
|
||||
* @param y Y Position
|
||||
* @param z Z Position
|
||||
* @return A GuiScreen/Container to be displayed to the user, null if none.
|
||||
*/
|
||||
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z);
|
||||
|
@ -40,18 +34,12 @@ public interface IGuiHandler
|
|||
* needs to return a instance of GuiScreen On the server side, this needs to
|
||||
* return a instance of Container
|
||||
*
|
||||
* @param ID
|
||||
* The Gui ID Number
|
||||
* @param player
|
||||
* The player viewing the Gui
|
||||
* @param world
|
||||
* The current world
|
||||
* @param x
|
||||
* X Position
|
||||
* @param y
|
||||
* Y Position
|
||||
* @param z
|
||||
* Z Position
|
||||
* @param ID The Gui ID Number
|
||||
* @param player The player viewing the Gui
|
||||
* @param world The current world
|
||||
* @param x X Position
|
||||
* @param y Y Position
|
||||
* @param z Z Position
|
||||
* @return A GuiScreen/Container to be displayed to the user, null if none.
|
||||
*/
|
||||
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z);
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.network;
|
||||
|
||||
import net.minecraft.network.packet.*;
|
||||
|
||||
public interface ITinyPacketHandler
|
||||
{
|
||||
void handle(NetHandler handler, Packet131MapData mapData);
|
||||
}
|
|
@ -1,16 +1,259 @@
|
|||
package cpw.mods.fml.common.network;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import sun.net.ProgressSource.State;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.util.AttributeKey;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
import io.netty.util.concurrent.ScheduledFuture;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.EnumConnectionState;
|
||||
import net.minecraft.network.NetHandlerPlayServer;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.play.client.C17PacketCustomPayload;
|
||||
import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
||||
import net.minecraft.server.management.ServerConfigurationManager;
|
||||
|
||||
import com.google.common.collect.ListMultimap;
|
||||
|
||||
public class NetworkDispatcher {
|
||||
private static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = new AttributeKey<NetworkDispatcher>("fml:dispatcher");
|
||||
private static final AttributeKey<ListMultimap<String,IPacketHandler>> FML_PACKET_HANDLERS = new AttributeKey<ListMultimap<String,IPacketHandler>>("fml:packet_handlers");
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.network.packet.PacketManager;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
|
||||
private static enum ConnectionState {
|
||||
OPENING, AWAITING_HANDSHAKE, HANDSHAKING, CONNECTED;
|
||||
}
|
||||
|
||||
private static enum ConnectionType {
|
||||
MODDED, BUKKIT, VANILLA;
|
||||
}
|
||||
|
||||
public static NetworkDispatcher get(NetworkManager manager)
|
||||
{
|
||||
return manager.channel().attr(FML_DISPATCHER).get();
|
||||
}
|
||||
|
||||
public static NetworkDispatcher allocAndSet(NetworkManager manager)
|
||||
{
|
||||
NetworkDispatcher net = new NetworkDispatcher(manager);
|
||||
manager.channel().attr(FML_DISPATCHER).getAndSet(net);
|
||||
return net;
|
||||
}
|
||||
|
||||
public static NetworkDispatcher allocAndSet(NetworkManager manager, ServerConfigurationManager scm)
|
||||
{
|
||||
NetworkDispatcher net = new NetworkDispatcher(manager, scm);
|
||||
manager.channel().attr(FML_DISPATCHER).getAndSet(net);
|
||||
return net;
|
||||
}
|
||||
|
||||
private static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = new AttributeKey<NetworkDispatcher>("fml:dispatcher");
|
||||
private static final AttributeKey<ListMultimap<String,NetworkModHolder>> FML_PACKET_HANDLERS = new AttributeKey<ListMultimap<String,NetworkModHolder>>("fml:packet_handlers");
|
||||
private final NetworkManager manager;
|
||||
private final ServerConfigurationManager scm;
|
||||
private EntityPlayerMP player;
|
||||
private ConnectionState state;
|
||||
private ConnectionType connectionType;
|
||||
private Side side;
|
||||
|
||||
public NetworkDispatcher(NetworkManager manager)
|
||||
{
|
||||
super(Packet.class, false);
|
||||
this.manager = manager;
|
||||
this.scm = null;
|
||||
this.side = Side.CLIENT;
|
||||
}
|
||||
|
||||
public NetworkDispatcher(NetworkManager manager, ServerConfigurationManager scm)
|
||||
{
|
||||
super(Packet.class, false);
|
||||
this.manager = manager;
|
||||
this.scm = scm;
|
||||
this.side = Side.SERVER;
|
||||
}
|
||||
|
||||
public void serverToClientHandshake(EntityPlayerMP player)
|
||||
{
|
||||
this.player = player;
|
||||
insertIntoChannel();
|
||||
}
|
||||
|
||||
private void insertIntoChannel()
|
||||
{
|
||||
this.manager.channel().config().setAutoRead(false);
|
||||
// Insert ourselves into the pipeline
|
||||
this.manager.channel().pipeline().addBefore("packet_handler", "fml:packet_handler", this);
|
||||
}
|
||||
|
||||
public void clientToServerHandshake()
|
||||
{
|
||||
insertIntoChannel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
this.state = ConnectionState.OPENING;
|
||||
if (side == Side.CLIENT)
|
||||
{
|
||||
clientListenForServerHandshake();
|
||||
}
|
||||
else
|
||||
{
|
||||
serverInitiateHandshake();
|
||||
}
|
||||
this.manager.channel().config().setAutoRead(true);
|
||||
}
|
||||
|
||||
private void serverInitiateHandshake()
|
||||
{
|
||||
// Send mod salutation to the client
|
||||
// This will be ignored by vanilla clients
|
||||
this.state = ConnectionState.AWAITING_HANDSHAKE;
|
||||
this.manager.channel().pipeline().addFirst("fml:vanilla_detector", new VanillaTimeoutWaiter());
|
||||
this.manager.func_150725_a(new S3FPacketCustomPayload("FML", new byte[0]));
|
||||
}
|
||||
|
||||
private void clientListenForServerHandshake()
|
||||
{
|
||||
manager.func_150723_a(EnumConnectionState.PLAY);
|
||||
this.state = ConnectionState.AWAITING_HANDSHAKE;
|
||||
}
|
||||
|
||||
private void continueToClientPlayState()
|
||||
{
|
||||
this.state = ConnectionState.CONNECTED;
|
||||
this.connectionType = ConnectionType.MODDED;
|
||||
completeClientSideConnection();
|
||||
// Send modded ack to server
|
||||
this.manager.func_150725_a(new C17PacketCustomPayload("FML", new byte[0]));
|
||||
}
|
||||
|
||||
private void completeClientSideConnection()
|
||||
{
|
||||
}
|
||||
|
||||
private void continueToServerPlayState()
|
||||
{
|
||||
this.state = ConnectionState.CONNECTED;
|
||||
this.connectionType = ConnectionType.MODDED;
|
||||
completeServerSideConnection();
|
||||
}
|
||||
|
||||
private void completeServerSideConnection()
|
||||
{
|
||||
NetHandlerPlayServer nethandler = new NetHandlerPlayServer(scm.func_72365_p(), manager, player);
|
||||
// NULL the play server here - we restore it further on. If not, there are packets sent before the login
|
||||
player.field_71135_a = null;
|
||||
scm.func_72355_a(manager, player, nethandler);
|
||||
}
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, Packet msg) throws Exception
|
||||
{
|
||||
boolean handled = false;
|
||||
if (msg instanceof C17PacketCustomPayload)
|
||||
{
|
||||
handled = handleServerSideCustomPacket((C17PacketCustomPayload) msg);
|
||||
}
|
||||
else if (msg instanceof S3FPacketCustomPayload)
|
||||
{
|
||||
handled = handleClientSideCustomPacket((S3FPacketCustomPayload)msg);
|
||||
}
|
||||
else if (state != ConnectionState.CONNECTED)
|
||||
{
|
||||
FMLLog.info("Unexpected packet during modded negotiation - assuming vanilla");
|
||||
handleVanillaConnection();
|
||||
}
|
||||
if (!handled)
|
||||
{
|
||||
ctx.fireChannelRead(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception
|
||||
{
|
||||
if (evt instanceof ConnectionType && side == Side.SERVER)
|
||||
{
|
||||
FMLLog.info("Timeout occurred, assuming a vanilla client");
|
||||
handleVanillaConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVanillaConnection()
|
||||
{
|
||||
state = ConnectionState.CONNECTED;
|
||||
connectionType = ConnectionType.VANILLA;
|
||||
if (side == Side.CLIENT)
|
||||
{
|
||||
completeClientSideConnection();
|
||||
}
|
||||
else
|
||||
{
|
||||
completeServerSideConnection();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleClientSideCustomPacket(S3FPacketCustomPayload msg)
|
||||
{
|
||||
if ("FML".equals(msg.func_149169_c()))
|
||||
{
|
||||
continueToClientPlayState();
|
||||
FMLLog.info("Client side modded connection established");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean handleServerSideCustomPacket(C17PacketCustomPayload msg)
|
||||
{
|
||||
if (state == ConnectionState.AWAITING_HANDSHAKE)
|
||||
{
|
||||
this.manager.channel().pipeline().remove("fml:vanilla_detector");
|
||||
state = ConnectionState.HANDSHAKING;
|
||||
}
|
||||
if ("FML".equals(msg.func_149559_c()))
|
||||
{
|
||||
FMLLog.info("Server side modded connection established");
|
||||
continueToServerPlayState();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private class VanillaTimeoutWaiter extends ChannelInboundHandlerAdapter
|
||||
{
|
||||
private ScheduledFuture<Void> future;
|
||||
|
||||
@Override
|
||||
public void handlerAdded(final ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
future = ctx.executor().schedule(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception
|
||||
{
|
||||
if (state != ConnectionState.CONNECTED)
|
||||
{
|
||||
FMLLog.info("Timeout occurred waiting for response, assuming vanilla connection");
|
||||
ctx.fireUserEventTriggered(ConnectionType.VANILLA);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, 10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
future.cancel(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,370 +0,0 @@
|
|||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.network;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
|
||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.InvalidVersionSpecificationException;
|
||||
import cpw.mods.fml.common.versioning.VersionRange;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
public class NetworkModHandler
|
||||
{
|
||||
private static Object connectionHandlerDefaultValue;
|
||||
private static Object packetHandlerDefaultValue;
|
||||
private static Object clientHandlerDefaultValue;
|
||||
private static Object serverHandlerDefaultValue;
|
||||
private static Object tinyPacketHandlerDefaultValue;
|
||||
|
||||
private static int assignedIds = 1;
|
||||
|
||||
private int localId;
|
||||
private int networkId;
|
||||
|
||||
private ModContainer container;
|
||||
private NetworkMod mod;
|
||||
private Method checkHandler;
|
||||
|
||||
private VersionRange acceptableRange;
|
||||
private ITinyPacketHandler tinyPacketHandler;
|
||||
|
||||
public NetworkModHandler(ModContainer container, NetworkMod modAnnotation)
|
||||
{
|
||||
this.container = container;
|
||||
this.mod = modAnnotation;
|
||||
this.localId = assignedIds++;
|
||||
this.networkId = this.localId;
|
||||
// Skip over the map object because it has special network id meaning
|
||||
if (Item.field_77744_bd.field_77779_bT == assignedIds)
|
||||
{
|
||||
assignedIds++;
|
||||
}
|
||||
}
|
||||
public NetworkModHandler(ModContainer container, Class<?> networkModClass, ASMDataTable table)
|
||||
{
|
||||
this(container, networkModClass.getAnnotation(NetworkMod.class));
|
||||
if (this.mod == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Set<ASMData> versionCheckHandlers = table.getAnnotationsFor(container).get(NetworkMod.VersionCheckHandler.class.getName());
|
||||
String versionCheckHandlerMethod = null;
|
||||
for (ASMData vch : versionCheckHandlers)
|
||||
{
|
||||
if (vch.getClassName().equals(networkModClass.getName()))
|
||||
{
|
||||
versionCheckHandlerMethod = vch.getObjectName();
|
||||
versionCheckHandlerMethod = versionCheckHandlerMethod.substring(0,versionCheckHandlerMethod.indexOf('('));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (versionCheckHandlerMethod != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Method checkHandlerMethod = networkModClass.getDeclaredMethod(versionCheckHandlerMethod, String.class);
|
||||
if (checkHandlerMethod.isAnnotationPresent(NetworkMod.VersionCheckHandler.class))
|
||||
{
|
||||
this.checkHandler = checkHandlerMethod;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, e, "The declared version check handler method %s on network mod id %s is not accessible", versionCheckHandlerMethod, container.getModId());
|
||||
}
|
||||
}
|
||||
|
||||
configureNetworkMod(container);
|
||||
}
|
||||
protected void configureNetworkMod(ModContainer container)
|
||||
{
|
||||
if (this.checkHandler == null)
|
||||
{
|
||||
String versionBounds = mod.versionBounds();
|
||||
if (!Strings.isNullOrEmpty(versionBounds))
|
||||
{
|
||||
try
|
||||
{
|
||||
this.acceptableRange = VersionRange.createFromVersionSpec(versionBounds);
|
||||
}
|
||||
catch (InvalidVersionSpecificationException e)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, e, "Invalid bounded range %s specified for network mod id %s", versionBounds, container.getModId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FMLLog.finest("Testing mod %s to verify it accepts its own version in a remote connection", container.getModId());
|
||||
boolean acceptsSelf = acceptVersion(container.getVersion());
|
||||
if (!acceptsSelf)
|
||||
{
|
||||
FMLLog.severe("The mod %s appears to reject its own version number (%s) in its version handling. This is likely a severe bug in the mod!", container.getModId(), container.getVersion());
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.finest("The mod %s accepts its own version (%s)", container.getModId(), container.getVersion());
|
||||
}
|
||||
|
||||
tryCreatingPacketHandler(container, mod.packetHandler(), mod.channels(), null);
|
||||
if (FMLCommonHandler.instance().getSide().isClient())
|
||||
{
|
||||
if (mod.clientPacketHandlerSpec() != getClientHandlerSpecDefaultValue())
|
||||
{
|
||||
tryCreatingPacketHandler(container, mod.clientPacketHandlerSpec().packetHandler(), mod.clientPacketHandlerSpec().channels(), Side.CLIENT);
|
||||
}
|
||||
}
|
||||
if (mod.serverPacketHandlerSpec() != getServerHandlerSpecDefaultValue())
|
||||
{
|
||||
tryCreatingPacketHandler(container, mod.serverPacketHandlerSpec().packetHandler(), mod.serverPacketHandlerSpec().channels(), Side.SERVER);
|
||||
}
|
||||
|
||||
if (mod.connectionHandler() != getConnectionHandlerDefaultValue())
|
||||
{
|
||||
IConnectionHandler instance;
|
||||
try
|
||||
{
|
||||
instance = mod.connectionHandler().newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "Unable to create connection handler instance %s", mod.connectionHandler().getName());
|
||||
throw new FMLNetworkException(e);
|
||||
}
|
||||
|
||||
NetworkRegistry.instance().registerConnectionHandler(instance);
|
||||
}
|
||||
|
||||
if (mod.tinyPacketHandler()!=getTinyPacketHandlerDefaultValue())
|
||||
{
|
||||
try
|
||||
{
|
||||
tinyPacketHandler = mod.tinyPacketHandler().newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "Unable to create tiny packet handler instance %s", mod.tinyPacketHandler().getName());
|
||||
throw new FMLNetworkException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param container
|
||||
*/
|
||||
private void tryCreatingPacketHandler(ModContainer container, Class<? extends IPacketHandler> clazz, String[] channels, Side side)
|
||||
{
|
||||
if (side!=null && side.isClient() && ! FMLCommonHandler.instance().getSide().isClient())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (clazz!=getPacketHandlerDefaultValue())
|
||||
{
|
||||
if (channels.length==0)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, "The mod id %s attempted to register a packet handler without specifying channels for it", container.getModId());
|
||||
}
|
||||
else
|
||||
{
|
||||
IPacketHandler instance;
|
||||
try
|
||||
{
|
||||
instance = clazz.newInstance();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.SEVERE, e, "Unable to create a packet handler instance %s for mod %s", clazz.getName(), container.getModId());
|
||||
throw new FMLNetworkException(e);
|
||||
}
|
||||
|
||||
for (String channel : channels)
|
||||
{
|
||||
NetworkRegistry.instance().registerChannel(instance, channel, side);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (channels.length > 0)
|
||||
{
|
||||
FMLLog.warning("The mod id %s attempted to register channels without specifying a packet handler", container.getModId());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return the default {@link NetworkMod#connectionHandler()} annotation value
|
||||
*/
|
||||
private Object getConnectionHandlerDefaultValue()
|
||||
{
|
||||
try {
|
||||
if (connectionHandlerDefaultValue == null)
|
||||
{
|
||||
connectionHandlerDefaultValue = NetworkMod.class.getMethod("connectionHandler").getDefaultValue();
|
||||
}
|
||||
return connectionHandlerDefaultValue;
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
throw new RuntimeException("Derp?", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default {@link NetworkMod#packetHandler()} annotation value
|
||||
*/
|
||||
private Object getPacketHandlerDefaultValue()
|
||||
{
|
||||
try {
|
||||
if (packetHandlerDefaultValue == null)
|
||||
{
|
||||
packetHandlerDefaultValue = NetworkMod.class.getMethod("packetHandler").getDefaultValue();
|
||||
}
|
||||
return packetHandlerDefaultValue;
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
throw new RuntimeException("Derp?", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default {@link NetworkMod#tinyPacketHandler()} annotation value
|
||||
*/
|
||||
private Object getTinyPacketHandlerDefaultValue()
|
||||
{
|
||||
try {
|
||||
if (tinyPacketHandlerDefaultValue == null)
|
||||
{
|
||||
tinyPacketHandlerDefaultValue = NetworkMod.class.getMethod("tinyPacketHandler").getDefaultValue();
|
||||
}
|
||||
return tinyPacketHandlerDefaultValue;
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
throw new RuntimeException("Derp?", e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return the {@link NetworkMod#clientPacketHandlerSpec()} default annotation value
|
||||
*/
|
||||
private Object getClientHandlerSpecDefaultValue()
|
||||
{
|
||||
try {
|
||||
if (clientHandlerDefaultValue == null)
|
||||
{
|
||||
clientHandlerDefaultValue = NetworkMod.class.getMethod("clientPacketHandlerSpec").getDefaultValue();
|
||||
}
|
||||
return clientHandlerDefaultValue;
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
throw new RuntimeException("Derp?", e);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return the default {@link NetworkMod#serverPacketHandlerSpec()} annotation value
|
||||
*/
|
||||
private Object getServerHandlerSpecDefaultValue()
|
||||
{
|
||||
try {
|
||||
if (serverHandlerDefaultValue == null)
|
||||
{
|
||||
serverHandlerDefaultValue = NetworkMod.class.getMethod("serverPacketHandlerSpec").getDefaultValue();
|
||||
}
|
||||
return serverHandlerDefaultValue;
|
||||
}
|
||||
catch (NoSuchMethodException e)
|
||||
{
|
||||
throw new RuntimeException("Derp?", e);
|
||||
}
|
||||
}
|
||||
public boolean requiresClientSide()
|
||||
{
|
||||
return mod.clientSideRequired();
|
||||
}
|
||||
|
||||
public boolean requiresServerSide()
|
||||
{
|
||||
return mod.serverSideRequired();
|
||||
}
|
||||
|
||||
public boolean acceptVersion(String version)
|
||||
{
|
||||
if (checkHandler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Boolean)checkHandler.invoke(container.getMod(), version);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, e, "There was a problem invoking the checkhandler method %s for network mod id %s", checkHandler.getName(), container.getModId());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptableRange!=null)
|
||||
{
|
||||
return acceptableRange.containsVersion(new DefaultArtifactVersion(version));
|
||||
}
|
||||
|
||||
return container.getVersion().equals(version);
|
||||
}
|
||||
|
||||
public int getLocalId()
|
||||
{
|
||||
return localId;
|
||||
}
|
||||
|
||||
public int getNetworkId()
|
||||
{
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public ModContainer getContainer()
|
||||
{
|
||||
return container;
|
||||
}
|
||||
|
||||
public NetworkMod getMod()
|
||||
{
|
||||
return mod;
|
||||
}
|
||||
|
||||
public boolean isNetworkMod()
|
||||
{
|
||||
return mod != null;
|
||||
}
|
||||
|
||||
public void setNetworkId(int value)
|
||||
{
|
||||
this.networkId = value;
|
||||
}
|
||||
|
||||
public boolean hasTinyPacketHandler()
|
||||
{
|
||||
return tinyPacketHandler != null;
|
||||
}
|
||||
public ITinyPacketHandler getTinyPacketHandler()
|
||||
{
|
||||
return tinyPacketHandler;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Forge Mod Loader
|
||||
* Copyright (c) 2012-2013 cpw.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the GNU Lesser Public License v2.1
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* Contributors:
|
||||
* cpw - implementation
|
||||
*/
|
||||
|
||||
package cpw.mods.fml.common.network;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable;
|
||||
import cpw.mods.fml.common.discovery.ASMDataTable.ASMData;
|
||||
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
|
||||
import cpw.mods.fml.common.versioning.InvalidVersionSpecificationException;
|
||||
import cpw.mods.fml.common.versioning.VersionRange;
|
||||
|
||||
public class NetworkModHolder
|
||||
{
|
||||
private static int assignedIds = 1;
|
||||
|
||||
private int localId;
|
||||
private int networkId;
|
||||
|
||||
private ModContainer container;
|
||||
private NetworkMod mod;
|
||||
private Method checkHandler;
|
||||
|
||||
private VersionRange acceptableRange;
|
||||
|
||||
private IPacketHandlerFactory packetHandlerFactory;
|
||||
|
||||
public NetworkModHolder(ModContainer container, NetworkMod modAnnotation)
|
||||
{
|
||||
this.container = container;
|
||||
this.mod = modAnnotation;
|
||||
this.localId = assignedIds++;
|
||||
this.networkId = this.localId;
|
||||
}
|
||||
public NetworkModHolder(ModContainer container, Class<?> networkModClass, ASMDataTable table)
|
||||
{
|
||||
this(container, networkModClass.getAnnotation(NetworkMod.class));
|
||||
if (this.mod == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Set<ASMData> versionCheckHandlers = table.getAnnotationsFor(container).get(NetworkMod.VersionCheckHandler.class.getName());
|
||||
String versionCheckHandlerMethod = null;
|
||||
for (ASMData vch : versionCheckHandlers)
|
||||
{
|
||||
if (vch.getClassName().equals(networkModClass.getName()))
|
||||
{
|
||||
versionCheckHandlerMethod = vch.getObjectName();
|
||||
versionCheckHandlerMethod = versionCheckHandlerMethod.substring(0,versionCheckHandlerMethod.indexOf('('));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (versionCheckHandlerMethod != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Method checkHandlerMethod = networkModClass.getDeclaredMethod(versionCheckHandlerMethod, String.class);
|
||||
if (checkHandlerMethod.isAnnotationPresent(NetworkMod.VersionCheckHandler.class))
|
||||
{
|
||||
this.checkHandler = checkHandlerMethod;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, e, "The declared version check handler method %s on network mod id %s is not accessible", versionCheckHandlerMethod, container.getModId());
|
||||
}
|
||||
}
|
||||
|
||||
configureNetworkMod(container);
|
||||
}
|
||||
protected void configureNetworkMod(ModContainer container)
|
||||
{
|
||||
if (this.checkHandler == null)
|
||||
{
|
||||
String versionBounds = mod.versionBounds();
|
||||
if (!Strings.isNullOrEmpty(versionBounds))
|
||||
{
|
||||
try
|
||||
{
|
||||
this.acceptableRange = VersionRange.createFromVersionSpec(versionBounds);
|
||||
}
|
||||
catch (InvalidVersionSpecificationException e)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, e, "Invalid bounded range %s specified for network mod id %s", versionBounds, container.getModId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FMLLog.finest("Testing mod %s to verify it accepts its own version in a remote connection", container.getModId());
|
||||
boolean acceptsSelf = acceptVersion(container.getVersion());
|
||||
if (!acceptsSelf)
|
||||
{
|
||||
FMLLog.severe("The mod %s appears to reject its own version number (%s) in its version handling. This is likely a severe bug in the mod!", container.getModId(), container.getVersion());
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.finest("The mod %s accepts its own version (%s)", container.getModId(), container.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean acceptVersion(String version)
|
||||
{
|
||||
if (checkHandler != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (Boolean)checkHandler.invoke(container.getMod(), version);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FMLLog.log(Level.WARNING, e, "There was a problem invoking the checkhandler method %s for network mod id %s", checkHandler.getName(), container.getModId());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptableRange!=null)
|
||||
{
|
||||
return acceptableRange.containsVersion(new DefaultArtifactVersion(version));
|
||||
}
|
||||
|
||||
return container.getVersion().equals(version);
|
||||
}
|
||||
|
||||
public int getLocalId()
|
||||
{
|
||||
return localId;
|
||||
}
|
||||
|
||||
public int getNetworkId()
|
||||
{
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public ModContainer getContainer()
|
||||
{
|
||||
return container;
|
||||
}
|
||||
|
||||
public NetworkMod getMod()
|
||||
{
|
||||
return mod;
|
||||
}
|
||||
|
||||
public boolean isNetworkMod()
|
||||
{
|
||||
return mod != null;
|
||||
}
|
||||
|
||||
public void setNetworkId(int value)
|
||||
{
|
||||
this.networkId = value;
|
||||
}
|
||||
|
||||
}
|
|
@ -40,41 +40,22 @@ import com.google.common.collect.Sets;
|
|||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.LoaderException;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.network.packet.FMLPacket;
|
||||
import cpw.mods.fml.common.network.packet.FMLPacket.Type;
|
||||
import cpw.mods.fml.common.network.packet.PacketManager;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
/**
|
||||
* @author cpw
|
||||
*
|
||||
*/
|
||||
public class NetworkRegistry
|
||||
public enum NetworkRegistry
|
||||
{
|
||||
|
||||
private static final NetworkRegistry INSTANCE = new NetworkRegistry();
|
||||
/**
|
||||
* A map of active channels per player
|
||||
*/
|
||||
private Multimap<Player, String> activeChannels = ArrayListMultimap.create();
|
||||
/**
|
||||
* A map of the packet handlers for packets
|
||||
*/
|
||||
private Multimap<String, IPacketHandler> universalPacketHandlers = ArrayListMultimap.create();
|
||||
private Multimap<String, IPacketHandler> clientPacketHandlers = ArrayListMultimap.create();
|
||||
private Multimap<String, IPacketHandler> serverPacketHandlers = ArrayListMultimap.create();
|
||||
/**
|
||||
* A linked set of registered connection handlers
|
||||
*/
|
||||
private Set<IConnectionHandler> connectionHandlers = Sets.newLinkedHashSet();
|
||||
INSTANCE;
|
||||
private Map<ModContainer, IGuiHandler> serverGuiHandlers = Maps.newHashMap();
|
||||
private Map<ModContainer, IGuiHandler> clientGuiHandlers = Maps.newHashMap();
|
||||
private List<IChatListener> chatListeners = Lists.newArrayList();
|
||||
|
||||
public static NetworkRegistry instance()
|
||||
{
|
||||
return INSTANCE;
|
||||
}
|
||||
/**
|
||||
* Get the packet 250 channel registration string
|
||||
* @return the {@link Packet250CustomPayload} channel registration string
|
||||
|
@ -286,10 +267,10 @@ public class NetworkRegistry
|
|||
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
|
||||
if (mc == null)
|
||||
{
|
||||
mc = Loader.instance().activeModContainer();
|
||||
FMLLog.log(Level.WARNING, "Mod %s attempted to register a gui network handler during a construction phase", mc.getModId());
|
||||
FMLLog.log(Level.SEVERE, "Mod %s attempted to register a gui network handler during a construction phase", mc.getModId());
|
||||
throw new RuntimeException("Invalid attempt to create a GUI during mod construction. Use an EventHandler instead");
|
||||
}
|
||||
NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mc);
|
||||
NetworkModHolder nmh = mc.getNetworkModHolder();
|
||||
if (nmh == null)
|
||||
{
|
||||
FMLLog.log(Level.FINE, "The mod %s needs to be a @NetworkMod to register a Networked Gui Handler", mc.getModId());
|
||||
|
@ -303,7 +284,7 @@ public class NetworkRegistry
|
|||
void openRemoteGui(ModContainer mc, EntityPlayerMP player, int modGuiId, World world, int x, int y, int z)
|
||||
{
|
||||
IGuiHandler handler = serverGuiHandlers.get(mc);
|
||||
NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mc);
|
||||
NetworkModHolder nmh = mc.getNetworkModHolder();
|
||||
if (handler != null && nmh != null)
|
||||
{
|
||||
Container container = (Container)handler.getServerGuiElement(modGuiId, player, world, x, y, z);
|
||||
|
@ -312,10 +293,7 @@ public class NetworkRegistry
|
|||
player.func_71117_bO();
|
||||
player.func_71128_l();
|
||||
int windowId = player.field_71139_cq;
|
||||
Packet250CustomPayload pkt = new Packet250CustomPayload();
|
||||
pkt.field_73630_a = "FML";
|
||||
pkt.field_73629_c = FMLPacket.makePacket(Type.GUIOPEN, windowId, nmh.getNetworkId(), modGuiId, x, y, z);
|
||||
pkt.field_73628_b = pkt.field_73629_c.length;
|
||||
Packet pkt = PacketManager.INSTANCE.makeGuiPacket(windowId, nmh.getNetworkId(), modGuiId, x, y, z);
|
||||
player.field_71135_a.func_72567_b(pkt);
|
||||
player.field_71070_bA = container;
|
||||
player.field_71070_bA.field_75152_c = windowId;
|
||||
|
@ -328,35 +306,4 @@ public class NetworkRegistry
|
|||
IGuiHandler handler = clientGuiHandlers.get(mc);
|
||||
FMLCommonHandler.instance().showGuiScreen(handler.getClientGuiElement(modGuiId, player, world, x, y, z));
|
||||
}
|
||||
public Packet3Chat handleChat(NetHandler handler, Packet3Chat chat)
|
||||
{
|
||||
Side s = Side.CLIENT;
|
||||
if (handler instanceof NetServerHandler)
|
||||
{
|
||||
s = Side.SERVER;
|
||||
}
|
||||
for (IChatListener listener : chatListeners)
|
||||
{
|
||||
chat = s.isClient() ? listener.clientChat(handler, chat) : listener.serverChat(handler, chat);
|
||||
}
|
||||
|
||||
return chat;
|
||||
}
|
||||
public void handleTinyPacket(NetHandler handler, Packet131MapData mapData)
|
||||
{
|
||||
NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler((int)mapData.field_73438_a);
|
||||
if (nmh == null)
|
||||
{
|
||||
FMLLog.info("Received a tiny packet for network id %d that is not recognised here", mapData.field_73438_a);
|
||||
return;
|
||||
}
|
||||
if (nmh.hasTinyPacketHandler())
|
||||
{
|
||||
nmh.getTinyPacketHandler().handle(handler, mapData);
|
||||
}
|
||||
else
|
||||
{
|
||||
FMLLog.info("Received a tiny packet for a network mod that does not accept tiny packets %s", nmh.getContainer().getModId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ public class PacketDispatcher
|
|||
|
||||
public static Packet131MapData getTinyPacket(Object mod, short tag, byte[] data)
|
||||
{
|
||||
NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mod);
|
||||
NetworkModHolder nmh = FMLNetworkHandler.instance().findNetworkModHandler(mod);
|
||||
return new Packet131MapData((short) nmh.getNetworkId(), tag, data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class EntitySpawnAdjustmentPacket extends FMLPacket
|
|||
public int serverZ;
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
public byte[] generatePacketData(Object... data)
|
||||
{
|
||||
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
|
||||
dat.writeInt((Integer) data[0]);
|
||||
|
@ -47,7 +47,7 @@ public class EntitySpawnAdjustmentPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
public FMLPacket consumePacketData(byte[] data)
|
||||
{
|
||||
ByteArrayDataInput dat = ByteStreams.newDataInput(data);
|
||||
entityId = dat.readInt();
|
||||
|
|
|
@ -33,7 +33,7 @@ import cpw.mods.fml.common.FMLCommonHandler;
|
|||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||
import cpw.mods.fml.common.network.NetworkModHandler;
|
||||
import cpw.mods.fml.common.network.NetworkModHolder;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
|
@ -68,11 +68,11 @@ public class EntitySpawnPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
public byte[] generatePacketData(Object... data)
|
||||
{
|
||||
EntityRegistration er = (EntityRegistration) data[0];
|
||||
Entity ent = (Entity) data[1];
|
||||
NetworkModHandler handler = (NetworkModHandler) data[2];
|
||||
NetworkModHolder handler = (NetworkModHolder) data[2];
|
||||
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
|
||||
|
||||
dat.writeInt(handler.getNetworkId());
|
||||
|
@ -142,7 +142,7 @@ public class EntitySpawnPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
public FMLPacket consumePacketData(byte[] data)
|
||||
{
|
||||
ByteArrayDataInput dat = ByteStreams.newDataInput(data);
|
||||
networkId = dat.readInt();
|
||||
|
@ -183,7 +183,7 @@ public class EntitySpawnPacket extends FMLPacket
|
|||
@Override
|
||||
public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName)
|
||||
{
|
||||
NetworkModHandler nmh = handler.findNetworkModHandler(networkId);
|
||||
NetworkModHolder nmh = handler.findNetworkModHandler(networkId);
|
||||
ModContainer mc = nmh.getContainer();
|
||||
|
||||
EntityRegistration registration = EntityRegistry.instance().lookupModSpawn(mc, modEntityId);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package cpw.mods.fml.common.network.packet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
@ -52,7 +53,7 @@ public abstract class FMLPacket
|
|||
/**
|
||||
* Open a GUI on the client from the server
|
||||
*/
|
||||
GUIOPEN(OpenGuiPacket.class, false),
|
||||
GUIOPEN(OpenGuiPacket.class, false, "OpenGuiHandler"),
|
||||
/**
|
||||
* Spawn an entity on the client from the server
|
||||
*/
|
||||
|
@ -69,12 +70,15 @@ public abstract class FMLPacket
|
|||
|
||||
private Class<? extends FMLPacket> packetType;
|
||||
private boolean isMultipart;
|
||||
private String executorClass;
|
||||
|
||||
private ConcurrentMap<INetworkManager, FMLPacket> partTracker;
|
||||
|
||||
private Type(Class<? extends FMLPacket> clazz, boolean isMultipart)
|
||||
private Type(Class<? extends FMLPacket> clazz, boolean isMultipart, String executorClass)
|
||||
{
|
||||
this.packetType = clazz;
|
||||
this.isMultipart = isMultipart;
|
||||
this.executorClass = executorClass;
|
||||
}
|
||||
|
||||
FMLPacket make()
|
||||
|
@ -91,12 +95,12 @@ public abstract class FMLPacket
|
|||
}
|
||||
}
|
||||
|
||||
public boolean isMultipart()
|
||||
boolean isMultipart()
|
||||
{
|
||||
return isMultipart;
|
||||
}
|
||||
|
||||
private FMLPacket findCurrentPart(INetworkManager network)
|
||||
private FMLPacket findCurrentPart(NetworkManager network)
|
||||
{
|
||||
if (partTracker == null)
|
||||
{
|
||||
|
@ -110,16 +114,13 @@ public abstract class FMLPacket
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Type type;
|
||||
|
||||
public static byte[][] makePacketSet(Type type, Object... data)
|
||||
{
|
||||
if (!type.isMultipart())
|
||||
{
|
||||
return new byte[0][];
|
||||
}
|
||||
byte[] packetData = type.make().generatePacket(data);
|
||||
byte[] packetData = type.make().generatePacketData(data);
|
||||
|
||||
byte[][] chunks = new byte[packetData.length / 32000 + 1][];
|
||||
for (int i = 0; i < packetData.length / 32000 + 1; i++)
|
||||
|
@ -129,36 +130,13 @@ public abstract class FMLPacket
|
|||
}
|
||||
return chunks;
|
||||
}
|
||||
public static byte[] makePacket(Type type, Object... data)
|
||||
static byte[] makePacket(Type type, Object... data)
|
||||
{
|
||||
byte[] packetData = type.make().generatePacket(data);
|
||||
byte[] packetData = type.make().generatePacketData(data);
|
||||
return Bytes.concat(new byte[] { UnsignedBytes.checkedCast(type.ordinal()) }, packetData );
|
||||
}
|
||||
|
||||
public static FMLPacket readPacket(INetworkManager network, byte[] payload)
|
||||
{
|
||||
int type = UnsignedBytes.toInt(payload[0]);
|
||||
Type eType = Type.values()[type];
|
||||
FMLPacket pkt;
|
||||
if (eType.isMultipart())
|
||||
{
|
||||
pkt = eType.findCurrentPart(network);
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = eType.make();
|
||||
}
|
||||
return pkt.consumePacket(Arrays.copyOfRange(payload, 1, payload.length));
|
||||
}
|
||||
abstract byte[] generatePacketData(Object... data);
|
||||
|
||||
public FMLPacket(Type type)
|
||||
{
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public abstract byte[] generatePacket(Object... data);
|
||||
|
||||
public abstract FMLPacket consumePacket(byte[] data);
|
||||
|
||||
public abstract void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName);
|
||||
abstract FMLPacket consumePacketData(byte[] data);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ModIdMapPacket extends FMLPacket {
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
public byte[] generatePacketData(Object... data)
|
||||
{
|
||||
NBTTagList completeList = (NBTTagList) data[0];
|
||||
NBTTagCompound wrap = new NBTTagCompound();
|
||||
|
@ -63,7 +63,7 @@ public class ModIdMapPacket extends FMLPacket {
|
|||
}
|
||||
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
public FMLPacket consumePacketData(byte[] data)
|
||||
{
|
||||
ByteArrayDataInput bdi = ByteStreams.newDataInput(data);
|
||||
int chunkIdx = UnsignedBytes.toInt(bdi.readByte());
|
||||
|
|
|
@ -27,7 +27,7 @@ import com.google.common.io.ByteArrayDataOutput;
|
|||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||
import cpw.mods.fml.common.network.NetworkModHandler;
|
||||
import cpw.mods.fml.common.network.NetworkModHolder;
|
||||
|
||||
public class ModIdentifiersPacket extends FMLPacket
|
||||
{
|
||||
|
@ -40,13 +40,13 @@ public class ModIdentifiersPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
public byte[] generatePacketData(Object... data)
|
||||
{
|
||||
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
|
||||
Collection<NetworkModHandler >networkMods = FMLNetworkHandler.instance().getNetworkIdMap().values();
|
||||
Collection<NetworkModHolder >networkMods = FMLNetworkHandler.instance().getNetworkIdMap().values();
|
||||
|
||||
dat.writeInt(networkMods.size());
|
||||
for (NetworkModHandler handler : networkMods)
|
||||
for (NetworkModHolder handler : networkMods)
|
||||
{
|
||||
dat.writeUTF(handler.getContainer().getModId());
|
||||
dat.writeInt(handler.getNetworkId());
|
||||
|
@ -57,7 +57,7 @@ public class ModIdentifiersPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
public FMLPacket consumePacketData(byte[] data)
|
||||
{
|
||||
ByteArrayDataInput dat = ByteStreams.newDataInput(data);
|
||||
int listSize = dat.readInt();
|
||||
|
|
|
@ -34,7 +34,7 @@ import cpw.mods.fml.common.FMLLog;
|
|||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||
import cpw.mods.fml.common.network.NetworkModHandler;
|
||||
import cpw.mods.fml.common.network.NetworkModHolder;
|
||||
import cpw.mods.fml.common.network.PacketDispatcher;
|
||||
|
||||
public class ModListRequestPacket extends FMLPacket
|
||||
|
@ -48,7 +48,7 @@ public class ModListRequestPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
public byte[] generatePacketData(Object... data)
|
||||
{
|
||||
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
|
||||
Set<ModContainer> activeMods = FMLNetworkHandler.instance().getNetworkModList();
|
||||
|
@ -62,7 +62,7 @@ public class ModListRequestPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
public FMLPacket consumePacketData(byte[] data)
|
||||
{
|
||||
sentModList = Lists.newArrayList();
|
||||
ByteArrayDataInput in = ByteStreams.newDataInput(data);
|
||||
|
@ -114,7 +114,7 @@ public class ModListRequestPacket extends FMLPacket
|
|||
{
|
||||
if (e.getValue().isNetworkMod())
|
||||
{
|
||||
NetworkModHandler missingHandler = FMLNetworkHandler.instance().findNetworkModHandler(e.getValue());
|
||||
NetworkModHolder missingHandler = FMLNetworkHandler.instance().findNetworkModHandler(e.getValue());
|
||||
if (missingHandler.requiresServerSide())
|
||||
{
|
||||
// TODO : what should we do if a mod is marked "serverSideRequired"? Stop the connection?
|
||||
|
|
|
@ -38,7 +38,7 @@ import cpw.mods.fml.common.FMLLog;
|
|||
import cpw.mods.fml.common.Loader;
|
||||
import cpw.mods.fml.common.ModContainer;
|
||||
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||
import cpw.mods.fml.common.network.NetworkModHandler;
|
||||
import cpw.mods.fml.common.network.NetworkModHolder;
|
||||
import cpw.mods.fml.common.network.PacketDispatcher;
|
||||
import cpw.mods.fml.common.registry.GameData;
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class ModListResponsePacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
public byte[] generatePacketData(Object... data)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String,String> modVersions = (Map<String, String>) data[0];
|
||||
|
@ -75,7 +75,7 @@ public class ModListResponsePacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
public FMLPacket consumePacketData(byte[] data)
|
||||
{
|
||||
ByteArrayDataInput dat = ByteStreams.newDataInput(data);
|
||||
int versionListSize = dat.readInt();
|
||||
|
@ -107,7 +107,7 @@ public class ModListResponsePacket extends FMLPacket
|
|||
for (String m : missingMods)
|
||||
{
|
||||
ModContainer mc = indexedModList.get(m);
|
||||
NetworkModHandler networkMod = handler.findNetworkModHandler(mc);
|
||||
NetworkModHolder networkMod = handler.findNetworkModHandler(mc);
|
||||
if (networkMod.requiresClientSide())
|
||||
{
|
||||
missingClientMods.add(m);
|
||||
|
@ -117,7 +117,7 @@ public class ModListResponsePacket extends FMLPacket
|
|||
for (Entry<String,String> modVersion : modVersions.entrySet())
|
||||
{
|
||||
ModContainer mc = indexedModList.get(modVersion.getKey());
|
||||
NetworkModHandler networkMod = handler.findNetworkModHandler(mc);
|
||||
NetworkModHolder networkMod = handler.findNetworkModHandler(mc);
|
||||
if (!networkMod.acceptVersion(modVersion.getValue()))
|
||||
{
|
||||
versionIncorrectMods.add(modVersion.getKey());
|
||||
|
|
|
@ -44,7 +44,7 @@ public class ModMissingPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
public byte[] generatePacketData(Object... data)
|
||||
{
|
||||
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
|
||||
|
||||
|
@ -76,7 +76,7 @@ public class ModMissingPacket extends FMLPacket
|
|||
String modVersion;
|
||||
}
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
public FMLPacket consumePacketData(byte[] data)
|
||||
{
|
||||
ByteArrayDataInput dat = ByteStreams.newDataInput(data);
|
||||
int missingLen = dat.readInt();
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package cpw.mods.fml.common.network.packet;
|
||||
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import cpw.mods.fml.client.FMLClientHandler;
|
||||
import cpw.mods.fml.common.network.packet.PacketManager.PacketExecutor;
|
||||
|
||||
public class OpenGuiHandler extends PacketExecutor<OpenGuiPacket, NetHandlerPlayClient> {
|
||||
@Override
|
||||
public Void call() throws Exception
|
||||
{
|
||||
EntityPlayer player = FMLClientHandler.instance().getClient().field_71439_g;
|
||||
player.openGui(packet.networkId, packet.modGuiId, player.field_70170_p, packet.x, packet.y, packet.z);
|
||||
player.field_71070_bA.field_75152_c = packet.windowId;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -12,32 +12,21 @@
|
|||
|
||||
package cpw.mods.fml.common.network.packet;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.network.INetworkManager;
|
||||
import net.minecraft.network.packet.NetHandler;
|
||||
|
||||
import com.google.common.io.ByteArrayDataInput;
|
||||
import com.google.common.io.ByteArrayDataOutput;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import cpw.mods.fml.common.network.FMLNetworkHandler;
|
||||
|
||||
public class OpenGuiPacket extends FMLPacket
|
||||
{
|
||||
private int windowId;
|
||||
private int networkId;
|
||||
private int modGuiId;
|
||||
private int x;
|
||||
private int y;
|
||||
private int z;
|
||||
|
||||
public OpenGuiPacket()
|
||||
{
|
||||
super(Type.GUIOPEN);
|
||||
}
|
||||
int windowId;
|
||||
int networkId;
|
||||
int modGuiId;
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
|
||||
@Override
|
||||
public byte[] generatePacket(Object... data)
|
||||
byte[] generatePacketData(Object... data)
|
||||
{
|
||||
ByteArrayDataOutput dat = ByteStreams.newDataOutput();
|
||||
dat.writeInt((Integer) data[0]); // windowId
|
||||
|
@ -50,7 +39,7 @@ public class OpenGuiPacket extends FMLPacket
|
|||
}
|
||||
|
||||
@Override
|
||||
public FMLPacket consumePacket(byte[] data)
|
||||
public FMLPacket consumePacketData(byte[] data)
|
||||
{
|
||||
ByteArrayDataInput dat = ByteStreams.newDataInput(data);
|
||||
windowId = dat.readInt();
|
||||
|
@ -62,12 +51,5 @@ public class OpenGuiPacket extends FMLPacket
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName)
|
||||
{
|
||||
EntityPlayer player = netHandler.getPlayer();
|
||||
player.openGui(networkId, modGuiId, player.field_70170_p, x, y, z);
|
||||
player.field_71070_bA.field_75152_c = windowId;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package cpw.mods.fml.common.network.packet;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import net.minecraft.network.INetHandler;
|
||||
import net.minecraft.network.play.client.C17PacketCustomPayload;
|
||||
import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.primitives.UnsignedBytes;
|
||||
|
||||
import cpw.mods.fml.common.network.NetworkDispatcher;
|
||||
import cpw.mods.fml.common.network.packet.FMLPacket.Type;
|
||||
|
||||
public enum PacketManager {
|
||||
INSTANCE;
|
||||
|
||||
private Map<Class<? extends FMLPacket>, PacketExecutor<?,?>> packetExecutors = Maps.newHashMap();
|
||||
|
||||
|
||||
public C17PacketCustomPayload makeGuiPacket(int windowId, int i, int modGuiId, int x, int y, int z)
|
||||
{
|
||||
byte[] data = FMLPacket.makePacket(Type.GUIOPEN, windowId, i, modGuiId, x, y, z);
|
||||
C17PacketCustomPayload packet = new C17PacketCustomPayload("FML", data);
|
||||
return packet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public FMLPacket readPacket(NetworkDispatcher dispatcher, C17PacketCustomPayload clientSentPacket)
|
||||
{
|
||||
byte[] payload = clientSentPacket.func_149558_e();
|
||||
return buildPacket(dispatcher, payload);
|
||||
}
|
||||
public FMLPacket readPacket(NetworkDispatcher dispatcher, S3FPacketCustomPayload serverSentPacket)
|
||||
{
|
||||
byte[] payload = serverSentPacket.func_149168_d();
|
||||
return buildPacket(dispatcher, payload);
|
||||
}
|
||||
|
||||
private FMLPacket buildPacket(NetworkDispatcher dispatcher, byte[] payload)
|
||||
{
|
||||
int type = UnsignedBytes.toInt(payload[0]);
|
||||
Type eType = Type.values()[type];
|
||||
FMLPacket pkt;
|
||||
if (eType.isMultipart())
|
||||
{
|
||||
pkt = eType.findCurrentPart(network);
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = eType.make();
|
||||
}
|
||||
return pkt.consumePacketData(Arrays.copyOfRange(payload, 1, payload.length));
|
||||
}
|
||||
|
||||
|
||||
static abstract class PacketExecutor<P, T extends INetHandler> implements Callable<Void>
|
||||
{
|
||||
P packet;
|
||||
T netHandler;
|
||||
}
|
||||
|
||||
|
||||
public Packet makeFMLHandshake()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -105,7 +105,7 @@ public class LanguageRegistry
|
|||
if (objectToName instanceof Item) {
|
||||
objectName=((Item)objectToName).func_77658_a();
|
||||
} else if (objectToName instanceof Block) {
|
||||
objectName=((Block)objectToName).func_71917_a();
|
||||
objectName=((Block)objectToName).func_149739_a();
|
||||
} else if (objectToName instanceof ItemStack) {
|
||||
objectName=((ItemStack)objectToName).func_77973_b().func_77667_c((ItemStack)objectToName);
|
||||
} else {
|
||||
|
|
|
@ -238,7 +238,7 @@ public class VillagerRegistry
|
|||
{
|
||||
EntityVillager.field_70960_bC.put(item, new Tuple(min, max));
|
||||
}
|
||||
EntityVillager.func_146089_b(list, item.func_77612_l(), random, chance);
|
||||
EntityVillager.func_146089_b(list, item, random, chance);
|
||||
}
|
||||
|
||||
public static void applyRandomTrade(EntityVillager villager, Random rand)
|
||||
|
|
|
@ -23,15 +23,10 @@ import java.util.zip.ZipEntry;
|
|||
import java.util.zip.ZipFile;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.INetworkManager;
|
||||
import net.minecraft.network.packet.NetHandler;
|
||||
import net.minecraft.network.packet.Packet;
|
||||
import net.minecraft.network.packet.Packet131MapData;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.StringTranslate;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.MapDifference;
|
||||
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
|
@ -43,7 +38,6 @@ import cpw.mods.fml.common.network.packet.EntitySpawnPacket;
|
|||
import cpw.mods.fml.common.network.packet.ModMissingPacket;
|
||||
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
|
||||
import cpw.mods.fml.common.registry.GameData;
|
||||
import cpw.mods.fml.common.registry.ItemData;
|
||||
import cpw.mods.fml.common.registry.LanguageRegistry;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
|
@ -163,40 +157,14 @@ public class FMLServerHandler implements IFMLSidedHandler
|
|||
// NOOP
|
||||
}
|
||||
@Override
|
||||
public void sendPacket(Packet packet)
|
||||
{
|
||||
throw new RuntimeException("You cannot send a bare packet without a target on the server!");
|
||||
}
|
||||
@Override
|
||||
public void displayMissingMods(ModMissingPacket modMissingPacket)
|
||||
{
|
||||
// NOOP on server
|
||||
}
|
||||
@Override
|
||||
public void handleTinyPacket(NetHandler handler, Packet131MapData mapData)
|
||||
{
|
||||
// NOOP on server
|
||||
}
|
||||
@Override
|
||||
public void setClientCompatibilityLevel(byte compatibilityLevel)
|
||||
{
|
||||
// NOOP on server
|
||||
}
|
||||
@Override
|
||||
public byte getClientCompatibilityLevel()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldServerShouldBeKilledQuietly()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void disconnectIDMismatch(MapDifference<Integer, ItemData> s, NetHandler handler, INetworkManager mgr)
|
||||
{
|
||||
|
||||
}
|
||||
@Override
|
||||
public void addModAsResource(ModContainer container)
|
||||
|
|
|
@ -37,8 +37,8 @@ public net.minecraft.util.WeightedRandom$Item.field_76292_a #probability
|
|||
#public jy.a(Ljy;Z)Z #MD:NetLoginHandler/func_72531_a #'complete connection'
|
||||
#public jy.g #FD:NetLoginHandler/field_72543_h #userName
|
||||
## EntityPlayerMP getNextWindowId
|
||||
#public jv.bN()V #MD:EntityPlayerMP/func_71117_bO
|
||||
#public jv.bY #FD:EntityPlayerMP/field_71139_cq
|
||||
public net.minecraft.entity.player.EntityPlayerMP.func_71117_bO()V
|
||||
public net.minecraft.entity.player.EntityPlayerMP.field_71139_cq
|
||||
## EntityAITaskEntry
|
||||
#public pu #CL:EntityAITaskEntry
|
||||
## EntityAITasks
|
||||
|
|
Loading…
Reference in a new issue