Handle differing network versions for FML gracefully?

Signed-off-by: cpw <cpw+github@weeksfamily.ca>
This commit is contained in:
cpw committed 2019-02-28 00:59:27 -05:00
1 parent 7f1ea578d6
commit cb70702ab5
8 files changed
+52 -37

No files matched your search

@@ -19,23 +19,23 @@
package net.minecraftforge.fml.network;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Function;
public enum ConnectionType
{
MODDED(NetworkHooks.NETVERSION), VANILLA(NetworkHooks.NOVERSION);
MODDED(s->Integer.valueOf(s.substring(FMLNetworkConstants.FMLNETMARKER.length()))), VANILLA(s->0);
private final String versionString;
private final Function<String, Integer> versionExtractor;
ConnectionType(String versionString)
{
this.versionString = versionString;
ConnectionType(Function<String, Integer> versionExtractor) {
this.versionExtractor = versionExtractor;
}
public static ConnectionType forVersionFlag(String vers)
{
return Arrays.stream(values()).filter(ct->Objects.equals(ct.versionString, vers)).
findFirst().orElse(ConnectionType.VANILLA);
return vers.startsWith(FMLNetworkConstants.FMLNETMARKER) ? MODDED : VANILLA;
}
public int getFMLVersionNumber(final String fmlVersion) {
return versionExtractor.apply(fmlVersion);
}
}
@@ -72,7 +72,7 @@ import static net.minecraftforge.registries.ForgeRegistry.REGISTRIES;
* final login phase will commence.
*/
public class FMLHandshakeHandler {
static final Marker FMLHSMARKER = MarkerManager.getMarker("FMLHANDSHAKE").setParents(FMLNetworking.NETWORK);
static final Marker FMLHSMARKER = MarkerManager.getMarker("FMLHANDSHAKE").setParents(FMLNetworkConstants.NETWORK);
private static final Logger LOGGER = LogManager.getLogger();
static final ResourceLocation FML_HANDSHAKE_RESOURCE = new ResourceLocation("fml:handshake");
private static final AttributeKey<FMLHandshakeHandler> FML_HANDSHAKE_HANDLER_ATTRIBUTE_KEY = AttributeKey.newInstance("fml:handshake");
@@ -83,7 +83,7 @@ public class FMLHandshakeHandler {
channel = NetworkRegistry.ChannelBuilder.named(FML_HANDSHAKE_RESOURCE).
clientAcceptedVersions(a -> true).
serverAcceptedVersions(a -> true).
networkProtocolVersion(() -> NetworkHooks.NETVERSION).
networkProtocolVersion(() -> FMLNetworkConstants.NETVERSION).
simpleChannel();
channel.messageBuilder(FMLHandshakeMessages.C2SAcknowledge.class, 99).
loginIndex(FMLHandshakeMessages.LoginIndexedMessage::getLoginIndex, FMLHandshakeMessages.LoginIndexedMessage::setLoginIndex).
@@ -208,7 +208,7 @@ public class FMLHandshakeHandler {
channel.reply(reply, c.get());
LOGGER.debug(FMLHSMARKER, "Accepted server connection");
// Set the modded marker on the channel so we know we got packets
c.get().getNetworkManager().channel().attr(FMLNetworking.FML_MARKER).set(NetworkHooks.NETVERSION);
c.get().getNetworkManager().channel().attr(FMLNetworkConstants.FML_MARKER).set(FMLNetworkConstants.NETVERSION);
this.registriesToReceive = new HashSet<>(serverModList.getRegistries());
LOGGER.debug(REGISTRIES, "Expecting {} registries: {}", ()->this.registriesToReceive.size(), ()->this.registriesToReceive);
}
@@ -41,7 +41,7 @@ public class FMLLoginWrapper {
wrapperChannel = NetworkRegistry.ChannelBuilder.named(FMLLoginWrapper.WRAPPER).
clientAcceptedVersions(a->true).
serverAcceptedVersions(a->true).
networkProtocolVersion(()->NetworkHooks.NETVERSION)
networkProtocolVersion(()-> FMLNetworkConstants.NETVERSION)
.eventNetworkChannel();
wrapperChannel.addListener(this::wrapperReceived);
}
@@ -23,8 +23,15 @@ import io.netty.util.AttributeKey;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
public class FMLNetworking
/**
* Constants related to networking
*/
public class FMLNetworkConstants
{
public static final String FMLNETMARKER = "FML";
public static final int FMLNETVERSION = 1;
public static final String NETVERSION = FMLNETMARKER + FMLNETVERSION;
public static final String NOVERSION = "NONE";
static final Marker NETWORK = MarkerManager.getMarker("FMLNETWORK");
static final AttributeKey<String> FML_MARKER = AttributeKey.valueOf("fml:marker");
}
@@ -28,7 +28,7 @@ public class FMLPlayHandler
.named(new ResourceLocation("fml", "play"))
.clientAcceptedVersions(a -> true)
.serverAcceptedVersions(a -> true)
.networkProtocolVersion(() -> NetworkHooks.NETVERSION)
.networkProtocolVersion(() -> FMLNetworkConstants.NETVERSION)
.simpleChannel();
static
{
@@ -44,22 +44,15 @@ import java.util.function.Supplier;
public class NetworkHooks
{
private static final Logger LOGGER = LogManager.getLogger();
public static final String NETVERSION = "FML1";
public static final String NOVERSION = "NONE";
public static String getFMLVersion(final String ip)
{
return ip.contains("\0") ? Objects.equals(ip.split("\0")[1], NETVERSION) ? NETVERSION : ip.split("\0")[1] : NOVERSION;
}
public static boolean accepts(final CPacketHandshake packet)
{
return Objects.equals(packet.getFMLVersion(), NETVERSION) || NetworkRegistry.acceptsVanillaClientConnections();
return ip.contains("\0") ? Objects.equals(ip.split("\0")[1], FMLNetworkConstants.NETVERSION) ? FMLNetworkConstants.NETVERSION : ip.split("\0")[1] : FMLNetworkConstants.NOVERSION;
}
public static ConnectionType getConnectionType(final Supplier<NetworkManager> connection)
{
return ConnectionType.forVersionFlag(connection.get().channel().attr(FMLNetworking.FML_MARKER).get());
return ConnectionType.forVersionFlag(connection.get().channel().attr(FMLNetworkConstants.FML_MARKER).get());
}
public static Packet<?> getEntitySpawningPacket(Entity entity)
@@ -78,14 +71,14 @@ public class NetworkHooks
public static void registerServerLoginChannel(NetworkManager manager, CPacketHandshake packet)
{
manager.channel().attr(FMLNetworking.FML_MARKER).set(packet.getFMLVersion());
manager.channel().attr(FMLNetworkConstants.FML_MARKER).set(packet.getFMLVersion());
FMLHandshakeHandler.registerHandshake(manager, NetworkDirection.LOGIN_TO_CLIENT);
}
public static void registerClientLoginChannel(NetworkManager manager)
{
if (manager == null || manager.channel() == null) return;
manager.channel().attr(FMLNetworking.FML_MARKER).set(NOVERSION);
manager.channel().attr(FMLNetworkConstants.FML_MARKER).set(FMLNetworkConstants.NOVERSION);
FMLHandshakeHandler.registerHandshake(manager, NetworkDirection.LOGIN_TO_SERVER);
}
@@ -68,7 +68,7 @@ public class NetworkRegistry
return listRejectedVanillaMods(NetworkInstance::tryClientVersionOnServer);
}
static boolean acceptsVanillaClientConnections() {
public static boolean acceptsVanillaClientConnections() {
return instances.isEmpty() || getNonVanillaNetworkMods().isEmpty();
}
@@ -37,7 +37,10 @@ import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppedEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.loading.FileUtils;
import net.minecraftforge.fml.network.ConnectionType;
import net.minecraftforge.fml.network.FMLNetworkConstants;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.packs.ResourcePackLoader;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -120,15 +123,19 @@ public class ServerLifecycleHooks
return false;
}
if (packet.getRequestedState() == EnumConnectionState.LOGIN && !NetworkHooks.accepts(packet))
{
manager.setConnectionState(EnumConnectionState.LOGIN);
TextComponentString text = new TextComponentString("This server has mods that require Forge to be installed on the client. Contact your server admin for more details.");
List<String> modNames = net.minecraftforge.fml.network.NetworkRegistry.getNonVanillaNetworkMods();
LOGGER.info(SERVERHOOKS,"Disconnecting vanilla connection attempt. Required mods {}", modNames);
manager.sendPacket(new SPacketDisconnectLogin(text));
manager.closeChannel(text);
return false;
if (packet.getRequestedState() == EnumConnectionState.LOGIN) {
final ConnectionType connectionType = ConnectionType.forVersionFlag(packet.getFMLVersion());
final int versionNumber = connectionType.getFMLVersionNumber(packet.getFMLVersion());
if (connectionType == ConnectionType.MODDED && versionNumber != FMLNetworkConstants.FMLNETVERSION) {
rejectConnection(manager, connectionType, "This modded server is not network compatible with your modded client. Please verify your Forge version closely matches the server. Got net version "+ versionNumber + " this server is net version "+FMLNetworkConstants.FMLNETVERSION);
return false;
}
if (connectionType == ConnectionType.VANILLA && !NetworkRegistry.acceptsVanillaClientConnections()) {
rejectConnection(manager, connectionType, "This server has mods that require Forge to be installed on the client. Contact your server admin for more details.");
return false;
}
}
if (packet.getRequestedState() == EnumConnectionState.STATUS) return true;
@@ -138,6 +145,14 @@ public class ServerLifecycleHooks
}
private static void rejectConnection(final NetworkManager manager, ConnectionType type, String message) {
manager.setConnectionState(EnumConnectionState.LOGIN);
LOGGER.info(SERVERHOOKS, "Disconnecting {} connection attempt: ", type, message);
TextComponentString text = new TextComponentString(message);
manager.sendPacket(new SPacketDisconnectLogin(text));
manager.closeChannel(text);
}
public static void handleExit(int retVal)
{
/*