From 34d12c9e2723627594c3a105df398904307427d8 Mon Sep 17 00:00:00 2001 From: fllipeis Date: Thu, 13 Aug 2026 22:11:06 +0200 Subject: [PATCH 1/2] fix: report live player presence from game servers --- .../presence/ProxyPresenceResponder.java | 49 ++++++---- .../api/presence/ProxyPresencePlayer.java | 2 +- .../presence/ProxyPresencePlayerProvider.java | 2 +- .../presence/ProxyPresenceResponderTest.java | 96 +++++++++++++++++++ platform/fabric/build.gradle.kts | 1 + .../platform/fabric/FabricApiProvider.java | 61 +++++++++++- .../api/platform/folia/FoliaApiProvider.java | 44 ++++++++- platform/neoforge/build.gradle.kts | 1 + .../neoforge/NeoForgeApiProvider.java | 60 +++++++++++- platform/paper/build.gradle.kts | 1 + .../api/provider/paper/PaperApiProvider.java | 47 ++++++++- platform/spigot-legacy/build.gradle.kts | 1 + .../legacy/LegacySpigotApiProvider.java | 43 ++++++++- platform/spigot/build.gradle.kts | 1 + .../platform/spigot/SpigotApiProvider.java | 43 ++++++++- 15 files changed, 418 insertions(+), 34 deletions(-) create mode 100644 api/src/test/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponderTest.java diff --git a/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponder.java b/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponder.java index ea794c4..7702f6d 100644 --- a/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponder.java +++ b/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponder.java @@ -18,7 +18,7 @@ import java.util.logging.Logger; /** - * Responds to controller presence-compare requests for a single proxy. + * Responds to controller presence-compare requests for a single proxy or game server. */ public final class ProxyPresenceResponder { @@ -93,17 +93,7 @@ private void handleCompareRequest(Message message) { try { PresenceCompareRequest request = PresenceCompareRequest.parseFrom(message.getData()); List players = currentPlayers(); - int localHash = computeHash(players); - boolean match = localHash == request.getHash(); - - ProxyPresenceCompareResponse.Builder response = ProxyPresenceCompareResponse.newBuilder() - .setMatch(match); - - if (!match) { - response.addAllPlayers(players.stream().map(ProxyPresencePlayer::toProto).toList()); - } - - natsConnection.publish(replyTo, response.build().toByteArray()); + natsConnection.publish(replyTo, buildResponse(request, players).toByteArray()); } catch (Exception e) { LOGGER.log(Level.WARNING, "Failed to process presence compare request for " + subject, e); } @@ -126,18 +116,41 @@ private List currentPlayers() { .toList(); } + static ProxyPresenceCompareResponse buildResponse( + PresenceCompareRequest request, + Collection players + ) { + Objects.requireNonNull(request, "request"); + List currentPlayers = (players == null ? List.of() : players).stream() + .filter(Objects::nonNull) + .sorted(Comparator.comparing(ProxyPresencePlayer::hashRecord)) + .toList(); + boolean match = computeHash(currentPlayers) == request.getHash(); + + ProxyPresenceCompareResponse.Builder response = ProxyPresenceCompareResponse.newBuilder() + .setMatch(match); + if (!match) { + response.addAllPlayers(currentPlayers.stream().map(ProxyPresencePlayer::toProto).toList()); + } + return response.build(); + } + static int computeHash(Collection players) { if (players == null || players.isEmpty()) { return 0; } + List records = players.stream() + .filter(Objects::nonNull) + .map(ProxyPresencePlayer::hashRecord) + .sorted() + .toList(); + String payload = records.size() + "\u001e" + String.join("\u001e", records); + int hash = FNV_32A_OFFSET_BASIS; - for (ProxyPresencePlayer player : players) { - byte[] bytes = player.hashRecord().getBytes(StandardCharsets.UTF_8); - for (byte currentByte : bytes) { - hash ^= currentByte & 0xff; - hash *= FNV_32A_PRIME; - } + for (byte currentByte : payload.getBytes(StandardCharsets.UTF_8)) { + hash ^= currentByte & 0xff; + hash *= FNV_32A_PRIME; } return hash; } diff --git a/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayer.java b/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayer.java index 3117bc1..6b33942 100644 --- a/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayer.java +++ b/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayer.java @@ -3,7 +3,7 @@ import build.buf.gen.simplecloud.controller.v2.ProxyPresencePlayerSnapshot; /** - * Immutable player snapshot used for proxy presence reconciliation. + * Immutable player snapshot used for proxy and game-server presence reconciliation. */ public final class ProxyPresencePlayer { diff --git a/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayerProvider.java b/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayerProvider.java index fc2f36a..9b46ba3 100644 --- a/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayerProvider.java +++ b/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayerProvider.java @@ -3,7 +3,7 @@ import java.util.Collection; /** - * Supplies the current set of players connected through a proxy. + * Supplies the current set of players visible to this proxy or game server. */ public interface ProxyPresencePlayerProvider { diff --git a/api/src/test/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponderTest.java b/api/src/test/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponderTest.java new file mode 100644 index 0000000..24b29c2 --- /dev/null +++ b/api/src/test/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponderTest.java @@ -0,0 +1,96 @@ +package app.simplecloud.api.internal.integration.presence; + +import app.simplecloud.api.presence.ProxyPresencePlayer; +import build.buf.gen.simplecloud.controller.v2.PresenceCompareRequest; +import build.buf.gen.simplecloud.controller.v2.ProxyPresenceCompareResponse; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class ProxyPresenceResponderTest { + + @Test + void returnsMatchWithoutSnapshotWhenSummaryMatches() { + ProxyPresenceCompareResponse response = ProxyPresenceResponder.buildResponse( + PresenceCompareRequest.newBuilder().setHash(0).build(), + List.of() + ); + + assertTrue(response.getMatch()); + assertTrue(response.getPlayersList().isEmpty()); + } + + @Test + void returnsEveryLivePlayerWhenSummaryDiffers() { + ProxyPresencePlayer player = new ProxyPresencePlayer( + "player-1", + "PlayerOne", + "PlayerOne", + "", + "Proxy-1", + 1L, + "en_US", + 765, + true, + "session-1" + ); + + ProxyPresenceCompareResponse response = ProxyPresenceResponder.buildResponse( + PresenceCompareRequest.newBuilder().setHash(0).build(), + List.of(player) + ); + + assertFalse(response.getMatch()); + assertTrue(response.getPlayersList().stream().anyMatch(snapshot -> snapshot.getPlayerId().equals("player-1"))); + } + + @Test + void equalCountsWithDifferentPlayersProduceDifferentHashes() { + ProxyPresencePlayer first = player("player-1"); + ProxyPresencePlayer second = player("player-2"); + + assertNotEquals( + ProxyPresenceResponder.computeHash(List.of(first)), + ProxyPresenceResponder.computeHash(List.of(second)) + ); + assertEquals(0, ProxyPresenceResponder.computeHash(List.of())); + } + + @Test + void hashMatchesControllerWireContract() { + ProxyPresencePlayer player = new ProxyPresencePlayer( + "player-1", + "PlayerOne", + "PlayerOne", + "Lobby-1", + "", + 0L, + "", + 0, + true, + "" + ); + + assertEquals(1745198624, ProxyPresenceResponder.computeHash(List.of(player))); + } + + private static ProxyPresencePlayer player(String playerId) { + return new ProxyPresencePlayer( + playerId, + playerId, + playerId, + "", + "Proxy-1", + 1L, + "en_US", + 765, + true, + "session-1" + ); + } +} diff --git a/platform/fabric/build.gradle.kts b/platform/fabric/build.gradle.kts index 36a2414..3113dfd 100644 --- a/platform/fabric/build.gradle.kts +++ b/platform/fabric/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { implementation(rootProject.libs.fabric.loader) implementation(rootProject.libs.fabric.api) + compileOnly(rootProject.libs.jnats) implementation(project(":platform:shared")) implementation(project(":api")) diff --git a/platform/fabric/src/main/java/app/simplecloud/api/platform/fabric/FabricApiProvider.java b/platform/fabric/src/main/java/app/simplecloud/api/platform/fabric/FabricApiProvider.java index 6d083af..505b672 100644 --- a/platform/fabric/src/main/java/app/simplecloud/api/platform/fabric/FabricApiProvider.java +++ b/platform/fabric/src/main/java/app/simplecloud/api/platform/fabric/FabricApiProvider.java @@ -1,17 +1,25 @@ package app.simplecloud.api.platform.fabric; import app.simplecloud.api.CloudApi; +import app.simplecloud.api.internal.CloudApiImpl; +import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; import app.simplecloud.api.platform.shared.PlayerSynchronizer; +import app.simplecloud.api.presence.ProxyPresencePlayer; +import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.runtime.SimpleCloudRuntime; import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents; +import net.minecraft.SharedConstants; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; import java.util.concurrent.atomic.AtomicLong; -public final class FabricApiProvider implements DedicatedServerModInitializer { +public final class FabricApiProvider implements DedicatedServerModInitializer, ProxyPresencePlayerProvider { public static final String MOD_ID = "simplecloud_api"; private static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); @@ -19,8 +27,9 @@ public final class FabricApiProvider implements DedicatedServerModInitializer { private final AtomicLong onlinePlayerCount = new AtomicLong(); private MinecraftServer server; - private CloudApi cloudApi; + private CloudApiImpl cloudApi; private PlayerSynchronizer playerSynchronizer; + private ProxyPresenceResponder presenceResponder; @Override public void onInitializeServer() { @@ -33,14 +42,27 @@ public void onInitializeServer() { private void onServerStarted(MinecraftServer server) { this.server = server; this.onlinePlayerCount.set(server.getPlayerList().getPlayerCount()); - this.cloudApi = CloudApi.create(); + this.cloudApi = (CloudApiImpl) CloudApi.create(); this.playerSynchronizer = new PlayerSynchronizer(cloudApi, onlinePlayerCount::get); + this.presenceResponder = new ProxyPresenceResponder( + cloudApi.getNatsConnection(), + cloudApi.getNetworkId(), + SimpleCloudRuntime.serverId(), + this + ); this.playerSynchronizer.start(); + this.presenceResponder.start(); this.playerSynchronizer.updatePlayerCount(); LOGGER.info("SimpleCloud v3 API provider initialized"); } private void onServerStopping(MinecraftServer server) { + ProxyPresenceResponder responder = this.presenceResponder; + if (responder != null) { + responder.stop(); + this.presenceResponder = null; + } + PlayerSynchronizer synchronizer = this.playerSynchronizer; if (synchronizer != null) { synchronizer.stop(); @@ -70,4 +92,37 @@ private void refreshPlayerCount(MinecraftServer eventServer) { } }); } + + @Override + public List getProxyPresencePlayers() { + MinecraftServer currentServer = this.server; + if (currentServer == null) { + return List.of(); + } + + String serverName = SimpleCloudRuntime.serverName(); + return currentServer.getPlayerList().getPlayers().stream() + .map(player -> toPresencePlayer(currentServer, player, serverName)) + .toList(); + } + + private ProxyPresencePlayer toPresencePlayer( + MinecraftServer currentServer, + ServerPlayer player, + String serverName + ) { + String name = player.getName().getString(); + return new ProxyPresencePlayer( + player.getStringUUID(), + name, + player.getDisplayName().getString(), + serverName, + "", + 0L, + player.clientInformation().language(), + SharedConstants.getProtocolVersion(), + currentServer.usesAuthentication(), + "" + ); + } } diff --git a/platform/folia/src/main/java/app/simplecloud/api/platform/folia/FoliaApiProvider.java b/platform/folia/src/main/java/app/simplecloud/api/platform/folia/FoliaApiProvider.java index e6db5c5..03124d6 100644 --- a/platform/folia/src/main/java/app/simplecloud/api/platform/folia/FoliaApiProvider.java +++ b/platform/folia/src/main/java/app/simplecloud/api/platform/folia/FoliaApiProvider.java @@ -2,11 +2,18 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; +import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; +import app.simplecloud.api.presence.ProxyPresencePlayer; +import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.runtime.SimpleCloudRuntime; import dev.faststats.Metrics; import dev.faststats.bukkit.BukkitContext; +import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; -public class FoliaApiProvider extends JavaPlugin { +import java.util.List; + +public class FoliaApiProvider extends JavaPlugin implements ProxyPresencePlayerProvider { private final BukkitContext fastStatsContext = new BukkitContext.Factory( this, @@ -14,12 +21,20 @@ public class FoliaApiProvider extends JavaPlugin { ).metrics(Metrics.Factory::create).create(); private CloudApiImpl cloudApi; private FoliaAdventureIntegration foliaAdventureIntegration; + private ProxyPresenceResponder presenceResponder; @Override public void onEnable() { this.cloudApi = (CloudApiImpl) CloudApi.create(); this.foliaAdventureIntegration = new FoliaAdventureIntegration(this, cloudApi); + this.presenceResponder = new ProxyPresenceResponder( + cloudApi.getNatsConnection(), + cloudApi.getNetworkId(), + SimpleCloudRuntime.serverId(), + this + ); this.foliaAdventureIntegration.start(); + this.presenceResponder.start(); fastStatsContext.ready(); getLogger().info("SimpleCloud v3 API provider initialized!"); @@ -27,6 +42,9 @@ public void onEnable() { @Override public void onDisable() { + if (presenceResponder != null) { + presenceResponder.stop(); + } if (foliaAdventureIntegration != null) { foliaAdventureIntegration.stop(); } @@ -37,4 +55,28 @@ public void onDisable() { getLogger().info("SimpleCloud v3 API provider uninitialized!"); } + + @Override + public List getProxyPresencePlayers() { + String serverName = currentServerName(); + return Bukkit.getOnlinePlayers().stream() + .map(player -> new ProxyPresencePlayer( + player.getUniqueId().toString(), + player.getName(), + player.getName(), + serverName, + "", + 0L, + player.getLocale(), + 0, + Bukkit.getOnlineMode(), + "" + )) + .toList(); + } + + private String currentServerName() { + String serverName = SimpleCloudRuntime.serverName(); + return serverName == null || serverName.isBlank() ? SimpleCloudRuntime.serverId() : serverName; + } } diff --git a/platform/neoforge/build.gradle.kts b/platform/neoforge/build.gradle.kts index 9e6d0f4..95c7f7b 100644 --- a/platform/neoforge/build.gradle.kts +++ b/platform/neoforge/build.gradle.kts @@ -9,6 +9,7 @@ val shade = configurations.create("shade") dependencies { implementation(rootProject.libs.neoforge) + compileOnly(rootProject.libs.jnats) implementation(project(":platform:shared")) implementation(project(":api")) diff --git a/platform/neoforge/src/main/java/app/simplecloud/api/platform/neoforge/NeoForgeApiProvider.java b/platform/neoforge/src/main/java/app/simplecloud/api/platform/neoforge/NeoForgeApiProvider.java index 44169db..e112add 100644 --- a/platform/neoforge/src/main/java/app/simplecloud/api/platform/neoforge/NeoForgeApiProvider.java +++ b/platform/neoforge/src/main/java/app/simplecloud/api/platform/neoforge/NeoForgeApiProvider.java @@ -1,7 +1,13 @@ package app.simplecloud.api.platform.neoforge; import app.simplecloud.api.CloudApi; +import app.simplecloud.api.internal.CloudApiImpl; +import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; import app.simplecloud.api.platform.shared.PlayerSynchronizer; +import app.simplecloud.api.presence.ProxyPresencePlayer; +import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.runtime.SimpleCloudRuntime; +import net.minecraft.SharedConstants; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.neoforged.api.distmarker.Dist; @@ -13,10 +19,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; import java.util.concurrent.atomic.AtomicLong; @Mod(value = NeoForgeApiProvider.MOD_ID, dist = Dist.DEDICATED_SERVER) -public final class NeoForgeApiProvider { +public final class NeoForgeApiProvider implements ProxyPresencePlayerProvider { public static final String MOD_ID = "simplecloud_api"; private static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); @@ -24,8 +31,9 @@ public final class NeoForgeApiProvider { private final AtomicLong onlinePlayerCount = new AtomicLong(); private MinecraftServer server; - private CloudApi cloudApi; + private CloudApiImpl cloudApi; private PlayerSynchronizer playerSynchronizer; + private ProxyPresenceResponder presenceResponder; public NeoForgeApiProvider() { NeoForge.EVENT_BUS.addListener(this::onServerStarted); @@ -37,14 +45,27 @@ public NeoForgeApiProvider() { private void onServerStarted(ServerStartedEvent event) { this.server = event.getServer(); this.onlinePlayerCount.set(server.getPlayerList().getPlayerCount()); - this.cloudApi = CloudApi.create(); + this.cloudApi = (CloudApiImpl) CloudApi.create(); this.playerSynchronizer = new PlayerSynchronizer(cloudApi, onlinePlayerCount::get); + this.presenceResponder = new ProxyPresenceResponder( + cloudApi.getNatsConnection(), + cloudApi.getNetworkId(), + SimpleCloudRuntime.serverId(), + this + ); this.playerSynchronizer.start(); + this.presenceResponder.start(); this.playerSynchronizer.updatePlayerCount(); LOGGER.info("SimpleCloud v3 API provider initialized"); } private void onServerStopping(ServerStoppingEvent event) { + ProxyPresenceResponder responder = this.presenceResponder; + if (responder != null) { + responder.stop(); + this.presenceResponder = null; + } + PlayerSynchronizer synchronizer = this.playerSynchronizer; if (synchronizer != null) { synchronizer.stop(); @@ -86,4 +107,37 @@ private void refreshPlayerCount(MinecraftServer eventServer) { } }); } + + @Override + public List getProxyPresencePlayers() { + MinecraftServer currentServer = this.server; + if (currentServer == null) { + return List.of(); + } + + String serverName = SimpleCloudRuntime.serverName(); + return currentServer.getPlayerList().getPlayers().stream() + .map(player -> toPresencePlayer(currentServer, player, serverName)) + .toList(); + } + + private ProxyPresencePlayer toPresencePlayer( + MinecraftServer currentServer, + ServerPlayer player, + String serverName + ) { + String name = player.getName().getString(); + return new ProxyPresencePlayer( + player.getStringUUID(), + name, + player.getDisplayName().getString(), + serverName, + "", + 0L, + player.clientInformation().language(), + SharedConstants.getProtocolVersion(), + currentServer.usesAuthentication(), + "" + ); + } } diff --git a/platform/paper/build.gradle.kts b/platform/paper/build.gradle.kts index 99a220e..36b8a7e 100644 --- a/platform/paper/build.gradle.kts +++ b/platform/paper/build.gradle.kts @@ -4,6 +4,7 @@ plugins { dependencies { compileOnly(rootProject.libs.paper.api) + compileOnly(rootProject.libs.jnats) implementation(project(":platform:shared")) implementation(project(":api")) { exclude(group = "net.kyori") diff --git a/platform/paper/src/main/java/app/simplecloud/api/provider/paper/PaperApiProvider.java b/platform/paper/src/main/java/app/simplecloud/api/provider/paper/PaperApiProvider.java index e12e58a..a296b9d 100644 --- a/platform/paper/src/main/java/app/simplecloud/api/provider/paper/PaperApiProvider.java +++ b/platform/paper/src/main/java/app/simplecloud/api/provider/paper/PaperApiProvider.java @@ -1,7 +1,11 @@ package app.simplecloud.api.provider.paper; import app.simplecloud.api.CloudApi; +import app.simplecloud.api.internal.CloudApiImpl; import app.simplecloud.api.internal.integration.adventure.AdventureIntegration; +import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; +import app.simplecloud.api.presence.ProxyPresencePlayer; +import app.simplecloud.api.presence.ProxyPresencePlayerProvider; import app.simplecloud.api.runtime.SimpleCloudRuntime; import dev.faststats.Metrics; import dev.faststats.bukkit.BukkitContext; @@ -9,18 +13,21 @@ import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; -public class PaperApiProvider extends JavaPlugin { +import java.util.List; + +public class PaperApiProvider extends JavaPlugin implements ProxyPresencePlayerProvider { private final BukkitContext fastStatsContext = new BukkitContext.Factory( this, "2e8308cb6431a46a68fa0f59362978f7" ).metrics(Metrics.Factory::create).create(); - private CloudApi cloudApi; + private CloudApiImpl cloudApi; private AdventureIntegration adventureIntegration; + private ProxyPresenceResponder presenceResponder; @Override public void onEnable() { - this.cloudApi = CloudApi.create(); + this.cloudApi = (CloudApiImpl) CloudApi.create(); String serverId = SimpleCloudRuntime.serverId(); String groupName = SimpleCloudRuntime.groupName(); @@ -32,7 +39,14 @@ public void onEnable() { .forServer(serverId) .forGroup(groupName != null ? groupName : serverId) .build(); + this.presenceResponder = new ProxyPresenceResponder( + cloudApi.getNatsConnection(), + cloudApi.getNetworkId(), + serverId, + this + ); adventureIntegration.start(); + presenceResponder.start(); fastStatsContext.ready(); getLogger().info("SimpleCloud v3 API provider initialized!"); @@ -40,6 +54,9 @@ public void onEnable() { @Override public void onDisable() { + if (presenceResponder != null) { + presenceResponder.stop(); + } if (adventureIntegration != null) { adventureIntegration.stop(); } @@ -49,4 +66,28 @@ public void onDisable() { fastStatsContext.shutdown(); getLogger().info("SimpleCloud v3 API provider uninitialized!"); } + + @Override + public List getProxyPresencePlayers() { + String serverName = currentServerName(); + return Bukkit.getOnlinePlayers().stream() + .map(player -> new ProxyPresencePlayer( + player.getUniqueId().toString(), + player.getName(), + player.getName(), + serverName, + "", + 0L, + player.getLocale(), + 0, + Bukkit.getOnlineMode(), + "" + )) + .toList(); + } + + private String currentServerName() { + String serverName = SimpleCloudRuntime.serverName(); + return serverName == null || serverName.isBlank() ? SimpleCloudRuntime.serverId() : serverName; + } } diff --git a/platform/spigot-legacy/build.gradle.kts b/platform/spigot-legacy/build.gradle.kts index e6dd8aa..815d4ef 100644 --- a/platform/spigot-legacy/build.gradle.kts +++ b/platform/spigot-legacy/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { api(project(":platform:shared")) compileOnly(rootProject.libs.paper.api) + compileOnly(rootProject.libs.jnats) implementation(project(":api")) implementation(rootProject.libs.faststats.bukkit) } diff --git a/platform/spigot-legacy/src/main/java/app/simplecloud/api/platform/spigot/legacy/LegacySpigotApiProvider.java b/platform/spigot-legacy/src/main/java/app/simplecloud/api/platform/spigot/legacy/LegacySpigotApiProvider.java index d78d17f..f38cba2 100644 --- a/platform/spigot-legacy/src/main/java/app/simplecloud/api/platform/spigot/legacy/LegacySpigotApiProvider.java +++ b/platform/spigot-legacy/src/main/java/app/simplecloud/api/platform/spigot/legacy/LegacySpigotApiProvider.java @@ -1,23 +1,36 @@ package app.simplecloud.api.platform.spigot.legacy; import app.simplecloud.api.CloudApi; +import app.simplecloud.api.internal.CloudApiImpl; +import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; import app.simplecloud.api.platform.shared.PlayerSynchronizer; +import app.simplecloud.api.presence.ProxyPresencePlayer; +import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.runtime.SimpleCloudRuntime; import dev.faststats.Metrics; import dev.faststats.bukkit.BukkitContext; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; -public class LegacySpigotApiProvider extends JavaPlugin { +import java.util.List; + +public class LegacySpigotApiProvider extends JavaPlugin implements ProxyPresencePlayerProvider { private final BukkitContext fastStatsContext = new BukkitContext.Factory( this, "2e8308cb6431a46a68fa0f59362978f7" ).metrics(Metrics.Factory::create).create(); - private final CloudApi cloudApi = CloudApi.create(); + private final CloudApiImpl cloudApi = (CloudApiImpl) CloudApi.create(); private final PlayerSynchronizer playerSynchronizer = new PlayerSynchronizer( cloudApi, () -> (long) Bukkit.getOnlinePlayers().size() ); + private final ProxyPresenceResponder presenceResponder = new ProxyPresenceResponder( + cloudApi.getNatsConnection(), + cloudApi.getNetworkId(), + SimpleCloudRuntime.serverId(), + this + ); @Override public void onEnable() { @@ -25,14 +38,40 @@ public void onEnable() { Bukkit.getPluginManager().registerEvents(new PlayerConnectionListener(playerSynchronizer), this); playerSynchronizer.start(); + presenceResponder.start(); fastStatsContext.ready(); } @Override public void onDisable() { getLogger().info("SimpleCloud v3 API provider uninitialized!"); + presenceResponder.stop(); playerSynchronizer.stop(); cloudApi.close(); fastStatsContext.shutdown(); } + + @Override + public List getProxyPresencePlayers() { + String serverName = currentServerName(); + return Bukkit.getOnlinePlayers().stream() + .map(player -> new ProxyPresencePlayer( + player.getUniqueId().toString(), + player.getName(), + player.getDisplayName(), + serverName, + "", + 0L, + "", + 0, + Bukkit.getOnlineMode(), + "" + )) + .toList(); + } + + private String currentServerName() { + String serverName = SimpleCloudRuntime.serverName(); + return serverName == null || serverName.isBlank() ? SimpleCloudRuntime.serverId() : serverName; + } } diff --git a/platform/spigot/build.gradle.kts b/platform/spigot/build.gradle.kts index 45bffb4..8f4112b 100644 --- a/platform/spigot/build.gradle.kts +++ b/platform/spigot/build.gradle.kts @@ -5,6 +5,7 @@ plugins { dependencies { api(project(":platform:shared")) compileOnly(rootProject.libs.paper.api) + compileOnly(rootProject.libs.jnats) implementation(project(":api")) implementation(rootProject.libs.faststats.bukkit) } diff --git a/platform/spigot/src/main/java/app/simplecloud/api/platform/spigot/SpigotApiProvider.java b/platform/spigot/src/main/java/app/simplecloud/api/platform/spigot/SpigotApiProvider.java index 035d6c3..395a6c0 100644 --- a/platform/spigot/src/main/java/app/simplecloud/api/platform/spigot/SpigotApiProvider.java +++ b/platform/spigot/src/main/java/app/simplecloud/api/platform/spigot/SpigotApiProvider.java @@ -1,23 +1,36 @@ package app.simplecloud.api.platform.spigot; import app.simplecloud.api.CloudApi; +import app.simplecloud.api.internal.CloudApiImpl; +import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; import app.simplecloud.api.platform.shared.PlayerSynchronizer; +import app.simplecloud.api.presence.ProxyPresencePlayer; +import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.runtime.SimpleCloudRuntime; import dev.faststats.Metrics; import dev.faststats.bukkit.BukkitContext; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; -public class SpigotApiProvider extends JavaPlugin { +import java.util.List; + +public class SpigotApiProvider extends JavaPlugin implements ProxyPresencePlayerProvider { private final BukkitContext fastStatsContext = new BukkitContext.Factory( this, "2e8308cb6431a46a68fa0f59362978f7" ).metrics(Metrics.Factory::create).create(); - private final CloudApi cloudApi = CloudApi.create(); + private final CloudApiImpl cloudApi = (CloudApiImpl) CloudApi.create(); private final PlayerSynchronizer playerSynchronizer = new PlayerSynchronizer( cloudApi, () -> (long) Bukkit.getOnlinePlayers().size() ); + private final ProxyPresenceResponder presenceResponder = new ProxyPresenceResponder( + cloudApi.getNatsConnection(), + cloudApi.getNetworkId(), + SimpleCloudRuntime.serverId(), + this + ); @Override public void onEnable() { @@ -25,14 +38,40 @@ public void onEnable() { Bukkit.getPluginManager().registerEvents(new PlayerConnectionListener(playerSynchronizer), this); playerSynchronizer.start(); + presenceResponder.start(); fastStatsContext.ready(); } @Override public void onDisable() { getLogger().info("SimpleCloud v3 API provider uninitialized!"); + presenceResponder.stop(); playerSynchronizer.stop(); cloudApi.close(); fastStatsContext.shutdown(); } + + @Override + public List getProxyPresencePlayers() { + String serverName = currentServerName(); + return Bukkit.getOnlinePlayers().stream() + .map(player -> new ProxyPresencePlayer( + player.getUniqueId().toString(), + player.getName(), + player.getDisplayName(), + serverName, + "", + 0L, + player.getLocale(), + 0, + Bukkit.getOnlineMode(), + "" + )) + .toList(); + } + + private String currentServerName() { + String serverName = SimpleCloudRuntime.serverName(); + return serverName == null || serverName.isBlank() ? SimpleCloudRuntime.serverId() : serverName; + } } From 3533be688731eba9057d9289ca4c5ca7562ad6d8 Mon Sep 17 00:00:00 2001 From: fllipeis Date: Thu, 13 Aug 2026 22:24:36 +0200 Subject: [PATCH 2/2] refactor: use generic presence type names --- ...eResponder.java => PresenceResponder.java} | 40 +++++++++---------- .../presence/ProxyPresenceTracker.java | 6 +-- ...resencePlayer.java => PresencePlayer.java} | 4 +- ...vider.java => PresencePlayerProvider.java} | 4 +- ...erTest.java => PresenceResponderTest.java} | 28 ++++++------- .../bungeecord/BungeeCordApiProvider.java | 20 +++++----- .../platform/fabric/FabricApiProvider.java | 20 +++++----- .../api/platform/folia/FoliaApiProvider.java | 16 ++++---- .../neoforge/NeoForgeApiProvider.java | 20 +++++----- .../api/provider/paper/PaperApiProvider.java | 16 ++++---- .../legacy/LegacySpigotApiProvider.java | 14 +++---- .../platform/spigot/SpigotApiProvider.java | 14 +++---- .../velocity/CloudApiVelocityPlugin.java | 20 +++++----- 13 files changed, 111 insertions(+), 111 deletions(-) rename api/src/main/java/app/simplecloud/api/internal/integration/presence/{ProxyPresenceResponder.java => PresenceResponder.java} (76%) rename api/src/main/java/app/simplecloud/api/presence/{ProxyPresencePlayer.java => PresencePlayer.java} (97%) rename api/src/main/java/app/simplecloud/api/presence/{ProxyPresencePlayerProvider.java => PresencePlayerProvider.java} (58%) rename api/src/test/java/app/simplecloud/api/internal/integration/presence/{ProxyPresenceResponderTest.java => PresenceResponderTest.java} (69%) diff --git a/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponder.java b/api/src/main/java/app/simplecloud/api/internal/integration/presence/PresenceResponder.java similarity index 76% rename from api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponder.java rename to api/src/main/java/app/simplecloud/api/internal/integration/presence/PresenceResponder.java index 7702f6d..5824376 100644 --- a/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponder.java +++ b/api/src/main/java/app/simplecloud/api/internal/integration/presence/PresenceResponder.java @@ -1,7 +1,7 @@ package app.simplecloud.api.internal.integration.presence; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import build.buf.gen.simplecloud.controller.v2.PresenceCompareRequest; import build.buf.gen.simplecloud.controller.v2.ProxyPresenceCompareResponse; import io.nats.client.Connection; @@ -20,9 +20,9 @@ /** * Responds to controller presence-compare requests for a single proxy or game server. */ -public final class ProxyPresenceResponder { +public final class PresenceResponder { - private static final Logger LOGGER = Logger.getLogger(ProxyPresenceResponder.class.getName()); + private static final Logger LOGGER = Logger.getLogger(PresenceResponder.class.getName()); private static final int FNV_32A_OFFSET_BASIS = 0x811c9dc5; private static final int FNV_32A_PRIME = 0x01000193; @@ -30,15 +30,15 @@ public final class ProxyPresenceResponder { private final String serverId; private final String subject; private final AtomicBoolean running = new AtomicBoolean(false); - private volatile ProxyPresencePlayerProvider playerProvider; + private volatile PresencePlayerProvider playerProvider; private Dispatcher dispatcher; - public ProxyPresenceResponder( + public PresenceResponder( Connection natsConnection, String networkId, String serverId, - ProxyPresencePlayerProvider playerProvider + PresencePlayerProvider playerProvider ) { this.natsConnection = Objects.requireNonNull(natsConnection, "natsConnection"); this.serverId = serverId == null ? "" : serverId; @@ -46,7 +46,7 @@ public ProxyPresenceResponder( this.playerProvider = playerProvider; } - public ProxyPresenceResponder( + public PresenceResponder( Connection natsConnection, String networkId, String serverId @@ -67,7 +67,7 @@ public void start() { dispatcher.subscribe(subject, this::handleCompareRequest); } - public void registerPlayerProvider(ProxyPresencePlayerProvider playerProvider) { + public void registerPlayerProvider(PresencePlayerProvider playerProvider) { this.playerProvider = Objects.requireNonNull(playerProvider, "playerProvider"); } @@ -92,57 +92,57 @@ private void handleCompareRequest(Message message) { try { PresenceCompareRequest request = PresenceCompareRequest.parseFrom(message.getData()); - List players = currentPlayers(); + List players = currentPlayers(); natsConnection.publish(replyTo, buildResponse(request, players).toByteArray()); } catch (Exception e) { LOGGER.log(Level.WARNING, "Failed to process presence compare request for " + subject, e); } } - private List currentPlayers() { - ProxyPresencePlayerProvider currentProvider = playerProvider; + private List currentPlayers() { + PresencePlayerProvider currentProvider = playerProvider; if (currentProvider == null) { return List.of(); } - Collection suppliedPlayers = currentProvider.getProxyPresencePlayers(); + Collection suppliedPlayers = currentProvider.getPresencePlayers(); if (suppliedPlayers == null || suppliedPlayers.isEmpty()) { return List.of(); } return suppliedPlayers.stream() .filter(Objects::nonNull) - .sorted(Comparator.comparing(ProxyPresencePlayer::hashRecord)) + .sorted(Comparator.comparing(PresencePlayer::hashRecord)) .toList(); } static ProxyPresenceCompareResponse buildResponse( PresenceCompareRequest request, - Collection players + Collection players ) { Objects.requireNonNull(request, "request"); - List currentPlayers = (players == null ? List.of() : players).stream() + List currentPlayers = (players == null ? List.of() : players).stream() .filter(Objects::nonNull) - .sorted(Comparator.comparing(ProxyPresencePlayer::hashRecord)) + .sorted(Comparator.comparing(PresencePlayer::hashRecord)) .toList(); boolean match = computeHash(currentPlayers) == request.getHash(); ProxyPresenceCompareResponse.Builder response = ProxyPresenceCompareResponse.newBuilder() .setMatch(match); if (!match) { - response.addAllPlayers(currentPlayers.stream().map(ProxyPresencePlayer::toProto).toList()); + response.addAllPlayers(currentPlayers.stream().map(PresencePlayer::toProto).toList()); } return response.build(); } - static int computeHash(Collection players) { + static int computeHash(Collection players) { if (players == null || players.isEmpty()) { return 0; } List records = players.stream() .filter(Objects::nonNull) - .map(ProxyPresencePlayer::hashRecord) + .map(PresencePlayer::hashRecord) .sorted() .toList(); String payload = records.size() + "\u001e" + String.join("\u001e", records); diff --git a/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceTracker.java b/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceTracker.java index 613376c..46f854b 100644 --- a/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceTracker.java +++ b/api/src/main/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceTracker.java @@ -1,6 +1,6 @@ package app.simplecloud.api.internal.integration.presence; -import app.simplecloud.api.presence.ProxyPresencePlayer; +import app.simplecloud.api.presence.PresencePlayer; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -32,7 +32,7 @@ public void remove(String playerId) { players.remove(normalize(playerId)); } - public ProxyPresencePlayer createSnapshot( + public PresencePlayer createSnapshot( String playerId, String name, String displayName, @@ -44,7 +44,7 @@ public ProxyPresencePlayer createSnapshot( String normalizedPlayerId = normalize(playerId); TrackedPlayerMetadata metadata = players.get(normalizedPlayerId); - return new ProxyPresencePlayer( + return new PresencePlayer( normalizedPlayerId, name, displayName, diff --git a/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayer.java b/api/src/main/java/app/simplecloud/api/presence/PresencePlayer.java similarity index 97% rename from api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayer.java rename to api/src/main/java/app/simplecloud/api/presence/PresencePlayer.java index 6b33942..b41e6ed 100644 --- a/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayer.java +++ b/api/src/main/java/app/simplecloud/api/presence/PresencePlayer.java @@ -5,7 +5,7 @@ /** * Immutable player snapshot used for proxy and game-server presence reconciliation. */ -public final class ProxyPresencePlayer { +public final class PresencePlayer { private final String playerId; private final String name; @@ -18,7 +18,7 @@ public final class ProxyPresencePlayer { private final boolean onlineMode; private final String sessionId; - public ProxyPresencePlayer( + public PresencePlayer( String playerId, String name, String displayName, diff --git a/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayerProvider.java b/api/src/main/java/app/simplecloud/api/presence/PresencePlayerProvider.java similarity index 58% rename from api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayerProvider.java rename to api/src/main/java/app/simplecloud/api/presence/PresencePlayerProvider.java index 9b46ba3..ad7536a 100644 --- a/api/src/main/java/app/simplecloud/api/presence/ProxyPresencePlayerProvider.java +++ b/api/src/main/java/app/simplecloud/api/presence/PresencePlayerProvider.java @@ -5,7 +5,7 @@ /** * Supplies the current set of players visible to this proxy or game server. */ -public interface ProxyPresencePlayerProvider { +public interface PresencePlayerProvider { - Collection getProxyPresencePlayers(); + Collection getPresencePlayers(); } diff --git a/api/src/test/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponderTest.java b/api/src/test/java/app/simplecloud/api/internal/integration/presence/PresenceResponderTest.java similarity index 69% rename from api/src/test/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponderTest.java rename to api/src/test/java/app/simplecloud/api/internal/integration/presence/PresenceResponderTest.java index 24b29c2..26bba33 100644 --- a/api/src/test/java/app/simplecloud/api/internal/integration/presence/ProxyPresenceResponderTest.java +++ b/api/src/test/java/app/simplecloud/api/internal/integration/presence/PresenceResponderTest.java @@ -1,6 +1,6 @@ package app.simplecloud.api.internal.integration.presence; -import app.simplecloud.api.presence.ProxyPresencePlayer; +import app.simplecloud.api.presence.PresencePlayer; import build.buf.gen.simplecloud.controller.v2.PresenceCompareRequest; import build.buf.gen.simplecloud.controller.v2.ProxyPresenceCompareResponse; import org.junit.jupiter.api.Test; @@ -12,11 +12,11 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -class ProxyPresenceResponderTest { +class PresenceResponderTest { @Test void returnsMatchWithoutSnapshotWhenSummaryMatches() { - ProxyPresenceCompareResponse response = ProxyPresenceResponder.buildResponse( + ProxyPresenceCompareResponse response = PresenceResponder.buildResponse( PresenceCompareRequest.newBuilder().setHash(0).build(), List.of() ); @@ -27,7 +27,7 @@ void returnsMatchWithoutSnapshotWhenSummaryMatches() { @Test void returnsEveryLivePlayerWhenSummaryDiffers() { - ProxyPresencePlayer player = new ProxyPresencePlayer( + PresencePlayer player = new PresencePlayer( "player-1", "PlayerOne", "PlayerOne", @@ -40,7 +40,7 @@ void returnsEveryLivePlayerWhenSummaryDiffers() { "session-1" ); - ProxyPresenceCompareResponse response = ProxyPresenceResponder.buildResponse( + ProxyPresenceCompareResponse response = PresenceResponder.buildResponse( PresenceCompareRequest.newBuilder().setHash(0).build(), List.of(player) ); @@ -51,19 +51,19 @@ void returnsEveryLivePlayerWhenSummaryDiffers() { @Test void equalCountsWithDifferentPlayersProduceDifferentHashes() { - ProxyPresencePlayer first = player("player-1"); - ProxyPresencePlayer second = player("player-2"); + PresencePlayer first = player("player-1"); + PresencePlayer second = player("player-2"); assertNotEquals( - ProxyPresenceResponder.computeHash(List.of(first)), - ProxyPresenceResponder.computeHash(List.of(second)) + PresenceResponder.computeHash(List.of(first)), + PresenceResponder.computeHash(List.of(second)) ); - assertEquals(0, ProxyPresenceResponder.computeHash(List.of())); + assertEquals(0, PresenceResponder.computeHash(List.of())); } @Test void hashMatchesControllerWireContract() { - ProxyPresencePlayer player = new ProxyPresencePlayer( + PresencePlayer player = new PresencePlayer( "player-1", "PlayerOne", "PlayerOne", @@ -76,11 +76,11 @@ void hashMatchesControllerWireContract() { "" ); - assertEquals(1745198624, ProxyPresenceResponder.computeHash(List.of(player))); + assertEquals(1745198624, PresenceResponder.computeHash(List.of(player))); } - private static ProxyPresencePlayer player(String playerId) { - return new ProxyPresencePlayer( + private static PresencePlayer player(String playerId) { + return new PresencePlayer( playerId, playerId, playerId, diff --git a/platform/bungeecord/src/main/java/app/simplecloud/api/platform/bungeecord/BungeeCordApiProvider.java b/platform/bungeecord/src/main/java/app/simplecloud/api/platform/bungeecord/BungeeCordApiProvider.java index f902275..24970d3 100644 --- a/platform/bungeecord/src/main/java/app/simplecloud/api/platform/bungeecord/BungeeCordApiProvider.java +++ b/platform/bungeecord/src/main/java/app/simplecloud/api/platform/bungeecord/BungeeCordApiProvider.java @@ -3,10 +3,10 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; import app.simplecloud.api.internal.integration.player.PlayerIntegration; -import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; +import app.simplecloud.api.internal.integration.presence.PresenceResponder; import app.simplecloud.api.internal.integration.presence.ProxyPresenceTracker; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import app.simplecloud.api.player.CloudPlayer; import app.simplecloud.api.runtime.SimpleCloudRuntime; import app.simplecloud.api.platform.shared.LuckPermsPlayerPropertySynchronizer; @@ -26,7 +26,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; -public class BungeeCordApiProvider extends Plugin implements ProxyPresencePlayerProvider { +public class BungeeCordApiProvider extends Plugin implements PresencePlayerProvider { private final BungeeContext fastStatsContext = new BungeeContext.Factory( this, @@ -37,7 +37,7 @@ public class BungeeCordApiProvider extends Plugin implements ProxyPresencePlayer private PlayerSynchronizer playerSynchronizer; private PlayerIntegration playerIntegration; private ProxyPresenceTracker proxyPresenceTracker; - private ProxyPresenceResponder proxyPresenceResponder; + private PresenceResponder presenceResponder; private LuckPermsPlayerPropertySynchronizer luckPermsSynchronizer; private BungeeAudiences bungeeAudiences; @@ -55,7 +55,7 @@ public void onEnable() { ); this.playerIntegration = new PlayerIntegration(cloudApi); this.proxyPresenceTracker = new ProxyPresenceTracker(proxyName); - this.proxyPresenceResponder = new ProxyPresenceResponder( + this.presenceResponder = new PresenceResponder( cloudApi.getNatsConnection(), cloudApi.getNetworkId(), SimpleCloudRuntime.serverId(), @@ -81,14 +81,14 @@ public void onEnable() { playerSynchronizer.start(); playerIntegration.start(); - proxyPresenceResponder.start(); + presenceResponder.start(); fastStatsContext.ready(); } @Override public void onDisable() { getLogger().info("SimpleCloud v3 API provider uninitialized!"); - proxyPresenceResponder.stop(); + presenceResponder.stop(); if (luckPermsSynchronizer != null) { luckPermsSynchronizer.stop(); } @@ -135,13 +135,13 @@ private void forgetLuckPermsProperties(UUID uniqueId) { } @Override - public List getProxyPresencePlayers() { + public List getPresencePlayers() { return getProxy().getPlayers().stream() .map(this::toPresencePlayer) .toList(); } - private ProxyPresencePlayer toPresencePlayer(ProxiedPlayer player) { + private PresencePlayer toPresencePlayer(ProxiedPlayer player) { String connectedServerName = player.getServer() != null ? player.getServer().getInfo().getName() : ""; Locale locale = player.getLocale(); var pendingConnection = player.getPendingConnection(); diff --git a/platform/fabric/src/main/java/app/simplecloud/api/platform/fabric/FabricApiProvider.java b/platform/fabric/src/main/java/app/simplecloud/api/platform/fabric/FabricApiProvider.java index 505b672..94a1202 100644 --- a/platform/fabric/src/main/java/app/simplecloud/api/platform/fabric/FabricApiProvider.java +++ b/platform/fabric/src/main/java/app/simplecloud/api/platform/fabric/FabricApiProvider.java @@ -2,10 +2,10 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; -import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; +import app.simplecloud.api.internal.integration.presence.PresenceResponder; import app.simplecloud.api.platform.shared.PlayerSynchronizer; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import app.simplecloud.api.runtime.SimpleCloudRuntime; import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; @@ -19,7 +19,7 @@ import java.util.List; import java.util.concurrent.atomic.AtomicLong; -public final class FabricApiProvider implements DedicatedServerModInitializer, ProxyPresencePlayerProvider { +public final class FabricApiProvider implements DedicatedServerModInitializer, PresencePlayerProvider { public static final String MOD_ID = "simplecloud_api"; private static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); @@ -29,7 +29,7 @@ public final class FabricApiProvider implements DedicatedServerModInitializer, P private MinecraftServer server; private CloudApiImpl cloudApi; private PlayerSynchronizer playerSynchronizer; - private ProxyPresenceResponder presenceResponder; + private PresenceResponder presenceResponder; @Override public void onInitializeServer() { @@ -44,7 +44,7 @@ private void onServerStarted(MinecraftServer server) { this.onlinePlayerCount.set(server.getPlayerList().getPlayerCount()); this.cloudApi = (CloudApiImpl) CloudApi.create(); this.playerSynchronizer = new PlayerSynchronizer(cloudApi, onlinePlayerCount::get); - this.presenceResponder = new ProxyPresenceResponder( + this.presenceResponder = new PresenceResponder( cloudApi.getNatsConnection(), cloudApi.getNetworkId(), SimpleCloudRuntime.serverId(), @@ -57,7 +57,7 @@ private void onServerStarted(MinecraftServer server) { } private void onServerStopping(MinecraftServer server) { - ProxyPresenceResponder responder = this.presenceResponder; + PresenceResponder responder = this.presenceResponder; if (responder != null) { responder.stop(); this.presenceResponder = null; @@ -94,7 +94,7 @@ private void refreshPlayerCount(MinecraftServer eventServer) { } @Override - public List getProxyPresencePlayers() { + public List getPresencePlayers() { MinecraftServer currentServer = this.server; if (currentServer == null) { return List.of(); @@ -106,13 +106,13 @@ public List getProxyPresencePlayers() { .toList(); } - private ProxyPresencePlayer toPresencePlayer( + private PresencePlayer toPresencePlayer( MinecraftServer currentServer, ServerPlayer player, String serverName ) { String name = player.getName().getString(); - return new ProxyPresencePlayer( + return new PresencePlayer( player.getStringUUID(), name, player.getDisplayName().getString(), diff --git a/platform/folia/src/main/java/app/simplecloud/api/platform/folia/FoliaApiProvider.java b/platform/folia/src/main/java/app/simplecloud/api/platform/folia/FoliaApiProvider.java index 03124d6..07f06b7 100644 --- a/platform/folia/src/main/java/app/simplecloud/api/platform/folia/FoliaApiProvider.java +++ b/platform/folia/src/main/java/app/simplecloud/api/platform/folia/FoliaApiProvider.java @@ -2,9 +2,9 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; -import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.internal.integration.presence.PresenceResponder; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import app.simplecloud.api.runtime.SimpleCloudRuntime; import dev.faststats.Metrics; import dev.faststats.bukkit.BukkitContext; @@ -13,7 +13,7 @@ import java.util.List; -public class FoliaApiProvider extends JavaPlugin implements ProxyPresencePlayerProvider { +public class FoliaApiProvider extends JavaPlugin implements PresencePlayerProvider { private final BukkitContext fastStatsContext = new BukkitContext.Factory( this, @@ -21,13 +21,13 @@ public class FoliaApiProvider extends JavaPlugin implements ProxyPresencePlayerP ).metrics(Metrics.Factory::create).create(); private CloudApiImpl cloudApi; private FoliaAdventureIntegration foliaAdventureIntegration; - private ProxyPresenceResponder presenceResponder; + private PresenceResponder presenceResponder; @Override public void onEnable() { this.cloudApi = (CloudApiImpl) CloudApi.create(); this.foliaAdventureIntegration = new FoliaAdventureIntegration(this, cloudApi); - this.presenceResponder = new ProxyPresenceResponder( + this.presenceResponder = new PresenceResponder( cloudApi.getNatsConnection(), cloudApi.getNetworkId(), SimpleCloudRuntime.serverId(), @@ -57,10 +57,10 @@ public void onDisable() { } @Override - public List getProxyPresencePlayers() { + public List getPresencePlayers() { String serverName = currentServerName(); return Bukkit.getOnlinePlayers().stream() - .map(player -> new ProxyPresencePlayer( + .map(player -> new PresencePlayer( player.getUniqueId().toString(), player.getName(), player.getName(), diff --git a/platform/neoforge/src/main/java/app/simplecloud/api/platform/neoforge/NeoForgeApiProvider.java b/platform/neoforge/src/main/java/app/simplecloud/api/platform/neoforge/NeoForgeApiProvider.java index e112add..1c4fdc5 100644 --- a/platform/neoforge/src/main/java/app/simplecloud/api/platform/neoforge/NeoForgeApiProvider.java +++ b/platform/neoforge/src/main/java/app/simplecloud/api/platform/neoforge/NeoForgeApiProvider.java @@ -2,10 +2,10 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; -import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; +import app.simplecloud.api.internal.integration.presence.PresenceResponder; import app.simplecloud.api.platform.shared.PlayerSynchronizer; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import app.simplecloud.api.runtime.SimpleCloudRuntime; import net.minecraft.SharedConstants; import net.minecraft.server.MinecraftServer; @@ -23,7 +23,7 @@ import java.util.concurrent.atomic.AtomicLong; @Mod(value = NeoForgeApiProvider.MOD_ID, dist = Dist.DEDICATED_SERVER) -public final class NeoForgeApiProvider implements ProxyPresencePlayerProvider { +public final class NeoForgeApiProvider implements PresencePlayerProvider { public static final String MOD_ID = "simplecloud_api"; private static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); @@ -33,7 +33,7 @@ public final class NeoForgeApiProvider implements ProxyPresencePlayerProvider { private MinecraftServer server; private CloudApiImpl cloudApi; private PlayerSynchronizer playerSynchronizer; - private ProxyPresenceResponder presenceResponder; + private PresenceResponder presenceResponder; public NeoForgeApiProvider() { NeoForge.EVENT_BUS.addListener(this::onServerStarted); @@ -47,7 +47,7 @@ private void onServerStarted(ServerStartedEvent event) { this.onlinePlayerCount.set(server.getPlayerList().getPlayerCount()); this.cloudApi = (CloudApiImpl) CloudApi.create(); this.playerSynchronizer = new PlayerSynchronizer(cloudApi, onlinePlayerCount::get); - this.presenceResponder = new ProxyPresenceResponder( + this.presenceResponder = new PresenceResponder( cloudApi.getNatsConnection(), cloudApi.getNetworkId(), SimpleCloudRuntime.serverId(), @@ -60,7 +60,7 @@ private void onServerStarted(ServerStartedEvent event) { } private void onServerStopping(ServerStoppingEvent event) { - ProxyPresenceResponder responder = this.presenceResponder; + PresenceResponder responder = this.presenceResponder; if (responder != null) { responder.stop(); this.presenceResponder = null; @@ -109,7 +109,7 @@ private void refreshPlayerCount(MinecraftServer eventServer) { } @Override - public List getProxyPresencePlayers() { + public List getPresencePlayers() { MinecraftServer currentServer = this.server; if (currentServer == null) { return List.of(); @@ -121,13 +121,13 @@ public List getProxyPresencePlayers() { .toList(); } - private ProxyPresencePlayer toPresencePlayer( + private PresencePlayer toPresencePlayer( MinecraftServer currentServer, ServerPlayer player, String serverName ) { String name = player.getName().getString(); - return new ProxyPresencePlayer( + return new PresencePlayer( player.getStringUUID(), name, player.getDisplayName().getString(), diff --git a/platform/paper/src/main/java/app/simplecloud/api/provider/paper/PaperApiProvider.java b/platform/paper/src/main/java/app/simplecloud/api/provider/paper/PaperApiProvider.java index a296b9d..efb841f 100644 --- a/platform/paper/src/main/java/app/simplecloud/api/provider/paper/PaperApiProvider.java +++ b/platform/paper/src/main/java/app/simplecloud/api/provider/paper/PaperApiProvider.java @@ -3,9 +3,9 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; import app.simplecloud.api.internal.integration.adventure.AdventureIntegration; -import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.internal.integration.presence.PresenceResponder; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import app.simplecloud.api.runtime.SimpleCloudRuntime; import dev.faststats.Metrics; import dev.faststats.bukkit.BukkitContext; @@ -15,7 +15,7 @@ import java.util.List; -public class PaperApiProvider extends JavaPlugin implements ProxyPresencePlayerProvider { +public class PaperApiProvider extends JavaPlugin implements PresencePlayerProvider { private final BukkitContext fastStatsContext = new BukkitContext.Factory( this, @@ -23,7 +23,7 @@ public class PaperApiProvider extends JavaPlugin implements ProxyPresencePlayerP ).metrics(Metrics.Factory::create).create(); private CloudApiImpl cloudApi; private AdventureIntegration adventureIntegration; - private ProxyPresenceResponder presenceResponder; + private PresenceResponder presenceResponder; @Override public void onEnable() { @@ -39,7 +39,7 @@ public void onEnable() { .forServer(serverId) .forGroup(groupName != null ? groupName : serverId) .build(); - this.presenceResponder = new ProxyPresenceResponder( + this.presenceResponder = new PresenceResponder( cloudApi.getNatsConnection(), cloudApi.getNetworkId(), serverId, @@ -68,10 +68,10 @@ public void onDisable() { } @Override - public List getProxyPresencePlayers() { + public List getPresencePlayers() { String serverName = currentServerName(); return Bukkit.getOnlinePlayers().stream() - .map(player -> new ProxyPresencePlayer( + .map(player -> new PresencePlayer( player.getUniqueId().toString(), player.getName(), player.getName(), diff --git a/platform/spigot-legacy/src/main/java/app/simplecloud/api/platform/spigot/legacy/LegacySpigotApiProvider.java b/platform/spigot-legacy/src/main/java/app/simplecloud/api/platform/spigot/legacy/LegacySpigotApiProvider.java index f38cba2..e156b6c 100644 --- a/platform/spigot-legacy/src/main/java/app/simplecloud/api/platform/spigot/legacy/LegacySpigotApiProvider.java +++ b/platform/spigot-legacy/src/main/java/app/simplecloud/api/platform/spigot/legacy/LegacySpigotApiProvider.java @@ -2,10 +2,10 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; -import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; +import app.simplecloud.api.internal.integration.presence.PresenceResponder; import app.simplecloud.api.platform.shared.PlayerSynchronizer; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import app.simplecloud.api.runtime.SimpleCloudRuntime; import dev.faststats.Metrics; import dev.faststats.bukkit.BukkitContext; @@ -14,7 +14,7 @@ import java.util.List; -public class LegacySpigotApiProvider extends JavaPlugin implements ProxyPresencePlayerProvider { +public class LegacySpigotApiProvider extends JavaPlugin implements PresencePlayerProvider { private final BukkitContext fastStatsContext = new BukkitContext.Factory( this, @@ -25,7 +25,7 @@ public class LegacySpigotApiProvider extends JavaPlugin implements ProxyPresence cloudApi, () -> (long) Bukkit.getOnlinePlayers().size() ); - private final ProxyPresenceResponder presenceResponder = new ProxyPresenceResponder( + private final PresenceResponder presenceResponder = new PresenceResponder( cloudApi.getNatsConnection(), cloudApi.getNetworkId(), SimpleCloudRuntime.serverId(), @@ -52,10 +52,10 @@ public void onDisable() { } @Override - public List getProxyPresencePlayers() { + public List getPresencePlayers() { String serverName = currentServerName(); return Bukkit.getOnlinePlayers().stream() - .map(player -> new ProxyPresencePlayer( + .map(player -> new PresencePlayer( player.getUniqueId().toString(), player.getName(), player.getDisplayName(), diff --git a/platform/spigot/src/main/java/app/simplecloud/api/platform/spigot/SpigotApiProvider.java b/platform/spigot/src/main/java/app/simplecloud/api/platform/spigot/SpigotApiProvider.java index 395a6c0..b56f9a4 100644 --- a/platform/spigot/src/main/java/app/simplecloud/api/platform/spigot/SpigotApiProvider.java +++ b/platform/spigot/src/main/java/app/simplecloud/api/platform/spigot/SpigotApiProvider.java @@ -2,10 +2,10 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; -import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; +import app.simplecloud.api.internal.integration.presence.PresenceResponder; import app.simplecloud.api.platform.shared.PlayerSynchronizer; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import app.simplecloud.api.runtime.SimpleCloudRuntime; import dev.faststats.Metrics; import dev.faststats.bukkit.BukkitContext; @@ -14,7 +14,7 @@ import java.util.List; -public class SpigotApiProvider extends JavaPlugin implements ProxyPresencePlayerProvider { +public class SpigotApiProvider extends JavaPlugin implements PresencePlayerProvider { private final BukkitContext fastStatsContext = new BukkitContext.Factory( this, @@ -25,7 +25,7 @@ public class SpigotApiProvider extends JavaPlugin implements ProxyPresencePlayer cloudApi, () -> (long) Bukkit.getOnlinePlayers().size() ); - private final ProxyPresenceResponder presenceResponder = new ProxyPresenceResponder( + private final PresenceResponder presenceResponder = new PresenceResponder( cloudApi.getNatsConnection(), cloudApi.getNetworkId(), SimpleCloudRuntime.serverId(), @@ -52,10 +52,10 @@ public void onDisable() { } @Override - public List getProxyPresencePlayers() { + public List getPresencePlayers() { String serverName = currentServerName(); return Bukkit.getOnlinePlayers().stream() - .map(player -> new ProxyPresencePlayer( + .map(player -> new PresencePlayer( player.getUniqueId().toString(), player.getName(), player.getDisplayName(), diff --git a/platform/velocity/src/main/java/app/simplecloud/api/platform/velocity/CloudApiVelocityPlugin.java b/platform/velocity/src/main/java/app/simplecloud/api/platform/velocity/CloudApiVelocityPlugin.java index 9ed8406..fd0d6c1 100644 --- a/platform/velocity/src/main/java/app/simplecloud/api/platform/velocity/CloudApiVelocityPlugin.java +++ b/platform/velocity/src/main/java/app/simplecloud/api/platform/velocity/CloudApiVelocityPlugin.java @@ -3,10 +3,10 @@ import app.simplecloud.api.CloudApi; import app.simplecloud.api.internal.CloudApiImpl; import app.simplecloud.api.internal.integration.player.PlayerIntegration; -import app.simplecloud.api.internal.integration.presence.ProxyPresenceResponder; +import app.simplecloud.api.internal.integration.presence.PresenceResponder; import app.simplecloud.api.internal.integration.presence.ProxyPresenceTracker; -import app.simplecloud.api.presence.ProxyPresencePlayer; -import app.simplecloud.api.presence.ProxyPresencePlayerProvider; +import app.simplecloud.api.presence.PresencePlayer; +import app.simplecloud.api.presence.PresencePlayerProvider; import app.simplecloud.api.player.CloudPlayer; import app.simplecloud.api.runtime.SimpleCloudRuntime; import app.simplecloud.api.platform.shared.LuckPermsPlayerPropertySynchronizer; @@ -38,7 +38,7 @@ authors = {"Fllip"}, dependencies = {@Dependency(id = "luckperms", optional = true)} ) -public class CloudApiVelocityPlugin implements ProxyPresencePlayerProvider { +public class CloudApiVelocityPlugin implements PresencePlayerProvider { private final Logger logger; private final ProxyServer proxyServer; @@ -48,7 +48,7 @@ public class CloudApiVelocityPlugin implements ProxyPresencePlayerProvider { private final PlayerSynchronizer playerSynchronizer; private final PlayerIntegration playerIntegration; private final ProxyPresenceTracker proxyPresenceTracker; - private final ProxyPresenceResponder proxyPresenceResponder; + private final PresenceResponder presenceResponder; private LuckPermsPlayerPropertySynchronizer luckPermsSynchronizer; private final GsonComponentSerializer gsonComponentSerializer = GsonComponentSerializer.gson(); @@ -73,7 +73,7 @@ public CloudApiVelocityPlugin( ); this.playerIntegration = new PlayerIntegration(cloudApi); this.proxyPresenceTracker = new ProxyPresenceTracker(proxyName); - this.proxyPresenceResponder = new ProxyPresenceResponder( + this.presenceResponder = new PresenceResponder( cloudApi.getNatsConnection(), cloudApi.getNetworkId(), SimpleCloudRuntime.serverId(), @@ -99,14 +99,14 @@ public void onProxyInitialize(ProxyInitializeEvent event) { playerSynchronizer.start(); playerIntegration.start(); - proxyPresenceResponder.start(); + presenceResponder.start(); fastStatsContext.ready(); } @Subscribe public void onProxyShutdown(ProxyShutdownEvent event) { logger.info("SimpleCloud v3 API provider uninitialized!"); - proxyPresenceResponder.stop(); + presenceResponder.stop(); if (luckPermsSynchronizer != null) { luckPermsSynchronizer.stop(); } @@ -149,13 +149,13 @@ private void forgetLuckPermsProperties(UUID uniqueId) { } @Override - public List getProxyPresencePlayers() { + public List getPresencePlayers() { return proxyServer.getAllPlayers().stream() .map(this::toPresencePlayer) .toList(); } - private ProxyPresencePlayer toPresencePlayer(Player player) { + private PresencePlayer toPresencePlayer(Player player) { String connectedServerName = player.getCurrentServer() .map(serverConnection -> serverConnection.getServerInfo().getName()) .orElse("");