parent
7930adec70
commit
161b47ee75
4 changed files with 70 additions and 47 deletions
|
@ -24,6 +24,7 @@ import io.netty.channel.ChannelHandlerContext;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
@ -55,26 +56,35 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
|
|||
START
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeClientState> cons)
|
||||
{
|
||||
cons.accept(HELLO);
|
||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
||||
dispatcher.clientListenForServerHandshake();
|
||||
return HELLO;
|
||||
}
|
||||
},
|
||||
HELLO
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeClientState> cons)
|
||||
{
|
||||
boolean isVanilla = msg == null;
|
||||
if (isVanilla)
|
||||
{
|
||||
cons.accept(DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
cons.accept(WAITINGSERVERDATA);
|
||||
}
|
||||
// write our custom packet registration, always
|
||||
ctx.writeAndFlush(FMLHandshakeMessage.makeCustomChannelRegistration(NetworkRegistry.INSTANCE.channelNamesFor(Side.CLIENT)));
|
||||
if (msg == null)
|
||||
if (isVanilla)
|
||||
{
|
||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
||||
dispatcher.abortClientHandshake("VANILLA");
|
||||
// VANILLA login
|
||||
return DONE;
|
||||
return;
|
||||
}
|
||||
|
||||
ServerHello serverHelloPacket = (FMLHandshakeMessage.ServerHello)msg;
|
||||
|
@ -87,37 +97,38 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
|
|||
}
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.ClientHello()).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.ModList(Loader.instance().getActiveModList())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
return WAITINGSERVERDATA;
|
||||
}
|
||||
},
|
||||
|
||||
WAITINGSERVERDATA
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeClientState> cons)
|
||||
{
|
||||
String result = FMLNetworkHandler.checkModList((FMLHandshakeMessage.ModList) msg, Side.SERVER);
|
||||
if (result != null)
|
||||
{
|
||||
cons.accept(ERROR);
|
||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
||||
dispatcher.rejectHandshake(result);
|
||||
return ERROR;
|
||||
return;
|
||||
}
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.HandshakeAck(ordinal())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
if (!ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get())
|
||||
{
|
||||
return WAITINGSERVERCOMPLETE;
|
||||
cons.accept(WAITINGSERVERCOMPLETE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return PENDINGCOMPLETE;
|
||||
cons.accept(PENDINGCOMPLETE);
|
||||
}
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.HandshakeAck(ordinal())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
|
||||
}
|
||||
},
|
||||
WAITINGSERVERCOMPLETE
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeClientState> cons)
|
||||
{
|
||||
FMLHandshakeMessage.RegistryData pkt = (FMLHandshakeMessage.RegistryData)msg;
|
||||
Map<ResourceLocation, ForgeRegistry.Snapshot> snap = ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).get();
|
||||
|
@ -135,8 +146,9 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
|
|||
|
||||
if (pkt.hasMore())
|
||||
{
|
||||
cons.accept(WAITINGSERVERCOMPLETE);
|
||||
FMLLog.log.debug("Received Mod Registry mapping for {}: {} IDs {} overrides {} dummied", pkt.getName(), entry.ids.size(), entry.overrides.size(), entry.dummied.size());
|
||||
return WAITINGSERVERCOMPLETE;
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.channel().attr(NetworkDispatcher.FML_GAMEDATA_SNAPSHOT).set(null);
|
||||
|
@ -144,57 +156,56 @@ enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
|
|||
Multimap<ResourceLocation, ResourceLocation> locallyMissing = GameData.injectSnapshot(snap, false, false);
|
||||
if (!locallyMissing.isEmpty())
|
||||
{
|
||||
cons.accept(ERROR);
|
||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
||||
dispatcher.rejectHandshake("Fatally missing registry entries");
|
||||
FMLLog.log.fatal("Failed to connect to server: there are {} missing registry items", locallyMissing.size());
|
||||
locallyMissing.asMap().forEach((key, value) -> FMLLog.log.debug("Missing {} Entries: {}", key, value));
|
||||
return ERROR;
|
||||
return;
|
||||
}
|
||||
cons.accept(PENDINGCOMPLETE);
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.HandshakeAck(ordinal())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
return PENDINGCOMPLETE;
|
||||
}
|
||||
},
|
||||
PENDINGCOMPLETE
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeClientState> cons)
|
||||
{
|
||||
cons.accept(COMPLETE);
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.HandshakeAck(ordinal())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
return COMPLETE;
|
||||
}
|
||||
},
|
||||
COMPLETE
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeClientState> cons)
|
||||
{
|
||||
cons.accept(DONE);
|
||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
||||
dispatcher.completeClientHandshake();
|
||||
FMLMessage.CompleteHandshake complete = new FMLMessage.CompleteHandshake(Side.CLIENT);
|
||||
ctx.fireChannelRead(complete);
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.HandshakeAck(ordinal())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
return DONE;
|
||||
}
|
||||
},
|
||||
DONE
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeClientState> cons)
|
||||
{
|
||||
if (msg instanceof FMLHandshakeMessage.HandshakeReset)
|
||||
{
|
||||
cons.accept(HELLO);
|
||||
GameData.revertToFrozen();
|
||||
return HELLO;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
},
|
||||
ERROR
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeClientState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeClientState> cons)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import io.netty.channel.ChannelHandlerContext;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
|
@ -41,25 +42,25 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
|
|||
START
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeServerState> cons)
|
||||
{
|
||||
cons.accept(HELLO);
|
||||
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
|
||||
int overrideDim = dispatcher.serverInitiateHandshake();
|
||||
ctx.writeAndFlush(FMLHandshakeMessage.makeCustomChannelRegistration(NetworkRegistry.INSTANCE.channelNamesFor(Side.SERVER))).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.ServerHello(overrideDim)).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
return HELLO;
|
||||
}
|
||||
},
|
||||
HELLO
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeServerState> cons)
|
||||
{
|
||||
// Hello packet first
|
||||
if (msg instanceof FMLHandshakeMessage.ClientHello)
|
||||
{
|
||||
FMLLog.log.info("Client protocol version {}", Integer.toHexString(((FMLHandshakeMessage.ClientHello)msg).protocolVersion()));
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
FMLHandshakeMessage.ModList client = (FMLHandshakeMessage.ModList)msg;
|
||||
|
@ -69,18 +70,20 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
|
|||
String result = FMLNetworkHandler.checkModList(client, Side.CLIENT);
|
||||
if (result != null)
|
||||
{
|
||||
cons.accept(ERROR);
|
||||
dispatcher.rejectHandshake(result);
|
||||
return ERROR;
|
||||
return;
|
||||
}
|
||||
cons.accept(WAITINGCACK);
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.ModList(Loader.instance().getActiveModList()));
|
||||
return WAITINGCACK;
|
||||
}
|
||||
},
|
||||
WAITINGCACK
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeServerState> cons)
|
||||
{
|
||||
cons.accept(COMPLETE);
|
||||
if (!ctx.channel().attr(NetworkDispatcher.IS_LOCAL).get())
|
||||
{
|
||||
Map<ResourceLocation, ForgeRegistry.Snapshot> snapshot = RegistryManager.ACTIVE.takeSnapshot(false);
|
||||
|
@ -93,35 +96,32 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
|
|||
}
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.HandshakeAck(ordinal())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
NetworkRegistry.INSTANCE.fireNetworkHandshake(ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get(), Side.SERVER);
|
||||
return COMPLETE;
|
||||
}
|
||||
},
|
||||
COMPLETE
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeServerState> cons)
|
||||
{
|
||||
cons.accept(DONE);
|
||||
// Poke the client
|
||||
ctx.writeAndFlush(new FMLHandshakeMessage.HandshakeAck(ordinal())).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
FMLMessage.CompleteHandshake complete = new FMLMessage.CompleteHandshake(Side.SERVER);
|
||||
ctx.fireChannelRead(complete);
|
||||
return DONE;
|
||||
}
|
||||
},
|
||||
DONE
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeServerState> cons)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
},
|
||||
ERROR
|
||||
{
|
||||
@Override
|
||||
public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
|
||||
public void accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg, Consumer<? super FMLHandshakeServerState> cons)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -43,26 +43,30 @@ public class HandshakeMessageHandler<S extends Enum<S> & IHandshakeState<S>> ext
|
|||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, FMLHandshakeMessage msg) throws Exception
|
||||
{
|
||||
S state = ctx.attr(fmlHandshakeState).get();
|
||||
S state = ctx.channel().attr(fmlHandshakeState).get();
|
||||
FMLLog.log.debug("{}: {}->{}:{}", stateType.getSimpleName(), msg.toString(stateType), state.getClass().getName().substring(state.getClass().getName().lastIndexOf('.')+1), state);
|
||||
S newState = state.accept(ctx, msg);
|
||||
FMLLog.log.debug(" Next: {}", newState.name());
|
||||
ctx.attr(fmlHandshakeState).set(newState);
|
||||
state.accept(ctx, msg, s ->
|
||||
{
|
||||
FMLLog.log.debug(" Next: {}", s.name());
|
||||
ctx.channel().attr(fmlHandshakeState).set(s);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
ctx.attr(fmlHandshakeState).set(initialState);
|
||||
ctx.channel().attr(fmlHandshakeState).set(initialState);
|
||||
}
|
||||
@Override
|
||||
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception
|
||||
{
|
||||
S state = ctx.attr(fmlHandshakeState).get();
|
||||
FMLLog.log.debug("{}: null->{}:{}", stateType.getSimpleName(), state.getClass().getName().substring(state.getClass().getName().lastIndexOf('.')+1), state);
|
||||
S newState = state.accept(ctx, null);
|
||||
FMLLog.log.debug(" Next: {}", newState.name());
|
||||
ctx.attr(fmlHandshakeState).set(newState);
|
||||
state.accept(ctx, null, s ->
|
||||
{
|
||||
FMLLog.log.debug(" Next: {}", s.name());
|
||||
ctx.channel().attr(fmlHandshakeState).set(s);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,8 +21,16 @@ package net.minecraftforge.fml.common.network.handshake;
|
|||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface IHandshakeState<S> {
|
||||
S accept(ChannelHandlerContext ctx, @Nullable FMLHandshakeMessage msg);
|
||||
/**
|
||||
* Accepts FML handshake message for this state, and if needed - switches to another handshake state
|
||||
* using the provided consumer.
|
||||
*
|
||||
* The consumer allows to set new state before sending any messages to avoid race conditions.
|
||||
*/
|
||||
void accept(ChannelHandlerContext ctx, @Nullable FMLHandshakeMessage msg, Consumer<? super S> cons);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue