diff --git a/src/main/java/net/minecraftforge/fml/network/ConnectionType.java b/src/main/java/net/minecraftforge/fml/network/ConnectionType.java index ee209e688b..c4379085ea 100644 --- a/src/main/java/net/minecraftforge/fml/network/ConnectionType.java +++ b/src/main/java/net/minecraftforge/fml/network/ConnectionType.java @@ -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 versionExtractor; - ConnectionType(String versionString) - { - this.versionString = versionString; + ConnectionType(Function 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); } } diff --git a/src/main/java/net/minecraftforge/fml/network/FMLHandshakeHandler.java b/src/main/java/net/minecraftforge/fml/network/FMLHandshakeHandler.java index 249cc0b619..a5456fe7df 100644 --- a/src/main/java/net/minecraftforge/fml/network/FMLHandshakeHandler.java +++ b/src/main/java/net/minecraftforge/fml/network/FMLHandshakeHandler.java @@ -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 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); } diff --git a/src/main/java/net/minecraftforge/fml/network/FMLLoginWrapper.java b/src/main/java/net/minecraftforge/fml/network/FMLLoginWrapper.java index 4f868b3d61..d282839d29 100644 --- a/src/main/java/net/minecraftforge/fml/network/FMLLoginWrapper.java +++ b/src/main/java/net/minecraftforge/fml/network/FMLLoginWrapper.java @@ -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); } diff --git a/src/main/java/net/minecraftforge/fml/network/FMLNetworking.java b/src/main/java/net/minecraftforge/fml/network/FMLNetworkConstants.java similarity index 78% rename from src/main/java/net/minecraftforge/fml/network/FMLNetworking.java rename to src/main/java/net/minecraftforge/fml/network/FMLNetworkConstants.java index 539cb43e2d..e1ccc1c261 100644 --- a/src/main/java/net/minecraftforge/fml/network/FMLNetworking.java +++ b/src/main/java/net/minecraftforge/fml/network/FMLNetworkConstants.java @@ -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 FML_MARKER = AttributeKey.valueOf("fml:marker"); } diff --git a/src/main/java/net/minecraftforge/fml/network/FMLPlayHandler.java b/src/main/java/net/minecraftforge/fml/network/FMLPlayHandler.java index 5125c76f52..052f03e1ff 100644 --- a/src/main/java/net/minecraftforge/fml/network/FMLPlayHandler.java +++ b/src/main/java/net/minecraftforge/fml/network/FMLPlayHandler.java @@ -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 { diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java b/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java index 630add73c9..f76e9e812d 100644 --- a/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkHooks.java @@ -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 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); } diff --git a/src/main/java/net/minecraftforge/fml/network/NetworkRegistry.java b/src/main/java/net/minecraftforge/fml/network/NetworkRegistry.java index e06a6a9458..1ec2699200 100644 --- a/src/main/java/net/minecraftforge/fml/network/NetworkRegistry.java +++ b/src/main/java/net/minecraftforge/fml/network/NetworkRegistry.java @@ -68,7 +68,7 @@ public class NetworkRegistry return listRejectedVanillaMods(NetworkInstance::tryClientVersionOnServer); } - static boolean acceptsVanillaClientConnections() { + public static boolean acceptsVanillaClientConnections() { return instances.isEmpty() || getNonVanillaNetworkMods().isEmpty(); } diff --git a/src/main/java/net/minecraftforge/fml/server/ServerLifecycleHooks.java b/src/main/java/net/minecraftforge/fml/server/ServerLifecycleHooks.java index 0a0bbd38fd..b621efaa90 100644 --- a/src/main/java/net/minecraftforge/fml/server/ServerLifecycleHooks.java +++ b/src/main/java/net/minecraftforge/fml/server/ServerLifecycleHooks.java @@ -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 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) { /*