ID syncing.

This commit is contained in:
Christian 2013-12-10 14:31:50 -05:00
parent 9f76245783
commit 531334b122
10 changed files with 187 additions and 52 deletions

View file

@ -30,7 +30,7 @@ import com.google.common.collect.Lists;
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.handshake.FMLHandshakeMessage.ClientModList; import cpw.mods.fml.common.network.handshake.FMLHandshakeMessage;
import cpw.mods.fml.common.network.handshake.NetworkDispatcher; import cpw.mods.fml.common.network.handshake.NetworkDispatcher;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
@ -451,13 +451,13 @@ public class FMLNetworkHandler
return null; return null;
} }
public static String checkClientModList(ClientModList clientModList) public static String checkModList(FMLHandshakeMessage.ModList modListPacket, Side side)
{ {
Map<String,String> modList = clientModList.modList(); Map<String,String> modList = modListPacket.modList();
List<ModContainer> rejects = Lists.newArrayList(); List<ModContainer> rejects = Lists.newArrayList();
for (Entry<ModContainer, NetworkModHolder> networkMod : NetworkRegistry.INSTANCE.registry().entrySet()) for (Entry<ModContainer, NetworkModHolder> networkMod : NetworkRegistry.INSTANCE.registry().entrySet())
{ {
boolean result = networkMod.getValue().check(modList, Side.CLIENT); boolean result = networkMod.getValue().check(modList, side);
if (!result) if (!result)
{ {
rejects.add(networkMod.getKey()); rejects.add(networkMod.getKey());
@ -469,7 +469,7 @@ public class FMLNetworkHandler
} }
else else
{ {
FMLLog.info("Rejecting client : %s", rejects); FMLLog.info("Rejecting connection %s: %s", side, rejects);
return String.format("Mod rejections %s",rejects); return String.format("Mod rejections %s",rejects);
} }
} }

View file

@ -6,13 +6,12 @@ import io.netty.channel.embedded.EmbeddedChannel;
import java.io.IOException; import java.io.IOException;
import cpw.mods.fml.relauncher.Side;
import net.minecraft.network.INetHandler; import net.minecraft.network.INetHandler;
import net.minecraft.network.Packet; import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload; import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.network.play.server.S3FPacketCustomPayload; import net.minecraft.network.play.server.S3FPacketCustomPayload;
import cpw.mods.fml.relauncher.Side;
public class FMLProxyPacket extends Packet { public class FMLProxyPacket extends Packet {
final String channel; final String channel;
@ -65,11 +64,18 @@ public class FMLProxyPacket extends Packet {
} }
} }
public String channel()
{
return channel;
}
public ByteBuf payload() public ByteBuf payload()
{ {
return payload; return payload;
} }
public INetHandler handler()
{
return netHandler;
}
public Packet toC17Packet() public Packet toC17Packet()
{ {
return new C17PacketCustomPayload(channel, payload.array()); return new C17PacketCustomPayload(channel, payload.array());

View file

@ -19,14 +19,13 @@ import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.util.AttributeKey; import io.netty.util.AttributeKey;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
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.NetworkManager; import net.minecraft.network.NetworkManager;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -542,4 +541,9 @@ public enum NetworkRegistry
{ {
return registry; return registry;
} }
public Set<String> channelNamesFor(Side side)
{
return channels.get(side).keySet();
}
} }

View file

@ -0,0 +1,33 @@
package cpw.mods.fml.common.network.handshake;
import com.google.common.base.Charsets;
import cpw.mods.fml.common.network.FMLProxyPacket;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.relauncher.Side;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
public class ChannelRegistrationHandler extends SimpleChannelInboundHandler<FMLProxyPacket> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, FMLProxyPacket msg) throws Exception
{
Side side = ctx.channel().attr(NetworkRegistry.CHANNEL_SOURCE).get();
if (msg.channel().equals("REGISTER") || msg.channel().equals("UNREGISTER"))
{
byte[] data = new byte[msg.payload().readableBytes()];
msg.payload().readBytes(data);
String channels = new String(data,Charsets.UTF_8);
String[] split = channels.split("\0");
for (String channel : split)
{
System.out.printf("Register %s from %s\n",channel, side);
}
}
else
{
ctx.fireChannelRead(msg);
}
}
}

View file

@ -3,7 +3,22 @@ package cpw.mods.fml.common.network.handshake;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
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.network.FMLNetworkHandler;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.relauncher.Side;
/**
* Packet handshake sequence manager- client side (responding to remote server)
*
* Flow:
* 1. Wait for server hello. (START). Move to HELLO state.
* 2. Receive Server Hello. Send customchannel registration. Send Client Hello. Send our modlist. Move to WAITINGFORSERVERDATA state.
* 3. Receive server modlist. Send ack if acceptable, else send nack and exit error. Receive server IDs. Move to COMPLETE state. Send ack.
*
* @author cpw
*
*/
enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState> enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
{ {
START START
@ -22,8 +37,26 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg) public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
{ {
FMLLog.info("Server protocol version %x", ((FMLHandshakeMessage.ServerHello)msg).protocolVersion()); FMLLog.info("Server protocol version %x", ((FMLHandshakeMessage.ServerHello)msg).protocolVersion());
ctx.writeAndFlush(FMLHandshakeMessage.makeCustomChannelRegistration(NetworkRegistry.INSTANCE.channelNamesFor(Side.CLIENT)));
ctx.writeAndFlush(new FMLHandshakeMessage.ClientHello()); ctx.writeAndFlush(new FMLHandshakeMessage.ClientHello());
ctx.writeAndFlush(new FMLHandshakeMessage.ClientModList(Loader.instance().getActiveModList())); ctx.writeAndFlush(new FMLHandshakeMessage.ModList(Loader.instance().getActiveModList()));
return WAITINGSERVERDATA;
}
},
WAITINGSERVERDATA
{
@Override
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
{
String result = FMLNetworkHandler.checkModList((FMLHandshakeMessage.ModList) msg, Side.SERVER);
if (result != null)
{
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
dispatcher.rejectHandshake(result);
return ERROR;
}
ctx.writeAndFlush(new FMLHandshakeMessage.ClientAck());
return COMPLETE; return COMPLETE;
} }
}, },
@ -34,9 +67,22 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
{ {
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(); NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
dispatcher.continueToClientPlayState(); dispatcher.continueToClientPlayState();
if (!ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get())
{
FMLHandshakeMessage.ModIdData modIds = (FMLHandshakeMessage.ModIdData)msg;
GameData.injectWorldIDMap(modIds.dataList());
}
FMLLog.info("Client side modded connection established"); FMLLog.info("Client side modded connection established");
ctx.writeAndFlush(new FMLHandshakeMessage.ClientAck()); ctx.writeAndFlush(new FMLHandshakeMessage.ClientAck());
return this; return this;
} }
},
ERROR
{
@Override
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
{
return this;
}
}; };
} }

View file

@ -9,8 +9,8 @@ public class FMLHandshakeCodec extends FMLIndexedMessageToMessageCodec<FMLHandsh
{ {
addDiscriminator((byte)0, FMLHandshakeMessage.ServerHello.class); addDiscriminator((byte)0, FMLHandshakeMessage.ServerHello.class);
addDiscriminator((byte)1, FMLHandshakeMessage.ClientHello.class); addDiscriminator((byte)1, FMLHandshakeMessage.ClientHello.class);
addDiscriminator((byte)2, FMLHandshakeMessage.ClientModList.class); addDiscriminator((byte)2, FMLHandshakeMessage.ModList.class);
addDiscriminator((byte)3, FMLHandshakeMessage.ServerModList.class); addDiscriminator((byte)3, FMLHandshakeMessage.ModIdData.class);
addDiscriminator((byte)-1, FMLHandshakeMessage.ClientAck.class); addDiscriminator((byte)-1, FMLHandshakeMessage.ClientAck.class);
} }
@Override @Override

View file

@ -1,19 +1,31 @@
package cpw.mods.fml.common.network.handshake; package cpw.mods.fml.common.network.handshake;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.collect.Lists; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import cpw.mods.fml.common.ModContainer; import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.ByteBufUtils; import cpw.mods.fml.common.network.ByteBufUtils;
import cpw.mods.fml.common.network.FMLProxyPacket;
import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.network.NetworkRegistry;
public abstract class FMLHandshakeMessage { public abstract class FMLHandshakeMessage {
public static FMLProxyPacket makeCustomChannelRegistration(Set<String> channels)
{
String salutation = Joiner.on('\0').join(Iterables.concat(Arrays.asList("FML|HS","FML"),channels));
FMLProxyPacket proxy = new FMLProxyPacket(Unpooled.wrappedBuffer(salutation.getBytes(Charsets.UTF_8)), "REGISTER");
return proxy;
}
public static class ServerHello extends FMLHandshakeMessage { public static class ServerHello extends FMLHandshakeMessage {
private byte serverProtocolVersion; private byte serverProtocolVersion;
public void toBytes(ByteBuf buffer) public void toBytes(ByteBuf buffer)
@ -48,38 +60,12 @@ public abstract class FMLHandshakeMessage {
return serverProtocolVersion; return serverProtocolVersion;
} }
} }
public static class ServerModList extends FMLHandshakeMessage { public static class ModList extends FMLHandshakeMessage {
private List<String> modTags = Lists.newArrayList(); public ModList()
@Override
public void toBytes(ByteBuf buffer)
{
super.toBytes(buffer);
ByteBufUtils.writeVarInt(buffer, modTags.size(), 2);
for (String modTag: modTags)
{
ByteBufUtils.writeUTF8String(buffer, modTag);
}
}
@Override
public void fromBytes(ByteBuf buffer)
{
super.fromBytes(buffer);
int modCount = ByteBufUtils.readVarInt(buffer, 2);
for (int i = 0; i < modCount; i++)
{
modTags.add(ByteBufUtils.readUTF8String(buffer));
}
}
}
public static class ClientModList extends FMLHandshakeMessage {
public ClientModList()
{ {
} }
public ClientModList(List<ModContainer> modList) public ModList(List<ModContainer> modList)
{ {
for (ModContainer mod : modList) for (ModContainer mod : modList)
{ {
@ -126,6 +112,45 @@ public abstract class FMLHandshakeMessage {
} }
} }
public static class ModIdData extends FMLHandshakeMessage {
public ModIdData()
{
}
public ModIdData(Map<String,Integer> modIds)
{
this.modIds = modIds;
}
private Map<String,Integer> modIds;
public void fromBytes(ByteBuf buffer)
{
int length = ByteBufUtils.readVarInt(buffer, 3);
modIds = Maps.newHashMap();
for (int i = 0; i < length; i++)
{
modIds.put(ByteBufUtils.readUTF8String(buffer),ByteBufUtils.readVarInt(buffer, 3));
}
}
@Override
public void toBytes(ByteBuf buffer)
{
ByteBufUtils.writeVarInt(buffer, modIds.size(), 3);
for (Entry<String, Integer> entry: modIds.entrySet())
{
ByteBufUtils.writeUTF8String(buffer, entry.getKey());
ByteBufUtils.writeVarInt(buffer, entry.getValue(), 3);
}
}
public Map<String,Integer> dataList()
{
return modIds;
}
}
public static class ClientAck extends FMLHandshakeMessage { public static class ClientAck extends FMLHandshakeMessage {
} }

View file

@ -2,7 +2,11 @@ package cpw.mods.fml.common.network.handshake;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import cpw.mods.fml.common.FMLLog; import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.network.FMLNetworkHandler; import cpw.mods.fml.common.network.FMLNetworkHandler;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.relauncher.Side;
enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState> enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
{ {
@ -13,6 +17,7 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
{ {
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(); NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
dispatcher.serverInitiateHandshake(); dispatcher.serverInitiateHandshake();
ctx.writeAndFlush(FMLHandshakeMessage.makeCustomChannelRegistration(NetworkRegistry.INSTANCE.channelNamesFor(Side.SERVER)));
ctx.writeAndFlush(new FMLHandshakeMessage.ServerHello()); ctx.writeAndFlush(new FMLHandshakeMessage.ServerHello());
return HELLO; return HELLO;
} }
@ -29,16 +34,29 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
return this; return this;
} }
FMLHandshakeMessage.ClientModList client = (FMLHandshakeMessage.ClientModList)msg; FMLHandshakeMessage.ModList client = (FMLHandshakeMessage.ModList)msg;
FMLLog.info("Client attempting to join with %d mods : %s", client.modListSize(), client.modListAsString()); FMLLog.info("Client attempting to join with %d mods : %s", client.modListSize(), client.modListAsString());
String result = FMLNetworkHandler.checkClientModList(client); String result = FMLNetworkHandler.checkModList(client, Side.CLIENT);
if (result != null) if (result != null)
{ {
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(); NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
dispatcher.rejectHandshake(result); dispatcher.rejectHandshake(result);
return ERROR; return ERROR;
} }
ctx.writeAndFlush(new FMLHandshakeMessage.ServerModList()); ctx.writeAndFlush(new FMLHandshakeMessage.ModList(Loader.instance().getActiveModList()));
if (ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get())
{
return COMPLETE;
}
return WAITINGCACK;
}
},
WAITINGCACK
{
@Override
public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
{
ctx.writeAndFlush(new FMLHandshakeMessage.ModIdData(GameData.buildItemDataList()));
return COMPLETE; return COMPLETE;
} }
}, },

View file

@ -56,6 +56,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
} }
public static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = new AttributeKey<NetworkDispatcher>("fml:dispatcher"); public static final AttributeKey<NetworkDispatcher> FML_DISPATCHER = new AttributeKey<NetworkDispatcher>("fml:dispatcher");
public static final AttributeKey<Boolean> IS_LOCAL = new AttributeKey<Boolean>("fml:isLocal");
private final NetworkManager manager; private final NetworkManager manager;
private final ServerConfigurationManager scm; private final ServerConfigurationManager scm;
private EntityPlayerMP player; private EntityPlayerMP player;
@ -70,9 +71,11 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
this.manager = manager; this.manager = manager;
this.scm = null; this.scm = null;
this.side = Side.CLIENT; this.side = Side.CLIENT;
this.handshakeChannel = new EmbeddedChannel(new HandshakeInjector(this), new FMLHandshakeCodec(), new HandshakeMessageHandler<FMLHandshakeClientState>(FMLHandshakeClientState.class)); this.handshakeChannel = new EmbeddedChannel(new HandshakeInjector(this), new ChannelRegistrationHandler(), new FMLHandshakeCodec(), new HandshakeMessageHandler<FMLHandshakeClientState>(FMLHandshakeClientState.class));
this.handshakeChannel.attr(FML_DISPATCHER).set(this); this.handshakeChannel.attr(FML_DISPATCHER).set(this);
this.handshakeChannel.attr(NetworkRegistry.CHANNEL_SOURCE).set(Side.SERVER);
this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS"); this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS");
this.handshakeChannel.attr(IS_LOCAL).set(manager.func_150731_c());
} }
public NetworkDispatcher(NetworkManager manager, ServerConfigurationManager scm) public NetworkDispatcher(NetworkManager manager, ServerConfigurationManager scm)
@ -81,9 +84,11 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
this.manager = manager; this.manager = manager;
this.scm = scm; this.scm = scm;
this.side = Side.SERVER; this.side = Side.SERVER;
this.handshakeChannel = new EmbeddedChannel(new HandshakeInjector(this), new FMLHandshakeCodec(), new HandshakeMessageHandler<FMLHandshakeServerState>(FMLHandshakeServerState.class)); this.handshakeChannel = new EmbeddedChannel(new HandshakeInjector(this), new ChannelRegistrationHandler(), new FMLHandshakeCodec(), new HandshakeMessageHandler<FMLHandshakeServerState>(FMLHandshakeServerState.class));
this.handshakeChannel.attr(FML_DISPATCHER).set(this); this.handshakeChannel.attr(FML_DISPATCHER).set(this);
this.handshakeChannel.attr(NetworkRegistry.CHANNEL_SOURCE).set(Side.CLIENT);
this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS"); this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS");
this.handshakeChannel.attr(IS_LOCAL).set(manager.func_150731_c());
} }
public void serverToClientHandshake(EntityPlayerMP player) public void serverToClientHandshake(EntityPlayerMP player)
@ -210,7 +215,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
private boolean handleClientSideCustomPacket(S3FPacketCustomPayload msg, ChannelHandlerContext context) private boolean handleClientSideCustomPacket(S3FPacketCustomPayload msg, ChannelHandlerContext context)
{ {
String channelName = msg.func_149169_c(); String channelName = msg.func_149169_c();
if ("FML|HS".equals(channelName)) if ("FML|HS".equals(channelName) || "REGISTER".equals(channelName) || "UNREGISTER".equals(channelName))
{ {
FMLProxyPacket proxy = new FMLProxyPacket(msg); FMLProxyPacket proxy = new FMLProxyPacket(msg);
handshakeChannel.writeInbound(proxy); handshakeChannel.writeInbound(proxy);
@ -233,7 +238,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
state = ConnectionState.HANDSHAKING; state = ConnectionState.HANDSHAKING;
} }
String channelName = msg.func_149559_c(); String channelName = msg.func_149559_c();
if ("FML|HS".equals(channelName)) if ("FML|HS".equals(channelName) || "REGISTER".equals(channelName) || "UNREGISTER".equals(channelName))
{ {
FMLProxyPacket proxy = new FMLProxyPacket(msg); FMLProxyPacket proxy = new FMLProxyPacket(msg);
handshakeChannel.writeInbound(proxy); handshakeChannel.writeInbound(proxy);

View file

@ -38,7 +38,6 @@ import cpw.mods.fml.common.network.packet.EntitySpawnAdjustmentPacket;
import cpw.mods.fml.common.network.packet.EntitySpawnPacket; 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.LanguageRegistry; import cpw.mods.fml.common.registry.LanguageRegistry;
import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.Side;
@ -96,7 +95,6 @@ public class FMLServerHandler implements IFMLSidedHandler
{ {
Loader.instance().initializeMods(); Loader.instance().initializeMods();
LanguageRegistry.reloadLanguageTable(); LanguageRegistry.reloadLanguageTable();
GameData.initializeServerGate(1);
} }
@Override @Override