OK, network channels appear to be working well for both dedi and integrated servers.

The beginnings of the new mod structure too.
This commit is contained in:
Christian 2013-12-06 14:52:33 -05:00
parent 89c7a02146
commit bead2dab97
18 changed files with 168 additions and 275 deletions

View file

@ -81,19 +81,3 @@
this.field_71424_I.func_76319_b();
this.field_71423_H = func_71386_F();
}
@@ -2046,6 +2063,7 @@
networkmanager.func_150725_a(new C00Handshake(4, socketaddress.toString(), 0, EnumConnectionState.LOGIN), new GenericFutureListener[0]);
networkmanager.func_150725_a(new C00PacketLoginStart(this.func_110432_I().func_148256_e()), new GenericFutureListener[0]);
this.field_71453_ak = networkmanager;
+ FMLClientHandler.instance().currentConnection(networkmanager, true);
}
public void func_71403_a(WorldClient p_71403_1_)
@@ -2076,6 +2094,7 @@
this.field_71451_h = null;
this.field_71453_ak = null;
+ FMLClientHandler.instance().currentConnection(null, p_71353_1_ == null);
if (this.field_71461_s != null)
{

View file

@ -123,8 +123,6 @@ public class FMLClientHandler implements IFMLSidedHandler
private Map<String, IResourcePack> resourcePackMap;
private NetworkManager networkConnection;
/**
* Called to start the whole game off
*
@ -571,11 +569,6 @@ public class FMLClientHandler implements IFMLSidedHandler
@Override
public NetworkManager getClientToServerNetworkManager()
{
return this.networkConnection;
}
public void currentConnection(NetworkManager networkManager, boolean shouldChange)
{
if (shouldChange) this.networkConnection = networkManager;
return this.client.func_147114_u()!=null ? this.client.func_147114_u().func_147298_b() : null;
}
}

View file

@ -61,7 +61,7 @@ import cpw.mods.fml.common.event.FMLServerStartedEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.event.FMLServerStoppedEvent;
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
import cpw.mods.fml.common.network.FMLNetworkHandler;
import cpw.mods.fml.common.network.NetworkRegistry;
import cpw.mods.fml.common.versioning.ArtifactVersion;
import cpw.mods.fml.common.versioning.DefaultArtifactVersion;
import cpw.mods.fml.common.versioning.VersionParser;
@ -494,6 +494,7 @@ public class FMLModContainer implements ModContainer
Method factoryMethod = gatherAnnotations(clazz);
modInstance = getLanguageAdapter().getNewInstance(this,clazz, modClassLoader, factoryMethod);
NetworkRegistry.INSTANCE.register(this, clazz, (String)(descriptor.containsKey("acceptableRemoteVersions") ? descriptor.get("acceptableRemoteVersions") : null), event.getASMHarvestedData());
if (fingerprintNotPresent)
{
eventBus.post(new FMLFingerprintViolationEvent(source.isDirectory(), source, ImmutableSet.copyOf(this.sourceFingerprints), expectedFingerprint));

View file

@ -29,8 +29,7 @@ import cpw.mods.fml.common.event.FMLServerStartedEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.event.FMLServerStoppedEvent;
import cpw.mods.fml.common.event.FMLServerStoppingEvent;
import cpw.mods.fml.common.network.IPacketHandler;
import cpw.mods.fml.common.network.NetworkMod;
import cpw.mods.fml.common.network.NetworkCheckHandler;
import cpw.mods.fml.common.registry.GameRegistry;
/**
@ -40,19 +39,12 @@ import cpw.mods.fml.common.registry.GameRegistry;
* at pre-defined times during the loading of the game, based on where you have applied the {@link EventHandler}
* annotation.
*
* This annotation is usually paired with a second annotation {@link NetworkMod}, which declares the
* network related properties of this mod.
*
* <p>This is a simple example of a Mod. It has the modId of "MyModId", the name of "My example mod", it is
* version 1.0, and depends on FML being loaded. It has the {@link NetworkMod} annotation as well, declaring it uses channel
* "MyModChannel" and {@link IPacketHandler} class PacketHandler.
* version 1.0, and depends on FML being loaded.
* <pre>{@code
* package mymod;
* // Declare that this is a mod with modId "MyModId", name "My example mod", version "1.0" and dependency on FML.
* {@literal @}Mod(modId="MyModId",name="My example mod",version="1.0",dependencies="required-after:FML")
* // Declare that this is a network mod using the {@link Packet250CustomPayload} channel "MyModChannel", required on the client if it's present
* // on the server, with {@link IPacketHandler} class PacketHandler.
* {@literal @}NetworkMod(channels = { "MyModChannel" }, clientSideRequired = true, serverSideRequired = false, packetHandler = PacketHandler.class)
* public class MyMod {
* // Populate this field with the instance of the mod created by FML
* {@literal @}Instance("MyModId")
@ -103,6 +95,16 @@ public @interface Mod
* @return A version range as specified by the maven version range specification or the empty string
*/
String acceptedMinecraftVersions() default "";
/**
* A replacement for the no-longer-existing "versionRange" of NetworkMod. Specify a remote version range
* that this mod will accept as valid. Defaults to nothing, which is interpreted as "only this version".
* Another special value is '*' which means accept all versions.
*
* This is ignored if there is a {@link NetworkCheckHandler} annotation on a method in this class.
*
* @return
*/
String acceptableRemoteVersions() default "";
/**
* An optional bukkit plugin that will be injected into the bukkit plugin framework if
* this mod is loaded into the FML framework and the bukkit coremod is present.

View file

@ -1,23 +0,0 @@
package cpw.mods.fml.common.network;
import cpw.mods.fml.common.network.NetworkSide.ClientSide;
import net.minecraft.network.play.server.S3FPacketCustomPayload;
/**
* Handle packets <em>from</em> the server at the client.
*
* @author cpw
*
*/
public abstract class ClientSidePacketHandler implements IPacketHandler<ClientSide> {
@Override
public ClientSide side()
{
return NetworkSide.CLIENT;
}
/**
* Handle the custompayload packet
* @param packet
*/
public abstract void handleCustomPayload(S3FPacketCustomPayload packet);
}

View file

@ -32,7 +32,7 @@ public abstract class FMLIndexedMessageToMessageCodec<A> extends MessageToMessag
byte discriminator = types.get(clazz);
buffer.writeByte(discriminator);
encodeInto(ctx, msg, buffer);
FMLProxyPacket proxy = new FMLProxyPacket(buffer, ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get());
FMLProxyPacket proxy = new FMLProxyPacket(buffer.copy(), ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get());
out.add(proxy);
}

View file

@ -12,19 +12,28 @@
package cpw.mods.fml.common.network;
import org.apache.logging.log4j.core.helpers.Integers;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import cpw.mods.fml.common.network.handshake.NetworkDispatcher;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
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.Packet;
import net.minecraft.server.management.ServerConfigurationManager;
import net.minecraft.world.World;
import org.apache.logging.log4j.core.helpers.Integers;
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.NetworkDispatcher;
import cpw.mods.fml.relauncher.Side;
public class FMLNetworkHandler
{
public static final int READ_TIMEOUT = Integers.parseInt(System.getProperty("fml.readTimeout","30"),30);
@ -442,4 +451,27 @@ public class FMLNetworkHandler
return null;
}
public static String checkClientModList(ClientModList clientModList)
{
Map<String,String> modList = clientModList.modList();
List<ModContainer> rejects = Lists.newArrayList();
for (Entry<ModContainer, NetworkModHolder> networkMod : NetworkRegistry.INSTANCE.registry().entrySet())
{
boolean result = networkMod.getValue().check(modList, Side.CLIENT);
if (!result)
{
rejects.add(networkMod.getKey());
}
}
if (rejects.isEmpty())
{
return null;
}
else
{
FMLLog.info("Rejecting client : %s", rejects);
return String.format("Mod rejections %s",rejects);
}
}
}

View file

@ -1,11 +0,0 @@
package cpw.mods.fml.common.network;
/**
* Marker for packet handlers
* @author cpw
*
*/
public interface IPacketHandler<S extends NetworkSide> {
S side();
}

View file

@ -1,52 +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 cpw.mods.fml.common.network.NetworkSide.ClientSide;
import cpw.mods.fml.common.network.NetworkSide.ServerSide;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetworkManager;
/**
* Whenever a network connection is constructed, the appropriate factory method is called, once for each channel.
* Return null if you don't want a handler for a specific channel on a specific side.
*
* @author cpw
*
*/
public interface IPacketHandlerFactory
{
/**
* Return the list of channels this packet handler factory wants to claim
* @return a list of channels
*/
public String[] channels();
/**
* Return a client side packet handler for the specified channel or null if it is not handled on this side
*
* @param mod
* @param manager
* @param clientPlayHandler
* @param channel
* @return
*/
public IPacketHandler<ClientSide> makeClientPacketHandler(NetworkManager manager, INetHandler clientPlayHandler, String channel);
/**
* Return a server side packet handler for the specified channel or null if it is not handled on this side
* @param mod
* @param manager
* @param serverPlayHandler
* @return
*/
public IPacketHandler<ServerSide> makeServerPacketHandler(NetworkManager manager, INetHandler serverPlayHandler, String channel);
}

View file

@ -0,0 +1,6 @@
package cpw.mods.fml.common.network;
public @interface NetworkCheckHandler
{
}

View file

@ -1,58 +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.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import cpw.mods.fml.common.Mod;
/**
* {@link Mod} classes also adorned with this annotation are considered network capable mods.
* They require a {@link IPacketHandlerFactory} that will generate instances of packet handlers.
* They are version checked for compatibility between client and server. The default mechanism
* matches the {@link Mod#version()} on client and server. It can be overridden with either a
* {@link #versionBounds()} or a more complex {@link VersionCheckHandler}.
*
* @author cpw
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface NetworkMod
{
/**
* A packet handler implementation for channels registered through this annotation
* - this packet handler will be universal and handle both client and server
* requests.
*/
Class<? extends IPacketHandlerFactory> packetHandlerFactory();
/**
* An optional range check for client to server communication version compatibility.
*/
String versionBounds() default "";
/**
* A marker for a method that will be offered the client's version string
* if more sophisticated version rejection handling is required:
* The method should accept a "String" (the version) and return a boolean true
* if the version can be accepted.
* It can only be applied to the {@link NetworkMod} annotated class.
* @author cpw
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface VersionCheckHandler { }
}

View file

@ -13,6 +13,7 @@
package cpw.mods.fml.common.network;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
@ -25,71 +26,87 @@ 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 NetworkModHolder
{
private abstract class NetworkChecker {
public abstract boolean check(Map<String,String> remoteVersions, Side side);
}
private class DefaultNetworkChecker extends NetworkChecker {
@Override
public boolean check(Map<String,String> remoteVersions, Side side)
{
return acceptVersion(remoteVersions.get(container.getModId()));
}
}
private class MethodNetworkChecker extends NetworkChecker {
@Override
public boolean check(Map<String,String> remoteVersions, Side side)
{
try
{
return (Boolean) checkHandler.invoke(container, remoteVersions, side);
}
catch (Exception e)
{
FMLLog.log(Level.SEVERE, e, "Error occurred invoking NetworkCheckHandler %s at %s", checkHandler.getName(), container);
return false;
}
}
}
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;
private NetworkChecker checker;
public NetworkModHolder(ModContainer container, NetworkMod modAnnotation)
public NetworkModHolder(ModContainer container)
{
this.container = container;
this.mod = modAnnotation;
this.localId = assignedIds++;
this.networkId = this.localId;
}
public NetworkModHolder(ModContainer container, Class<?> networkModClass, ASMDataTable table)
public NetworkModHolder(ModContainer container, Class<?> modClass, String acceptableVersionRange, 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;
this(container);
Set<ASMData> versionCheckHandlers = table.getAnnotationsFor(container).get(NetworkCheckHandler.class.getName());
String networkCheckHandlerMethod = null;
for (ASMData vch : versionCheckHandlers)
{
if (vch.getClassName().equals(networkModClass.getName()))
if (vch.getClassName().equals(modClass.getName()))
{
versionCheckHandlerMethod = vch.getObjectName();
versionCheckHandlerMethod = versionCheckHandlerMethod.substring(0,versionCheckHandlerMethod.indexOf('('));
networkCheckHandlerMethod = vch.getObjectName();
networkCheckHandlerMethod = networkCheckHandlerMethod.substring(0,networkCheckHandlerMethod.indexOf('('));
break;
}
}
if (versionCheckHandlerMethod != null)
if (networkCheckHandlerMethod != null)
{
try
{
Method checkHandlerMethod = networkModClass.getDeclaredMethod(versionCheckHandlerMethod, String.class);
if (checkHandlerMethod.isAnnotationPresent(NetworkMod.VersionCheckHandler.class))
Method checkHandlerMethod = modClass.getDeclaredMethod(networkCheckHandlerMethod, Map.class, Side.class);
if (checkHandlerMethod.isAnnotationPresent(NetworkCheckHandler.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());
FMLLog.log(Level.WARNING, e, "The declared version check handler method %s on network mod id %s is not accessible", networkCheckHandlerMethod, container.getModId());
}
}
configureNetworkMod(container);
}
protected void configureNetworkMod(ModContainer container)
{
if (this.checkHandler == null)
{
String versionBounds = mod.versionBounds();
String versionBounds = acceptableVersionRange;
if (!Strings.isNullOrEmpty(versionBounds))
{
try
@ -113,23 +130,12 @@ public class NetworkModHolder
{
FMLLog.finest("The mod %s accepts its own version (%s)", container.getModId(), container.getVersion());
}
this.checker = checkHandler == null ? new DefaultNetworkChecker() : new MethodNetworkChecker();
}
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));
@ -138,6 +144,11 @@ public class NetworkModHolder
return container.getVersion().equals(version);
}
public boolean check(Map<String,String> data, Side side)
{
return checker.check(data, side);
}
public int getLocalId()
{
return localId;
@ -153,16 +164,6 @@ public class NetworkModHolder
return container;
}
public NetworkMod getMod()
{
return mod;
}
public boolean isNetworkMod()
{
return mod != null;
}
public void setNetworkId(int value)
{
this.networkId = value;

View file

@ -26,6 +26,7 @@ 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;
@ -35,6 +36,7 @@ import com.google.common.collect.Maps;
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.network.handshake.NetworkDispatcher;
import cpw.mods.fml.relauncher.Side;
@ -46,6 +48,7 @@ public enum NetworkRegistry
{
INSTANCE;
private EnumMap<Side,Map<String,FMLEmbeddedChannel>> channels = Maps.newEnumMap(Side.class);
private Map<ModContainer, NetworkModHolder> registry = Maps.newHashMap();
private Map<ModContainer, IGuiHandler> serverGuiHandlers = Maps.newHashMap();
private Map<ModContainer, IGuiHandler> clientGuiHandlers = Maps.newHashMap();
@ -504,4 +507,15 @@ public enum NetworkRegistry
{
return channels.get(source).containsKey(channelName);
}
public void register(ModContainer fmlModContainer, Class<?> clazz, String remoteVersionRange, ASMDataTable asmHarvestedData)
{
NetworkModHolder networkModHolder = new NetworkModHolder(fmlModContainer, clazz, remoteVersionRange, asmHarvestedData);
registry.put(fmlModContainer, networkModHolder);
}
Map<ModContainer,NetworkModHolder> registry()
{
return registry;
}
}

View file

@ -1,20 +0,0 @@
package cpw.mods.fml.common.network;
import net.minecraft.network.play.client.C17PacketCustomPayload;
import cpw.mods.fml.common.network.NetworkSide.ServerSide;
/**
* Handle packets <em>from</em> the client at the server.
*
* @author cpw
*
*/
public abstract class ServerSidePacketHandler implements IPacketHandler<ServerSide> {
@Override
public ServerSide side()
{
return NetworkSide.SERVER;
}
public abstract void handleCustomPayload(C17PacketCustomPayload packet);
}

View file

@ -1,12 +1,8 @@
package cpw.mods.fml.common.network.handshake;
import java.util.List;
import io.netty.channel.ChannelHandlerContext;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.NetworkRegistry;
enum FMLHandshakeClientState implements IHandshakeState<FMLHandshakeClientState>
{

View file

@ -3,8 +3,11 @@ package cpw.mods.fml.common.network.handshake;
import io.netty.buffer.ByteBuf;
import java.util.List;
import java.util.Map;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import cpw.mods.fml.common.ModContainer;
import cpw.mods.fml.common.network.ByteBufUtils;
@ -80,20 +83,20 @@ public abstract class FMLHandshakeMessage {
{
for (ModContainer mod : modList)
{
modTags.add(new String[] { mod.getModId(), mod.getVersion() });
modTags.put(mod.getModId(), mod.getVersion());
}
}
private List<String[]> modTags = Lists.newArrayList();
private Map<String,String> modTags = Maps.newHashMap();
@Override
public void toBytes(ByteBuf buffer)
{
super.toBytes(buffer);
ByteBufUtils.writeVarInt(buffer, modTags.size(), 2);
for (String[] modTag: modTags)
for (Map.Entry<String,String> modTag: modTags.entrySet())
{
ByteBufUtils.writeUTF8String(buffer, modTag[0]);
ByteBufUtils.writeUTF8String(buffer, modTag[1]);
ByteBufUtils.writeUTF8String(buffer, modTag.getKey());
ByteBufUtils.writeUTF8String(buffer, modTag.getValue());
}
}
@ -104,28 +107,23 @@ public abstract class FMLHandshakeMessage {
int modCount = ByteBufUtils.readVarInt(buffer, 2);
for (int i = 0; i < modCount; i++)
{
modTags.add(new String[] { ByteBufUtils.readUTF8String(buffer), ByteBufUtils.readUTF8String(buffer)});
modTags.put(ByteBufUtils.readUTF8String(buffer), ByteBufUtils.readUTF8String(buffer));
}
}
public String modListAsString()
{
StringBuffer sb = new StringBuffer();
sb.append("[ ");
for (int i = 0; i < modTags.size(); i++)
{
String[] mod = modTags.get(i);
sb.append(mod[0]).append("@").append(mod[1]);
if (i < modTags.size() - 1) sb.append(", ");
}
sb.append(" ]");
return sb.toString();
return Joiner.on(',').withKeyValueSeparator("@").join(modTags);
}
public int modListSize()
{
return modTags.size();
}
public Map<String, String> modList()
{
return modTags;
}
}
public static class ClientAck extends FMLHandshakeMessage {

View file

@ -2,6 +2,7 @@ package cpw.mods.fml.common.network.handshake;
import io.netty.channel.ChannelHandlerContext;
import cpw.mods.fml.common.FMLLog;
import cpw.mods.fml.common.network.FMLNetworkHandler;
enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
{
@ -29,7 +30,14 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
}
FMLHandshakeMessage.ClientModList client = (FMLHandshakeMessage.ClientModList)msg;
FMLLog.info("Client joining 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);
if (result != null)
{
NetworkDispatcher dispatcher = ctx.channel().attr(NetworkDispatcher.FML_DISPATCHER).get();
dispatcher.rejectHandshake(result);
return ERROR;
}
ctx.writeAndFlush(new FMLHandshakeMessage.ServerModList());
return COMPLETE;
}
@ -44,5 +52,13 @@ enum FMLHandshakeServerState implements IHandshakeState<FMLHandshakeServerState>
dispatcher.continueToServerPlayState();
return this;
}
},
ERROR
{
@Override
public FMLHandshakeServerState accept(ChannelHandlerContext ctx, FMLHandshakeMessage msg)
{
return this;
}
};
}

View file

@ -164,6 +164,11 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
{
handled = handleClientSideCustomPacket((S3FPacketCustomPayload)msg, ctx);
}
else if (msg instanceof S40PacketDisconnect && state != ConnectionState.CONNECTED)
{
// Switch to play state to handle the disconnect message
continueToClientPlayState();
}
else if (state != ConnectionState.CONNECTED)
{
FMLLog.info("Unexpected packet during modded negotiation - assuming vanilla");
@ -187,7 +192,11 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
private void kickVanilla()
{
final ChatComponentText chatcomponenttext = new ChatComponentText("This is modded. No modded response received. Bye!");
kickWithMessage("This is modded. No modded response received. Bye!");
}
private void kickWithMessage(String message)
{
final ChatComponentText chatcomponenttext = new ChatComponentText(message);
manager.func_150725_a(new S40PacketDisconnect(chatcomponenttext), new GenericFutureListener<Future<?>>()
{
public void operationComplete(Future<?> result)
@ -282,4 +291,9 @@ public class NetworkDispatcher extends SimpleChannelInboundHandler<Packet> {
else
manager.func_150725_a(msg.toS3FPacket());
}
public void rejectHandshake(String result)
{
kickWithMessage(result);
}
}