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.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.relauncher.Side;
@ -451,13 +451,13 @@ public class FMLNetworkHandler
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();
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)
{
rejects.add(networkMod.getKey());
@ -469,7 +469,7 @@ public class FMLNetworkHandler
}
else
{
FMLLog.info("Rejecting client : %s", rejects);
FMLLog.info("Rejecting connection %s: %s", side, 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 cpw.mods.fml.relauncher.Side;
import net.minecraft.network.INetHandler;
import net.minecraft.network.Packet;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
import cpw.mods.fml.relauncher.Side;
public class FMLProxyPacket extends Packet {
final String channel;
@ -65,11 +64,18 @@ public class FMLProxyPacket extends Packet {
}
}
public String channel()
{
return channel;
}
public ByteBuf payload()
{
return payload;
}
public INetHandler handler()
{
return netHandler;
}
public Packet toC17Packet()
{
return new C17PacketCustomPayload(channel, payload.array());

View file

@ -19,14 +19,13 @@ import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.util.AttributeKey;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetworkManager;
import net.minecraft.world.World;
@ -542,4 +541,9 @@ public enum NetworkRegistry
{
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 cpw.mods.fml.common.FMLLog;
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>
{
START
@ -22,8 +37,26 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
{
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.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;
}
},
@ -34,9 +67,22 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
{
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
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");
ctx.writeAndFlush(new FMLHandshakeMessage.ClientAck());
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)1, FMLHandshakeMessage.ClientHello.class);
addDiscriminator((byte)2, FMLHandshakeMessage.ClientModList.class);
addDiscriminator((byte)3, FMLHandshakeMessage.ServerModList.class);
addDiscriminator((byte)2, FMLHandshakeMessage.ModList.class);
addDiscriminator((byte)3, FMLHandshakeMessage.ModIdData.class);
addDiscriminator((byte)-1, FMLHandshakeMessage.ClientAck.class);
}
@Override

View file

@ -1,19 +1,31 @@
package cpw.mods.fml.common.network.handshake;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.Arrays;
import java.util.List;
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.collect.Lists;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.ByteBufUtils;
import cpw.mods.fml.common.network.FMLProxyPacket;
import cpw.mods.fml.common.network.NetworkRegistry;
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 {
private byte serverProtocolVersion;
public void toBytes(ByteBuf buffer)
@ -48,38 +60,12 @@ public abstract class FMLHandshakeMessage {
return serverProtocolVersion;
}
}
public static class ServerModList extends FMLHandshakeMessage {
private List<String> modTags = Lists.newArrayList();
@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 static class ModList extends FMLHandshakeMessage {
public ModList()
{
}
public ClientModList(List<ModContainer> modList)
public ModList(List<ModContainer> 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 {
}

View file

@ -2,7 +2,11 @@ package cpw.mods.fml.common.network.handshake;
import io.netty.channel.ChannelHandlerContext;
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.NetworkRegistry;
import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.relauncher.Side;
enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
{
@ -13,6 +17,7 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
{
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
dispatcher.serverInitiateHandshake();
ctx.writeAndFlush(FMLHandshakeMessage.makeCustomChannelRegistration(NetworkRegistry.INSTANCE.channelNamesFor(Side.SERVER)));
ctx.writeAndFlush(new FMLHandshakeMessage.ServerHello());
return HELLO;
}
@ -29,16 +34,29 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
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());
String result = FMLNetworkHandler.checkClientModList(client);
String result = FMLNetworkHandler.checkModList(client, Side.CLIENT);
if (result != null)
{
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
dispatcher.rejectHandshake(result);
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;
}
},

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<Boolean> IS_LOCAL = new AttributeKey<Boolean>("fml:isLocal");
private final NetworkManager manager;
private final ServerConfigurationManager scm;
private EntityPlayerMP player;
@ -70,9 +71,11 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
this.manager = manager;
this.scm = null;
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(NetworkRegistry.CHANNEL_SOURCE).set(Side.SERVER);
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)
@ -81,9 +84,11 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
this.manager = manager;
this.scm = scm;
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(NetworkRegistry.CHANNEL_SOURCE).set(Side.CLIENT);
this.handshakeChannel.attr(NetworkRegistry.FML_CHANNEL).set("FML|HS");
this.handshakeChannel.attr(IS_LOCAL).set(manager.func_150731_c());
}
public void serverToClientHandshake(EntityPlayerMP player)
@ -210,7 +215,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
private boolean handleClientSideCustomPacket(S3FPacketCustomPayload msg, ChannelHandlerContext context)
{
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);
handshakeChannel.writeInbound(proxy);
@ -233,7 +238,7 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
state = ConnectionState.HANDSHAKING;
}
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);
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.ModMissingPacket;
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.relauncher.Side;
@ -96,7 +95,6 @@ public class FMLServerHandler implements IFMLSidedHandler
{
Loader.instance().initializeMods();
LanguageRegistry.reloadLanguageTable();
GameData.initializeServerGate(1);
}
@Override