From 016f3ad029d76b4a184e535333a9989b44f2891e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ZX=E5=A4=8F=E5=A4=9C=E4=B9=8B=E9=A3=8E?= Date: Sat, 8 Nov 2025 23:12:42 +0800 Subject: [PATCH 1/3] fix: cache registered channels separately to prevent mod list from being overwritten --- .../java/org/adde0109/ambassador/Ambassador.java | 13 +++++++++++++ .../forge/VelocityForgeClientConnectionPhase.java | 4 ++-- .../ambassador/velocity/VelocityEventHandler.java | 11 +++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index d3748fd..6bda7e9 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -1,5 +1,7 @@ package org.adde0109.ambassador; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; import com.google.inject.Inject; import com.velocitypowered.api.event.PostOrder; import com.velocitypowered.api.event.Subscribe; @@ -14,8 +16,10 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.nio.file.Files; import java.util.HashMap; +import java.util.List; import java.util.Map; +import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.connection.MinecraftConnection; @@ -60,6 +64,15 @@ public class Ambassador { public AmbassadorConfig config; private static final MapWithExpiration TEMPORARY_FORCED = new MapWithExpiration<>(); + private static final ListMultimap PLAYER_REGISTERED_CHANNELS = ArrayListMultimap.create(); + + public List getPlayerRegisteredChannels(String username) { + return PLAYER_REGISTERED_CHANNELS.get(username); + } + + public void removePlayerRegisteredChannels(String username) { + PLAYER_REGISTERED_CHANNELS.removeAll(username); + } private static Ambassador instance; public static Ambassador getInstance() { diff --git a/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java index 6b065c8..2ee2fe2 100644 --- a/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java @@ -198,8 +198,8 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase if (player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("clientresetpacket")))) { return ClientResetType.CRP; } else if (Ambassador.getInstance().config.getServerSwitchCancellationTime() >= 0 && - player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("serverredirect") - || mod.getId().equals("srvredirect:red"))) + (player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("serverredirect"))) + || Ambassador.getInstance().getPlayerRegisteredChannels(player.getUsername()).stream().anyMatch(identifier -> identifier.getId().equals("srvredirect:red"))) && player.getVirtualHost().isPresent()) { return ClientResetType.SR; } diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java index ac5301f..5fc6fea 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java @@ -3,6 +3,7 @@ package org.adde0109.ambassador.velocity; import com.velocitypowered.api.event.Continuation; import com.velocitypowered.api.event.PostOrder; import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.DisconnectEvent; import com.velocitypowered.api.event.connection.PostLoginEvent; import com.velocitypowered.api.event.player.*; import com.velocitypowered.api.proxy.server.RegisteredServer; @@ -68,9 +69,13 @@ public class VelocityEventHandler { if (!(player.getConnection().getType() instanceof ForgeFMLConnectionType)) { return; } + // Do not overwrite the mod info stored by the proxy or the server redirect based on Client Reset Packet will stop working + /* player.setModInfo(new ModInfo("Channels", event.getChannels().stream().map((id) -> { return new ModInfo.Mod(id.getId(), ""); }).toList())); + */ + Ambassador.getInstance().getPlayerRegisteredChannels(player.getUsername()).addAll(event.getChannels()); VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase(); //If reset typ is still unknown, set it! @@ -79,4 +84,10 @@ public class VelocityEventHandler { } } + // fixme remove unregistered channels when player channel unregister event is fired (that event does not exist?!) + + @Subscribe + public void onPlayerDisconnectEvent(DisconnectEvent event) { + Ambassador.getInstance().removePlayerRegisteredChannels(event.getPlayer().getUsername()); + } } From 6b6173951f2f52d609e78ee248251adc8de5bcc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ZX=E5=A4=8F=E5=A4=9C=E4=B9=8B=E9=A3=8E?= Date: Sun, 9 Nov 2025 11:21:25 +0800 Subject: [PATCH 2/3] fix: don't track client side channels by ourselves, use API from newer Velocity The plugin requires at least Velocity 3.0 build 490 now --- Velocity | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../org/adde0109/ambassador/Ambassador.java | 19 +++++-------------- .../VelocityForgeClientConnectionPhase.java | 2 +- .../velocity/VelocityEventHandler.java | 8 -------- 5 files changed, 8 insertions(+), 25 deletions(-) diff --git a/Velocity b/Velocity index c3583e1..b6b6b20 160000 --- a/Velocity +++ b/Velocity @@ -1 +1 @@ -Subproject commit c3583e182ca6585e40d1eef0da8c18547c0b1bc1 +Subproject commit b6b6b20fe97cd9cb0d6b4e817d3e7db72aca2d8d diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37aef8d..fa5602a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/org/adde0109/ambassador/Ambassador.java b/src/main/java/org/adde0109/ambassador/Ambassador.java index 6bda7e9..c27da55 100644 --- a/src/main/java/org/adde0109/ambassador/Ambassador.java +++ b/src/main/java/org/adde0109/ambassador/Ambassador.java @@ -54,7 +54,7 @@ import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdenti public class Ambassador { //Don't forget to update checkCompatibleVersion() when changing this value - private static final String minVelocityVersion = "velocity-3.3.0-SNAPSHOT-330"; + private static final String minVelocityVersion = "velocity-3.3.0-SNAPSHOT-490"; public ProxyServer server; public final Logger logger; @@ -64,15 +64,6 @@ public class Ambassador { public AmbassadorConfig config; private static final MapWithExpiration TEMPORARY_FORCED = new MapWithExpiration<>(); - private static final ListMultimap PLAYER_REGISTERED_CHANNELS = ArrayListMultimap.create(); - - public List getPlayerRegisteredChannels(String username) { - return PLAYER_REGISTERED_CHANNELS.get(username); - } - - public void removePlayerRegisteredChannels(String username) { - PLAYER_REGISTERED_CHANNELS.removeAll(username); - } private static Ambassador instance; public static Ambassador getInstance() { @@ -92,11 +83,11 @@ public class Ambassador { boolean checkCompatibleVersion() { //Update this when changing minVelocityVersion try { - Class.forName("com.velocitypowered.proxy.protocol.packet.DisconnectPacket"); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); + ConnectedPlayer.class.getMethod("getClientsideChannels"); + } catch (NoSuchMethodException e) { + return false; } - return true; + return true; } @Subscribe(order = PostOrder.LAST) diff --git a/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java b/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java index 2ee2fe2..11929f7 100644 --- a/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java +++ b/src/main/java/org/adde0109/ambassador/forge/VelocityForgeClientConnectionPhase.java @@ -199,7 +199,7 @@ public enum VelocityForgeClientConnectionPhase implements ClientConnectionPhase return ClientResetType.CRP; } else if (Ambassador.getInstance().config.getServerSwitchCancellationTime() >= 0 && (player.getModInfo().get().getMods().stream().anyMatch((mod -> mod.getId().equals("serverredirect"))) - || Ambassador.getInstance().getPlayerRegisteredChannels(player.getUsername()).stream().anyMatch(identifier -> identifier.getId().equals("srvredirect:red"))) + || player.getClientsideChannels().stream().anyMatch(identifier -> identifier.getId().equals("srvredirect:red"))) && player.getVirtualHost().isPresent()) { return ClientResetType.SR; } diff --git a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java index 5fc6fea..edd85f9 100644 --- a/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java +++ b/src/main/java/org/adde0109/ambassador/velocity/VelocityEventHandler.java @@ -75,7 +75,6 @@ public class VelocityEventHandler { return new ModInfo.Mod(id.getId(), ""); }).toList())); */ - Ambassador.getInstance().getPlayerRegisteredChannels(player.getUsername()).addAll(event.getChannels()); VelocityForgeClientConnectionPhase clientPhase = (VelocityForgeClientConnectionPhase) player.getPhase(); //If reset typ is still unknown, set it! @@ -83,11 +82,4 @@ public class VelocityEventHandler { clientPhase.updateResetType(player); } } - - // fixme remove unregistered channels when player channel unregister event is fired (that event does not exist?!) - - @Subscribe - public void onPlayerDisconnectEvent(DisconnectEvent event) { - Ambassador.getInstance().removePlayerRegisteredChannels(event.getPlayer().getUsername()); - } } From d5354a8040d76227ef917a08734a64896efa17ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?ZX=E5=A4=8F=E5=A4=9C=E4=B9=8B=E9=A3=8E?= Date: Sun, 9 Nov 2025 12:26:50 +0800 Subject: [PATCH 3/3] build: the build requires Java 21 now but the final JAR should be Java 17 compatible --- build.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 7abec89..f7d5195 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,3 +37,8 @@ tasks { archiveBaseName.set("Ambassador-Velocity") } } + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} \ No newline at end of file