The basic network handshaking for FML is done. All scenarios seem to work.

This commit is contained in:
Christian 2013-12-04 00:11:08 -05:00
parent 37a00f0158
commit fadff73489
25 changed files with 625 additions and 612 deletions

View file

@ -21,6 +21,7 @@ import java.util.Set;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.eventbus.EventBus; 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.ArtifactVersion;
import cpw.mods.fml.common.versioning.VersionRange; import cpw.mods.fml.common.versioning.VersionRange;
@ -140,4 +141,6 @@ public interface ModContainer
public Class<?> getCustomResourcePackClass(); public Class<?> getCustomResourcePackClass();
Map<String, String> getSharedModDescriptor(); Map<String, String> getSharedModDescriptor();
NetworkModHolder getNetworkModHolder();
} }

View file

@ -15,6 +15,7 @@ package cpw.mods.fml.common.network;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetHandlerPlayServer; import net.minecraft.network.NetHandlerPlayServer;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet; 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); NetworkDispatcher dispatcher = NetworkDispatcher.allocAndSet(manager, scm);
player.field_71135_a = null; dispatcher.serverToClientHandshake(player);
scm.func_72355_a(manager, player, nethandler); }
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) 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 // TODO Auto-generated method stub
return null; return null;
} }
} }

View file

@ -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;
}
}

View file

@ -20,18 +20,12 @@ public interface IGuiHandler
/** /**
* Returns a Server side Container to be displayed to the user. * Returns a Server side Container to be displayed to the user.
* *
* @param ID * @param ID The Gui ID Number
* The Gui ID Number * @param player The player viewing the Gui
* @param player * @param world The current world
* The player viewing the Gui * @param x X Position
* @param world * @param y Y Position
* The current world * @param z Z Position
* @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. * @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); 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 * needs to return a instance of GuiScreen On the server side, this needs to
* return a instance of Container * return a instance of Container
* *
* @param ID * @param ID The Gui ID Number
* The Gui ID Number * @param player The player viewing the Gui
* @param player * @param world The current world
* The player viewing the Gui * @param x X Position
* @param world * @param y Y Position
* The current world * @param z Z Position
* @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. * @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); public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z);

View file

@ -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);
}

View file

@ -1,16 +1,259 @@
package cpw.mods.fml.common.network; 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.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.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; import com.google.common.collect.ListMultimap;
public class NetworkDispatcher { import cpw.mods.fml.common.FMLLog;
private static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = new AttributeKey<NetworkDispatcher>("fml:dispatcher"); import cpw.mods.fml.common.network.packet.PacketManager;
private static final AttributeKey<ListMultimap<String,IPacketHandler>> FML_PACKET_HANDLERS = new AttributeKey<ListMultimap<String,IPacketHandler>>("fml:packet_handlers"); 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) public static NetworkDispatcher get(NetworkManager manager)
{ {
return manager.channel().attr(FML_DISPATCHER).get(); 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);
}
}
} }

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -40,41 +40,22 @@ import com.google.common.collect.Sets;
import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.LoaderException;
import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.packet.FMLPacket; import cpw.mods.fml.common.network.packet.FMLPacket;
import cpw.mods.fml.common.network.packet.FMLPacket.Type; import cpw.mods.fml.common.network.packet.FMLPacket.Type;
import cpw.mods.fml.common.network.packet.PacketManager;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
/** /**
* @author cpw * @author cpw
* *
*/ */
public class NetworkRegistry public enum NetworkRegistry
{ {
INSTANCE;
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();
private Map<ModContainer, IGuiHandler> serverGuiHandlers = Maps.newHashMap(); private Map<ModContainer, IGuiHandler> serverGuiHandlers = Maps.newHashMap();
private Map<ModContainer, IGuiHandler> clientGuiHandlers = 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 * Get the packet 250 channel registration string
* @return the {@link Packet250CustomPayload} channel registration string * @return the {@link Packet250CustomPayload} channel registration string
@ -286,10 +267,10 @@ public class NetworkRegistry
ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod); ModContainer mc = FMLCommonHandler.instance().findContainerFor(mod);
if (mc == null) if (mc == null)
{ {
mc = Loader.instance().activeModContainer(); FMLLog.log(Level.SEVERE, "Mod %s attempted to register a gui network handler during a construction phase", mc.getModId());
FMLLog.log(Level.WARNING, "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) if (nmh == null)
{ {
FMLLog.log(Level.FINE, "The mod %s needs to be a @NetworkMod to register a Networked Gui Handler", mc.getModId()); 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) void openRemoteGui(ModContainer mc, EntityPlayerMP player, int modGuiId, World world, int x, int y, int z)
{ {
IGuiHandler handler = serverGuiHandlers.get(mc); IGuiHandler handler = serverGuiHandlers.get(mc);
NetworkModHandler nmh = FMLNetworkHandler.instance().findNetworkModHandler(mc); NetworkModHolder nmh = mc.getNetworkModHolder();
if (handler != null && nmh != null) if (handler != null && nmh != null)
{ {
Container container = (Container)handler.getServerGuiElement(modGuiId, player, world, x, y, z); Container container = (Container)handler.getServerGuiElement(modGuiId, player, world, x, y, z);
@ -312,10 +293,7 @@ public class NetworkRegistry
player.func_71117_bO(); player.func_71117_bO();
player.func_71128_l(); player.func_71128_l();
int windowId = player.field_71139_cq; int windowId = player.field_71139_cq;
Packet250CustomPayload pkt = new Packet250CustomPayload(); Packet pkt = PacketManager.INSTANCE.makeGuiPacket(windowId, nmh.getNetworkId(), modGuiId, x, y, z);
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;
player.field_71135_a.func_72567_b(pkt); player.field_71135_a.func_72567_b(pkt);
player.field_71070_bA = container; player.field_71070_bA = container;
player.field_71070_bA.field_75152_c = windowId; player.field_71070_bA.field_75152_c = windowId;
@ -328,35 +306,4 @@ public class NetworkRegistry
IGuiHandler handler = clientGuiHandlers.get(mc); IGuiHandler handler = clientGuiHandlers.get(mc);
FMLCommonHandler.instance().showGuiScreen(handler.getClientGuiElement(modGuiId, player, world, x, y, z)); 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());
}
}
} }

View file

@ -87,7 +87,7 @@ public class PacketDispatcher
public static Packet131MapData getTinyPacket(Object mod, short tag, byte[] data) 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); return new Packet131MapData((short) nmh.getNetworkId(), tag, data);
} }
} }

View file

@ -36,7 +36,7 @@ public class EntitySpawnAdjustmentPacket extends FMLPacket
public int serverZ; public int serverZ;
@Override @Override
public byte[] generatePacket(Object... data) public byte[] generatePacketData(Object... data)
{ {
ByteArrayDataOutput dat = ByteStreams.newDataOutput(); ByteArrayDataOutput dat = ByteStreams.newDataOutput();
dat.writeInt((Integer) data[0]); dat.writeInt((Integer) data[0]);
@ -47,7 +47,7 @@ public class EntitySpawnAdjustmentPacket extends FMLPacket
} }
@Override @Override
public FMLPacket consumePacket(byte[] data) public FMLPacket consumePacketData(byte[] data)
{ {
ByteArrayDataInput dat = ByteStreams.newDataInput(data); ByteArrayDataInput dat = ByteStreams.newDataInput(data);
entityId = dat.readInt(); entityId = dat.readInt();

View file

@ -33,7 +33,7 @@ import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.FMLNetworkHandler; 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;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration; import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData; import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
@ -68,11 +68,11 @@ public class EntitySpawnPacket extends FMLPacket
} }
@Override @Override
public byte[] generatePacket(Object... data) public byte[] generatePacketData(Object... data)
{ {
EntityRegistration er = (EntityRegistration) data[0]; EntityRegistration er = (EntityRegistration) data[0];
Entity ent = (Entity) data[1]; Entity ent = (Entity) data[1];
NetworkModHandler handler = (NetworkModHandler) data[2]; NetworkModHolder handler = (NetworkModHolder) data[2];
ByteArrayDataOutput dat = ByteStreams.newDataOutput(); ByteArrayDataOutput dat = ByteStreams.newDataOutput();
dat.writeInt(handler.getNetworkId()); dat.writeInt(handler.getNetworkId());
@ -142,7 +142,7 @@ public class EntitySpawnPacket extends FMLPacket
} }
@Override @Override
public FMLPacket consumePacket(byte[] data) public FMLPacket consumePacketData(byte[] data)
{ {
ByteArrayDataInput dat = ByteStreams.newDataInput(data); ByteArrayDataInput dat = ByteStreams.newDataInput(data);
networkId = dat.readInt(); networkId = dat.readInt();
@ -183,7 +183,7 @@ public class EntitySpawnPacket extends FMLPacket
@Override @Override
public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName) 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(); ModContainer mc = nmh.getContainer();
EntityRegistration registration = EntityRegistry.instance().lookupModSpawn(mc, modEntityId); EntityRegistration registration = EntityRegistry.instance().lookupModSpawn(mc, modEntityId);

View file

@ -13,6 +13,7 @@
package cpw.mods.fml.common.network.packet; package cpw.mods.fml.common.network.packet;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level; import java.util.logging.Level;
@ -52,7 +53,7 @@ public abstract class FMLPacket
/** /**
* Open a GUI on the client from the server * 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 * Spawn an entity on the client from the server
*/ */
@ -69,12 +70,15 @@ public abstract class FMLPacket
private Class<? extends FMLPacket> packetType; private Class<? extends FMLPacket> packetType;
private boolean isMultipart; private boolean isMultipart;
private String executorClass;
private ConcurrentMap<INetworkManager, FMLPacket> partTracker; 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.packetType = clazz;
this.isMultipart = isMultipart; this.isMultipart = isMultipart;
this.executorClass = executorClass;
} }
FMLPacket make() FMLPacket make()
@ -91,12 +95,12 @@ public abstract class FMLPacket
} }
} }
public boolean isMultipart() boolean isMultipart()
{ {
return isMultipart; return isMultipart;
} }
private FMLPacket findCurrentPart(INetworkManager network) private FMLPacket findCurrentPart(NetworkManager network)
{ {
if (partTracker == null) if (partTracker == null)
{ {
@ -110,16 +114,13 @@ public abstract class FMLPacket
} }
} }
@SuppressWarnings("unused")
private Type type;
public static byte[][] makePacketSet(Type type, Object... data) public static byte[][] makePacketSet(Type type, Object... data)
{ {
if (!type.isMultipart()) if (!type.isMultipart())
{ {
return new byte[0][]; return new byte[0][];
} }
byte[] packetData = type.make().generatePacket(data); byte[] packetData = type.make().generatePacketData(data);
byte[][] chunks = new byte[packetData.length / 32000 + 1][]; byte[][] chunks = new byte[packetData.length / 32000 + 1][];
for (int i = 0; i < packetData.length / 32000 + 1; i++) for (int i = 0; i < packetData.length / 32000 + 1; i++)
@ -129,36 +130,13 @@ public abstract class FMLPacket
} }
return chunks; 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 ); return Bytes.concat(new byte[] { UnsignedBytes.checkedCast(type.ordinal()) }, packetData );
} }
public static FMLPacket readPacket(INetworkManager network, byte[] payload) abstract byte[] generatePacketData(Object... data);
{
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));
}
public FMLPacket(Type type) abstract FMLPacket consumePacketData(byte[] data);
{
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);
} }

View file

@ -46,7 +46,7 @@ public class ModIdMapPacket extends FMLPacket {
} }
@Override @Override
public byte[] generatePacket(Object... data) public byte[] generatePacketData(Object... data)
{ {
NBTTagList completeList = (NBTTagList) data[0]; NBTTagList completeList = (NBTTagList) data[0];
NBTTagCompound wrap = new NBTTagCompound(); NBTTagCompound wrap = new NBTTagCompound();
@ -63,7 +63,7 @@ public class ModIdMapPacket extends FMLPacket {
} }
@Override @Override
public FMLPacket consumePacket(byte[] data) public FMLPacket consumePacketData(byte[] data)
{ {
ByteArrayDataInput bdi = ByteStreams.newDataInput(data); ByteArrayDataInput bdi = ByteStreams.newDataInput(data);
int chunkIdx = UnsignedBytes.toInt(bdi.readByte()); int chunkIdx = UnsignedBytes.toInt(bdi.readByte());

View file

@ -27,7 +27,7 @@ import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import cpw.mods.fml.common.network.FMLNetworkHandler; 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 public class ModIdentifiersPacket extends FMLPacket
{ {
@ -40,13 +40,13 @@ public class ModIdentifiersPacket extends FMLPacket
} }
@Override @Override
public byte[] generatePacket(Object... data) public byte[] generatePacketData(Object... data)
{ {
ByteArrayDataOutput dat = ByteStreams.newDataOutput(); ByteArrayDataOutput dat = ByteStreams.newDataOutput();
Collection<NetworkModHandler >networkMods = FMLNetworkHandler.instance().getNetworkIdMap().values(); Collection<NetworkModHolder >networkMods = FMLNetworkHandler.instance().getNetworkIdMap().values();
dat.writeInt(networkMods.size()); dat.writeInt(networkMods.size());
for (NetworkModHandler handler : networkMods) for (NetworkModHolder handler : networkMods)
{ {
dat.writeUTF(handler.getContainer().getModId()); dat.writeUTF(handler.getContainer().getModId());
dat.writeInt(handler.getNetworkId()); dat.writeInt(handler.getNetworkId());
@ -57,7 +57,7 @@ public class ModIdentifiersPacket extends FMLPacket
} }
@Override @Override
public FMLPacket consumePacket(byte[] data) public FMLPacket consumePacketData(byte[] data)
{ {
ByteArrayDataInput dat = ByteStreams.newDataInput(data); ByteArrayDataInput dat = ByteStreams.newDataInput(data);
int listSize = dat.readInt(); int listSize = dat.readInt();

View file

@ -34,7 +34,7 @@ import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.FMLNetworkHandler; 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.network.PacketDispatcher;
public class ModListRequestPacket extends FMLPacket public class ModListRequestPacket extends FMLPacket
@ -48,7 +48,7 @@ public class ModListRequestPacket extends FMLPacket
} }
@Override @Override
public byte[] generatePacket(Object... data) public byte[] generatePacketData(Object... data)
{ {
ByteArrayDataOutput dat = ByteStreams.newDataOutput(); ByteArrayDataOutput dat = ByteStreams.newDataOutput();
Set<ModContainer> activeMods = FMLNetworkHandler.instance().getNetworkModList(); Set<ModContainer> activeMods = FMLNetworkHandler.instance().getNetworkModList();
@ -62,7 +62,7 @@ public class ModListRequestPacket extends FMLPacket
} }
@Override @Override
public FMLPacket consumePacket(byte[] data) public FMLPacket consumePacketData(byte[] data)
{ {
sentModList = Lists.newArrayList(); sentModList = Lists.newArrayList();
ByteArrayDataInput in = ByteStreams.newDataInput(data); ByteArrayDataInput in = ByteStreams.newDataInput(data);
@ -114,7 +114,7 @@ public class ModListRequestPacket extends FMLPacket
{ {
if (e.getValue().isNetworkMod()) if (e.getValue().isNetworkMod())
{ {
NetworkModHandler missingHandler = FMLNetworkHandler.instance().findNetworkModHandler(e.getValue()); NetworkModHolder missingHandler = FMLNetworkHandler.instance().findNetworkModHandler(e.getValue());
if (missingHandler.requiresServerSide()) if (missingHandler.requiresServerSide())
{ {
// TODO : what should we do if a mod is marked "serverSideRequired"? Stop the connection? // TODO : what should we do if a mod is marked "serverSideRequired"? Stop the connection?

View file

@ -38,7 +38,7 @@ import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.FMLNetworkHandler; 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.network.PacketDispatcher;
import cpw.mods.fml.common.registry.GameData; import cpw.mods.fml.common.registry.GameData;
@ -53,7 +53,7 @@ public class ModListResponsePacket extends FMLPacket
} }
@Override @Override
public byte[] generatePacket(Object... data) public byte[] generatePacketData(Object... data)
{ {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Map<String,String> modVersions = (Map<String, String>) data[0]; Map<String,String> modVersions = (Map<String, String>) data[0];
@ -75,7 +75,7 @@ public class ModListResponsePacket extends FMLPacket
} }
@Override @Override
public FMLPacket consumePacket(byte[] data) public FMLPacket consumePacketData(byte[] data)
{ {
ByteArrayDataInput dat = ByteStreams.newDataInput(data); ByteArrayDataInput dat = ByteStreams.newDataInput(data);
int versionListSize = dat.readInt(); int versionListSize = dat.readInt();
@ -107,7 +107,7 @@ public class ModListResponsePacket extends FMLPacket
for (String m : missingMods) for (String m : missingMods)
{ {
ModContainer mc = indexedModList.get(m); ModContainer mc = indexedModList.get(m);
NetworkModHandler networkMod = handler.findNetworkModHandler(mc); NetworkModHolder networkMod = handler.findNetworkModHandler(mc);
if (networkMod.requiresClientSide()) if (networkMod.requiresClientSide())
{ {
missingClientMods.add(m); missingClientMods.add(m);
@ -117,7 +117,7 @@ public class ModListResponsePacket extends FMLPacket
for (Entry<String,String> modVersion : modVersions.entrySet()) for (Entry<String,String> modVersion : modVersions.entrySet())
{ {
ModContainer mc = indexedModList.get(modVersion.getKey()); ModContainer mc = indexedModList.get(modVersion.getKey());
NetworkModHandler networkMod = handler.findNetworkModHandler(mc); NetworkModHolder networkMod = handler.findNetworkModHandler(mc);
if (!networkMod.acceptVersion(modVersion.getValue())) if (!networkMod.acceptVersion(modVersion.getValue()))
{ {
versionIncorrectMods.add(modVersion.getKey()); versionIncorrectMods.add(modVersion.getKey());

View file

@ -44,7 +44,7 @@ public class ModMissingPacket extends FMLPacket
} }
@Override @Override
public byte[] generatePacket(Object... data) public byte[] generatePacketData(Object... data)
{ {
ByteArrayDataOutput dat = ByteStreams.newDataOutput(); ByteArrayDataOutput dat = ByteStreams.newDataOutput();
@ -76,7 +76,7 @@ public class ModMissingPacket extends FMLPacket
String modVersion; String modVersion;
} }
@Override @Override
public FMLPacket consumePacket(byte[] data) public FMLPacket consumePacketData(byte[] data)
{ {
ByteArrayDataInput dat = ByteStreams.newDataInput(data); ByteArrayDataInput dat = ByteStreams.newDataInput(data);
int missingLen = dat.readInt(); int missingLen = dat.readInt();

View file

@ -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;
}
}

View file

@ -12,32 +12,21 @@
package cpw.mods.fml.common.network.packet; 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.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import cpw.mods.fml.common.network.FMLNetworkHandler;
public class OpenGuiPacket extends FMLPacket public class OpenGuiPacket extends FMLPacket
{ {
private int windowId; int windowId;
private int networkId; int networkId;
private int modGuiId; int modGuiId;
private int x; int x;
private int y; int y;
private int z; int z;
public OpenGuiPacket()
{
super(Type.GUIOPEN);
}
@Override @Override
public byte[] generatePacket(Object... data) byte[] generatePacketData(Object... data)
{ {
ByteArrayDataOutput dat = ByteStreams.newDataOutput(); ByteArrayDataOutput dat = ByteStreams.newDataOutput();
dat.writeInt((Integer) data[0]); // windowId dat.writeInt((Integer) data[0]); // windowId
@ -50,7 +39,7 @@ public class OpenGuiPacket extends FMLPacket
} }
@Override @Override
public FMLPacket consumePacket(byte[] data) public FMLPacket consumePacketData(byte[] data)
{ {
ByteArrayDataInput dat = ByteStreams.newDataInput(data); ByteArrayDataInput dat = ByteStreams.newDataInput(data);
windowId = dat.readInt(); windowId = dat.readInt();
@ -62,12 +51,5 @@ public class OpenGuiPacket extends FMLPacket
return this; 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;
}
} }

View file

@ -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;
}
}

View file

@ -105,7 +105,7 @@ public class LanguageRegistry
if (objectToName instanceof Item) { if (objectToName instanceof Item) {
objectName=((Item)objectToName).func_77658_a(); objectName=((Item)objectToName).func_77658_a();
} else if (objectToName instanceof Block) { } else if (objectToName instanceof Block) {
objectName=((Block)objectToName).func_71917_a(); objectName=((Block)objectToName).func_149739_a();
} else if (objectToName instanceof ItemStack) { } else if (objectToName instanceof ItemStack) {
objectName=((ItemStack)objectToName).func_77973_b().func_77667_c((ItemStack)objectToName); objectName=((ItemStack)objectToName).func_77973_b().func_77667_c((ItemStack)objectToName);
} else { } else {

View file

@ -238,7 +238,7 @@ public class VillagerRegistry
{ {
EntityVillager.field_70960_bC.put(item, new Tuple(min, max)); 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) public static void applyRandomTrade(EntityVillager villager, Random rand)

View file

@ -23,15 +23,10 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import net.minecraft.entity.Entity; 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.server.MinecraftServer;
import net.minecraft.util.StringTranslate; import net.minecraft.util.StringTranslate;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.MapDifference;
import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog; 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.network.packet.ModMissingPacket;
import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration; import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration;
import cpw.mods.fml.common.registry.GameData; 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.common.registry.LanguageRegistry;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
@ -163,40 +157,14 @@ public class FMLServerHandler implements IFMLSidedHandler
// NOOP // NOOP
} }
@Override @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) public void displayMissingMods(ModMissingPacket modMissingPacket)
{ {
// NOOP on server // 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 @Override
public boolean shouldServerShouldBeKilledQuietly() public boolean shouldServerShouldBeKilledQuietly()
{ {
return false; return false;
}
@Override
public void disconnectIDMismatch(MapDifference<Integer, ItemData> s, NetHandler handler, INetworkManager mgr)
{
} }
@Override @Override
public void addModAsResource(ModContainer container) public void addModAsResource(ModContainer container)

View file

@ -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.a(Ljy;Z)Z #MD:NetLoginHandler/func_72531_a #'complete connection'
#public jy.g #FD:NetLoginHandler/field_72543_h #userName #public jy.g #FD:NetLoginHandler/field_72543_h #userName
## EntityPlayerMP getNextWindowId ## EntityPlayerMP getNextWindowId
#public jv.bN()V #MD:EntityPlayerMP/func_71117_bO public net.minecraft.entity.player.EntityPlayerMP.func_71117_bO()V
#public jv.bY #FD:EntityPlayerMP/field_71139_cq public net.minecraft.entity.player.EntityPlayerMP.field_71139_cq
## EntityAITaskEntry ## EntityAITaskEntry
#public pu #CL:EntityAITaskEntry #public pu #CL:EntityAITaskEntry
## EntityAITasks ## EntityAITasks