diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index 88b13e5..2480dfe 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -96,7 +96,6 @@ public class Ambassador { Path configPath = dataDirectory.resolve("Ambassador.toml"); config = AmbassadorConfig.read(configPath); - config.validate(); inject(); @@ -111,7 +110,6 @@ public class Ambassador { try { Path configPath = dataDirectory.resolve("Ambassador.toml"); final AmbassadorConfig newconfig = AmbassadorConfig.read(configPath); - newconfig.validate(); config = newconfig; } catch (Exception e) { diff --git a/src/main/java/org/adde0109/ambassador/AmbassadorConfig.java b/src/main/java/org/adde0109/ambassador/AmbassadorConfig.java index 677dcd0..6eddaf6 100644 --- a/src/main/java/org/adde0109/ambassador/AmbassadorConfig.java +++ b/src/main/java/org/adde0109/ambassador/AmbassadorConfig.java @@ -7,36 +7,31 @@ import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; +import java.io.IOException; import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; public class AmbassadorConfig { - @Expose - private String disconnectResetMessage = "Please reconnect"; - - @Expose - private int serverSwitchCancellationTime = 120; + private int serverSwitchCancellationTime = 30; @Expose private boolean silenceWarnings = false; - private net.kyori.adventure.text.@MonotonicNonNull Component messageAsAsComponent; + @Expose + private boolean bypassRegistryCheck = false; + @Expose + private boolean bypassModCheck = false; - private AmbassadorConfig(String kickResetMessage, int serverSwitchCancellationTime, boolean silenceWarnings) { - this.disconnectResetMessage = kickResetMessage; - this.serverSwitchCancellationTime = serverSwitchCancellationTime; + private AmbassadorConfig(boolean silenceWarnings, boolean bypassRegistryCheck, boolean bypassModCheck) { this.silenceWarnings = silenceWarnings; + this.bypassRegistryCheck = bypassRegistryCheck; + this.bypassModCheck = bypassModCheck; }; - public void validate() { - if (serverSwitchCancellationTime <= 0) { - throw new InvalidValueException("'server-switch-cancellation-time' can't be less than nor equal to zero: server-switch-cancellation-time=" + serverSwitchCancellationTime); - } - } - - public static AmbassadorConfig read(Path path) { + public static AmbassadorConfig read(Path path) throws IOException { URL defaultConfigLocation = AmbassadorConfig.class.getClassLoader() .getResource("default-ambassador.toml"); if (defaultConfigLocation == null) { @@ -58,28 +53,28 @@ public class AmbassadorConfig { configVersion = 1.0; } - if (configVersion < 1.1) { - config.set("silence-warnings", false); - config.set("config-version", "1.2"); - } - - String kickResetMessage = config.getOrElse("disconnect-reset-message", "Please reconnect"); - int serverSwitchCancellationTime = config.getIntOrElse("server-switch-cancellation-time", 120); - boolean silenceWarnings = config.getOrElse("silence-warnings", false); - return new AmbassadorConfig(kickResetMessage, serverSwitchCancellationTime, silenceWarnings); - } - - public net.kyori.adventure.text.Component getDisconnectResetMessage() { - if (messageAsAsComponent == null) { - if (disconnectResetMessage.startsWith("{")) { - messageAsAsComponent = GsonComponentSerializer.gson().deserialize(disconnectResetMessage); - } else { - messageAsAsComponent = LegacyComponentSerializer.legacyAmpersand().deserialize(disconnectResetMessage); - } + //Upgrade config + if (configVersion <= 1.2) { + Files.delete(path); + config = CommentedFileConfig.builder(path) + .defaultData(defaultConfigLocation) + .autosave() + .preserveInsertionOrder() + .sync() + .build(); + config.load(); + config.set("silence-warnings", silenceWarnings); } - return messageAsAsComponent; + + int serverSwitchCancellationTime = config.getOrElse("serverRedirectTimeout", 30); + + boolean bypassRegistryCheck = config.getOrElse("bypass-registry-checks", false); + + boolean bypassModCheck = config.getOrElse("bypass-mod-checks", false); + + return new AmbassadorConfig(bypassRegistryCheck, bypassModCheck, silenceWarnings); } public int getServerSwitchCancellationTime() { @@ -89,4 +84,12 @@ public class AmbassadorConfig { public boolean isSilenceWarnings() { return silenceWarnings; } + + public boolean isBypassRegistryCheck() { + return bypassRegistryCheck; + } + + public boolean isBypassModCheck() { + return bypassModCheck; + } } diff --git a/src/main/java/org/adde0109/ambassador/forge/VelocityForgeBackendConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/VelocityForgeBackendConnectionPhase.java index b1bc920..d3afe91 100644 --- a/src/main/java/org/adde0109/ambassador/forge/VelocityForgeBackendConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/VelocityForgeBackendConnectionPhase.java @@ -8,6 +8,7 @@ import com.velocitypowered.proxy.network.Connections; import com.velocitypowered.proxy.protocol.ProtocolUtils; import com.velocitypowered.proxy.protocol.packet.AvailableCommands; import com.velocitypowered.proxy.protocol.packet.PluginMessage; +import org.adde0109.ambassador.Ambassador; import org.adde0109.ambassador.forge.packet.*; import org.adde0109.ambassador.forge.pipeline.CommandDecoderErrorCatcher; @@ -91,7 +92,8 @@ public enum VelocityForgeBackendConnectionPhase implements BackendConnectionPhas throw new RuntimeException(e); } }).thenAcceptAsync((v) -> { - if (clientPhase.forgeHandshake.isCompatible(handshake)) { + if (Ambassador.getInstance().config.isBypassRegistryCheck() || + clientPhase.forgeHandshake.isCompatible(handshake)) { server.ensureConnected().write(clientPhase.forgeHandshake.getModListReplyPacket()); } else { server.disconnect(); diff --git a/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java index 2548ccc..b7f7989 100644 --- a/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java @@ -141,8 +141,6 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase buf.writeBytes((player.getVirtualHost().get().getHostName() + ":" + player.getVirtualHost().get().getPort()).getBytes(StandardCharsets.UTF_8)); player.getConnection().write(new PluginMessage("srvredirect:red", buf)); - } else { - player.disconnect(Ambassador.getInstance().config.getDisconnectResetMessage()); } } diff --git a/src/main/resources/default-ambassador.toml b/src/main/resources/default-ambassador.toml index 4c14918..3a24bec 100644 --- a/src/main/resources/default-ambassador.toml +++ b/src/main/resources/default-ambassador.toml @@ -1,9 +1,18 @@ # Do not change this -config-version = "1.1" +config-version = "2.0" -# Message displayed to the player when disconnected from proxy during server switch. -# Legacy color codes and JSON are accepted. -disconnect-reset-message = "&6Please reconnect" # How much time the player has to reconnect before canceling the server switch. (In seconds) -server-switch-cancellation-time = 120 +# Only for players with ServerRedirect mod installed. Set to -1 to disable ServerRedirect mod support. +serverRedirectTimeout = 30 + +# Silence PCF absence warnings. silence-warnings = false + +# Allow server switches without reset even though the new server's registries don't match the old server’s registry. +# Large modpacks often needs this set to true. Warning: This is a safety measure and setting this to true +# can lead to unstable behaviour. +bypass-registry-checks = false + +# Allow player to switch without reset when the server's mods don't match. Even more unstable than bypassRegistryCheck. +# Warning: This is a safety measure for when bypassRegistryCheck is true. Setting this to also true can cause crashes. +bypass-mod-checks = false \ No newline at end of file