ID syncing.
This commit is contained in:
parent
9f76245783
commit
531334b122
10 changed files with 187 additions and 52 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue