diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 7b16813..6801dbf 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -29,14 +29,14 @@ jobs: # Artifact name name: RedisBungee-Bungee # Destination path - path: proxies/bungeecord/build/libs/* + path: redisbungee/proxies/bungeecord/build/libs/* - name: Upload Velocity uses: actions/upload-artifact@v4.4.0 with: name: RedisBungee-Velocity - path: proxies/velocity/build/libs/* + path: redisbungee/proxies/velocity/build/libs/* - name: Upload API uses: actions/upload-artifact@v4.4.0 with: name: RedisBungee-API - path: api/build/libs/* + path: redisbungee/api/build/libs/* diff --git a/build.gradle.kts b/build.gradle.kts index d7db9cd..7934b91 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,11 +25,14 @@ subprojects { } } extensions.configure { + var redisBungeeProjects = sequenceOf("RedisBungee-API", "RedisBungee-Lang", "RedisBungee-Commands", "RedisBungee-Bungee", "RedisBungee-Proxy-Bungee", "RedisBungee-Velocity", "RedisBungee-Proxy-Velocity") java { removeUnusedImports() googleJavaFormat() if (project.name == "valiobungee-api") { licenseHeaderFile(file("copyright_header.txt")) + } else if (redisBungeeProjects.contains(project.name)) { + licenseHeaderFile(rootProject.file("redisbungee/copyright_header.txt")) } else { licenseHeaderFile(rootProject.file("copyright_header.txt")) } diff --git a/gradle.properties b/gradle.properties index 1c6aa28..27abe91 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,6 @@ group=net.limework version=1.0.0-SNAPSHOT -api-version=v1 \ No newline at end of file +api-version=v1 + +redisbungee-group=com.imaginarycode.minecraft +redisbungee-version=0.13.0-SNAPSHOT \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e32a413..7db40fe 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,22 +3,52 @@ protobuf-plugin = "0.9.5" protobuf = "3.25.8" # needed for reference to be used for protoc slf4j = "2.0.17" +guava = "33.5.0-jre" +jedis = "5.2.0" +okhttp = "4.12.0" +configurateV3 = "3.7.3" +caffeine = "3.2.3" +adventure = "4.26.1" +adventure-bungeecord-platform = "4.4.1" +acf = "e2005dd62d" +bungeecordApi = "1.21-R0.5-SNAPSHOT" +velocity = "3.5.0-SNAPSHOT" + [plugins] blossom = "net.kyori.blossom:2.2.0" indragit = "net.kyori.indra.git:4.0.0" shadow = "com.gradleup.shadow:9.3.1" spotless = "com.diffplug.spotless:8.2.0" protobuf = { id = "com.google.protobuf", version.ref = "protobuf-plugin" } +run-velocity = { id = "xyz.jpenilla.run-velocity", version = "2.3.1" } [libraries] -redisson = "org.redisson:redisson:4.3.0" +# protobuf protobuf = { group = "com.google.protobuf", name = "protobuf-java", version.ref = "protobuf" } protoc = { group = "com.google.protobuf", name = "protoc", version.ref = "protobuf" } -caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3" +# valiobungee +redisson = "org.redisson:redisson:4.3.0" +caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3" # logging slf4j = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" } + # testing testing-juipter = "org.junit.jupiter:junit-jupiter:6.0.3" testing-slf4j-simple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j" } +# redisbungee speific +guava = { module = "com.google.guava:guava", version.ref = "guava" } +jedis = { module = "redis.clients:jedis", version.ref = "jedis" } +okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } +configurateV3 = { module = "org.spongepowered:configurate-yaml", version.ref = "configurateV3" } + +# minecraft speific +adventure-api = { module = "net.kyori:adventure-api", version.ref = "adventure" } +adventure-miniMessage = { module = "net.kyori:adventure-text-minimessage", version.ref = "adventure" } +acf-core = { module = "com.github.ProxioDev.commands:acf-core", version.ref = "acf" } +acf-bungeecord = { module = "com.github.ProxioDev.commands:acf-bungee", version.ref = "acf" } +acf-velocity = { module = "com.github.ProxioDev.commands:acf-velocity", version.ref = "acf" } +platform-bungeecord = { module = "net.md-5:bungeecord-api", version.ref = "bungeecordApi" } +adventure-platforms-bungeecord = { module = "net.kyori:adventure-platform-bungeecord", version.ref = "adventure-bungeecord-platform" } +platform-velocity = { module = "com.velocitypowered:velocity-api", version.ref = "velocity" } diff --git a/redisbungee/api/build.gradle.kts b/redisbungee/api/build.gradle.kts index 02f3e9b..167679d 100644 --- a/redisbungee/api/build.gradle.kts +++ b/redisbungee/api/build.gradle.kts @@ -1,5 +1,3 @@ -import java.io.ByteArrayOutputStream - plugins { `java-library` `maven-publish` @@ -8,6 +6,10 @@ plugins { } +version = property("redisbungee-version").toString() +group = property("redisbungee-group").toString() + + dependencies { api(libs.guava) api(libs.jedis) @@ -22,8 +24,8 @@ sourceSets { main { blossom { javaSources { - property("version", "$version") - property("git-commit", indraGit.commit().toString()) + property("version", version.toString()) + property("git", indraGit.commit().get().name) } } } diff --git a/redisbungee/api/src/main/java-templates/com/imaginarycode/minecraft/redisbungee/Constants.java.peb b/redisbungee/api/src/main/java-templates/com/imaginarycode/minecraft/redisbungee/Constants.java.peb new file mode 100644 index 0000000..06a6805 --- /dev/null +++ b/redisbungee/api/src/main/java-templates/com/imaginarycode/minecraft/redisbungee/Constants.java.peb @@ -0,0 +1,20 @@ +/* +* Copyright (c) 2013-2013 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ +package com.imaginarycode.minecraft.redisbungee; + +public class Constants { + + public static final String VERSION = "{{ version }}"; + public static final String GIT_COMMIT = "{{ git }}"; + + public static String getGithubCommitLink() { + return "https://github.com/ProxioDev/ValioBungee/commit/" + GIT_COMMIT; + } +} diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/AbstractRedisBungeeAPI.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/AbstractRedisBungeeAPI.java index f0335e1..f1a72ee 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/AbstractRedisBungeeAPI.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/AbstractRedisBungeeAPI.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import com.google.common.collect.ImmutableSet; @@ -15,13 +14,12 @@ import com.google.common.collect.Multimap; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeeMode; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.api.summoners.Summoner; +import java.net.InetAddress; +import java.util.*; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import redis.clients.jedis.JedisPool; -import java.net.InetAddress; -import java.util.*; - /** * This abstract class is extended by platform plugin to provide some platform specific methods. * overall its general contains all methods needed by external usage. @@ -31,309 +29,321 @@ import java.util.*; */ @SuppressWarnings("unused") public abstract class AbstractRedisBungeeAPI { - protected final RedisBungeePlugin plugin; - private static AbstractRedisBungeeAPI abstractRedisBungeeAPI; + protected final RedisBungeePlugin plugin; + private static AbstractRedisBungeeAPI abstractRedisBungeeAPI; - public AbstractRedisBungeeAPI(RedisBungeePlugin plugin) { - // this does make sure that no one can replace first initiated API class. - if (abstractRedisBungeeAPI == null) { - abstractRedisBungeeAPI = this; - } - this.plugin = plugin; + public AbstractRedisBungeeAPI(RedisBungeePlugin plugin) { + // this does make sure that no one can replace first initiated API class. + if (abstractRedisBungeeAPI == null) { + abstractRedisBungeeAPI = this; } + this.plugin = plugin; + } - /** - * Get a combined count of all players on this network. - * - * @return a count of all players found - */ - public final int getPlayerCount() { - return plugin.proxyDataManager().totalNetworkPlayers(); + /** + * Get a combined count of all players on this network. + * + * @return a count of all players found + */ + public final int getPlayerCount() { + return plugin.proxyDataManager().totalNetworkPlayers(); + } + + /** + * Get the last time a player was on. If the player is currently online, this will return 0. If + * the player has not been recorded, this will return -1. Otherwise it will return a value in + * milliseconds. + * + * @param player a player name + * @return the last time a player was on, if online returns a 0 + */ + public final long getLastOnline(@NonNull UUID player) { + return plugin.playerDataManager().getLastOnline(player); + } + + /** + * Get the server where the specified player is playing. This function also deals with the case of + * local players as well, and will return local information on them. + * + * @param player a player uuid + * @return a String name for the server the player is on. Can be Null if plugins is doing weird + * stuff to the proxy internals + */ + @Nullable + public final String getServerNameFor(@NonNull UUID player) { + return plugin.playerDataManager().getServerFor(player); + } + + /** + * Get a combined list of players on this network. + * + *

Note that this function returns an instance of {@link + * com.google.common.collect.ImmutableSet}. + * + * @return a Set with all players found + */ + public final Set getPlayersOnline() { + return plugin.proxyDataManager().networkPlayers(); + } + + /** + * Get a combined list of players on this network, as a collection of usernames. + * + * @return a Set with all players found + * @see #getNameFromUuid(java.util.UUID) + * @since 0.3 + */ + public final Collection getHumanPlayersOnline() { + Set names = new HashSet<>(); + for (UUID uuid : getPlayersOnline()) { + names.add(getNameFromUuid(uuid, false)); } + return names; + } - /** - * Get the last time a player was on. If the player is currently online, this will return 0. If the player has not been recorded, - * this will return -1. Otherwise it will return a value in milliseconds. - * - * @param player a player name - * @return the last time a player was on, if online returns a 0 - */ - public final long getLastOnline(@NonNull UUID player) { - return plugin.playerDataManager().getLastOnline(player); - } + /** + * Get a full list of players on all servers. + * + * @return a immutable Multimap with all players found on this network + * @since 0.2.5 + */ + public final Multimap getServerToPlayers() { + return plugin.playerDataManager().serversToPlayers(); + } - /** - * Get the server where the specified player is playing. This function also deals with the case of local players - * as well, and will return local information on them. - * - * @param player a player uuid - * @return a String name for the server the player is on. Can be Null if plugins is doing weird stuff to the proxy internals - */ - @Nullable - public final String getServerNameFor(@NonNull UUID player) { - return plugin.playerDataManager().getServerFor(player); - } + /** + * Get a list of players on the server with the given name. + * + * @param server a server name + * @return a Set with all players found on this server + */ + public final Set getPlayersOnServer(@NonNull String server) { + return ImmutableSet.copyOf(getServerToPlayers().get(server)); + } - /** - * Get a combined list of players on this network. - *

- * Note that this function returns an instance of {@link com.google.common.collect.ImmutableSet}. - * - * @return a Set with all players found - */ - public final Set getPlayersOnline() { - return plugin.proxyDataManager().networkPlayers(); - } + /** + * Get a list of players on the specified proxy. + * + * @param proxyID proxy id + * @return a Set with all UUIDs found on this proxy + */ + public final Set getPlayersOnProxy(@NonNull String proxyID) { + return plugin.proxyDataManager().getPlayersOn(proxyID); + } - /** - * Get a combined list of players on this network, as a collection of usernames. - * - * @return a Set with all players found - * @see #getNameFromUuid(java.util.UUID) - * @since 0.3 - */ - public final Collection getHumanPlayersOnline() { - Set names = new HashSet<>(); - for (UUID uuid : getPlayersOnline()) { - names.add(getNameFromUuid(uuid, false)); - } - return names; - } + /** + * Convenience method: Checks if the specified player is online. + * + * @param player a player name + * @return if the player is online + */ + public final boolean isPlayerOnline(@NonNull UUID player) { + return getLastOnline(player) == 0; + } - /** - * Get a full list of players on all servers. - * - * @return a immutable Multimap with all players found on this network - * @since 0.2.5 - */ - public final Multimap getServerToPlayers() { - return plugin.playerDataManager().serversToPlayers(); - } + /** + * Get the {@link java.net.InetAddress} associated with this player. + * + * @param player the player to fetch the IP for + * @return an {@link java.net.InetAddress} if the player is online, null otherwise + * @since 0.2.4 + */ + public final InetAddress getPlayerIp(@NonNull UUID player) { + return plugin.playerDataManager().getIpFor(player); + } - /** - * Get a list of players on the server with the given name. - * - * @param server a server name - * @return a Set with all players found on this server - */ - public final Set getPlayersOnServer(@NonNull String server) { - return ImmutableSet.copyOf(getServerToPlayers().get(server)); - } + /** + * Get the RedisBungee proxy ID this player is connected to. + * + * @param player the player to fetch the IP for + * @return the proxy the player is connected to, or null if they are offline + * @since 0.3.3 + */ + public final String getProxy(@NonNull UUID player) { + return plugin.playerDataManager().getProxyFor(player); + } - /** - * Get a list of players on the specified proxy. - * - * @param proxyID proxy id - * @return a Set with all UUIDs found on this proxy - */ - public final Set getPlayersOnProxy(@NonNull String proxyID) { - return plugin.proxyDataManager().getPlayersOn(proxyID); - } + /** + * Sends a proxy command to all proxies. + * + * @param command the command to send and execute + * @see #sendProxyCommand(String, String) + * @since 0.2.5 + */ + public final void sendProxyCommand(@NonNull String command) { + sendProxyCommand("allservers", command); + } - /** - * Convenience method: Checks if the specified player is online. - * - * @param player a player name - * @return if the player is online - */ - public final boolean isPlayerOnline(@NonNull UUID player) { - return getLastOnline(player) == 0; - } + /** + * Sends a proxy command to the proxy with the given ID. "allservers" means all proxies. + * + * @param proxyId a proxy ID + * @param command the command to send and execute + * @see #getProxyId() + * @see #getAllProxies() + * @since 0.2.5 + */ + public final void sendProxyCommand(@NonNull String proxyId, @NonNull String command) { + plugin.proxyDataManager().sendCommandTo(proxyId, command); + } - /** - * Get the {@link java.net.InetAddress} associated with this player. - * - * @param player the player to fetch the IP for - * @return an {@link java.net.InetAddress} if the player is online, null otherwise - * @since 0.2.4 - */ - public final InetAddress getPlayerIp(@NonNull UUID player) { - return plugin.playerDataManager().getIpFor(player); - } + /** + * Sends a message to a PubSub channel which makes PubSubMessageEvent fire. + * + *

Note: Since 0.12.0 registering a channel api is no longer required + * + * @param channel The PubSub channel + * @param message the message body to send + * @since 0.3.3 + */ + public final void sendChannelMessage(@NonNull String channel, @NonNull String message) { + plugin.proxyDataManager().sendChannelMessage(channel, message); + } - /** - * Get the RedisBungee proxy ID this player is connected to. - * - * @param player the player to fetch the IP for - * @return the proxy the player is connected to, or null if they are offline - * @since 0.3.3 - */ - public final String getProxy(@NonNull UUID player) { - return plugin.playerDataManager().getProxyFor(player); - } + /** + * Get the current BungeeCord / Velocity proxy ID for this server. + * + * @return the current server ID + * @see #getAllProxies() + * @since 0.8.0 + */ + public final String getProxyId() { + return plugin.proxyDataManager().proxyId(); + } - /** - * Sends a proxy command to all proxies. - * - * @param command the command to send and execute - * @see #sendProxyCommand(String, String) - * @since 0.2.5 - */ - public final void sendProxyCommand(@NonNull String command) { - sendProxyCommand("allservers", command); - } + /** + * Get all the linked proxies in this network. + * + * @return the list of all proxies + * @see #getProxyId() + * @since 0.8.0 + */ + public final List getAllProxies() { + return plugin.proxyDataManager().proxiesIds(); + } - /** - * Sends a proxy command to the proxy with the given ID. "allservers" means all proxies. - * - * @param proxyId a proxy ID - * @param command the command to send and execute - * @see #getProxyId() - * @see #getAllProxies() - * @since 0.2.5 - */ - public final void sendProxyCommand(@NonNull String proxyId, @NonNull String command) { - plugin.proxyDataManager().sendCommandTo(proxyId, command); - } + /** + * Fetch a name from the specified UUID. UUIDs are cached locally and in Redis. This function + * falls back to Mojang as a last resort, so calls may be blocking. + * + *

For the common use case of translating a list of UUIDs into names, use {@link + * #getHumanPlayersOnline()} instead. + * + *

If performance is a concern, use {@link #getNameFromUuid(java.util.UUID, boolean)} as this + * allows you to disable Mojang lookups. + * + * @param uuid the UUID to fetch the name for + * @return the name for the UUID + * @since 0.3 + */ + public final String getNameFromUuid(@NonNull UUID uuid) { + return getNameFromUuid(uuid, true); + } - /** - * Sends a message to a PubSub channel which makes PubSubMessageEvent fire. - *

- * Note: Since 0.12.0 registering a channel api is no longer required - * - * @param channel The PubSub channel - * @param message the message body to send - * @since 0.3.3 - */ - public final void sendChannelMessage(@NonNull String channel, @NonNull String message) { - plugin.proxyDataManager().sendChannelMessage(channel, message); - } + /** + * Fetch a name from the specified UUID. UUIDs are cached locally and in Redis. This function can + * fall back to Mojang as a last resort if {@code expensiveLookups} is true, so calls + * may be blocking. + * + *

For the common use case of translating the list of online players into names, use {@link + * #getHumanPlayersOnline()}. + * + *

If performance is a concern, set {@code expensiveLookups} to false as this will disable + * lookups via Mojang. + * + * @param uuid the UUID to fetch the name for + * @param expensiveLookups whether or not to perform potentially expensive lookups + * @return the name for the UUID + * @since 0.3.2 + */ + public final String getNameFromUuid(@NonNull UUID uuid, boolean expensiveLookups) { + return plugin.getUuidTranslator().getNameFromUuid(uuid, expensiveLookups); + } - /** - * Get the current BungeeCord / Velocity proxy ID for this server. - * - * @return the current server ID - * @see #getAllProxies() - * @since 0.8.0 - */ - public final String getProxyId() { - return plugin.proxyDataManager().proxyId(); - } + /** + * Fetch a UUID from the specified name. Names are cached locally and in Redis. This function + * falls back to Mojang as a last resort, so calls may be blocking. + * + *

If performance is a concern, see {@link #getUuidFromName(String, boolean)}, which disables + * the following functions: + * + *

+ * + * @param name the UUID to fetch the name for + * @return the UUID for the name + * @since 0.3 + */ + public final UUID getUuidFromName(@NonNull String name) { + return getUuidFromName(name, true); + } - /** - * Get all the linked proxies in this network. - * - * @return the list of all proxies - * @see #getProxyId() - * @since 0.8.0 - */ - public final List getAllProxies() { - return plugin.proxyDataManager().proxiesIds(); - } + /** + * Fetch a UUID from the specified name. Names are cached locally and in Redis. This function + * falls back to Mojang as a last resort if {@code expensiveLookups} is true, so calls + * may be blocking. + * + *

If performance is a concern, set {@code expensiveLookups} to false to disable searching + * Mojang and searching for usernames case-insensitively. + * + * @param name the UUID to fetch the name for + * @param expensiveLookups whether or not to perform potentially expensive lookups + * @return the {@link UUID} for the name + * @since 0.3.2 + */ + public final UUID getUuidFromName(@NonNull String name, boolean expensiveLookups) { + return plugin.getUuidTranslator().getTranslatedUuid(name, expensiveLookups); + } - /** - * Fetch a name from the specified UUID. UUIDs are cached locally and in Redis. This function falls back to Mojang - * as a last resort, so calls may be blocking. - *

- * For the common use case of translating a list of UUIDs into names, use {@link #getHumanPlayersOnline()} instead. - *

- * If performance is a concern, use {@link #getNameFromUuid(java.util.UUID, boolean)} as this allows you to disable Mojang lookups. - * - * @param uuid the UUID to fetch the name for - * @return the name for the UUID - * @since 0.3 - */ - public final String getNameFromUuid(@NonNull UUID uuid) { - return getNameFromUuid(uuid, true); - } + /** + * returns Summoner class responsible for Single Jedis {@link redis.clients.jedis.JedisPooled} + * with {@link JedisPool}, Cluster Jedis {@link redis.clients.jedis.JedisCluster} handling + * + * @return {@link Summoner} + * @since 0.8.0 + */ + public Summoner getSummoner() { + return this.plugin.getSummoner(); + } - /** - * Fetch a name from the specified UUID. UUIDs are cached locally and in Redis. This function can fall back to Mojang - * as a last resort if {@code expensiveLookups} is true, so calls may be blocking. - *

- * For the common use case of translating the list of online players into names, use {@link #getHumanPlayersOnline()}. - *

- * If performance is a concern, set {@code expensiveLookups} to false as this will disable lookups via Mojang. - * - * @param uuid the UUID to fetch the name for - * @param expensiveLookups whether or not to perform potentially expensive lookups - * @return the name for the UUID - * @since 0.3.2 - */ - public final String getNameFromUuid(@NonNull UUID uuid, boolean expensiveLookups) { - return plugin.getUuidTranslator().getNameFromUuid(uuid, expensiveLookups); - } + /** + * Kicks a player from the network using miniMessage calls {@link #getUuidFromName(String)} to get + * uuid ... + * + * @param playerName player name + * @param miniMessage kick message that player will see on kick using minimessage as format + * @since 0.13.0 + */ + public void kickPlayer(String playerName, String miniMessage) { + kickPlayer(getUuidFromName(playerName), miniMessage); + } - /** - * Fetch a UUID from the specified name. Names are cached locally and in Redis. This function falls back to Mojang - * as a last resort, so calls may be blocking. - *

- * If performance is a concern, see {@link #getUuidFromName(String, boolean)}, which disables the following functions: - *

- * - * @param name the UUID to fetch the name for - * @return the UUID for the name - * @since 0.3 - */ - public final UUID getUuidFromName(@NonNull String name) { - return getUuidFromName(name, true); - } + /** + * Kicks a player from the network ... + * + * @param player player uuid + * @param miniMessage kick message that player will see on kick using minimessage as format + * @since 0.13.0 + */ + public void kickPlayer(UUID player, String miniMessage) { + plugin.playerDataManager().serializedPlayerKick(player, miniMessage); + } - /** - * Fetch a UUID from the specified name. Names are cached locally and in Redis. This function falls back to Mojang - * as a last resort if {@code expensiveLookups} is true, so calls may be blocking. - *

- * If performance is a concern, set {@code expensiveLookups} to false to disable searching Mojang and searching for usernames - * case-insensitively. - * - * @param name the UUID to fetch the name for - * @param expensiveLookups whether or not to perform potentially expensive lookups - * @return the {@link UUID} for the name - * @since 0.3.2 - */ - public final UUID getUuidFromName(@NonNull String name, boolean expensiveLookups) { - return plugin.getUuidTranslator().getTranslatedUuid(name, expensiveLookups); - } + /** + * shows what mode is RedisBungee is on Basically what every redis mode is used like cluster or + * single instance. + * + * @return {@link RedisBungeeMode} + * @since 0.8.0 + */ + public RedisBungeeMode getMode() { + return this.plugin.getRedisBungeeMode(); + } - - /** - * returns Summoner class responsible for Single Jedis {@link redis.clients.jedis.JedisPooled} with {@link JedisPool}, Cluster Jedis {@link redis.clients.jedis.JedisCluster} handling - * - * @return {@link Summoner} - * @since 0.8.0 - */ - public Summoner getSummoner() { - return this.plugin.getSummoner(); - } - - /** - * Kicks a player from the network using miniMessage - * calls {@link #getUuidFromName(String)} to get uuid - * ... - * @param playerName player name - * @param miniMessage kick message that player will see on kick using minimessage as format - * @since 0.13.0 - */ - public void kickPlayer(String playerName, String miniMessage) { - kickPlayer(getUuidFromName(playerName), miniMessage); - } - - /** - * Kicks a player from the network - * ... - * @param player player uuid - * @param miniMessage kick message that player will see on kick using minimessage as format - * @since 0.13.0 - */ - public void kickPlayer(UUID player, String miniMessage) { - plugin.playerDataManager().serializedPlayerKick(player, miniMessage); - } - - /** - * shows what mode is RedisBungee is on - * Basically what every redis mode is used like cluster or single instance. - * - * @return {@link RedisBungeeMode} - * @since 0.8.0 - */ - public RedisBungeeMode getMode() { - return this.plugin.getRedisBungeeMode(); - } - - public static AbstractRedisBungeeAPI getAbstractRedisBungeeAPI() { - return abstractRedisBungeeAPI; - } + public static AbstractRedisBungeeAPI getAbstractRedisBungeeAPI() { + return abstractRedisBungeeAPI; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/Constants.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/Constants.java deleted file mode 100644 index 3c79f83..0000000 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/Constants.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - - -package com.imaginarycode.minecraft.redisbungee; - -public class Constants { - - public final static String VERSION = "{{ version }}"; - public final static String GIT_COMMIT = "{{ git-commit }}"; - - public static String getGithubCommitLink() { - return "https://github.com/ProxioDev/ValioBungee/commit/" + GIT_COMMIT; - } - -} diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/PlayerDataManager.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/PlayerDataManager.java index f2a0e10..8026ac8 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/PlayerDataManager.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/PlayerDataManager.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api; import com.github.benmanes.caffeine.cache.Caffeine; @@ -20,267 +19,293 @@ import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEv import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent; import com.imaginarycode.minecraft.redisbungee.api.events.IPubSubMessageEvent; import com.imaginarycode.minecraft.redisbungee.api.tasks.RedisPipelineTask; +import java.net.InetAddress; +import java.util.*; +import java.util.concurrent.TimeUnit; import org.json.JSONObject; import redis.clients.jedis.ClusterPipeline; import redis.clients.jedis.Pipeline; import redis.clients.jedis.Response; import redis.clients.jedis.UnifiedJedis; -import java.net.InetAddress; -import java.util.*; -import java.util.concurrent.TimeUnit; - public abstract class PlayerDataManager

{ - protected final RedisBungeePlugin

plugin; - private final Object SERVERS_TO_PLAYERS_KEY = new Object(); - private final UnifiedJedis unifiedJedis; - private final String proxyId; - private final String networkId; - private final LoadingCache serverCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getServerFromRedis); - private final LoadingCache lastServerCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getLastServerFromRedis); - private final LoadingCache proxyCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getProxyFromRedis); - private final LoadingCache ipCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getIpAddressFromRedis); - private final LoadingCache lastOnlineCache = Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getLastOnlineFromRedis); - private final LoadingCache> serverToPlayersCache = Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).build(this::serversToPlayersBuilder); + protected final RedisBungeePlugin

plugin; + private final Object SERVERS_TO_PLAYERS_KEY = new Object(); + private final UnifiedJedis unifiedJedis; + private final String proxyId; + private final String networkId; + private final LoadingCache serverCache = + Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getServerFromRedis); + private final LoadingCache lastServerCache = + Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getLastServerFromRedis); + private final LoadingCache proxyCache = + Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getProxyFromRedis); + private final LoadingCache ipCache = + Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getIpAddressFromRedis); + private final LoadingCache lastOnlineCache = + Caffeine.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(this::getLastOnlineFromRedis); + private final LoadingCache> serverToPlayersCache = + Caffeine.newBuilder() + .expireAfterWrite(10, TimeUnit.MINUTES) + .build(this::serversToPlayersBuilder); - public PlayerDataManager(RedisBungeePlugin

plugin) { - this.plugin = plugin; - this.unifiedJedis = plugin.proxyDataManager().unifiedJedis(); - this.proxyId = plugin.proxyDataManager().proxyId(); - this.networkId = plugin.proxyDataManager().networkId(); - } + public PlayerDataManager(RedisBungeePlugin

plugin) { + this.plugin = plugin; + this.unifiedJedis = plugin.proxyDataManager().unifiedJedis(); + this.proxyId = plugin.proxyDataManager().proxyId(); + this.networkId = plugin.proxyDataManager().networkId(); + } - // handle network wide - // server change - // public void onPlayerChangedServerNetworkEvent + // handle network wide + // server change + // public void onPlayerChangedServerNetworkEvent - // public void onNetworkPlayerQuit + // public void onNetworkPlayerQuit - // public void onNetworkPlayerJoin + // public void onNetworkPlayerJoin - // local events - // public void onPubSubMessageEvent + // local events + // public void onPubSubMessageEvent - // public void onServerConnectedEvent + // public void onServerConnectedEvent - // public void onLoginEvent + // public void onLoginEvent - // public void onDisconnectEvent + // public void onDisconnectEvent - protected void handleNetworkPlayerServerChange(IPlayerChangedServerNetworkEvent event) { - this.serverCache.invalidate(event.getUuid()); - this.lastServerCache.invalidate(event.getUuid()); + protected void handleNetworkPlayerServerChange(IPlayerChangedServerNetworkEvent event) { + this.serverCache.invalidate(event.getUuid()); + this.lastServerCache.invalidate(event.getUuid()); - //TODO: We could also rely on redisbungee-serverchange pubsub messages to update the cache in-place without querying redis. That would be a lot more efficient. - this.serverToPlayersCache.invalidate(SERVERS_TO_PLAYERS_KEY); - } + // TODO: We could also rely on redisbungee-serverchange pubsub messages to update the cache + // in-place without querying redis. That would be a lot more efficient. + this.serverToPlayersCache.invalidate(SERVERS_TO_PLAYERS_KEY); + } - protected void handleNetworkPlayerQuit(IPlayerLeftNetworkEvent event) { - this.proxyCache.invalidate(event.getUuid()); - this.serverCache.invalidate(event.getUuid()); - this.ipCache.invalidate(event.getUuid()); - this.lastOnlineCache.invalidate(event.getUuid()); + protected void handleNetworkPlayerQuit(IPlayerLeftNetworkEvent event) { + this.proxyCache.invalidate(event.getUuid()); + this.serverCache.invalidate(event.getUuid()); + this.ipCache.invalidate(event.getUuid()); + this.lastOnlineCache.invalidate(event.getUuid()); - //TODO: We could also rely on redisbungee-serverchange pubsub messages to update the cache in-place without querying redis. That would be a lot more efficient. - this.serverToPlayersCache.invalidate(SERVERS_TO_PLAYERS_KEY); - } + // TODO: We could also rely on redisbungee-serverchange pubsub messages to update the cache + // in-place without querying redis. That would be a lot more efficient. + this.serverToPlayersCache.invalidate(SERVERS_TO_PLAYERS_KEY); + } - protected void handleNetworkPlayerJoin(IPlayerJoinedNetworkEvent event) { - this.proxyCache.invalidate(event.getUuid()); - this.serverCache.invalidate(event.getUuid()); - this.ipCache.invalidate(event.getUuid()); - this.lastOnlineCache.invalidate(event.getUuid()); + protected void handleNetworkPlayerJoin(IPlayerJoinedNetworkEvent event) { + this.proxyCache.invalidate(event.getUuid()); + this.serverCache.invalidate(event.getUuid()); + this.ipCache.invalidate(event.getUuid()); + this.lastOnlineCache.invalidate(event.getUuid()); - //TODO: We could also rely on redisbungee-serverchange pubsub messages to update the cache in-place without querying redis. That would be a lot more efficient. - this.serverToPlayersCache.invalidate(SERVERS_TO_PLAYERS_KEY); - } + // TODO: We could also rely on redisbungee-serverchange pubsub messages to update the cache + // in-place without querying redis. That would be a lot more efficient. + this.serverToPlayersCache.invalidate(SERVERS_TO_PLAYERS_KEY); + } - - protected void handlePubSubMessageEvent(IPubSubMessageEvent event) { - switch (event.getChannel()) { - case "redisbungee-serverchange" -> { - JSONObject data = new JSONObject(event.getMessage()); - UUID uuid = UUID.fromString(data.getString("uuid")); - String from = null; - if (data.has("from")) from = data.getString("from"); - String to = data.getString("to"); - plugin.fireEvent(plugin.createPlayerChangedServerNetworkEvent(uuid, from, to)); - } - case "redisbungee-player-join" -> { - JSONObject data = new JSONObject(event.getMessage()); - UUID uuid = UUID.fromString(data.getString("uuid")); - plugin.fireEvent(plugin.createPlayerJoinedNetworkEvent(uuid)); - } - case "redisbungee-player-leave" -> { - JSONObject data = new JSONObject(event.getMessage()); - UUID uuid = UUID.fromString(data.getString("uuid")); - plugin.fireEvent(plugin.createPlayerLeftNetworkEvent(uuid)); - } - case "redisbungee-player-kick" -> { - JSONObject data = new JSONObject(event.getMessage()); - UUID uuid = UUID.fromString(data.getString("uuid")); - String message = data.getString("serialized-message"); - handleSerializedKick(uuid, message); - } - } - - } - - protected void playerChangedServer(UUID uuid, String from, String to) { - JSONObject data = new JSONObject(); - data.put("proxy", this.proxyId); - data.put("uuid", uuid); - data.put("from", from); - data.put("to", to); - plugin.proxyDataManager().sendChannelMessage("redisbungee-serverchange", data.toString()); + protected void handlePubSubMessageEvent(IPubSubMessageEvent event) { + switch (event.getChannel()) { + case "redisbungee-serverchange" -> { + JSONObject data = new JSONObject(event.getMessage()); + UUID uuid = UUID.fromString(data.getString("uuid")); + String from = null; + if (data.has("from")) from = data.getString("from"); + String to = data.getString("to"); plugin.fireEvent(plugin.createPlayerChangedServerNetworkEvent(uuid, from, to)); - handleServerChangeRedis(uuid, to); - } - - // must check if player is on the local proxy - // https://docs.advntr.dev/minimessage/index.html - // implemented downstream in Velocity and Bungeecord - protected abstract boolean handleSerializedKick(UUID player, String serializedMiniMessage); - - // https://docs.advntr.dev/minimessage/index.html - // implemented downstream in Velocity and Bungeecord - // called by kickPlayer in each impl of this class `NOT OVERRIDE` - public void serializedPlayerKick(UUID player, String serializedMiniMessage) { - JSONObject data = new JSONObject(); - data.put("proxy", this.proxyId); - data.put("uuid", player); - data.put("serialized-message", serializedMiniMessage); - if (!handleSerializedKick(player, serializedMiniMessage)) - plugin.proxyDataManager().sendChannelMessage("redisbungee-player-kick", data.toString()); - } - - private void handleServerChangeRedis(UUID uuid, String server) { - Map data = new HashMap<>(); - data.put("server", server); - data.put("last-server", server); - unifiedJedis.hset("redisbungee::" + this.networkId + "::player::" + uuid + "::data", data); - } - - protected void addPlayer(final UUID uuid, final String name, final InetAddress inetAddress) { - Map redisData = new HashMap<>(); - redisData.put("last-online", String.valueOf(0)); - redisData.put("proxy", this.proxyId); - redisData.put("ip", inetAddress.getHostAddress()); - unifiedJedis.hset("redisbungee::" + this.networkId + "::player::" + uuid + "::data", redisData); - plugin.getUuidTranslator().persistInfo(name, uuid, this.unifiedJedis); - JSONObject data = new JSONObject(); - data.put("proxy", this.proxyId); - data.put("uuid", uuid); - plugin.proxyDataManager().sendChannelMessage("redisbungee-player-join", data.toString()); + } + case "redisbungee-player-join" -> { + JSONObject data = new JSONObject(event.getMessage()); + UUID uuid = UUID.fromString(data.getString("uuid")); plugin.fireEvent(plugin.createPlayerJoinedNetworkEvent(uuid)); - this.plugin.proxyDataManager().addPlayer(uuid); - } - - protected void removePlayer(UUID uuid) { - unifiedJedis.hset("redisbungee::" + this.networkId + "::player::" + uuid + "::data", "last-online", String.valueOf(System.currentTimeMillis())); - unifiedJedis.hdel("redisbungee::" + this.networkId + "::player::" + uuid + "::data", "server", "proxy", "ip"); - JSONObject data = new JSONObject(); - data.put("proxy", this.proxyId); - data.put("uuid", uuid); - plugin.proxyDataManager().sendChannelMessage("redisbungee-player-leave", data.toString()); + } + case "redisbungee-player-leave" -> { + JSONObject data = new JSONObject(event.getMessage()); + UUID uuid = UUID.fromString(data.getString("uuid")); plugin.fireEvent(plugin.createPlayerLeftNetworkEvent(uuid)); - this.plugin.proxyDataManager().removePlayer(uuid); + } + case "redisbungee-player-kick" -> { + JSONObject data = new JSONObject(event.getMessage()); + UUID uuid = UUID.fromString(data.getString("uuid")); + String message = data.getString("serialized-message"); + handleSerializedKick(uuid, message); + } } + } + protected void playerChangedServer(UUID uuid, String from, String to) { + JSONObject data = new JSONObject(); + data.put("proxy", this.proxyId); + data.put("uuid", uuid); + data.put("from", from); + data.put("to", to); + plugin.proxyDataManager().sendChannelMessage("redisbungee-serverchange", data.toString()); + plugin.fireEvent(plugin.createPlayerChangedServerNetworkEvent(uuid, from, to)); + handleServerChangeRedis(uuid, to); + } - protected String getProxyFromRedis(UUID uuid) { - return unifiedJedis.hget("redisbungee::" + this.networkId + "::player::" + uuid + "::data", "proxy"); - } + // must check if player is on the local proxy + // https://docs.advntr.dev/minimessage/index.html + // implemented downstream in Velocity and Bungeecord + protected abstract boolean handleSerializedKick(UUID player, String serializedMiniMessage); - protected String getServerFromRedis(UUID uuid) { - return unifiedJedis.hget("redisbungee::" + this.networkId + "::player::" + uuid + "::data", "server"); - } + // https://docs.advntr.dev/minimessage/index.html + // implemented downstream in Velocity and Bungeecord + // called by kickPlayer in each impl of this class `NOT OVERRIDE` + public void serializedPlayerKick(UUID player, String serializedMiniMessage) { + JSONObject data = new JSONObject(); + data.put("proxy", this.proxyId); + data.put("uuid", player); + data.put("serialized-message", serializedMiniMessage); + if (!handleSerializedKick(player, serializedMiniMessage)) + plugin.proxyDataManager().sendChannelMessage("redisbungee-player-kick", data.toString()); + } - protected String getLastServerFromRedis(UUID uuid) { - return unifiedJedis.hget("redisbungee::" + this.networkId + "::player::" + uuid + "::data", "last-server"); - } + private void handleServerChangeRedis(UUID uuid, String server) { + Map data = new HashMap<>(); + data.put("server", server); + data.put("last-server", server); + unifiedJedis.hset("redisbungee::" + this.networkId + "::player::" + uuid + "::data", data); + } - protected InetAddress getIpAddressFromRedis(UUID uuid) { - String ip = unifiedJedis.hget("redisbungee::" + this.networkId + "::player::" + uuid + "::data", "ip"); - if (ip == null) return null; - return InetAddresses.forString(ip); - } + protected void addPlayer(final UUID uuid, final String name, final InetAddress inetAddress) { + Map redisData = new HashMap<>(); + redisData.put("last-online", String.valueOf(0)); + redisData.put("proxy", this.proxyId); + redisData.put("ip", inetAddress.getHostAddress()); + unifiedJedis.hset("redisbungee::" + this.networkId + "::player::" + uuid + "::data", redisData); + plugin.getUuidTranslator().persistInfo(name, uuid, this.unifiedJedis); + JSONObject data = new JSONObject(); + data.put("proxy", this.proxyId); + data.put("uuid", uuid); + plugin.proxyDataManager().sendChannelMessage("redisbungee-player-join", data.toString()); + plugin.fireEvent(plugin.createPlayerJoinedNetworkEvent(uuid)); + this.plugin.proxyDataManager().addPlayer(uuid); + } - protected long getLastOnlineFromRedis(UUID uuid) { - String unixString = unifiedJedis.hget("redisbungee::" + this.networkId + "::player::" + uuid + "::data", "last-online"); - if (unixString == null) return -1; - return Long.parseLong(unixString); - } + protected void removePlayer(UUID uuid) { + unifiedJedis.hset( + "redisbungee::" + this.networkId + "::player::" + uuid + "::data", + "last-online", + String.valueOf(System.currentTimeMillis())); + unifiedJedis.hdel( + "redisbungee::" + this.networkId + "::player::" + uuid + "::data", "server", "proxy", "ip"); + JSONObject data = new JSONObject(); + data.put("proxy", this.proxyId); + data.put("uuid", uuid); + plugin.proxyDataManager().sendChannelMessage("redisbungee-player-leave", data.toString()); + plugin.fireEvent(plugin.createPlayerLeftNetworkEvent(uuid)); + this.plugin.proxyDataManager().removePlayer(uuid); + } - public String getLastServerFor(UUID uuid) { - return this.lastServerCache.get(uuid); - } + protected String getProxyFromRedis(UUID uuid) { + return unifiedJedis.hget( + "redisbungee::" + this.networkId + "::player::" + uuid + "::data", "proxy"); + } - public String getServerFor(UUID uuid) { - return this.serverCache.get(uuid); - } + protected String getServerFromRedis(UUID uuid) { + return unifiedJedis.hget( + "redisbungee::" + this.networkId + "::player::" + uuid + "::data", "server"); + } - public String getProxyFor(UUID uuid) { - return this.proxyCache.get(uuid); - } + protected String getLastServerFromRedis(UUID uuid) { + return unifiedJedis.hget( + "redisbungee::" + this.networkId + "::player::" + uuid + "::data", "last-server"); + } - public InetAddress getIpFor(UUID uuid) { - return this.ipCache.get(uuid); - } + protected InetAddress getIpAddressFromRedis(UUID uuid) { + String ip = + unifiedJedis.hget("redisbungee::" + this.networkId + "::player::" + uuid + "::data", "ip"); + if (ip == null) return null; + return InetAddresses.forString(ip); + } - public long getLastOnline(UUID uuid) { - return this.lastOnlineCache.get(uuid); - } + protected long getLastOnlineFromRedis(UUID uuid) { + String unixString = + unifiedJedis.hget( + "redisbungee::" + this.networkId + "::player::" + uuid + "::data", "last-online"); + if (unixString == null) return -1; + return Long.parseLong(unixString); + } - public Multimap serversToPlayers() { - return this.serverToPlayersCache.get(SERVERS_TO_PLAYERS_KEY); - } + public String getLastServerFor(UUID uuid) { + return this.lastServerCache.get(uuid); + } - protected Multimap serversToPlayersBuilder(Object o) { - try { - return new RedisPipelineTask>(plugin) { - private final Set uuids = plugin.proxyDataManager().networkPlayers(); - private final ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); + public String getServerFor(UUID uuid) { + return this.serverCache.get(uuid); + } - @Override - public Multimap doPooledPipeline(Pipeline pipeline) { - HashMap> responses = new HashMap<>(); - for (UUID uuid : uuids) { - Optional.ofNullable(pipeline.hget("redisbungee::" + networkId + "::player::" + uuid + "::data", "server")).ifPresent(stringResponse -> { - responses.put(uuid, stringResponse); - }); - } - pipeline.sync(); - responses.forEach((uuid, response) -> { - String key = response.get(); - if (key == null) return; + public String getProxyFor(UUID uuid) { + return this.proxyCache.get(uuid); + } - builder.put(key, uuid); + public InetAddress getIpFor(UUID uuid) { + return this.ipCache.get(uuid); + } + + public long getLastOnline(UUID uuid) { + return this.lastOnlineCache.get(uuid); + } + + public Multimap serversToPlayers() { + return this.serverToPlayersCache.get(SERVERS_TO_PLAYERS_KEY); + } + + protected Multimap serversToPlayersBuilder(Object o) { + try { + return new RedisPipelineTask>(plugin) { + private final Set uuids = plugin.proxyDataManager().networkPlayers(); + private final ImmutableMultimap.Builder builder = ImmutableMultimap.builder(); + + @Override + public Multimap doPooledPipeline(Pipeline pipeline) { + HashMap> responses = new HashMap<>(); + for (UUID uuid : uuids) { + Optional.ofNullable( + pipeline.hget( + "redisbungee::" + networkId + "::player::" + uuid + "::data", "server")) + .ifPresent( + stringResponse -> { + responses.put(uuid, stringResponse); }); - return builder.build(); - } + } + pipeline.sync(); + responses.forEach( + (uuid, response) -> { + String key = response.get(); + if (key == null) return; - @Override - public Multimap clusterPipeline(ClusterPipeline pipeline) { - HashMap> responses = new HashMap<>(); - for (UUID uuid : uuids) { - Optional.ofNullable(pipeline.hget("redisbungee::" + networkId + "::player::" + uuid + "::data", "server")).ifPresent(stringResponse -> { - responses.put(uuid, stringResponse); - }); - } - pipeline.sync(); - responses.forEach((uuid, response) -> { - String key = response.get(); - if (key == null) return; - builder.put(key, uuid); - }); - return builder.build(); - } - }.call(); - } catch (Exception e) { - throw new RuntimeException(e); + builder.put(key, uuid); + }); + return builder.build(); } - } + @Override + public Multimap clusterPipeline(ClusterPipeline pipeline) { + HashMap> responses = new HashMap<>(); + for (UUID uuid : uuids) { + Optional.ofNullable( + pipeline.hget( + "redisbungee::" + networkId + "::player::" + uuid + "::data", "server")) + .ifPresent( + stringResponse -> { + responses.put(uuid, stringResponse); + }); + } + pipeline.sync(); + responses.forEach( + (uuid, response) -> { + String key = response.get(); + if (key == null) return; + builder.put(key, uuid); + }); + return builder.build(); + } + }.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/ProxyDataManager.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/ProxyDataManager.java index b88d7f6..98cbd95 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/ProxyDataManager.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/ProxyDataManager.java @@ -1,15 +1,16 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api; +import static com.google.common.base.Preconditions.checkArgument; + import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -25,384 +26,422 @@ import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson.PubSubPay import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson.RunCommandPayloadSerializer; import com.imaginarycode.minecraft.redisbungee.api.tasks.RedisPipelineTask; import com.imaginarycode.minecraft.redisbungee.api.util.RedisUtil; +import java.time.Instant; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; import redis.clients.jedis.*; import redis.clients.jedis.params.XAddParams; import redis.clients.jedis.params.XReadParams; import redis.clients.jedis.resps.StreamEntry; -import java.time.Instant; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; - -import static com.google.common.base.Preconditions.checkArgument; - public abstract class ProxyDataManager implements Runnable { - private static final int MAX_ENTRIES = 10000; + private static final int MAX_ENTRIES = 10000; - private final AtomicBoolean closed = new AtomicBoolean(false); + private final AtomicBoolean closed = new AtomicBoolean(false); - private final UnifiedJedis unifiedJedis; + private final UnifiedJedis unifiedJedis; - // data: - // Proxy id, heartbeat (unix epoch from instant), players as int - private final ConcurrentHashMap heartbeats = new ConcurrentHashMap<>(); + // data: + // Proxy id, heartbeat (unix epoch from instant), players as int + private final ConcurrentHashMap heartbeats = + new ConcurrentHashMap<>(); - private final String networkId; + private final String networkId; - private final String proxyId; + private final String proxyId; - private final String STREAM_ID; + private final String STREAM_ID; - // This different from proxy id, just to detect if there is duplicate proxy using same proxy id - private final UUID dataManagerUUID = UUID.randomUUID(); + // This different from proxy id, just to detect if there is duplicate proxy using same proxy id + private final UUID dataManagerUUID = UUID.randomUUID(); - protected final RedisBungeePlugin plugin; + protected final RedisBungeePlugin plugin; - private final Gson gson = new GsonBuilder().registerTypeAdapter(AbstractPayload.class, new AbstractPayloadSerializer()).registerTypeAdapter(HeartbeatPayload.class, new HeartbeatPayloadSerializer()).registerTypeAdapter(DeathPayload.class, new DeathPayloadSerializer()).registerTypeAdapter(PubSubPayload.class, new PubSubPayloadSerializer()).registerTypeAdapter(RunCommandPayload.class, new RunCommandPayloadSerializer()).create(); + private final Gson gson = + new GsonBuilder() + .registerTypeAdapter(AbstractPayload.class, new AbstractPayloadSerializer()) + .registerTypeAdapter(HeartbeatPayload.class, new HeartbeatPayloadSerializer()) + .registerTypeAdapter(DeathPayload.class, new DeathPayloadSerializer()) + .registerTypeAdapter(PubSubPayload.class, new PubSubPayloadSerializer()) + .registerTypeAdapter(RunCommandPayload.class, new RunCommandPayloadSerializer()) + .create(); - public ProxyDataManager(RedisBungeePlugin plugin) { - this.plugin = plugin; - this.proxyId = this.plugin.configuration().getProxyId(); - this.unifiedJedis = plugin.getSummoner().obtainResource(); - this.networkId = plugin.configuration().networkId(); - this.STREAM_ID = "network-" + this.networkId + "-redisbungee-stream"; - this.destroyProxyMembers(); + public ProxyDataManager(RedisBungeePlugin plugin) { + this.plugin = plugin; + this.proxyId = this.plugin.configuration().getProxyId(); + this.unifiedJedis = plugin.getSummoner().obtainResource(); + this.networkId = plugin.configuration().networkId(); + this.STREAM_ID = "network-" + this.networkId + "-redisbungee-stream"; + this.destroyProxyMembers(); + } + + public abstract Set getLocalOnlineUUIDs(); + + public Set getPlayersOn(String proxyId) { + checkArgument(proxiesIds().contains(proxyId), proxyId + " is not a valid proxy ID"); + if (proxyId.equals(this.proxyId)) return this.getLocalOnlineUUIDs(); + if (!this.heartbeats.containsKey(proxyId)) { + return new HashSet<>(); // return empty hashset or null? } + return getProxyMembers(proxyId); + } - public abstract Set getLocalOnlineUUIDs(); + // this skip checking if proxy is and its package private + // due proxy shutdown shenanigans + public boolean isPlayerTrulyOnProxy(String proxyId, UUID uuid) { + return unifiedJedis.sismember( + "redisbungee::" + this.networkId + "::proxies::" + proxyId + "::online-players", + uuid.toString()); + } - public Set getPlayersOn(String proxyId) { - checkArgument(proxiesIds().contains(proxyId), proxyId + " is not a valid proxy ID"); - if (proxyId.equals(this.proxyId)) return this.getLocalOnlineUUIDs(); - if (!this.heartbeats.containsKey(proxyId)) { - return new HashSet<>(); // return empty hashset or null? - } - return getProxyMembers(proxyId); + public List proxiesIds() { + return Collections.list(this.heartbeats.keys()); + } + + public synchronized void sendCommandTo(String proxyToRun, String command) { + if (isClosed()) return; + if (proxyToRun.equals("allservers") || proxyToRun.equals(this.proxyId())) { + handlePlatformCommandExecution(command); } + publishPayload(new RunCommandPayload(this.proxyId, proxyToRun, command)); + } - // this skip checking if proxy is and its package private - // due proxy shutdown shenanigans - public boolean isPlayerTrulyOnProxy(String proxyId, UUID uuid) { - return unifiedJedis.sismember("redisbungee::" + this.networkId + "::proxies::" + proxyId + "::online-players", uuid.toString()); - } + public synchronized void sendChannelMessage(String channel, String message) { + if (isClosed()) return; + publishPayload(new PubSubPayload(this.proxyId, channel, message)); + } + // call every 1 second + public synchronized void publishHeartbeat() { + if (isClosed()) return; + HeartbeatPayload.HeartbeatData heartbeatData = + new HeartbeatPayload.HeartbeatData( + Instant.now().getEpochSecond(), this.getLocalOnlineUUIDs().size()); + this.heartbeats.put(this.proxyId(), heartbeatData); + publishPayload(new HeartbeatPayload(this.proxyId, heartbeatData)); + } - public List proxiesIds() { - return Collections.list(this.heartbeats.keys()); - } - - public synchronized void sendCommandTo(String proxyToRun, String command) { - if (isClosed()) return; - if (proxyToRun.equals("allservers") || proxyToRun.equals(this.proxyId())) { - handlePlatformCommandExecution(command); - } - publishPayload(new RunCommandPayload(this.proxyId, proxyToRun, command)); - } - - public synchronized void sendChannelMessage(String channel, String message) { - if (isClosed()) return; - publishPayload(new PubSubPayload(this.proxyId, channel, message)); - } - - // call every 1 second - public synchronized void publishHeartbeat() { - if (isClosed()) return; - HeartbeatPayload.HeartbeatData heartbeatData = new HeartbeatPayload.HeartbeatData(Instant.now().getEpochSecond(), this.getLocalOnlineUUIDs().size()); - this.heartbeats.put(this.proxyId(), heartbeatData); - publishPayload(new HeartbeatPayload(this.proxyId, heartbeatData)); - } - - public Set networkPlayers() { - try { - return new RedisPipelineTask>(this.plugin) { - @Override - public Set doPooledPipeline(Pipeline pipeline) { - HashSet>> responses = new HashSet<>(); - for (String proxyId : proxiesIds()) { - responses.add(pipeline.smembers("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players")); - } - pipeline.sync(); - HashSet uuids = new HashSet<>(); - for (Response> response : responses) { - for (String stringUUID : response.get()) { - uuids.add(UUID.fromString(stringUUID)); - } - } - return uuids; - } - - @Override - public Set clusterPipeline(ClusterPipeline pipeline) { - HashSet>> responses = new HashSet<>(); - for (String proxyId : proxiesIds()) { - responses.add(pipeline.smembers("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players")); - } - pipeline.sync(); - HashSet uuids = new HashSet<>(); - for (Response> response : responses) { - for (String stringUUID : response.get()) { - uuids.add(UUID.fromString(stringUUID)); - } - } - return uuids; - } - }.call(); - } catch (Exception e) { - throw new RuntimeException("unable to get network players", e); - } - - } - - public int totalNetworkPlayers() { - int players = 0; - for (HeartbeatPayload.HeartbeatData value : this.heartbeats.values()) { - players += value.players(); - } - return players; - } - - public Map eachProxyCount() { - ImmutableMap.Builder builder = ImmutableMap.builder(); - heartbeats.forEach((proxy, data) -> builder.put(proxy, data.players())); - return builder.build(); - } - - // Call on close - private synchronized void publishDeath() { - publishPayload(new DeathPayload(this.proxyId)); - } - - private void publishPayload(AbstractPayload payload) { - Map data = new HashMap<>(); - data.put("payload", gson.toJson(payload)); - data.put("data-manager-uuid", this.dataManagerUUID.toString()); - data.put("class", payload.getClassName()); - this.unifiedJedis.xadd(STREAM_ID, XAddParams.xAddParams().maxLen(MAX_ENTRIES).id(StreamEntryID.NEW_ENTRY), data); - } - - - private void handleHeartBeat(HeartbeatPayload payload) { - String id = payload.senderProxy(); - if (!heartbeats.containsKey(id)) { - plugin.logInfo("Proxy {} has connected", id); - } - heartbeats.put(id, payload.data()); - } - - - // call every 1 minutes - public void correctionTask() { - // let's check this proxy players - Set localOnlineUUIDs = getLocalOnlineUUIDs(); - Set storedRedisUuids = getProxyMembers(this.proxyId); - - if (!localOnlineUUIDs.equals(storedRedisUuids)) { - plugin.logWarn("De-synced players set detected correcting...."); - Set add = new HashSet<>(localOnlineUUIDs); - Set remove = new HashSet<>(storedRedisUuids); - add.removeAll(storedRedisUuids); - remove.removeAll(localOnlineUUIDs); - for (UUID uuid : add) { - plugin.logWarn("found {} that isn't in the set, adding it to the Corrected set", uuid); + public Set networkPlayers() { + try { + return new RedisPipelineTask>(this.plugin) { + @Override + public Set doPooledPipeline(Pipeline pipeline) { + HashSet>> responses = new HashSet<>(); + for (String proxyId : proxiesIds()) { + responses.add( + pipeline.smembers( + "redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players")); + } + pipeline.sync(); + HashSet uuids = new HashSet<>(); + for (Response> response : responses) { + for (String stringUUID : response.get()) { + uuids.add(UUID.fromString(stringUUID)); } + } + return uuids; + } + + @Override + public Set clusterPipeline(ClusterPipeline pipeline) { + HashSet>> responses = new HashSet<>(); + for (String proxyId : proxiesIds()) { + responses.add( + pipeline.smembers( + "redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players")); + } + pipeline.sync(); + HashSet uuids = new HashSet<>(); + for (Response> response : responses) { + for (String stringUUID : response.get()) { + uuids.add(UUID.fromString(stringUUID)); + } + } + return uuids; + } + }.call(); + } catch (Exception e) { + throw new RuntimeException("unable to get network players", e); + } + } + + public int totalNetworkPlayers() { + int players = 0; + for (HeartbeatPayload.HeartbeatData value : this.heartbeats.values()) { + players += value.players(); + } + return players; + } + + public Map eachProxyCount() { + ImmutableMap.Builder builder = ImmutableMap.builder(); + heartbeats.forEach((proxy, data) -> builder.put(proxy, data.players())); + return builder.build(); + } + + // Call on close + private synchronized void publishDeath() { + publishPayload(new DeathPayload(this.proxyId)); + } + + private void publishPayload(AbstractPayload payload) { + Map data = new HashMap<>(); + data.put("payload", gson.toJson(payload)); + data.put("data-manager-uuid", this.dataManagerUUID.toString()); + data.put("class", payload.getClassName()); + this.unifiedJedis.xadd( + STREAM_ID, XAddParams.xAddParams().maxLen(MAX_ENTRIES).id(StreamEntryID.NEW_ENTRY), data); + } + + private void handleHeartBeat(HeartbeatPayload payload) { + String id = payload.senderProxy(); + if (!heartbeats.containsKey(id)) { + plugin.logInfo("Proxy {} has connected", id); + } + heartbeats.put(id, payload.data()); + } + + // call every 1 minutes + public void correctionTask() { + // let's check this proxy players + Set localOnlineUUIDs = getLocalOnlineUUIDs(); + Set storedRedisUuids = getProxyMembers(this.proxyId); + + if (!localOnlineUUIDs.equals(storedRedisUuids)) { + plugin.logWarn("De-synced players set detected correcting...."); + Set add = new HashSet<>(localOnlineUUIDs); + Set remove = new HashSet<>(storedRedisUuids); + add.removeAll(storedRedisUuids); + remove.removeAll(localOnlineUUIDs); + for (UUID uuid : add) { + plugin.logWarn("found {} that isn't in the set, adding it to the Corrected set", uuid); + } + for (UUID uuid : remove) { + plugin.logWarn( + "found {} that does not belong to this proxy removing it from the corrected set", uuid); + } + try { + new RedisPipelineTask(plugin) { + @Override + public Void doPooledPipeline(Pipeline pipeline) { + Set removeString = new HashSet<>(); for (UUID uuid : remove) { - plugin.logWarn("found {} that does not belong to this proxy removing it from the corrected set", uuid); + removeString.add(uuid.toString()); } - try { - new RedisPipelineTask(plugin) { - @Override - public Void doPooledPipeline(Pipeline pipeline) { - Set removeString = new HashSet<>(); - for (UUID uuid : remove) { - removeString.add(uuid.toString()); - } - Set addString = new HashSet<>(); - for (UUID uuid : add) { - addString.add(uuid.toString()); - } - pipeline.srem("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", removeString.toArray(new String[]{})); - pipeline.sadd("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", addString.toArray(new String[]{})); - pipeline.sync(); - return null; - } + Set addString = new HashSet<>(); + for (UUID uuid : add) { + addString.add(uuid.toString()); + } + pipeline.srem( + "redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", + removeString.toArray(new String[] {})); + pipeline.sadd( + "redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", + addString.toArray(new String[] {})); + pipeline.sync(); + return null; + } - @Override - public Void clusterPipeline(ClusterPipeline pipeline) { - Set removeString = new HashSet<>(); - for (UUID uuid : remove) { - removeString.add(uuid.toString()); - } - Set addString = new HashSet<>(); - for (UUID uuid : add) { - addString.add(uuid.toString()); - } - pipeline.srem("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", removeString.toArray(new String[]{})); - pipeline.sadd("redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", addString.toArray(new String[]{})); - pipeline.sync(); - return null; - } - }.call(); - } catch (Exception e) { - throw new RuntimeException(e); + @Override + public Void clusterPipeline(ClusterPipeline pipeline) { + Set removeString = new HashSet<>(); + for (UUID uuid : remove) { + removeString.add(uuid.toString()); } - plugin.logInfo("Player set has been corrected!"); + Set addString = new HashSet<>(); + for (UUID uuid : add) { + addString.add(uuid.toString()); + } + pipeline.srem( + "redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", + removeString.toArray(new String[] {})); + pipeline.sadd( + "redisbungee::" + networkId + "::proxies::" + proxyId + "::online-players", + addString.toArray(new String[] {})); + pipeline.sync(); + return null; + } + }.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + plugin.logInfo("Player set has been corrected!"); + } + + // handle dead proxies "THAT" Didn't send death payload but considered dead due TIMEOUT ~30 + // seconds + final Set deadProxies = new HashSet<>(); + for (Map.Entry stringHeartbeatDataEntry : + this.heartbeats.entrySet()) { + String id = stringHeartbeatDataEntry.getKey(); + long heartbeat = stringHeartbeatDataEntry.getValue().heartbeat(); + if (Instant.now().getEpochSecond() - heartbeat > RedisUtil.PROXY_TIMEOUT) { + deadProxies.add(id); + cleanProxy(id); + } + } + try { + new RedisPipelineTask(plugin) { + @Override + public Void doPooledPipeline(Pipeline pipeline) { + for (String deadProxy : deadProxies) { + pipeline.del( + "redisbungee::" + networkId + "::proxies::" + deadProxy + "::online-players"); + } + pipeline.sync(); + return null; } - - // handle dead proxies "THAT" Didn't send death payload but considered dead due TIMEOUT ~30 seconds - final Set deadProxies = new HashSet<>(); - for (Map.Entry stringHeartbeatDataEntry : this.heartbeats.entrySet()) { - String id = stringHeartbeatDataEntry.getKey(); - long heartbeat = stringHeartbeatDataEntry.getValue().heartbeat(); - if (Instant.now().getEpochSecond() - heartbeat > RedisUtil.PROXY_TIMEOUT) { - deadProxies.add(id); - cleanProxy(id); - } + @Override + public Void clusterPipeline(ClusterPipeline pipeline) { + for (String deadProxy : deadProxies) { + pipeline.del( + "redisbungee::" + networkId + "::proxies::" + deadProxy + "::online-players"); + } + pipeline.sync(); + return null; } + }.call(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void handleProxyDeath(DeathPayload payload) { + cleanProxy(payload.senderProxy()); + } + + private void cleanProxy(String id) { + if (id.equals(this.proxyId())) { + return; + } + for (UUID uuid : getProxyMembers(id)) + plugin.fireEvent(plugin.createPlayerLeftNetworkEvent(uuid)); + this.heartbeats.remove(id); + plugin.logInfo("Proxy {} has disconnected", id); + } + + private void handleChannelMessage(PubSubPayload payload) { + String channel = payload.channel(); + String message = payload.message(); + this.plugin.fireEvent(this.plugin.createPubSubEvent(channel, message)); + } + + protected abstract void handlePlatformCommandExecution(String command); + + private void handleCommand(RunCommandPayload payload) { + String proxyToRun = payload.proxyToRun(); + String command = payload.command(); + if (proxyToRun.equals("allservers") || proxyToRun.equals(this.proxyId())) { + handlePlatformCommandExecution(command); + } + } + + public void addPlayer(UUID uuid) { + this.unifiedJedis.sadd( + "redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players", + uuid.toString()); + } + + public void removePlayer(UUID uuid) { + this.unifiedJedis.srem( + "redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players", + uuid.toString()); + } + + private void destroyProxyMembers() { + unifiedJedis.del( + "redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players"); + } + + private Set getProxyMembers(String proxyId) { + Set uuidsStrings = + unifiedJedis.smembers( + "redisbungee::" + this.networkId + "::proxies::" + proxyId + "::online-players"); + HashSet uuids = new HashSet<>(); + for (String proxyMember : uuidsStrings) { + uuids.add(UUID.fromString(proxyMember)); + } + return uuids; + } + + private StreamEntryID lastStreamEntryID; + + // polling from stream + @Override + public void run() { + while (!isClosed()) { + try { + List>> data = + unifiedJedis.xread( + XReadParams.xReadParams().block(0), + Collections.singletonMap( + STREAM_ID, + lastStreamEntryID != null ? lastStreamEntryID : StreamEntryID.LAST_ENTRY)); + for (Map.Entry> datum : data) { + for (StreamEntry streamEntry : datum.getValue()) { + this.lastStreamEntryID = streamEntry.getID(); + String payloadData = streamEntry.getFields().get("payload"); + String clazz = streamEntry.getFields().get("class"); + UUID payloadDataManagerUUID = + UUID.fromString(streamEntry.getFields().get("data-manager-uuid")); + + AbstractPayload unknownPayload = + (AbstractPayload) gson.fromJson(payloadData, Class.forName(clazz)); + + if (unknownPayload.senderProxy().equals(this.proxyId)) { + if (!payloadDataManagerUUID.equals(this.dataManagerUUID)) { + plugin.logWarn( + "detected other proxy is using same ID! {} this can cause issues, please shutdown this proxy and change the id!", + this.proxyId); + } + continue; + } + if (unknownPayload instanceof HeartbeatPayload payload) { + handleHeartBeat(payload); + } else if (unknownPayload instanceof DeathPayload payload) { + handleProxyDeath(payload); + } else if (unknownPayload instanceof RunCommandPayload payload) { + handleCommand(payload); + } else if (unknownPayload instanceof PubSubPayload payload) { + handleChannelMessage(payload); + } else { + plugin.logWarn("got unknown data manager payload: {}", unknownPayload.getClassName()); + } + } + } + } catch (Exception e) { + this.plugin.logFatal("an error has occurred in the stream", e); try { - new RedisPipelineTask(plugin) { - @Override - public Void doPooledPipeline(Pipeline pipeline) { - for (String deadProxy : deadProxies) { - pipeline.del("redisbungee::" + networkId + "::proxies::" + deadProxy + "::online-players"); - } - pipeline.sync(); - return null; - } - - @Override - public Void clusterPipeline(ClusterPipeline pipeline) { - for (String deadProxy : deadProxies) { - pipeline.del("redisbungee::" + networkId + "::proxies::" + deadProxy + "::online-players"); - } - pipeline.sync(); - return null; - } - }.call(); - } catch (Exception e) { - throw new RuntimeException(e); + Thread.sleep(5000); + } catch (InterruptedException ignored) { } + } } + } - private void handleProxyDeath(DeathPayload payload) { - cleanProxy(payload.senderProxy()); - } + public void close() { + closed.set(true); + this.publishDeath(); + this.heartbeats.clear(); + this.destroyProxyMembers(); + } - private void cleanProxy(String id) { - if (id.equals(this.proxyId())) { - return; - } - for (UUID uuid : getProxyMembers(id)) plugin.fireEvent(plugin.createPlayerLeftNetworkEvent(uuid)); - this.heartbeats.remove(id); - plugin.logInfo("Proxy {} has disconnected", id); - } + public boolean isClosed() { + return closed.get(); + } - private void handleChannelMessage(PubSubPayload payload) { - String channel = payload.channel(); - String message = payload.message(); - this.plugin.fireEvent(this.plugin.createPubSubEvent(channel, message)); - } + public String proxyId() { + return proxyId; + } - protected abstract void handlePlatformCommandExecution(String command); + public UnifiedJedis unifiedJedis() { + return unifiedJedis; + } - private void handleCommand(RunCommandPayload payload) { - String proxyToRun = payload.proxyToRun(); - String command = payload.command(); - if (proxyToRun.equals("allservers") || proxyToRun.equals(this.proxyId())) { - handlePlatformCommandExecution(command); - } - } - - - public void addPlayer(UUID uuid) { - this.unifiedJedis.sadd("redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players", uuid.toString()); - } - - public void removePlayer(UUID uuid) { - this.unifiedJedis.srem("redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players", uuid.toString()); - } - - private void destroyProxyMembers() { - unifiedJedis.del("redisbungee::" + this.networkId + "::proxies::" + this.proxyId + "::online-players"); - } - - private Set getProxyMembers(String proxyId) { - Set uuidsStrings = unifiedJedis.smembers("redisbungee::" + this.networkId + "::proxies::" + proxyId + "::online-players"); - HashSet uuids = new HashSet<>(); - for (String proxyMember : uuidsStrings) { - uuids.add(UUID.fromString(proxyMember)); - } - return uuids; - } - - private StreamEntryID lastStreamEntryID; - - // polling from stream - @Override - public void run() { - while (!isClosed()) { - try { - List>> data = unifiedJedis.xread(XReadParams.xReadParams().block(0), Collections.singletonMap(STREAM_ID, lastStreamEntryID != null ? lastStreamEntryID : StreamEntryID.LAST_ENTRY)); - for (Map.Entry> datum : data) { - for (StreamEntry streamEntry : datum.getValue()) { - this.lastStreamEntryID = streamEntry.getID(); - String payloadData = streamEntry.getFields().get("payload"); - String clazz = streamEntry.getFields().get("class"); - UUID payloadDataManagerUUID = UUID.fromString(streamEntry.getFields().get("data-manager-uuid")); - - AbstractPayload unknownPayload = (AbstractPayload) gson.fromJson(payloadData, Class.forName(clazz)); - - if (unknownPayload.senderProxy().equals(this.proxyId)) { - if (!payloadDataManagerUUID.equals(this.dataManagerUUID)) { - plugin.logWarn("detected other proxy is using same ID! {} this can cause issues, please shutdown this proxy and change the id!", this.proxyId); - } - continue; - } - if (unknownPayload instanceof HeartbeatPayload payload) { - handleHeartBeat(payload); - } else if (unknownPayload instanceof DeathPayload payload) { - handleProxyDeath(payload); - } else if (unknownPayload instanceof RunCommandPayload payload) { - handleCommand(payload); - } else if (unknownPayload instanceof PubSubPayload payload) { - handleChannelMessage(payload); - } else { - plugin.logWarn("got unknown data manager payload: {}", unknownPayload.getClassName()); - } - } - } - } catch (Exception e) { - this.plugin.logFatal("an error has occurred in the stream", e); - try { - Thread.sleep(5000); - } catch (InterruptedException ignored) { - } - } - } - } - - public void close() { - closed.set(true); - this.publishDeath(); - this.heartbeats.clear(); - this.destroyProxyMembers(); - } - - public boolean isClosed() { - return closed.get(); - } - - public String proxyId() { - return proxyId; - } - - public UnifiedJedis unifiedJedis() { - return unifiedJedis; - } - - public String networkId() { - return networkId; - } + public String networkId() { + return networkId; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/RedisBungeeMode.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/RedisBungeeMode.java index 33a5b47..d31ed98 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/RedisBungeeMode.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/RedisBungeeMode.java @@ -1,15 +1,15 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api; public enum RedisBungeeMode { - SINGLE, CLUSTER + SINGLE, + CLUSTER } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/RedisBungeePlugin.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/RedisBungeePlugin.java index 4ec08e1..1d07cdb 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/RedisBungeePlugin.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/RedisBungeePlugin.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api; import com.imaginarycode.minecraft.redisbungee.AbstractRedisBungeeAPI; @@ -15,75 +14,71 @@ import com.imaginarycode.minecraft.redisbungee.api.config.RedisBungeeConfigurati import com.imaginarycode.minecraft.redisbungee.api.events.EventsPlatform; import com.imaginarycode.minecraft.redisbungee.api.summoners.Summoner; import com.imaginarycode.minecraft.redisbungee.api.util.uuid.UUIDTranslator; - import java.net.InetAddress; import java.util.UUID; import java.util.concurrent.TimeUnit; - /** - * This Class has all internal methods needed by every redis bungee plugin, and it can be used to implement another platforms than bungeecord or another forks of RedisBungee - *

- * Reason this is interface because some proxies implementations require the user to extend class for plugins for example bungeecord. + * This Class has all internal methods needed by every redis bungee plugin, and it can be used to + * implement another platforms than bungeecord or another forks of RedisBungee + * + *

Reason this is interface because some proxies implementations require the user to extend class + * for plugins for example bungeecord. * * @author Ham1255 * @since 0.7.0 */ public interface RedisBungeePlugin

extends EventsPlatform { - default void initialize() { + default void initialize() {} - } + default void stop() {} - default void stop() { + void logInfo(String msg); - } + void logInfo(String format, Object... object); - void logInfo(String msg); + void logWarn(String msg); - void logInfo(String format, Object... object); + void logWarn(String format, Object... object); - void logWarn(String msg); + void logFatal(String msg); - void logWarn(String format, Object... object); + void logFatal(String format, Throwable throwable); - void logFatal(String msg); + RedisBungeeConfiguration configuration(); - void logFatal(String format, Throwable throwable); + Summoner getSummoner(); - RedisBungeeConfiguration configuration(); + RedisBungeeMode getRedisBungeeMode(); - Summoner getSummoner(); + AbstractRedisBungeeAPI getAbstractRedisBungeeApi(); - RedisBungeeMode getRedisBungeeMode(); + ProxyDataManager proxyDataManager(); - AbstractRedisBungeeAPI getAbstractRedisBungeeApi(); + PlayerDataManager

playerDataManager(); - ProxyDataManager proxyDataManager(); + UUIDTranslator getUuidTranslator(); - PlayerDataManager

playerDataManager(); + boolean isOnlineMode(); - UUIDTranslator getUuidTranslator(); + P getPlayer(UUID uuid); - boolean isOnlineMode(); + P getPlayer(String name); - P getPlayer(UUID uuid); + UUID getPlayerUUID(String player); - P getPlayer(String name); + String getPlayerName(UUID player); - UUID getPlayerUUID(String player); + String getPlayerServerName(P player); - String getPlayerName(UUID player); + boolean isPlayerOnAServer(P player); - String getPlayerServerName(P player); + InetAddress getPlayerIp(P player); - boolean isPlayerOnAServer(P player); + void executeAsync(Runnable runnable); - InetAddress getPlayerIp(P player); + void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time); - void executeAsync(Runnable runnable); - - void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time); - - String platformId(); + String platformId(); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/HandleMotdOrder.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/HandleMotdOrder.java index 07b7f21..e39e8e5 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/HandleMotdOrder.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/HandleMotdOrder.java @@ -1,17 +1,16 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.config; public enum HandleMotdOrder { - FIRST, - NORMAL, - LAST + FIRST, + NORMAL, + LAST } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/RedisBungeeConfiguration.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/RedisBungeeConfiguration.java index 813654e..bf06495 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/RedisBungeeConfiguration.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/RedisBungeeConfiguration.java @@ -1,93 +1,109 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.config; import com.google.common.collect.ImmutableList; import com.google.common.net.InetAddresses; - import java.net.InetAddress; import java.util.List; public class RedisBungeeConfiguration { - private final String proxyId; - private final List exemptAddresses; - private final boolean kickWhenOnline; + private final String proxyId; + private final List exemptAddresses; + private final boolean kickWhenOnline; - private final boolean handleReconnectToLastServer; - private final boolean handleMotd; - private final HandleMotdOrder handleMotdOrder; + private final boolean handleReconnectToLastServer; + private final boolean handleMotd; + private final HandleMotdOrder handleMotdOrder; - private final CommandsConfiguration commandsConfiguration; - private final String networkId; + private final CommandsConfiguration commandsConfiguration; + private final String networkId; - - public RedisBungeeConfiguration(String networkId, String proxyId, List exemptAddresses, boolean kickWhenOnline, boolean handleReconnectToLastServer, boolean handleMotd, HandleMotdOrder handleMotdOrder, CommandsConfiguration commandsConfiguration) { - this.proxyId = proxyId; - ImmutableList.Builder addressBuilder = ImmutableList.builder(); - for (String s : exemptAddresses) { - addressBuilder.add(InetAddresses.forString(s)); - } - this.exemptAddresses = addressBuilder.build(); - this.kickWhenOnline = kickWhenOnline; - this.handleReconnectToLastServer = handleReconnectToLastServer; - this.handleMotd = handleMotd; - this.handleMotdOrder = handleMotdOrder; - this.commandsConfiguration = commandsConfiguration; - this.networkId = networkId; + public RedisBungeeConfiguration( + String networkId, + String proxyId, + List exemptAddresses, + boolean kickWhenOnline, + boolean handleReconnectToLastServer, + boolean handleMotd, + HandleMotdOrder handleMotdOrder, + CommandsConfiguration commandsConfiguration) { + this.proxyId = proxyId; + ImmutableList.Builder addressBuilder = ImmutableList.builder(); + for (String s : exemptAddresses) { + addressBuilder.add(InetAddresses.forString(s)); } + this.exemptAddresses = addressBuilder.build(); + this.kickWhenOnline = kickWhenOnline; + this.handleReconnectToLastServer = handleReconnectToLastServer; + this.handleMotd = handleMotd; + this.handleMotdOrder = handleMotdOrder; + this.commandsConfiguration = commandsConfiguration; + this.networkId = networkId; + } - public String getProxyId() { - return proxyId; - } + public String getProxyId() { + return proxyId; + } - public List getExemptAddresses() { - return exemptAddresses; - } + public List getExemptAddresses() { + return exemptAddresses; + } - public boolean kickWhenOnline() { - return kickWhenOnline; - } + public boolean kickWhenOnline() { + return kickWhenOnline; + } - public boolean handleMotd() { - return this.handleMotd; - } + public boolean handleMotd() { + return this.handleMotd; + } - public HandleMotdOrder handleMotdOrder() { - return handleMotdOrder; - } + public HandleMotdOrder handleMotdOrder() { + return handleMotdOrder; + } - public boolean handleReconnectToLastServer() { - return this.handleReconnectToLastServer; - } + public boolean handleReconnectToLastServer() { + return this.handleReconnectToLastServer; + } - public record CommandsConfiguration(boolean redisbungeeEnabled, boolean redisbungeeLegacyEnabled, - LegacySubCommandsConfiguration legacySubCommandsConfiguration) { + public record CommandsConfiguration( + boolean redisbungeeEnabled, + boolean redisbungeeLegacyEnabled, + LegacySubCommandsConfiguration legacySubCommandsConfiguration) {} - } + public record LegacySubCommandsConfiguration( + boolean findEnabled, + boolean glistEnabled, + boolean ipEnabled, + boolean lastseenEnabled, + boolean plistEnabled, + boolean pproxyEnabled, + boolean sendtoallEnabled, + boolean serveridEnabled, + boolean serveridsEnabled, + boolean installFind, + boolean installGlist, + boolean installIp, + boolean installLastseen, + boolean installPlist, + boolean installPproxy, + boolean installSendtoall, + boolean installServerid, + boolean installServerids) {} - public record LegacySubCommandsConfiguration(boolean findEnabled, boolean glistEnabled, boolean ipEnabled, - boolean lastseenEnabled, boolean plistEnabled, boolean pproxyEnabled, - boolean sendtoallEnabled, boolean serveridEnabled, - boolean serveridsEnabled, boolean installFind, boolean installGlist, boolean installIp, - boolean installLastseen, boolean installPlist, boolean installPproxy, - boolean installSendtoall, boolean installServerid, - boolean installServerids) { - } + public CommandsConfiguration commandsConfiguration() { + return commandsConfiguration; + } - public CommandsConfiguration commandsConfiguration() { - return commandsConfiguration; - } - - public String networkId() { - return networkId; - } + public String networkId() { + return networkId; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/loaders/ConfigLoader.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/loaders/ConfigLoader.java index 01ec289..6802b3d 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/loaders/ConfigLoader.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/loaders/ConfigLoader.java @@ -1,16 +1,14 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.config.loaders; - import com.google.common.reflect.TypeToken; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeeMode; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; @@ -19,6 +17,9 @@ import com.imaginarycode.minecraft.redisbungee.api.config.RedisBungeeConfigurati import com.imaginarycode.minecraft.redisbungee.api.summoners.JedisClusterSummoner; import com.imaginarycode.minecraft.redisbungee.api.summoners.JedisPooledSummoner; import com.imaginarycode.minecraft.redisbungee.api.summoners.Summoner; +import java.io.IOException; +import java.nio.file.Path; +import java.util.*; import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.objectmapping.ObjectMappingException; import ninja.leaping.configurate.yaml.YAMLConfigurationLoader; @@ -27,181 +28,271 @@ import redis.clients.jedis.*; import redis.clients.jedis.providers.ClusterConnectionProvider; import redis.clients.jedis.providers.PooledConnectionProvider; -import java.io.IOException; -import java.nio.file.Path; -import java.util.*; - public interface ConfigLoader extends GenericConfigLoader { - int CONFIG_VERSION = 2; + int CONFIG_VERSION = 2; - default void loadConfig(RedisBungeePlugin plugin, Path dataFolder) throws IOException { - Path configFile = createConfigFile(dataFolder, "config.yml", "config.yml"); - final YAMLConfigurationLoader yamlConfigurationFileLoader = YAMLConfigurationLoader.builder().setPath(configFile).build(); - ConfigurationNode node = yamlConfigurationFileLoader.load(); - if (node.getNode("config-version").getInt(0) != CONFIG_VERSION) { - handleOldConfig(dataFolder, "config.yml", "config.yml"); - node = yamlConfigurationFileLoader.load(); - } - final boolean useSSL = node.getNode("useSSL").getBoolean(false); - final boolean kickWhenOnline = node.getNode("kick-when-online").getBoolean(true); - String redisPassword = node.getNode("redis-password").getString(""); - String redisUsername = node.getNode("redis-username").getString(""); - String networkId = node.getNode("network-id").getString("main"); - String proxyId = node.getNode("proxy-id").getString("proxy-1"); + default void loadConfig(RedisBungeePlugin plugin, Path dataFolder) throws IOException { + Path configFile = createConfigFile(dataFolder, "config.yml", "config.yml"); + final YAMLConfigurationLoader yamlConfigurationFileLoader = + YAMLConfigurationLoader.builder().setPath(configFile).build(); + ConfigurationNode node = yamlConfigurationFileLoader.load(); + if (node.getNode("config-version").getInt(0) != CONFIG_VERSION) { + handleOldConfig(dataFolder, "config.yml", "config.yml"); + node = yamlConfigurationFileLoader.load(); + } + final boolean useSSL = node.getNode("useSSL").getBoolean(false); + final boolean kickWhenOnline = node.getNode("kick-when-online").getBoolean(true); + String redisPassword = node.getNode("redis-password").getString(""); + String redisUsername = node.getNode("redis-username").getString(""); + String networkId = node.getNode("network-id").getString("main"); + String proxyId = node.getNode("proxy-id").getString("proxy-1"); - final int maxConnections = node.getNode("max-redis-connections").getInt(10); - List exemptAddresses; - try { - exemptAddresses = node.getNode("exempt-ip-addresses").getList(TypeToken.of(String.class)); - } catch (ObjectMappingException e) { - exemptAddresses = Collections.emptyList(); - } + final int maxConnections = node.getNode("max-redis-connections").getInt(10); + List exemptAddresses; + try { + exemptAddresses = node.getNode("exempt-ip-addresses").getList(TypeToken.of(String.class)); + } catch (ObjectMappingException e) { + exemptAddresses = Collections.emptyList(); + } - // check redis password - if ((redisPassword.isEmpty() || redisPassword.equals("none"))) { - redisPassword = null; - plugin.logWarn("password is empty"); - } - if ((redisUsername.isEmpty() || redisUsername.equals("none"))) { - redisUsername = null; - } - // env var - String proxyIdFromEnv = System.getenv("REDISBUNGEE_PROXY_ID"); - if (proxyIdFromEnv != null) { - plugin.logInfo("Overriding current configured proxy id {} and been set to {} by Environment variable REDISBUNGEE_PROXY_ID", proxyId, proxyIdFromEnv); - proxyId = proxyIdFromEnv; - } + // check redis password + if ((redisPassword.isEmpty() || redisPassword.equals("none"))) { + redisPassword = null; + plugin.logWarn("password is empty"); + } + if ((redisUsername.isEmpty() || redisUsername.equals("none"))) { + redisUsername = null; + } + // env var + String proxyIdFromEnv = System.getenv("REDISBUNGEE_PROXY_ID"); + if (proxyIdFromEnv != null) { + plugin.logInfo( + "Overriding current configured proxy id {} and been set to {} by Environment variable REDISBUNGEE_PROXY_ID", + proxyId, + proxyIdFromEnv); + proxyId = proxyIdFromEnv; + } - String networkIdFromEnv = System.getenv("REDISBUNGEE_NETWORK_ID"); - if (networkIdFromEnv != null) { - plugin.logInfo("Overriding current configured network id {} and been set to {} by Environment variable REDISBUNGEE_NETWORK_ID", networkId, networkIdFromEnv); - networkId = networkIdFromEnv; - } + String networkIdFromEnv = System.getenv("REDISBUNGEE_NETWORK_ID"); + if (networkIdFromEnv != null) { + plugin.logInfo( + "Overriding current configured network id {} and been set to {} by Environment variable REDISBUNGEE_NETWORK_ID", + networkId, + networkIdFromEnv); + networkId = networkIdFromEnv; + } - // Configuration sanity checks. - if (proxyId == null || proxyId.isEmpty()) { - String genId = UUID.randomUUID().toString(); - plugin.logInfo("Generated proxy id " + genId + " and saving it to config."); - node.getNode("proxy-id").setValue(genId); - yamlConfigurationFileLoader.save(node); - proxyId = genId; - plugin.logInfo("proxy id was generated: " + proxyId); - } else { - plugin.logInfo("Loaded proxy id " + proxyId); - } + // Configuration sanity checks. + if (proxyId == null || proxyId.isEmpty()) { + String genId = UUID.randomUUID().toString(); + plugin.logInfo("Generated proxy id " + genId + " and saving it to config."); + node.getNode("proxy-id").setValue(genId); + yamlConfigurationFileLoader.save(node); + proxyId = genId; + plugin.logInfo("proxy id was generated: " + proxyId); + } else { + plugin.logInfo("Loaded proxy id " + proxyId); + } - if (networkId.isEmpty()) { - networkId = "main"; - plugin.logWarn("network id was empty and replaced with 'main'"); - } + if (networkId.isEmpty()) { + networkId = "main"; + plugin.logWarn("network id was empty and replaced with 'main'"); + } - plugin.logInfo("Loaded network id " + networkId); - // TO avoid proxies from different platforms from seeing each other. - networkId = plugin.platformId() + "-" + networkId; - plugin.logInfo("Platform is {} so network id is now is {}", plugin.platformId(), networkId); + plugin.logInfo("Loaded network id " + networkId); + // TO avoid proxies from different platforms from seeing each other. + networkId = plugin.platformId() + "-" + networkId; + plugin.logInfo("Platform is {} so network id is now is {}", plugin.platformId(), networkId); - boolean reconnectToLastServer = node.getNode("reconnect-to-last-server").getBoolean(); - boolean handleMotd = node.getNode("handle-motd").getBoolean(true); - plugin.logInfo("handle reconnect to last server: {}", reconnectToLastServer); - plugin.logInfo("handle motd: {}", handleMotd); + boolean reconnectToLastServer = node.getNode("reconnect-to-last-server").getBoolean(); + boolean handleMotd = node.getNode("handle-motd").getBoolean(true); + plugin.logInfo("handle reconnect to last server: {}", reconnectToLastServer); + plugin.logInfo("handle motd: {}", handleMotd); - HandleMotdOrder handleMotdOrder = HandleMotdOrder.NORMAL; - String handleMotdOrderName = node.getNode("handle-motd-priority").getString(); - if (handleMotdOrderName != null) { - try { - handleMotdOrder = HandleMotdOrder.valueOf(handleMotdOrderName.toUpperCase(Locale.ROOT)); - } catch (IllegalArgumentException e) { - plugin.logWarn("handle motd order value '{}' is unsupported (allowed: {})", handleMotdOrderName, HandleMotdOrder.values()); - } - } - plugin.logInfo("handle motd order: {}", handleMotdOrder); + HandleMotdOrder handleMotdOrder = HandleMotdOrder.NORMAL; + String handleMotdOrderName = node.getNode("handle-motd-priority").getString(); + if (handleMotdOrderName != null) { + try { + handleMotdOrder = HandleMotdOrder.valueOf(handleMotdOrderName.toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException e) { + plugin.logWarn( + "handle motd order value '{}' is unsupported (allowed: {})", + handleMotdOrderName, + HandleMotdOrder.values()); + } + } + plugin.logInfo("handle motd order: {}", handleMotdOrder); - // commands - boolean redisBungeeEnabled = node.getNode("commands", "redisbungee", "enabled").getBoolean(true); - boolean redisBungeeLegacyEnabled =node.getNode("commands", "redisbungee-legacy", "enabled").getBoolean(false); + // commands + boolean redisBungeeEnabled = + node.getNode("commands", "redisbungee", "enabled").getBoolean(true); + boolean redisBungeeLegacyEnabled = + node.getNode("commands", "redisbungee-legacy", "enabled").getBoolean(false); - boolean glistEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "glist", "enabled").getBoolean(false); - boolean findEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "find", "enabled").getBoolean(false); - boolean lastseenEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "lastseen", "enabled").getBoolean(false); - boolean ipEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "ip", "enabled").getBoolean(false); - boolean pproxyEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "pproxy", "enabled").getBoolean(false); - boolean sendToAllEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "sendtoall", "enabled").getBoolean(false); - boolean serverIdEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "serverid", "enabled").getBoolean(false); - boolean serverIdsEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "serverids", "enabled").getBoolean(false); - boolean pListEnabled = node.getNode("commands", "redisbungee-legacy", "subcommands", "plist", "enabled").getBoolean(false); + boolean glistEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "glist", "enabled") + .getBoolean(false); + boolean findEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "find", "enabled") + .getBoolean(false); + boolean lastseenEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "lastseen", "enabled") + .getBoolean(false); + boolean ipEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "ip", "enabled") + .getBoolean(false); + boolean pproxyEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "pproxy", "enabled") + .getBoolean(false); + boolean sendToAllEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "sendtoall", "enabled") + .getBoolean(false); + boolean serverIdEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "serverid", "enabled") + .getBoolean(false); + boolean serverIdsEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "serverids", "enabled") + .getBoolean(false); + boolean pListEnabled = + node.getNode("commands", "redisbungee-legacy", "subcommands", "plist", "enabled") + .getBoolean(false); - boolean installGlist = node.getNode("commands", "redisbungee-legacy", "subcommands", "glist", "install").getBoolean(false); - boolean installFind = node.getNode("commands", "redisbungee-legacy", "subcommands", "find", "install").getBoolean(false); - boolean installLastseen = node.getNode("commands", "redisbungee-legacy", "subcommands", "lastseen", "install").getBoolean(false); - boolean installIp = node.getNode("commands", "redisbungee-legacy", "subcommands", "ip", "install").getBoolean(false); - boolean installPproxy = node.getNode("commands", "redisbungee-legacy", "subcommands", "pproxy", "install").getBoolean(false); - boolean installSendToAll = node.getNode("commands", "redisbungee-legacy", "subcommands", "sendtoall", "install").getBoolean(false); - boolean installServerid = node.getNode("commands", "redisbungee-legacy", "subcommands", "serverid", "install").getBoolean(false); - boolean installServerIds = node.getNode("commands", "redisbungee-legacy", "subcommands", "serverids", "install").getBoolean(false); - boolean installPlist = node.getNode("commands", "redisbungee-legacy", "subcommands", "plist", "install").getBoolean(false); + boolean installGlist = + node.getNode("commands", "redisbungee-legacy", "subcommands", "glist", "install") + .getBoolean(false); + boolean installFind = + node.getNode("commands", "redisbungee-legacy", "subcommands", "find", "install") + .getBoolean(false); + boolean installLastseen = + node.getNode("commands", "redisbungee-legacy", "subcommands", "lastseen", "install") + .getBoolean(false); + boolean installIp = + node.getNode("commands", "redisbungee-legacy", "subcommands", "ip", "install") + .getBoolean(false); + boolean installPproxy = + node.getNode("commands", "redisbungee-legacy", "subcommands", "pproxy", "install") + .getBoolean(false); + boolean installSendToAll = + node.getNode("commands", "redisbungee-legacy", "subcommands", "sendtoall", "install") + .getBoolean(false); + boolean installServerid = + node.getNode("commands", "redisbungee-legacy", "subcommands", "serverid", "install") + .getBoolean(false); + boolean installServerIds = + node.getNode("commands", "redisbungee-legacy", "subcommands", "serverids", "install") + .getBoolean(false); + boolean installPlist = + node.getNode("commands", "redisbungee-legacy", "subcommands", "plist", "install") + .getBoolean(false); - - RedisBungeeConfiguration configuration = new RedisBungeeConfiguration(networkId, proxyId, exemptAddresses, kickWhenOnline, reconnectToLastServer, handleMotd, handleMotdOrder, + RedisBungeeConfiguration configuration = + new RedisBungeeConfiguration( + networkId, + proxyId, + exemptAddresses, + kickWhenOnline, + reconnectToLastServer, + handleMotd, + handleMotdOrder, new RedisBungeeConfiguration.CommandsConfiguration( - redisBungeeEnabled, redisBungeeLegacyEnabled, + redisBungeeEnabled, + redisBungeeLegacyEnabled, new RedisBungeeConfiguration.LegacySubCommandsConfiguration( - findEnabled, glistEnabled, ipEnabled, - lastseenEnabled, pListEnabled, pproxyEnabled, - sendToAllEnabled, serverIdEnabled, serverIdsEnabled, - installFind, installGlist, installIp, - installLastseen, installPlist, installPproxy, - installSendToAll, installServerid, installServerIds) - )); - Summoner summoner; - RedisBungeeMode redisBungeeMode; - if (useSSL) { - plugin.logInfo("Using ssl"); - } - if (node.getNode("cluster-mode-enabled").getBoolean(false)) { - plugin.logInfo("RedisBungee MODE: CLUSTER"); - Set hostAndPortSet = new HashSet<>(); - GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); - poolConfig.setMaxTotal(maxConnections); - poolConfig.setBlockWhenExhausted(true); - node.getNode("redis-cluster-servers").getChildrenList().forEach((childNode) -> { + findEnabled, + glistEnabled, + ipEnabled, + lastseenEnabled, + pListEnabled, + pproxyEnabled, + sendToAllEnabled, + serverIdEnabled, + serverIdsEnabled, + installFind, + installGlist, + installIp, + installLastseen, + installPlist, + installPproxy, + installSendToAll, + installServerid, + installServerIds))); + Summoner summoner; + RedisBungeeMode redisBungeeMode; + if (useSSL) { + plugin.logInfo("Using ssl"); + } + if (node.getNode("cluster-mode-enabled").getBoolean(false)) { + plugin.logInfo("RedisBungee MODE: CLUSTER"); + Set hostAndPortSet = new HashSet<>(); + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); + poolConfig.setMaxTotal(maxConnections); + poolConfig.setBlockWhenExhausted(true); + node.getNode("redis-cluster-servers") + .getChildrenList() + .forEach( + (childNode) -> { Map hostAndPort = childNode.getChildrenMap(); String host = hostAndPort.get("host").getString(); int port = hostAndPort.get("port").getInt(); hostAndPortSet.add(new HostAndPort(host, port)); - }); - plugin.logInfo(hostAndPortSet.size() + " cluster nodes were specified"); - if (hostAndPortSet.isEmpty()) { - throw new RuntimeException("No redis cluster servers specified"); - } - summoner = new JedisClusterSummoner(new ClusterConnectionProvider(hostAndPortSet, DefaultJedisClientConfig.builder().user(redisUsername).password(redisPassword).ssl(useSSL).socketTimeoutMillis(5000).timeoutMillis(10000).build(), poolConfig)); - redisBungeeMode = RedisBungeeMode.CLUSTER; - } else { - plugin.logInfo("RedisBungee MODE: SINGLE"); - final String redisServer = node.getNode("redis-server").getString("127.0.0.1"); - final int redisPort = node.getNode("redis-port").getInt(6379); - if (redisServer != null && redisServer.isEmpty()) { - throw new RuntimeException("No redis server specified"); - } - JedisPool jedisPool = null; - if (node.getNode("enable-jedis-pool-compatibility").getBoolean(false)) { - JedisPoolConfig config = new JedisPoolConfig(); - config.setMaxTotal(node.getNode("compatibility-max-connections").getInt(3)); - config.setBlockWhenExhausted(true); - jedisPool = new JedisPool(config, redisServer, redisPort, 5000, redisUsername, redisPassword, useSSL); - plugin.logInfo("Compatibility JedisPool was created"); - } - GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); - poolConfig.setMaxTotal(maxConnections); - poolConfig.setBlockWhenExhausted(true); - summoner = new JedisPooledSummoner(new PooledConnectionProvider(new ConnectionFactory(new HostAndPort(redisServer, redisPort), DefaultJedisClientConfig.builder().user(redisUsername).timeoutMillis(5000).ssl(useSSL).password(redisPassword).build()), poolConfig), jedisPool); - redisBungeeMode = RedisBungeeMode.SINGLE; - } - plugin.logInfo("Successfully connected to Redis."); - onConfigLoad(configuration, summoner, redisBungeeMode); + }); + plugin.logInfo(hostAndPortSet.size() + " cluster nodes were specified"); + if (hostAndPortSet.isEmpty()) { + throw new RuntimeException("No redis cluster servers specified"); + } + summoner = + new JedisClusterSummoner( + new ClusterConnectionProvider( + hostAndPortSet, + DefaultJedisClientConfig.builder() + .user(redisUsername) + .password(redisPassword) + .ssl(useSSL) + .socketTimeoutMillis(5000) + .timeoutMillis(10000) + .build(), + poolConfig)); + redisBungeeMode = RedisBungeeMode.CLUSTER; + } else { + plugin.logInfo("RedisBungee MODE: SINGLE"); + final String redisServer = node.getNode("redis-server").getString("127.0.0.1"); + final int redisPort = node.getNode("redis-port").getInt(6379); + if (redisServer != null && redisServer.isEmpty()) { + throw new RuntimeException("No redis server specified"); + } + JedisPool jedisPool = null; + if (node.getNode("enable-jedis-pool-compatibility").getBoolean(false)) { + JedisPoolConfig config = new JedisPoolConfig(); + config.setMaxTotal(node.getNode("compatibility-max-connections").getInt(3)); + config.setBlockWhenExhausted(true); + jedisPool = + new JedisPool( + config, redisServer, redisPort, 5000, redisUsername, redisPassword, useSSL); + plugin.logInfo("Compatibility JedisPool was created"); + } + GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); + poolConfig.setMaxTotal(maxConnections); + poolConfig.setBlockWhenExhausted(true); + summoner = + new JedisPooledSummoner( + new PooledConnectionProvider( + new ConnectionFactory( + new HostAndPort(redisServer, redisPort), + DefaultJedisClientConfig.builder() + .user(redisUsername) + .timeoutMillis(5000) + .ssl(useSSL) + .password(redisPassword) + .build()), + poolConfig), + jedisPool); + redisBungeeMode = RedisBungeeMode.SINGLE; } + plugin.logInfo("Successfully connected to Redis."); + onConfigLoad(configuration, summoner, redisBungeeMode); + } - void onConfigLoad(RedisBungeeConfiguration configuration, Summoner summoner, RedisBungeeMode mode); - - + void onConfigLoad( + RedisBungeeConfiguration configuration, Summoner summoner, RedisBungeeMode mode); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/loaders/GenericConfigLoader.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/loaders/GenericConfigLoader.java index 78a5d29..6186cb5 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/loaders/GenericConfigLoader.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/config/loaders/GenericConfigLoader.java @@ -1,58 +1,56 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.config.loaders; -import org.jetbrains.annotations.Nullable; - import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.time.Instant; - +import org.jetbrains.annotations.Nullable; public interface GenericConfigLoader { - // CHANGES on every reboot - String RANDOM_OLD = "backup-" + Instant.now().getEpochSecond(); + // CHANGES on every reboot + String RANDOM_OLD = "backup-" + Instant.now().getEpochSecond(); - default Path createConfigFile(Path dataFolder, String configFile, @Nullable String defaultResourceID) throws IOException { - if (Files.notExists(dataFolder)) { - Files.createDirectory(dataFolder); - } - Path file = dataFolder.resolve(configFile); - if (Files.notExists(file) && defaultResourceID != null) { - try (InputStream in = getClass().getClassLoader().getResourceAsStream(defaultResourceID)) { - Files.createFile(file); - assert in != null; - Files.copy(in, file, StandardCopyOption.REPLACE_EXISTING); - } - } - return file; + default Path createConfigFile( + Path dataFolder, String configFile, @Nullable String defaultResourceID) throws IOException { + if (Files.notExists(dataFolder)) { + Files.createDirectory(dataFolder); } - - default void handleOldConfig(Path dataFolder, String configFile, @Nullable String defaultResourceID) throws IOException { - Path oldConfigFolder = dataFolder.resolve("old_config"); - if (Files.notExists(oldConfigFolder)) { - Files.createDirectory(oldConfigFolder); - } - Path randomStoreConfigDirectory = oldConfigFolder.resolve(RANDOM_OLD); - if (Files.notExists(randomStoreConfigDirectory)) { - Files.createDirectory(randomStoreConfigDirectory); - } - Path oldConfigPath = dataFolder.resolve(configFile); - - Files.move(oldConfigPath, randomStoreConfigDirectory.resolve(configFile)); - createConfigFile(dataFolder, configFile, defaultResourceID); + Path file = dataFolder.resolve(configFile); + if (Files.notExists(file) && defaultResourceID != null) { + try (InputStream in = getClass().getClassLoader().getResourceAsStream(defaultResourceID)) { + Files.createFile(file); + assert in != null; + Files.copy(in, file, StandardCopyOption.REPLACE_EXISTING); + } } + return file; + } + default void handleOldConfig( + Path dataFolder, String configFile, @Nullable String defaultResourceID) throws IOException { + Path oldConfigFolder = dataFolder.resolve("old_config"); + if (Files.notExists(oldConfigFolder)) { + Files.createDirectory(oldConfigFolder); + } + Path randomStoreConfigDirectory = oldConfigFolder.resolve(RANDOM_OLD); + if (Files.notExists(randomStoreConfigDirectory)) { + Files.createDirectory(randomStoreConfigDirectory); + } + Path oldConfigPath = dataFolder.resolve(configFile); + + Files.move(oldConfigPath, randomStoreConfigDirectory.resolve(configFile)); + createConfigFile(dataFolder, configFile, defaultResourceID); + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/EventsPlatform.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/EventsPlatform.java index 79dabfa..1a970c0 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/EventsPlatform.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/EventsPlatform.java @@ -1,33 +1,33 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.events; import java.util.UUID; /** - * Since each platform have their own events' implementation for example Bungeecord events extends Event while velocity don't + * Since each platform have their own events' implementation for example Bungeecord events extends + * Event while velocity don't * * @author Ham1255 * @since 0.7.0 */ public interface EventsPlatform { - IPlayerChangedServerNetworkEvent createPlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server); + IPlayerChangedServerNetworkEvent createPlayerChangedServerNetworkEvent( + UUID uuid, String previousServer, String server); - IPlayerJoinedNetworkEvent createPlayerJoinedNetworkEvent(UUID uuid); + IPlayerJoinedNetworkEvent createPlayerJoinedNetworkEvent(UUID uuid); - IPlayerLeftNetworkEvent createPlayerLeftNetworkEvent(UUID uuid); + IPlayerLeftNetworkEvent createPlayerLeftNetworkEvent(UUID uuid); - IPubSubMessageEvent createPubSubEvent(String channel, String message); - - void fireEvent(Object event); + IPubSubMessageEvent createPubSubEvent(String channel, String message); + void fireEvent(Object event); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerChangedServerNetworkEvent.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerChangedServerNetworkEvent.java index 4b93759..78e48da 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerChangedServerNetworkEvent.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerChangedServerNetworkEvent.java @@ -1,23 +1,21 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.events; import java.util.UUID; public interface IPlayerChangedServerNetworkEvent extends RedisBungeeEvent { - UUID getUuid(); + UUID getUuid(); - String getServer(); - - String getPreviousServer(); + String getServer(); + String getPreviousServer(); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerJoinedNetworkEvent.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerJoinedNetworkEvent.java index 14db7b7..cdf929a 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerJoinedNetworkEvent.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerJoinedNetworkEvent.java @@ -1,19 +1,17 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.events; import java.util.UUID; public interface IPlayerJoinedNetworkEvent extends RedisBungeeEvent { - UUID getUuid(); - + UUID getUuid(); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerLeftNetworkEvent.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerLeftNetworkEvent.java index a7b6092..c07821e 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerLeftNetworkEvent.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPlayerLeftNetworkEvent.java @@ -1,19 +1,17 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.events; import java.util.UUID; public interface IPlayerLeftNetworkEvent extends RedisBungeeEvent { - UUID getUuid(); - + UUID getUuid(); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPubSubMessageEvent.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPubSubMessageEvent.java index a419e1c..3563777 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPubSubMessageEvent.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/IPubSubMessageEvent.java @@ -1,20 +1,17 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.events; public interface IPubSubMessageEvent extends RedisBungeeEvent { - String getChannel(); - - String getMessage(); - + String getChannel(); + String getMessage(); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/RedisBungeeEvent.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/RedisBungeeEvent.java index 63d1ab6..544c075 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/RedisBungeeEvent.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/events/RedisBungeeEvent.java @@ -1,14 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.events; -interface RedisBungeeEvent { -} +interface RedisBungeeEvent {} diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/AbstractPayload.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/AbstractPayload.java index e41ee5f..4249d67 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/AbstractPayload.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/AbstractPayload.java @@ -1,24 +1,31 @@ - +/* +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads; public abstract class AbstractPayload { - private final String senderProxy; + private final String senderProxy; - public AbstractPayload(String proxyId) { - this.senderProxy = proxyId; - } + public AbstractPayload(String proxyId) { + this.senderProxy = proxyId; + } - public AbstractPayload(String senderProxy, String className) { - this.senderProxy = senderProxy; - } + public AbstractPayload(String senderProxy, String className) { + this.senderProxy = senderProxy; + } - public String senderProxy() { - return senderProxy; - } - - public String getClassName() { - return getClass().getName(); - } + public String senderProxy() { + return senderProxy; + } + public String getClassName() { + return getClass().getName(); + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/gson/AbstractPayloadSerializer.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/gson/AbstractPayloadSerializer.java index 6769ff2..839c770 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/gson/AbstractPayloadSerializer.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/gson/AbstractPayloadSerializer.java @@ -1,34 +1,35 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.gson; import com.google.gson.*; import com.imaginarycode.minecraft.redisbungee.api.payloads.AbstractPayload; - import java.lang.reflect.Type; -public class AbstractPayloadSerializer implements JsonSerializer, JsonDeserializer { +public class AbstractPayloadSerializer + implements JsonSerializer, JsonDeserializer { + @Override + public AbstractPayload deserialize( + JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + return new AbstractPayload( + jsonObject.get("proxy").getAsString(), jsonObject.get("class").getAsString()) {}; + } - @Override - public AbstractPayload deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonObject jsonObject = json.getAsJsonObject(); - return new AbstractPayload(jsonObject.get("proxy").getAsString(), jsonObject.get("class").getAsString()) { - }; - } - - @Override - public JsonElement serialize(AbstractPayload src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject jsonObject = new JsonObject(); - jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); - return jsonObject; - } + @Override + public JsonElement serialize( + AbstractPayload src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jsonObject = new JsonObject(); + jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); + return jsonObject; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/DeathPayload.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/DeathPayload.java index 399071a..8c7cc3b 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/DeathPayload.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/DeathPayload.java @@ -1,19 +1,18 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.proxy; import com.imaginarycode.minecraft.redisbungee.api.payloads.AbstractPayload; public class DeathPayload extends AbstractPayload { - public DeathPayload(String proxyId) { - super(proxyId); - } + public DeathPayload(String proxyId) { + super(proxyId); + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/HeartbeatPayload.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/HeartbeatPayload.java index 02268fd..ad9005a 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/HeartbeatPayload.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/HeartbeatPayload.java @@ -1,31 +1,28 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.proxy; import com.imaginarycode.minecraft.redisbungee.api.payloads.AbstractPayload; public class HeartbeatPayload extends AbstractPayload { - public record HeartbeatData(long heartbeat, int players) { + public record HeartbeatData(long heartbeat, int players) {} - } + private final HeartbeatData data; - private final HeartbeatData data; + public HeartbeatPayload(String proxyId, HeartbeatData data) { + super(proxyId); + this.data = data; + } - public HeartbeatPayload(String proxyId, HeartbeatData data) { - super(proxyId); - this.data = data; - } - - public HeartbeatData data() { - return data; - } + public HeartbeatData data() { + return data; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/PubSubPayload.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/PubSubPayload.java index eaa9092..8b50b5d 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/PubSubPayload.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/PubSubPayload.java @@ -1,34 +1,32 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.proxy; import com.imaginarycode.minecraft.redisbungee.api.payloads.AbstractPayload; public class PubSubPayload extends AbstractPayload { - private final String channel; - private final String message; + private final String channel; + private final String message; + public PubSubPayload(String proxyId, String channel, String message) { + super(proxyId); + this.channel = channel; + this.message = message; + } - public PubSubPayload(String proxyId, String channel, String message) { - super(proxyId); - this.channel = channel; - this.message = message; - } + public String channel() { + return channel; + } - public String channel() { - return channel; - } - - public String message() { - return message; - } + public String message() { + return message; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/RunCommandPayload.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/RunCommandPayload.java index 6374e5c..5c13521 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/RunCommandPayload.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/RunCommandPayload.java @@ -1,36 +1,33 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.proxy; import com.imaginarycode.minecraft.redisbungee.api.payloads.AbstractPayload; public class RunCommandPayload extends AbstractPayload { + private final String proxyToRun; - private final String proxyToRun; + private final String command; - private final String command; + public RunCommandPayload(String proxyId, String proxyToRun, String command) { + super(proxyId); + this.proxyToRun = proxyToRun; + this.command = command; + } + public String proxyToRun() { + return proxyToRun; + } - public RunCommandPayload(String proxyId, String proxyToRun, String command) { - super(proxyId); - this.proxyToRun = proxyToRun; - this.command = command; - } - - public String proxyToRun() { - return proxyToRun; - } - - public String command() { - return command; - } + public String command() { + return command; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/DeathPayloadSerializer.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/DeathPayloadSerializer.java index d77dd51..464dedb 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/DeathPayloadSerializer.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/DeathPayloadSerializer.java @@ -1,36 +1,36 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson; import com.google.gson.*; import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.DeathPayload; - import java.lang.reflect.Type; -public class DeathPayloadSerializer implements JsonSerializer, JsonDeserializer { +public class DeathPayloadSerializer + implements JsonSerializer, JsonDeserializer { - private static final Gson gson = new Gson(); + private static final Gson gson = new Gson(); + @Override + public DeathPayload deserialize( + JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + String senderProxy = jsonObject.get("proxy").getAsString(); + return new DeathPayload(senderProxy); + } - @Override - public DeathPayload deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonObject jsonObject = json.getAsJsonObject(); - String senderProxy = jsonObject.get("proxy").getAsString(); - return new DeathPayload(senderProxy); - } - - @Override - public JsonElement serialize(DeathPayload src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject jsonObject = new JsonObject(); - jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); - return jsonObject; - } + @Override + public JsonElement serialize(DeathPayload src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jsonObject = new JsonObject(); + jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); + return jsonObject; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/HeartbeatPayloadSerializer.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/HeartbeatPayloadSerializer.java index 1f301f2..f272ea3 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/HeartbeatPayloadSerializer.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/HeartbeatPayloadSerializer.java @@ -1,38 +1,40 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson; import com.google.gson.*; import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.HeartbeatPayload; - import java.lang.reflect.Type; -public class HeartbeatPayloadSerializer implements JsonSerializer, JsonDeserializer { +public class HeartbeatPayloadSerializer + implements JsonSerializer, JsonDeserializer { + @Override + public HeartbeatPayload deserialize( + JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + String senderProxy = jsonObject.get("proxy").getAsString(); + long heartbeat = jsonObject.get("heartbeat").getAsLong(); + int players = jsonObject.get("players").getAsInt(); + return new HeartbeatPayload( + senderProxy, new HeartbeatPayload.HeartbeatData(heartbeat, players)); + } - @Override - public HeartbeatPayload deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonObject jsonObject = json.getAsJsonObject(); - String senderProxy = jsonObject.get("proxy").getAsString(); - long heartbeat = jsonObject.get("heartbeat").getAsLong(); - int players = jsonObject.get("players").getAsInt(); - return new HeartbeatPayload(senderProxy, new HeartbeatPayload.HeartbeatData(heartbeat, players)); - } - - @Override - public JsonElement serialize(HeartbeatPayload src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject jsonObject = new JsonObject(); - jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); - jsonObject.add("heartbeat", new JsonPrimitive(src.data().heartbeat())); - jsonObject.add("players", new JsonPrimitive(src.data().players())); - return jsonObject; - } + @Override + public JsonElement serialize( + HeartbeatPayload src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jsonObject = new JsonObject(); + jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); + jsonObject.add("heartbeat", new JsonPrimitive(src.data().heartbeat())); + jsonObject.add("players", new JsonPrimitive(src.data().players())); + return jsonObject; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/PubSubPayloadSerializer.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/PubSubPayloadSerializer.java index 01d66a5..eb568fe 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/PubSubPayloadSerializer.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/PubSubPayloadSerializer.java @@ -1,40 +1,41 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson; import com.google.gson.*; import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.PubSubPayload; - import java.lang.reflect.Type; -public class PubSubPayloadSerializer implements JsonSerializer, JsonDeserializer { +public class PubSubPayloadSerializer + implements JsonSerializer, JsonDeserializer { - private static final Gson gson = new Gson(); + private static final Gson gson = new Gson(); + @Override + public PubSubPayload deserialize( + JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + String senderProxy = jsonObject.get("proxy").getAsString(); + String channel = jsonObject.get("channel").getAsString(); + String message = jsonObject.get("message").getAsString(); + return new PubSubPayload(senderProxy, channel, message); + } - @Override - public PubSubPayload deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonObject jsonObject = json.getAsJsonObject(); - String senderProxy = jsonObject.get("proxy").getAsString(); - String channel = jsonObject.get("channel").getAsString(); - String message = jsonObject.get("message").getAsString(); - return new PubSubPayload(senderProxy, channel, message); - } - - @Override - public JsonElement serialize(PubSubPayload src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject jsonObject = new JsonObject(); - jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); - jsonObject.add("channel", new JsonPrimitive(src.channel())); - jsonObject.add("message", context.serialize(src.message())); - return jsonObject; - } + @Override + public JsonElement serialize( + PubSubPayload src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jsonObject = new JsonObject(); + jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); + jsonObject.add("channel", new JsonPrimitive(src.channel())); + jsonObject.add("message", context.serialize(src.message())); + return jsonObject; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/RunCommandPayloadSerializer.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/RunCommandPayloadSerializer.java index 2a7de33..0887838 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/RunCommandPayloadSerializer.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/payloads/proxy/gson/RunCommandPayloadSerializer.java @@ -1,38 +1,39 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.gson; import com.google.gson.*; import com.imaginarycode.minecraft.redisbungee.api.payloads.proxy.RunCommandPayload; - import java.lang.reflect.Type; -public class RunCommandPayloadSerializer implements JsonSerializer, JsonDeserializer { +public class RunCommandPayloadSerializer + implements JsonSerializer, JsonDeserializer { + @Override + public RunCommandPayload deserialize( + JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + String senderProxy = jsonObject.get("proxy").getAsString(); + String proxyToRun = jsonObject.get("proxy-to-run").getAsString(); + String command = jsonObject.get("command").getAsString(); + return new RunCommandPayload(senderProxy, proxyToRun, command); + } - @Override - public RunCommandPayload deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonObject jsonObject = json.getAsJsonObject(); - String senderProxy = jsonObject.get("proxy").getAsString(); - String proxyToRun = jsonObject.get("proxy-to-run").getAsString(); - String command = jsonObject.get("command").getAsString(); - return new RunCommandPayload(senderProxy, proxyToRun, command); - } - - @Override - public JsonElement serialize(RunCommandPayload src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject jsonObject = new JsonObject(); - jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); - jsonObject.add("proxy-to-run", new JsonPrimitive(src.proxyToRun())); - jsonObject.add("command", context.serialize(src.command())); - return jsonObject; - } + @Override + public JsonElement serialize( + RunCommandPayload src, Type typeOfSrc, JsonSerializationContext context) { + JsonObject jsonObject = new JsonObject(); + jsonObject.add("proxy", new JsonPrimitive(src.senderProxy())); + jsonObject.add("proxy-to-run", new JsonPrimitive(src.proxyToRun())); + jsonObject.add("command", context.serialize(src.command())); + return jsonObject; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/JedisClusterSummoner.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/JedisClusterSummoner.java index 14c2514..f4eb4d6 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/JedisClusterSummoner.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/JedisClusterSummoner.java @@ -1,42 +1,37 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.summoners; -import redis.clients.jedis.JedisCluster; -import redis.clients.jedis.providers.ClusterConnectionProvider; - import java.io.IOException; import java.time.Duration; +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.providers.ClusterConnectionProvider; public class JedisClusterSummoner implements Summoner { - private final ClusterConnectionProvider clusterConnectionProvider; + private final ClusterConnectionProvider clusterConnectionProvider; - public JedisClusterSummoner(ClusterConnectionProvider clusterConnectionProvider) { - this.clusterConnectionProvider = clusterConnectionProvider; - // test the connection - JedisCluster jedisCluster = obtainResource(); - jedisCluster.set("random_data", "0"); - jedisCluster.del("random_data"); - } - - - @Override - public void close() throws IOException { - this.clusterConnectionProvider.close(); - } - - @Override - public JedisCluster obtainResource() { - return new NotClosableJedisCluster(this.clusterConnectionProvider, 60, Duration.ofSeconds(10)); - } + public JedisClusterSummoner(ClusterConnectionProvider clusterConnectionProvider) { + this.clusterConnectionProvider = clusterConnectionProvider; + // test the connection + JedisCluster jedisCluster = obtainResource(); + jedisCluster.set("random_data", "0"); + jedisCluster.del("random_data"); + } + @Override + public void close() throws IOException { + this.clusterConnectionProvider.close(); + } + @Override + public JedisCluster obtainResource() { + return new NotClosableJedisCluster(this.clusterConnectionProvider, 60, Duration.ofSeconds(10)); + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/JedisPooledSummoner.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/JedisPooledSummoner.java index f0dd2b5..5ef3257 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/JedisPooledSummoner.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/JedisPooledSummoner.java @@ -1,60 +1,55 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.summoners; +import java.io.IOException; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPooled; import redis.clients.jedis.providers.PooledConnectionProvider; -import java.io.IOException; - public class JedisPooledSummoner implements Summoner { - private final PooledConnectionProvider connectionProvider; - private final JedisPool jedisPool; - - public JedisPooledSummoner(PooledConnectionProvider connectionProvider, JedisPool jedisPool) { - this.connectionProvider = connectionProvider; - this.jedisPool = jedisPool; - // test connections - if (jedisPool != null) { - try (Jedis jedis = this.jedisPool.getResource()) { - // Test the connection to make sure configuration is right - jedis.ping(); - } - - } - final JedisPooled jedisPooled = this.obtainResource(); - jedisPooled.set("random_data", "0"); - jedisPooled.del("random_data"); + private final PooledConnectionProvider connectionProvider; + private final JedisPool jedisPool; + public JedisPooledSummoner(PooledConnectionProvider connectionProvider, JedisPool jedisPool) { + this.connectionProvider = connectionProvider; + this.jedisPool = jedisPool; + // test connections + if (jedisPool != null) { + try (Jedis jedis = this.jedisPool.getResource()) { + // Test the connection to make sure configuration is right + jedis.ping(); + } } + final JedisPooled jedisPooled = this.obtainResource(); + jedisPooled.set("random_data", "0"); + jedisPooled.del("random_data"); + } - @Override - public JedisPooled obtainResource() { - // create UnClosable JedisPool *disposable* - return new NotClosableJedisPooled(this.connectionProvider); - } - - public JedisPool getCompatibilityJedisPool() { - return this.jedisPool; - } - - @Override - public void close() throws IOException { - if (this.jedisPool != null) { - this.jedisPool.close(); - } - this.connectionProvider.close(); - + @Override + public JedisPooled obtainResource() { + // create UnClosable JedisPool *disposable* + return new NotClosableJedisPooled(this.connectionProvider); + } + + public JedisPool getCompatibilityJedisPool() { + return this.jedisPool; + } + + @Override + public void close() throws IOException { + if (this.jedisPool != null) { + this.jedisPool.close(); } + this.connectionProvider.close(); + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/NotClosableJedisCluster.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/NotClosableJedisCluster.java index 5e09859..029a32f 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/NotClosableJedisCluster.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/NotClosableJedisCluster.java @@ -1,29 +1,25 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.summoners; +import java.time.Duration; import redis.clients.jedis.JedisCluster; import redis.clients.jedis.providers.ClusterConnectionProvider; -import java.time.Duration; - - public class NotClosableJedisCluster extends JedisCluster { - NotClosableJedisCluster(ClusterConnectionProvider provider, int maxAttempts, Duration maxTotalRetriesDuration) { - super(provider, maxAttempts, maxTotalRetriesDuration); - } + NotClosableJedisCluster( + ClusterConnectionProvider provider, int maxAttempts, Duration maxTotalRetriesDuration) { + super(provider, maxAttempts, maxTotalRetriesDuration); + } - @Override - public void close() { - - } + @Override + public void close() {} } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/NotClosableJedisPooled.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/NotClosableJedisPooled.java index 61e7caf..77fdbeb 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/NotClosableJedisPooled.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/NotClosableJedisPooled.java @@ -1,26 +1,22 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.summoners; import redis.clients.jedis.JedisPooled; import redis.clients.jedis.providers.PooledConnectionProvider; - public class NotClosableJedisPooled extends JedisPooled { - NotClosableJedisPooled(PooledConnectionProvider provider) { - super(provider); - } + NotClosableJedisPooled(PooledConnectionProvider provider) { + super(provider); + } - @Override - public void close() { - - } + @Override + public void close() {} } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/Summoner.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/Summoner.java index 36beac5..f8228b2 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/Summoner.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/summoners/Summoner.java @@ -1,19 +1,16 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.summoners; -import redis.clients.jedis.UnifiedJedis; - import java.io.Closeable; - +import redis.clients.jedis.UnifiedJedis; /** * This class intended for future release to support redis sentinel or redis clusters @@ -23,6 +20,5 @@ import java.io.Closeable; */ public interface Summoner

extends Closeable { - P obtainResource(); - + P obtainResource(); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/RedisPipelineTask.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/RedisPipelineTask.java index 21a5d29..b3bd303 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/RedisPipelineTask.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/RedisPipelineTask.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.tasks; import com.imaginarycode.minecraft.redisbungee.AbstractRedisBungeeAPI; @@ -16,34 +15,30 @@ import redis.clients.jedis.*; public abstract class RedisPipelineTask extends RedisTask { + public RedisPipelineTask(AbstractRedisBungeeAPI api) { + super(api); + } - public RedisPipelineTask(AbstractRedisBungeeAPI api) { - super(api); + public RedisPipelineTask(RedisBungeePlugin plugin) { + super(plugin); + } + + @Override + public T unifiedJedisTask(UnifiedJedis unifiedJedis) { + if (unifiedJedis instanceof JedisPooled pooled) { + try (Pipeline pipeline = pooled.pipelined()) { + return doPooledPipeline(pipeline); + } + } else if (unifiedJedis instanceof JedisCluster jedisCluster) { + try (ClusterPipeline pipeline = jedisCluster.pipelined()) { + return clusterPipeline(pipeline); + } } - public RedisPipelineTask(RedisBungeePlugin plugin) { - super(plugin); - } - - - @Override - public T unifiedJedisTask(UnifiedJedis unifiedJedis) { - if (unifiedJedis instanceof JedisPooled pooled) { - try (Pipeline pipeline = pooled.pipelined()) { - return doPooledPipeline(pipeline); - } - } else if (unifiedJedis instanceof JedisCluster jedisCluster) { - try (ClusterPipeline pipeline = jedisCluster.pipelined()) { - return clusterPipeline(pipeline); - } - } - - return null; - } - - public abstract T doPooledPipeline(Pipeline pipeline); - - public abstract T clusterPipeline(ClusterPipeline pipeline); + return null; + } + public abstract T doPooledPipeline(Pipeline pipeline); + public abstract T clusterPipeline(ClusterPipeline pipeline); } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/RedisTask.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/RedisTask.java index 9a6da17..0e8043f 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/RedisTask.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/RedisTask.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.tasks; import com.imaginarycode.minecraft.redisbungee.AbstractRedisBungeeAPI; @@ -16,52 +15,51 @@ import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.api.summoners.JedisClusterSummoner; import com.imaginarycode.minecraft.redisbungee.api.summoners.JedisPooledSummoner; import com.imaginarycode.minecraft.redisbungee.api.summoners.Summoner; +import java.util.concurrent.Callable; import redis.clients.jedis.UnifiedJedis; -import java.util.concurrent.Callable; - /** - * Since Jedis now have UnifiedJedis which basically extended by cluster / single connections classes - * can help us to have shared code. + * Since Jedis now have UnifiedJedis which basically extended by cluster / single connections + * classes can help us to have shared code. */ public abstract class RedisTask implements Runnable, Callable { - protected final Summoner summoner; + protected final Summoner summoner; - protected final RedisBungeeMode mode; + protected final RedisBungeeMode mode; - @Override - public V call() throws Exception { - return this.execute(); + @Override + public V call() throws Exception { + return this.execute(); + } + + public RedisTask(AbstractRedisBungeeAPI api) { + this.summoner = api.getSummoner(); + this.mode = api.getMode(); + } + + public RedisTask(RedisBungeePlugin plugin) { + this.summoner = plugin.getSummoner(); + this.mode = plugin.getRedisBungeeMode(); + } + + public abstract V unifiedJedisTask(UnifiedJedis unifiedJedis); + + @Override + public void run() { + this.execute(); + } + + public V execute() { + // JedisCluster, JedisPooled in fact is just UnifiedJedis does not need new instance since its + // single instance anyway. + if (mode == RedisBungeeMode.SINGLE) { + JedisPooledSummoner jedisSummoner = (JedisPooledSummoner) summoner; + return this.unifiedJedisTask(jedisSummoner.obtainResource()); + } else if (mode == RedisBungeeMode.CLUSTER) { + JedisClusterSummoner jedisClusterSummoner = (JedisClusterSummoner) summoner; + return this.unifiedJedisTask(jedisClusterSummoner.obtainResource()); } - - public RedisTask(AbstractRedisBungeeAPI api) { - this.summoner = api.getSummoner(); - this.mode = api.getMode(); - } - - public RedisTask(RedisBungeePlugin plugin) { - this.summoner = plugin.getSummoner(); - this.mode = plugin.getRedisBungeeMode(); - } - - public abstract V unifiedJedisTask(UnifiedJedis unifiedJedis); - - @Override - public void run() { - this.execute(); - } - - public V execute() { - // JedisCluster, JedisPooled in fact is just UnifiedJedis does not need new instance since its single instance anyway. - if (mode == RedisBungeeMode.SINGLE) { - JedisPooledSummoner jedisSummoner = (JedisPooledSummoner) summoner; - return this.unifiedJedisTask(jedisSummoner.obtainResource()); - } else if (mode == RedisBungeeMode.CLUSTER) { - JedisClusterSummoner jedisClusterSummoner = (JedisClusterSummoner) summoner; - return this.unifiedJedisTask(jedisClusterSummoner.obtainResource()); - } - return null; - } - + return null; + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/UUIDCleanupTask.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/UUIDCleanupTask.java index 6e080c4..4e2d27a 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/UUIDCleanupTask.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/tasks/UUIDCleanupTask.java @@ -1,56 +1,54 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.tasks; import com.google.gson.Gson; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.api.util.uuid.CachedUUIDEntry; +import java.util.ArrayList; import redis.clients.jedis.UnifiedJedis; import redis.clients.jedis.exceptions.JedisException; -import java.util.ArrayList; +public class UUIDCleanupTask extends RedisTask { + private final Gson gson = new Gson(); + private final RedisBungeePlugin plugin; -public class UUIDCleanupTask extends RedisTask{ + public UUIDCleanupTask(RedisBungeePlugin plugin) { + super(plugin); + this.plugin = plugin; + } - private final Gson gson = new Gson(); - private final RedisBungeePlugin plugin; - - public UUIDCleanupTask(RedisBungeePlugin plugin) { - super(plugin); - this.plugin = plugin; - } - - // this code is inspired from https://github.com/minecrafter/redisbungeeclean - @Override - public Void unifiedJedisTask(UnifiedJedis unifiedJedis) { - try { - final long number = unifiedJedis.hlen("uuid-cache"); - plugin.logInfo("Found {} entries", number); - ArrayList fieldsToRemove = new ArrayList<>(); - unifiedJedis.hgetAll("uuid-cache").forEach((field, data) -> { + // this code is inspired from https://github.com/minecrafter/redisbungeeclean + @Override + public Void unifiedJedisTask(UnifiedJedis unifiedJedis) { + try { + final long number = unifiedJedis.hlen("uuid-cache"); + plugin.logInfo("Found {} entries", number); + ArrayList fieldsToRemove = new ArrayList<>(); + unifiedJedis + .hgetAll("uuid-cache") + .forEach( + (field, data) -> { CachedUUIDEntry cachedUUIDEntry = gson.fromJson(data, CachedUUIDEntry.class); if (cachedUUIDEntry.expired()) { - fieldsToRemove.add(field); + fieldsToRemove.add(field); } - }); - if (!fieldsToRemove.isEmpty()) { - unifiedJedis.hdel("uuid-cache", fieldsToRemove.toArray(new String[0])); - } - plugin.logInfo("deleted {} entries", fieldsToRemove.size()); - } catch (JedisException e) { - plugin.logFatal("There was an error fetching information", e); - } - return null; + }); + if (!fieldsToRemove.isEmpty()) { + unifiedJedis.hdel("uuid-cache", fieldsToRemove.toArray(new String[0])); + } + plugin.logInfo("deleted {} entries", fieldsToRemove.size()); + } catch (JedisException e) { + plugin.logFatal("There was an error fetching information", e); } - - -} \ No newline at end of file + return null; + } +} diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/InitialUtils.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/InitialUtils.java index db90cf3..abb5c1c 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/InitialUtils.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/InitialUtils.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.util; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; @@ -15,34 +14,39 @@ import com.imaginarycode.minecraft.redisbungee.api.tasks.RedisTask; import redis.clients.jedis.Protocol; import redis.clients.jedis.UnifiedJedis; - public class InitialUtils { - public static void checkRedisVersion(RedisBungeePlugin plugin) { - new RedisTask(plugin) { - @Override - public Void unifiedJedisTask(UnifiedJedis unifiedJedis) { - // This is more portable than INFO

- String info = new String((byte[]) unifiedJedis.sendCommand(Protocol.Command.INFO)); - for (String s : info.split("\r\n")) { - if (s.startsWith("redis_version:")) { - String version = s.split(":")[1]; - plugin.logInfo("Redis server version: " + version); - if (!RedisUtil.isRedisVersionRight(version)) { - plugin.logFatal("Your version of Redis (" + version + ") is not at least version " + RedisUtil.MAJOR_VERSION + "." + RedisUtil.MINOR_VERSION + " RedisBungee requires a newer version of Redis."); - throw new RuntimeException("Unsupported Redis version detected"); - } - long uuidCacheSize = unifiedJedis.hlen("uuid-cache"); - if (uuidCacheSize > 750000) { - plugin.logInfo("Looks like you have a really big UUID cache! Run '/rb clean' to remove expired cache entries"); - } - break; - } - } - return null; + public static void checkRedisVersion(RedisBungeePlugin plugin) { + new RedisTask(plugin) { + @Override + public Void unifiedJedisTask(UnifiedJedis unifiedJedis) { + // This is more portable than INFO
+ String info = new String((byte[]) unifiedJedis.sendCommand(Protocol.Command.INFO)); + for (String s : info.split("\r\n")) { + if (s.startsWith("redis_version:")) { + String version = s.split(":")[1]; + plugin.logInfo("Redis server version: " + version); + if (!RedisUtil.isRedisVersionRight(version)) { + plugin.logFatal( + "Your version of Redis (" + + version + + ") is not at least version " + + RedisUtil.MAJOR_VERSION + + "." + + RedisUtil.MINOR_VERSION + + " RedisBungee requires a newer version of Redis."); + throw new RuntimeException("Unsupported Redis version detected"); } - }.execute(); - } - - + long uuidCacheSize = unifiedJedis.hlen("uuid-cache"); + if (uuidCacheSize > 750000) { + plugin.logInfo( + "Looks like you have a really big UUID cache! Run '/rb clean' to remove expired cache entries"); + } + break; + } + } + return null; + } + }.execute(); + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/RedisUtil.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/RedisUtil.java index 7e337db..92e2ba7 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/RedisUtil.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/RedisUtil.java @@ -1,31 +1,39 @@ +/* +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.util; import com.google.common.annotations.VisibleForTesting; @VisibleForTesting public class RedisUtil { - public final static int PROXY_TIMEOUT = 30; + public static final int PROXY_TIMEOUT = 30; - public static final int MAJOR_VERSION = 6; - public static final int MINOR_VERSION = 2; - - public static boolean isRedisVersionRight(String redisVersion) { - String[] args = redisVersion.split("\\."); - if (args.length < 2) { - return false; - } - int major = Integer.parseInt(args[0]); - int minor = Integer.parseInt(args[1]); - - if (major > MAJOR_VERSION) return true; - return major == MAJOR_VERSION && minor >= MINOR_VERSION; + public static final int MAJOR_VERSION = 6; + public static final int MINOR_VERSION = 2; + public static boolean isRedisVersionRight(String redisVersion) { + String[] args = redisVersion.split("\\."); + if (args.length < 2) { + return false; } + int major = Integer.parseInt(args[0]); + int minor = Integer.parseInt(args[1]); - // Ham1255: i am keeping this if some plugin uses this *IF* - @Deprecated - public static boolean canUseLua(String redisVersion) { - // Need to use >=3 to use Lua optimizations. - return isRedisVersionRight(redisVersion); - } + if (major > MAJOR_VERSION) return true; + return major == MAJOR_VERSION && minor >= MINOR_VERSION; + } + + // Ham1255: i am keeping this if some plugin uses this *IF* + @Deprecated + public static boolean canUseLua(String redisVersion) { + // Need to use >=3 to use Lua optimizations. + return isRedisVersionRight(redisVersion); + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/serialize/MultiMapSerialization.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/serialize/MultiMapSerialization.java index 71df20b..59cf347 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/serialize/MultiMapSerialization.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/serialize/MultiMapSerialization.java @@ -1,40 +1,48 @@ +/* +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.util.serialize; import com.google.common.collect.Multimap; import com.google.common.collect.Multiset; import com.google.common.io.ByteArrayDataOutput; - import java.util.Collection; import java.util.Map; public class MultiMapSerialization { - public static void serializeMultiset(Multiset collection, ByteArrayDataOutput output) { - output.writeInt(collection.elementSet().size()); - for (Multiset.Entry entry : collection.entrySet()) { - output.writeUTF(entry.getElement()); - output.writeInt(entry.getCount()); - } + public static void serializeMultiset(Multiset collection, ByteArrayDataOutput output) { + output.writeInt(collection.elementSet().size()); + for (Multiset.Entry entry : collection.entrySet()) { + output.writeUTF(entry.getElement()); + output.writeInt(entry.getCount()); } + } - @SuppressWarnings("SameParameterValue") - public static void serializeMultimap(Multimap collection, boolean includeNames, ByteArrayDataOutput output) { - output.writeInt(collection.keySet().size()); - for (Map.Entry> entry : collection.asMap().entrySet()) { - output.writeUTF(entry.getKey()); - if (includeNames) { - serializeCollection(entry.getValue(), output); - } else { - output.writeInt(entry.getValue().size()); - } - } + @SuppressWarnings("SameParameterValue") + public static void serializeMultimap( + Multimap collection, boolean includeNames, ByteArrayDataOutput output) { + output.writeInt(collection.keySet().size()); + for (Map.Entry> entry : collection.asMap().entrySet()) { + output.writeUTF(entry.getKey()); + if (includeNames) { + serializeCollection(entry.getValue(), output); + } else { + output.writeInt(entry.getValue().size()); + } } + } - public static void serializeCollection(Collection collection, ByteArrayDataOutput output) { - output.writeInt(collection.size()); - for (Object o : collection) { - output.writeUTF(o.toString()); - } + public static void serializeCollection(Collection collection, ByteArrayDataOutput output) { + output.writeInt(collection.size()); + for (Object o : collection) { + output.writeUTF(o.toString()); } - + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/CachedUUIDEntry.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/CachedUUIDEntry.java index f3729f4..80f5def 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/CachedUUIDEntry.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/CachedUUIDEntry.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.util.uuid; import java.util.Calendar; @@ -15,7 +14,7 @@ import java.util.UUID; public record CachedUUIDEntry(String name, UUID uuid, Calendar expiry) { - public boolean expired() { - return Calendar.getInstance().after(expiry); - } + public boolean expired() { + return Calendar.getInstance().after(expiry); + } } diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/NameFetcher.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/NameFetcher.java index ea27697..6dd9ef4 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/NameFetcher.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/NameFetcher.java @@ -1,55 +1,54 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.util.uuid; import com.google.gson.Gson; import com.google.gson.JsonObject; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.ResponseBody; - import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.UUID; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.ResponseBody; public class NameFetcher { - private static final OkHttpClient httpClient = new OkHttpClient(); - private static final Gson gson = new Gson(); + private static final OkHttpClient httpClient = new OkHttpClient(); + private static final Gson gson = new Gson(); - public static List nameHistoryFromUuid(UUID uuid) throws IOException { - String name = getName(uuid); - if (name == null) return Collections.emptyList(); - return Collections.singletonList(name); - } + public static List nameHistoryFromUuid(UUID uuid) throws IOException { + String name = getName(uuid); + if (name == null) return Collections.emptyList(); + return Collections.singletonList(name); + } - public static String getName(UUID uuid) throws IOException { - String url = "https://playerdb.co/api/player/minecraft/" + uuid.toString(); - Request request = new Request.Builder() - .addHeader("User-Agent", "RedisBungee-ProxioDev") - .url(url) - .get() - .build(); - ResponseBody body = httpClient.newCall(request).execute().body(); - String response = body.string(); - body.close(); + public static String getName(UUID uuid) throws IOException { + String url = "https://playerdb.co/api/player/minecraft/" + uuid.toString(); + Request request = + new Request.Builder() + .addHeader("User-Agent", "RedisBungee-ProxioDev") + .url(url) + .get() + .build(); + ResponseBody body = httpClient.newCall(request).execute().body(); + String response = body.string(); + body.close(); - JsonObject json = gson.fromJson(response, JsonObject.class); - if (!json.has("success") || !json.get("success").getAsBoolean()) return null; - if (!json.has("data")) return null; - JsonObject data = json.getAsJsonObject("data"); - if (!data.has("player")) return null; - JsonObject player = data.getAsJsonObject("player"); - if (!player.has("username")) return null; + JsonObject json = gson.fromJson(response, JsonObject.class); + if (!json.has("success") || !json.get("success").getAsBoolean()) return null; + if (!json.has("data")) return null; + JsonObject data = json.getAsJsonObject("data"); + if (!data.has("player")) return null; + JsonObject player = data.getAsJsonObject("player"); + if (!player.has("username")) return null; - return player.get("username").getAsString(); - } -} \ No newline at end of file + return player.get("username").getAsString(); + } +} diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/UUIDFetcher.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/UUIDFetcher.java index f1f649f..0be90a7 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/UUIDFetcher.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/UUIDFetcher.java @@ -1,71 +1,79 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.util.uuid; import com.google.common.collect.ImmutableList; import com.google.gson.Gson; -import okhttp3.*; - import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.Callable; +import okhttp3.*; /* Credits to evilmidget38 for this class. I modified it to use Gson. */ public class UUIDFetcher implements Callable> { - private static final double PROFILES_PER_REQUEST = 100; - private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; - private static final MediaType JSON = MediaType.parse("application/json"); - private final List names; - private final boolean rateLimiting; - private static final Gson gson = new Gson(); - private static final OkHttpClient httpClient = new OkHttpClient(); + private static final double PROFILES_PER_REQUEST = 100; + private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; + private static final MediaType JSON = MediaType.parse("application/json"); + private final List names; + private final boolean rateLimiting; + private static final Gson gson = new Gson(); + private static final OkHttpClient httpClient = new OkHttpClient(); - private UUIDFetcher(List names, boolean rateLimiting) { - this.names = ImmutableList.copyOf(names); - this.rateLimiting = rateLimiting; - } + private UUIDFetcher(List names, boolean rateLimiting) { + this.names = ImmutableList.copyOf(names); + this.rateLimiting = rateLimiting; + } - public UUIDFetcher(List names) { - this(names, true); - } + public UUIDFetcher(List names) { + this(names, true); + } - public static UUID getUUID(String id) { - return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); - } + public static UUID getUUID(String id) { + return UUID.fromString( + id.substring(0, 8) + + "-" + + id.substring(8, 12) + + "-" + + id.substring(12, 16) + + "-" + + id.substring(16, 20) + + "-" + + id.substring(20, 32)); + } - public Map call() throws Exception { - Map uuidMap = new HashMap<>(); - int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); - for (int i = 0; i < requests; i++) { - String body = gson.toJson(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); - Request request = new Request.Builder().url(PROFILE_URL).post(RequestBody.create(JSON, body)).build(); - ResponseBody responseBody = httpClient.newCall(request).execute().body(); - String response = responseBody.string(); - responseBody.close(); - Profile[] array = gson.fromJson(response, Profile[].class); - for (Profile profile : array) { - UUID uuid = UUIDFetcher.getUUID(profile.id); - uuidMap.put(profile.name, uuid); - } - if (rateLimiting && i != requests - 1) { - Thread.sleep(100L); - } - } - return uuidMap; + public Map call() throws Exception { + Map uuidMap = new HashMap<>(); + int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); + for (int i = 0; i < requests; i++) { + String body = gson.toJson(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); + Request request = + new Request.Builder().url(PROFILE_URL).post(RequestBody.create(JSON, body)).build(); + ResponseBody responseBody = httpClient.newCall(request).execute().body(); + String response = responseBody.string(); + responseBody.close(); + Profile[] array = gson.fromJson(response, Profile[].class); + for (Profile profile : array) { + UUID uuid = UUIDFetcher.getUUID(profile.id); + uuidMap.put(profile.name, uuid); + } + if (rateLimiting && i != requests - 1) { + Thread.sleep(100L); + } } + return uuidMap; + } - private static class Profile { - String id; - String name; - } -} \ No newline at end of file + private static class Profile { + String id; + String name; + } +} diff --git a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/UUIDTranslator.java b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/UUIDTranslator.java index ffb62b1..b7c55e6 100644 --- a/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/UUIDTranslator.java +++ b/redisbungee/api/src/main/java/com/imaginarycode/minecraft/redisbungee/api/util/uuid/UUIDTranslator.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.api.util.uuid; import com.google.common.base.Charsets; @@ -15,194 +14,188 @@ import com.google.common.collect.ImmutableMap; import com.google.gson.Gson; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.api.tasks.RedisTask; -import org.checkerframework.checker.nullness.qual.NonNull; -import redis.clients.jedis.UnifiedJedis; -import redis.clients.jedis.exceptions.JedisException; - import java.util.Calendar; import java.util.Collections; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; +import org.checkerframework.checker.nullness.qual.NonNull; +import redis.clients.jedis.UnifiedJedis; +import redis.clients.jedis.exceptions.JedisException; public final class UUIDTranslator { - private static final Pattern UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"); - private static final Pattern MOJANGIAN_UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{32}"); - private final RedisBungeePlugin plugin; - private final Map nameToUuidMap = new ConcurrentHashMap<>(128, 0.5f, 4); - private final Map uuidToNameMap = new ConcurrentHashMap<>(128, 0.5f, 4); - private static final Gson gson = new Gson(); + private static final Pattern UUID_PATTERN = + Pattern.compile( + "[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"); + private static final Pattern MOJANGIAN_UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{32}"); + private final RedisBungeePlugin plugin; + private final Map nameToUuidMap = new ConcurrentHashMap<>(128, 0.5f, 4); + private final Map uuidToNameMap = new ConcurrentHashMap<>(128, 0.5f, 4); + private static final Gson gson = new Gson(); - public UUIDTranslator(RedisBungeePlugin plugin) { - this.plugin = plugin; + public UUIDTranslator(RedisBungeePlugin plugin) { + this.plugin = plugin; + } + + private void addToMaps(String name, UUID uuid) { + // This is why I like LocalDate... + + // Cache the entry for three days. + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, 3); + + // Create the entry and populate the local maps + CachedUUIDEntry entry = new CachedUUIDEntry(name, uuid, calendar); + nameToUuidMap.put(name.toLowerCase(), entry); + uuidToNameMap.put(uuid, entry); + } + + public UUID getTranslatedUuid(@NonNull String player, boolean expensiveLookups) { + // If the player is online, give them their UUID. + // Remember, local data > remote data. + if (plugin.getPlayer(player) != null) return plugin.getPlayerUUID(player); + + // Check if it exists in the map + CachedUUIDEntry cachedUUIDEntry = nameToUuidMap.get(player.toLowerCase()); + if (cachedUUIDEntry != null) { + if (!cachedUUIDEntry.expired()) return cachedUUIDEntry.uuid(); + else nameToUuidMap.remove(player); } - private void addToMaps(String name, UUID uuid) { - // This is why I like LocalDate... - - // Cache the entry for three days. - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.DAY_OF_MONTH, 3); - - // Create the entry and populate the local maps - CachedUUIDEntry entry = new CachedUUIDEntry(name, uuid, calendar); - nameToUuidMap.put(name.toLowerCase(), entry); - uuidToNameMap.put(uuid, entry); + // Check if we can exit early + if (UUID_PATTERN.matcher(player).find()) { + return UUID.fromString(player); } - public UUID getTranslatedUuid(@NonNull String player, boolean expensiveLookups) { - // If the player is online, give them their UUID. - // Remember, local data > remote data. - if (plugin.getPlayer(player) != null) - return plugin.getPlayerUUID(player); + if (MOJANGIAN_UUID_PATTERN.matcher(player).find()) { + // Reconstruct the UUID + return UUIDFetcher.getUUID(player); + } - // Check if it exists in the map - CachedUUIDEntry cachedUUIDEntry = nameToUuidMap.get(player.toLowerCase()); - if (cachedUUIDEntry != null) { - if (!cachedUUIDEntry.expired()) - return cachedUUIDEntry.uuid(); - else - nameToUuidMap.remove(player); - } + // If we are in offline mode, UUID generation is simple. + // We don't even have to cache the UUID, since this is easy to recalculate. + if (!plugin.isOnlineMode()) { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player).getBytes(Charsets.UTF_8)); + } + RedisTask redisTask = + new RedisTask(plugin) { + @Override + public UUID unifiedJedisTask(UnifiedJedis unifiedJedis) { + String stored = unifiedJedis.hget("uuid-cache", player.toLowerCase()); + if (stored != null) { + // Found an entry value. Deserialize it. + CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class); - // Check if we can exit early - if (UUID_PATTERN.matcher(player).find()) { - return UUID.fromString(player); - } - - if (MOJANGIAN_UUID_PATTERN.matcher(player).find()) { - // Reconstruct the UUID - return UUIDFetcher.getUUID(player); - } - - // If we are in offline mode, UUID generation is simple. - // We don't even have to cache the UUID, since this is easy to recalculate. - if (!plugin.isOnlineMode()) { - return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player).getBytes(Charsets.UTF_8)); - } - RedisTask redisTask = new RedisTask(plugin) { - @Override - public UUID unifiedJedisTask(UnifiedJedis unifiedJedis) { - String stored = unifiedJedis.hget("uuid-cache", player.toLowerCase()); - if (stored != null) { - // Found an entry value. Deserialize it. - CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class); - - // Check for expiry: - if (entry.expired()) { - unifiedJedis.hdel("uuid-cache", player.toLowerCase()); - // Doesn't hurt to also remove the UUID entry as well. - unifiedJedis.hdel("uuid-cache", entry.uuid().toString()); - } else { - nameToUuidMap.put(player.toLowerCase(), entry); - uuidToNameMap.put(entry.uuid(), entry); - return entry.uuid(); - } - } - - // That didn't work. Let's ask Mojang. - if (!expensiveLookups || !plugin.isOnlineMode()) - return null; - - Map uuidMap1; - try { - uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call(); - } catch (Exception e) { - plugin.logFatal("Unable to fetch UUID from Mojang for " + player); - return null; - } - for (Map.Entry entry : uuidMap1.entrySet()) { - if (entry.getKey().equalsIgnoreCase(player)) { - persistInfo(entry.getKey(), entry.getValue(), unifiedJedis); - return entry.getValue(); - } - } - return null; + // Check for expiry: + if (entry.expired()) { + unifiedJedis.hdel("uuid-cache", player.toLowerCase()); + // Doesn't hurt to also remove the UUID entry as well. + unifiedJedis.hdel("uuid-cache", entry.uuid().toString()); + } else { + nameToUuidMap.put(player.toLowerCase(), entry); + uuidToNameMap.put(entry.uuid(), entry); + return entry.uuid(); + } } - }; - // Let's try Redis. - try { - return redisTask.execute(); - } catch (JedisException e) { - plugin.logFatal("Unable to fetch UUID for " + player); - } - return null; // Nope, game over! - } + // That didn't work. Let's ask Mojang. + if (!expensiveLookups || !plugin.isOnlineMode()) return null; - public String getNameFromUuid(@NonNull UUID player, boolean expensiveLookups) { - // If the player is online, give them their UUID. - // Remember, local data > remote data. - if (plugin.getPlayer(player) != null) - return plugin.getPlayerName(player); - - // Check if it exists in the map - CachedUUIDEntry cachedUUIDEntry = uuidToNameMap.get(player); - if (cachedUUIDEntry != null) { - if (!cachedUUIDEntry.expired()) - return cachedUUIDEntry.name(); - else - uuidToNameMap.remove(player); - } - - RedisTask redisTask = new RedisTask(plugin) { - @Override - public String unifiedJedisTask(UnifiedJedis unifiedJedis) { - String stored = unifiedJedis.hget("uuid-cache", player.toString()); - if (stored != null) { - // Found an entry value. Deserialize it. - CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class); - - // Check for expiry: - if (entry.expired()) { - unifiedJedis.hdel("uuid-cache", player.toString()); - // Doesn't hurt to also remove the named entry as well. - // TODO: Since UUIDs are fixed, we could look up the name and see if the UUID matches. - unifiedJedis.hdel("uuid-cache", entry.name()); - } else { - nameToUuidMap.put(entry.name().toLowerCase(), entry); - uuidToNameMap.put(player, entry); - return entry.name(); - } - } - - if (!expensiveLookups || !plugin.isOnlineMode()) - return null; - - // That didn't work. Let's ask PlayerDB. - String name; - try { - name = NameFetcher.getName(player); - } catch (Exception e) { - plugin.logFatal("Unable to fetch name from PlayerDB for " + player); - return null; - } - - if (name != null) { - persistInfo(name, player, unifiedJedis); - return name; - } - - return null; + Map uuidMap1; + try { + uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call(); + } catch (Exception e) { + plugin.logFatal("Unable to fetch UUID from Mojang for " + player); + return null; + } + for (Map.Entry entry : uuidMap1.entrySet()) { + if (entry.getKey().equalsIgnoreCase(player)) { + persistInfo(entry.getKey(), entry.getValue(), unifiedJedis); + return entry.getValue(); + } } - }; - - - // Okay, it wasn't locally cached. Let's try Redis. - try { - return redisTask.execute(); - } catch (JedisException e) { - plugin.logFatal("Unable to fetch name for " + player); return null; - } + } + }; + // Let's try Redis. + try { + return redisTask.execute(); + } catch (JedisException e) { + plugin.logFatal("Unable to fetch UUID for " + player); } - public void persistInfo(String name, UUID uuid, UnifiedJedis unifiedJedis) { - addToMaps(name, uuid); - String json = gson.toJson(uuidToNameMap.get(uuid)); - unifiedJedis.hset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json)); + return null; // Nope, game over! + } + + public String getNameFromUuid(@NonNull UUID player, boolean expensiveLookups) { + // If the player is online, give them their UUID. + // Remember, local data > remote data. + if (plugin.getPlayer(player) != null) return plugin.getPlayerName(player); + + // Check if it exists in the map + CachedUUIDEntry cachedUUIDEntry = uuidToNameMap.get(player); + if (cachedUUIDEntry != null) { + if (!cachedUUIDEntry.expired()) return cachedUUIDEntry.name(); + else uuidToNameMap.remove(player); } + RedisTask redisTask = + new RedisTask(plugin) { + @Override + public String unifiedJedisTask(UnifiedJedis unifiedJedis) { + String stored = unifiedJedis.hget("uuid-cache", player.toString()); + if (stored != null) { + // Found an entry value. Deserialize it. + CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class); + // Check for expiry: + if (entry.expired()) { + unifiedJedis.hdel("uuid-cache", player.toString()); + // Doesn't hurt to also remove the named entry as well. + // TODO: Since UUIDs are fixed, we could look up the name and see if the UUID + // matches. + unifiedJedis.hdel("uuid-cache", entry.name()); + } else { + nameToUuidMap.put(entry.name().toLowerCase(), entry); + uuidToNameMap.put(player, entry); + return entry.name(); + } + } + + if (!expensiveLookups || !plugin.isOnlineMode()) return null; + + // That didn't work. Let's ask PlayerDB. + String name; + try { + name = NameFetcher.getName(player); + } catch (Exception e) { + plugin.logFatal("Unable to fetch name from PlayerDB for " + player); + return null; + } + + if (name != null) { + persistInfo(name, player, unifiedJedis); + return name; + } + + return null; + } + }; + + // Okay, it wasn't locally cached. Let's try Redis. + try { + return redisTask.execute(); + } catch (JedisException e) { + plugin.logFatal("Unable to fetch name for " + player); + return null; + } + } + + public void persistInfo(String name, UUID uuid, UnifiedJedis unifiedJedis) { + addToMaps(name, uuid); + String json = gson.toJson(uuidToNameMap.get(uuid)); + unifiedJedis.hset( + "uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json)); + } } diff --git a/redisbungee/commands/build.gradle.kts b/redisbungee/commands/build.gradle.kts index 918d94f..579eddb 100644 --- a/redisbungee/commands/build.gradle.kts +++ b/redisbungee/commands/build.gradle.kts @@ -2,6 +2,9 @@ plugins { `java-library` } +version = property("redisbungee-version").toString() +group = property("redisbungee-group").toString() + dependencies { compileOnly(project(":RedisBungee-API")) implementation(libs.acf.core) diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandLoader.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandLoader.java index cddb1b3..983fed5 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandLoader.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandLoader.java @@ -1,50 +1,48 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands; import co.aikar.commands.CommandContexts; import co.aikar.commands.CommandManager; import co.aikar.commands.InvalidCommandArgument; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; - import com.imaginarycode.minecraft.redisbungee.commands.legacy.LegacyRedisBungeeCommands; - import java.util.UUID; public class CommandLoader { - public static void initCommands(CommandManager commandManager, RedisBungeePlugin plugin) { - registerContexts(commandManager); - var commandsConfiguration = plugin.configuration().commandsConfiguration(); - if (commandsConfiguration.redisbungeeEnabled()) { - commandManager.registerCommand(new CommandRedisBungee(plugin)); - } - if (commandsConfiguration.redisbungeeLegacyEnabled()) { - commandManager.registerCommand(new LegacyRedisBungeeCommands(commandManager,plugin)); - } - - commandManager.registerCommand(new CommandRedisBungeeDebug(plugin)); - - + public static void initCommands( + CommandManager commandManager, RedisBungeePlugin plugin) { + registerContexts(commandManager); + var commandsConfiguration = plugin.configuration().commandsConfiguration(); + if (commandsConfiguration.redisbungeeEnabled()) { + commandManager.registerCommand(new CommandRedisBungee(plugin)); } - private static void registerContexts(CommandManager commandManager) { - CommandContexts commandContexts = commandManager.getCommandContexts(); - commandContexts.registerContext(UUID.class, c -> { - String uuidString = c.popFirstArg(); - try { - return UUID.fromString(uuidString); - } catch (IllegalArgumentException e) { - throw new InvalidCommandArgument("invaild uuid"); - } + if (commandsConfiguration.redisbungeeLegacyEnabled()) { + commandManager.registerCommand(new LegacyRedisBungeeCommands(commandManager, plugin)); + } + + commandManager.registerCommand(new CommandRedisBungeeDebug(plugin)); + } + + private static void registerContexts(CommandManager commandManager) { + CommandContexts commandContexts = commandManager.getCommandContexts(); + commandContexts.registerContext( + UUID.class, + c -> { + String uuidString = c.popFirstArg(); + try { + return UUID.fromString(uuidString); + } catch (IllegalArgumentException e) { + throw new InvalidCommandArgument("invaild uuid"); + } }); - } - + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandRedisBungee.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandRedisBungee.java index c67b7a0..5771bfd 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandRedisBungee.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandRedisBungee.java @@ -1,23 +1,24 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands; import co.aikar.commands.CommandIssuer; -import co.aikar.commands.RegisteredCommand; import co.aikar.commands.annotation.*; import com.google.common.primitives.Ints; import com.imaginarycode.minecraft.redisbungee.Constants; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseCommand; import com.imaginarycode.minecraft.redisbungee.commands.utils.StopperUUIDCleanupTask; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.ClickEvent; @@ -26,26 +27,23 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - @CommandAlias("rb|redisbungee") @CommandPermission("redisbungee.command.use") @Description("Main command") public class CommandRedisBungee extends AdventureBaseCommand { - private final RedisBungeePlugin plugin; + private final RedisBungeePlugin plugin; - public CommandRedisBungee(RedisBungeePlugin plugin) { - this.plugin = plugin; - } + public CommandRedisBungee(RedisBungeePlugin plugin) { + this.plugin = plugin; + } - @Default - @Subcommand("info|version|git") - @Description("information about current redisbungee build") - public void info(CommandIssuer issuer) { - final String message = """ + @Default + @Subcommand("info|version|git") + @Description("information about current redisbungee build") + public void info(CommandIssuer issuer) { + final String message = + """ This proxy is running RedisBungee Limework's fork ======================================== RedisBungee version: @@ -61,129 +59,166 @@ public class CommandRedisBungee extends AdventureBaseCommand { Placeholder.component( "commit", Component.text(Constants.GIT_COMMIT.substring(0, 8)) - .clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, Constants.getGithubCommitLink())) - .hoverEvent(HoverEvent.showText(Component.text("Click me to open: " + Constants.getGithubCommitLink()))) - ))); + .clickEvent( + ClickEvent.clickEvent( + ClickEvent.Action.OPEN_URL, Constants.getGithubCommitLink())) + .hoverEvent( + HoverEvent.showText( + Component.text( + "Click me to open: " + Constants.getGithubCommitLink())))))); + } + + // ......: ...... + @HelpCommand + @Description("shows the help page") + public void help(CommandIssuer issuer) { + final String barFormat = "========================================"; + final String commandFormat = "/rb : "; + + TextComponent.Builder message = Component.text(); + message.append(MiniMessage.miniMessage().deserialize(barFormat)); + + getSubCommands() + .forEach( + (subCommand, registeredCommand) -> { + String[] split = registeredCommand.getCommand().split(" "); + if (split.length > 1 && subCommand.equalsIgnoreCase(split[1])) { + message + .appendNewline() + .append( + MiniMessage.miniMessage() + .deserialize( + commandFormat, + Placeholder.component("sub-command", Component.text(subCommand)), + Placeholder.component( + "description", + MiniMessage.miniMessage() + .deserialize(registeredCommand.getHelpText())))); + } + }); + + message.appendNewline().append(MiniMessage.miniMessage().deserialize(barFormat)); + + sendMessage(issuer, message.build()); + } + + @Subcommand("clean") + @Description( + "cleans up the uuid cache WARNING... command above could cause performance issues") + @Private + public void cleanUp(CommandIssuer issuer) { + if (StopperUUIDCleanupTask.isRunning) { + sendMessage( + issuer, Component.text("cleanup is currently running!").color(NamedTextColor.RED)); + return; } - // ......: ...... - @HelpCommand - @Description("shows the help page") - public void help(CommandIssuer issuer) { - final String barFormat = "========================================"; - final String commandFormat = "/rb : "; + sendMessage( + issuer, + Component.text("cleanup is Starting, you should see the output status in the proxy console") + .color(NamedTextColor.GOLD)); + plugin.executeAsync(new StopperUUIDCleanupTask(plugin)); + } - TextComponent.Builder message = Component.text(); - message.append(MiniMessage.miniMessage().deserialize(barFormat)); + private List> subListProxies( + List> data, final int currentPage, final int pageSize) { + return data.subList( + ((currentPage * pageSize) - pageSize), + Ints.constrainToRange(currentPage * pageSize, 0, data.size())); + } - getSubCommands().forEach((subCommand, registeredCommand) -> { - String[] split = registeredCommand.getCommand().split(" "); - if (split.length > 1 && subCommand.equalsIgnoreCase(split[1])) { - message.appendNewline().append(MiniMessage.miniMessage().deserialize(commandFormat, Placeholder.component("sub-command", Component.text(subCommand)), - Placeholder.component("description", MiniMessage.miniMessage().deserialize(registeredCommand.getHelpText())) - )); - } - }); + @Subcommand("show") + @Description("Shows proxies in this network") + public void showProxies(CommandIssuer issuer, String[] args) { + final String closer = "========================================"; + final String pageTop = + "Page: / Network ID: Proxies online: "; + final String proxy = " : online"; + final String proxyHere = " (#) "; + final String nextPage = ">>>>>"; + final String previousPage = "<<<<< "; + final String pageInvalid = "invalid page"; + final String noProxies = "No proxies were found :("; - message.appendNewline().append(MiniMessage.miniMessage().deserialize(barFormat)); + final int pageSize = 16; - sendMessage(issuer, message.build()); + int currentPage; + if (args.length > 0) { + try { + currentPage = Integer.parseInt(args[0]); + if (currentPage < 1) currentPage = 1; + } catch (NumberFormatException e) { + sendMessage(issuer, MiniMessage.miniMessage().deserialize(pageInvalid)); + return; + } + } else currentPage = 1; + + var data = new ArrayList<>(plugin.proxyDataManager().eachProxyCount().entrySet()); + // there is no way this runs because there is always an heartbeat. + // if not could be some shenanigans done by devs :P + if (data.isEmpty()) { + sendMessage(issuer, MiniMessage.miniMessage().deserialize(noProxies)); + return; } - @Subcommand("clean") - @Description("cleans up the uuid cache WARNING... command above could cause performance issues") - @Private - public void cleanUp(CommandIssuer issuer) { - if (StopperUUIDCleanupTask.isRunning) { - sendMessage(issuer, - Component.text("cleanup is currently running!").color(NamedTextColor.RED)); - return; - } - sendMessage(issuer, - Component.text("cleanup is Starting, you should see the output status in the proxy console").color(NamedTextColor.GOLD)); - plugin.executeAsync(new StopperUUIDCleanupTask(plugin)); + // compute the total pages + int maxPages = (int) Math.ceil(data.size() / (double) pageSize); + if (currentPage > maxPages) currentPage = maxPages; + var subList = subListProxies(data, currentPage, pageSize); + TextComponent.Builder builder = Component.text(); + builder.append(MiniMessage.miniMessage().deserialize(closer)).appendNewline(); + builder + .append( + MiniMessage.miniMessage() + .deserialize( + pageTop, + Placeholder.component("current", Component.text(currentPage)), + Placeholder.component("max", Component.text(maxPages)), + Placeholder.component( + "network", Component.text(plugin.proxyDataManager().networkId())), + Placeholder.component("proxies", Component.text(data.size())))) + .appendNewline(); + int left = pageSize; + for (Map.Entry entrySet : subList) { + builder + .append( + MiniMessage.miniMessage() + .deserialize( + proxy, + Placeholder.component("proxy", Component.text(entrySet.getKey())), + Placeholder.component( + "here", + Component.text( + plugin.proxyDataManager().proxyId().equals(entrySet.getKey()) + ? proxyHere + : "")), + Placeholder.component("players", Component.text(entrySet.getValue())))) + .appendNewline(); + left--; } - - - - private List> subListProxies(List> data, final int currentPage, final int pageSize) { - return data.subList(((currentPage * pageSize) - pageSize), Ints.constrainToRange(currentPage * pageSize, 0, data.size())); - + while (left > 0) { + builder.appendNewline(); + left--; } - @Subcommand("show") - @Description("Shows proxies in this network") - public void showProxies(CommandIssuer issuer, String[] args) { - final String closer = "========================================"; - final String pageTop = "Page: / Network ID: Proxies online: "; - final String proxy = " : online"; - final String proxyHere = " (#) "; - final String nextPage = ">>>>>"; - final String previousPage = "<<<<< "; - final String pageInvalid = "invalid page"; - final String noProxies = "No proxies were found :("; - - final int pageSize = 16; - - int currentPage; - if (args.length > 0) { - try { - currentPage = Integer.parseInt(args[0]); - if (currentPage < 1) currentPage = 1; - } catch (NumberFormatException e) { - sendMessage(issuer, MiniMessage.miniMessage().deserialize(pageInvalid)); - return; - } - } else currentPage = 1; - - var data = new ArrayList<>(plugin.proxyDataManager().eachProxyCount().entrySet()); - // there is no way this runs because there is always an heartbeat. - // if not could be some shenanigans done by devs :P - if (data.isEmpty()) { - sendMessage(issuer, MiniMessage.miniMessage().deserialize(noProxies)); - return; - } - // compute the total pages - int maxPages = (int) Math.ceil(data.size() / (double) pageSize); - if (currentPage > maxPages) currentPage = maxPages; - var subList = subListProxies(data, currentPage, pageSize); - TextComponent.Builder builder = Component.text(); - builder.append(MiniMessage.miniMessage().deserialize(closer)).appendNewline(); - builder.append(MiniMessage.miniMessage().deserialize(pageTop, - Placeholder.component("current", Component.text(currentPage)), - Placeholder.component("max", Component.text(maxPages)), - Placeholder.component("network", Component.text(plugin.proxyDataManager().networkId())), - Placeholder.component("proxies", Component.text(data.size())) - - - )).appendNewline(); - int left = pageSize; - for (Map.Entry entrySet : subList) { - builder.append(MiniMessage.miniMessage().deserialize(proxy, - - Placeholder.component("proxy", Component.text(entrySet.getKey())), - Placeholder.component("here", Component.text(plugin.proxyDataManager().proxyId().equals(entrySet.getKey()) ? proxyHere : "")), - Placeholder.component("players", Component.text(entrySet.getValue())) - - )).appendNewline(); - left--; - } - while(left > 0) { - builder.appendNewline(); - left--; - } - if (currentPage > 1) { - builder.append(MiniMessage.miniMessage().deserialize(previousPage) - .color(NamedTextColor.WHITE).clickEvent(ClickEvent.runCommand("/rb show " + (currentPage - 1)))); - } else { - builder.append(MiniMessage.miniMessage().deserialize(previousPage).color(NamedTextColor.GRAY)); - } - if (subList.size() == pageSize && !subListProxies(data, currentPage + 1, pageSize).isEmpty()) { - builder.append(MiniMessage.miniMessage().deserialize(nextPage) - .color(NamedTextColor.WHITE).clickEvent(ClickEvent.runCommand("/rb show " + (currentPage + 1)))); - } else { - builder.append(MiniMessage.miniMessage().deserialize(nextPage).color(NamedTextColor.GRAY)); - } - builder.appendNewline(); - builder.append(MiniMessage.miniMessage().deserialize(closer)); - sendMessage(issuer, builder.build()); - + if (currentPage > 1) { + builder.append( + MiniMessage.miniMessage() + .deserialize(previousPage) + .color(NamedTextColor.WHITE) + .clickEvent(ClickEvent.runCommand("/rb show " + (currentPage - 1)))); + } else { + builder.append( + MiniMessage.miniMessage().deserialize(previousPage).color(NamedTextColor.GRAY)); } + if (subList.size() == pageSize && !subListProxies(data, currentPage + 1, pageSize).isEmpty()) { + builder.append( + MiniMessage.miniMessage() + .deserialize(nextPage) + .color(NamedTextColor.WHITE) + .clickEvent(ClickEvent.runCommand("/rb show " + (currentPage + 1)))); + } else { + builder.append(MiniMessage.miniMessage().deserialize(nextPage).color(NamedTextColor.GRAY)); + } + builder.appendNewline(); + builder.append(MiniMessage.miniMessage().deserialize(closer)); + sendMessage(issuer, builder.build()); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandRedisBungeeDebug.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandRedisBungeeDebug.java index f12ae82..8037267 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandRedisBungeeDebug.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/CommandRedisBungeeDebug.java @@ -1,20 +1,18 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands; import co.aikar.commands.CommandIssuer; import co.aikar.commands.annotation.*; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseCommand; - import java.util.UUID; @CommandAlias("rbd|redisbungeedebug") @@ -22,25 +20,29 @@ import java.util.UUID; @Description("debug commands") public class CommandRedisBungeeDebug extends AdventureBaseCommand { - private final RedisBungeePlugin plugin; + private final RedisBungeePlugin plugin; - public CommandRedisBungeeDebug(RedisBungeePlugin plugin) { - this.plugin = plugin; - } - - @Subcommand("kickByName") - @Description("kicks a player from the network by name") - @Private - public void kick(CommandIssuer issuer, String playerName) { - plugin.playerDataManager().serializedPlayerKick(plugin.getUuidTranslator().getTranslatedUuid(playerName, false), "kicked using redisbungee api using name"); - } - - @Subcommand("kickByUUID") - @Description("kicks a player from the network by UUID") - @Private - public void kick(CommandIssuer issuer, UUID uuid) { - plugin.playerDataManager().serializedPlayerKick(uuid, "kicked using redisbungee api using uuid"); - } + public CommandRedisBungeeDebug(RedisBungeePlugin plugin) { + this.plugin = plugin; + } + @Subcommand("kickByName") + @Description("kicks a player from the network by name") + @Private + public void kick(CommandIssuer issuer, String playerName) { + plugin + .playerDataManager() + .serializedPlayerKick( + plugin.getUuidTranslator().getTranslatedUuid(playerName, false), + "kicked using redisbungee api using name"); + } + @Subcommand("kickByUUID") + @Description("kicks a player from the network by UUID") + @Private + public void kick(CommandIssuer issuer, UUID uuid) { + plugin + .playerDataManager() + .serializedPlayerKick(uuid, "kicked using redisbungee api using uuid"); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandFind.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandFind.java index 0a73d36..90e28f6 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandFind.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandFind.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,15 +19,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandPermission("redisbungee.command.find") public class CommandFind extends AdventureBaseCommand { - private final LegacyRedisBungeeCommands rootCommand; + private final LegacyRedisBungeeCommands rootCommand; - public CommandFind(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } - - @Default - public void find(CommandIssuer issuer, String[] args) { - rootCommand.find(issuer, args); - } + public CommandFind(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } + @Default + public void find(CommandIssuer issuer, String[] args) { + rootCommand.find(issuer, args); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandGList.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandGList.java index 54cc985..ea6c561 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandGList.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandGList.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,15 +19,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandPermission("redisbungee.command.glist") public class CommandGList extends AdventureBaseCommand { - private final LegacyRedisBungeeCommands rootCommand; + private final LegacyRedisBungeeCommands rootCommand; - public CommandGList(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } - - @Default - public void gList(CommandIssuer issuer, String[] args) { - rootCommand.gList(issuer, args); - } + public CommandGList(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } + @Default + public void gList(CommandIssuer issuer, String[] args) { + rootCommand.gList(issuer, args); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandIp.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandIp.java index 410ae91..1854096 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandIp.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandIp.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,15 +19,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandPermission("redisbungee.command.ip") public class CommandIp extends AdventureBaseCommand { - private final LegacyRedisBungeeCommands rootCommand; + private final LegacyRedisBungeeCommands rootCommand; - public CommandIp(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } + public CommandIp(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } - - @Default - public void ip(CommandIssuer issuer, String[] args) { - this.rootCommand.ip(issuer, args); - } + @Default + public void ip(CommandIssuer issuer, String[] args) { + this.rootCommand.ip(issuer, args); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandLastSeen.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandLastSeen.java index f44ea8e..a99af68 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandLastSeen.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandLastSeen.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,15 +19,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandPermission("redisbungee.command.lastseen") public class CommandLastSeen extends AdventureBaseCommand { + private final LegacyRedisBungeeCommands rootCommand; - private final LegacyRedisBungeeCommands rootCommand; + public CommandLastSeen(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } - public CommandLastSeen(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } - - @Default - public void lastSeen(CommandIssuer issuer, String[] args) { - this.rootCommand.lastSeen(issuer,args); - } + @Default + public void lastSeen(CommandIssuer issuer, String[] args) { + this.rootCommand.lastSeen(issuer, args); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandPProxy.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandPProxy.java index 70a949c..f51dafd 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandPProxy.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandPProxy.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -19,15 +18,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandAlias("pproxy") @CommandPermission("redisbungee.command.pproxy") public class CommandPProxy extends AdventureBaseCommand { - private final LegacyRedisBungeeCommands rootCommand; + private final LegacyRedisBungeeCommands rootCommand; - public CommandPProxy(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } - - @Default - public void playerProxy(CommandIssuer issuer, String[] args) { - this.rootCommand.playerProxy(issuer,args); - } + public CommandPProxy(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } + @Default + public void playerProxy(CommandIssuer issuer, String[] args) { + this.rootCommand.playerProxy(issuer, args); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandPlist.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandPlist.java index 04e1609..3af7e3d 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandPlist.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandPlist.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,16 +19,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandPermission("redisbungee.command.plist") public class CommandPlist extends AdventureBaseCommand { + private final LegacyRedisBungeeCommands rootCommand; - private final LegacyRedisBungeeCommands rootCommand; - - public CommandPlist(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } - - @Default - public void playerList(CommandIssuer issuer, String[] args) { - this.rootCommand.playerList(issuer, args); - } + public CommandPlist(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } + @Default + public void playerList(CommandIssuer issuer, String[] args) { + this.rootCommand.playerList(issuer, args); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandSendToAll.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandSendToAll.java index ad9e1da..1ff070d 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandSendToAll.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandSendToAll.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,14 +19,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandPermission("redisbungee.command.sendtoall") public class CommandSendToAll extends AdventureBaseCommand { + private final LegacyRedisBungeeCommands rootCommand; - private final LegacyRedisBungeeCommands rootCommand; + public CommandSendToAll(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } - public CommandSendToAll(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } - @Default - public void sendToAll(CommandIssuer issuer, String[] args) { - this.rootCommand.sendToAll(issuer, args); - } + @Default + public void sendToAll(CommandIssuer issuer, String[] args) { + this.rootCommand.sendToAll(issuer, args); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandServerId.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandServerId.java index c62c2f5..8823dc4 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandServerId.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandServerId.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,14 +19,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandPermission("redisbungee.command.serverid") public class CommandServerId extends AdventureBaseCommand { + private final LegacyRedisBungeeCommands rootCommand; - private final LegacyRedisBungeeCommands rootCommand; + public CommandServerId(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } - public CommandServerId(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } - @Default - public void serverId(CommandIssuer issuer) { - this.rootCommand.serverId(issuer); - } + @Default + public void serverId(CommandIssuer issuer) { + this.rootCommand.serverId(issuer); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandServerIds.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandServerIds.java index 85b53b7..333b9fc 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandServerIds.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/CommandServerIds.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,17 +19,14 @@ import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseComma @CommandPermission("redisbungee.command.serverids") public class CommandServerIds extends AdventureBaseCommand { + private final LegacyRedisBungeeCommands rootCommand; - private final LegacyRedisBungeeCommands rootCommand; - - public CommandServerIds(LegacyRedisBungeeCommands rootCommand) { - this.rootCommand = rootCommand; - } - - @Default - public void serverIds(CommandIssuer issuer) { - this.rootCommand.serverIds(issuer); - } - + public CommandServerIds(LegacyRedisBungeeCommands rootCommand) { + this.rootCommand = rootCommand; + } + @Default + public void serverIds(CommandIssuer issuer) { + this.rootCommand.serverIds(issuer); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/LegacyRedisBungeeCommands.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/LegacyRedisBungeeCommands.java index 6253e96..f97c70c 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/LegacyRedisBungeeCommands.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/legacy/LegacyRedisBungeeCommands.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.legacy; import co.aikar.commands.CommandIssuer; @@ -20,241 +19,281 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.commands.utils.AdventureBaseCommand; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.format.NamedTextColor; - import java.net.InetAddress; import java.text.SimpleDateFormat; import java.util.Set; import java.util.TreeSet; import java.util.UUID; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.NamedTextColor; @CommandAlias("rbl|redisbungeelegacy") @CommandPermission("redisbungee.legacy.use") public class LegacyRedisBungeeCommands extends AdventureBaseCommand { - private final RedisBungeePlugin plugin; + private final RedisBungeePlugin plugin; - public LegacyRedisBungeeCommands(CommandManager commandManager, RedisBungeePlugin plugin) { - this.plugin = plugin; - var commands = plugin.configuration().commandsConfiguration().legacySubCommandsConfiguration(); - if (!plugin.configuration().commandsConfiguration().redisbungeeLegacyEnabled()) throw new IllegalStateException("someone tried to init me while disabled!"); - if (commands == null) throw new NullPointerException("commands config is null!!"); + public LegacyRedisBungeeCommands( + CommandManager commandManager, RedisBungeePlugin plugin) { + this.plugin = plugin; + var commands = plugin.configuration().commandsConfiguration().legacySubCommandsConfiguration(); + if (!plugin.configuration().commandsConfiguration().redisbungeeLegacyEnabled()) + throw new IllegalStateException("someone tried to init me while disabled!"); + if (commands == null) throw new NullPointerException("commands config is null!!"); - if (commands.installGlist()) commandManager.registerCommand(new CommandGList(this)); - if (commands.installFind()) commandManager.registerCommand(new CommandFind(this)); - if (commands.installIp()) commandManager.registerCommand(new CommandIp(this)); - if (commands.installLastseen()) commandManager.registerCommand(new CommandLastSeen(this)); - if (commands.installPlist()) commandManager.registerCommand(new CommandPlist(this)); - if (commands.installPproxy()) commandManager.registerCommand(new CommandPProxy(this)); - if (commands.installSendtoall()) commandManager.registerCommand(new CommandSendToAll(this)); - if (commands.installServerid()) commandManager.registerCommand(new CommandServerId(this)); - if (commands.installServerids()) commandManager.registerCommand(new CommandServerIds(this)); - } + if (commands.installGlist()) commandManager.registerCommand(new CommandGList(this)); + if (commands.installFind()) commandManager.registerCommand(new CommandFind(this)); + if (commands.installIp()) commandManager.registerCommand(new CommandIp(this)); + if (commands.installLastseen()) commandManager.registerCommand(new CommandLastSeen(this)); + if (commands.installPlist()) commandManager.registerCommand(new CommandPlist(this)); + if (commands.installPproxy()) commandManager.registerCommand(new CommandPProxy(this)); + if (commands.installSendtoall()) commandManager.registerCommand(new CommandSendToAll(this)); + if (commands.installServerid()) commandManager.registerCommand(new CommandServerId(this)); + if (commands.installServerids()) commandManager.registerCommand(new CommandServerIds(this)); + } - private static final Component NO_PLAYER_SPECIFIED = - Component.text("You must specify a player name.", NamedTextColor.RED); - private static final Component PLAYER_NOT_FOUND = - Component.text("No such player found.", NamedTextColor.RED); - private static final Component NO_COMMAND_SPECIFIED = - Component.text("You must specify a command to be run.", NamedTextColor.RED); + private static final Component NO_PLAYER_SPECIFIED = + Component.text("You must specify a player name.", NamedTextColor.RED); + private static final Component PLAYER_NOT_FOUND = + Component.text("No such player found.", NamedTextColor.RED); + private static final Component NO_COMMAND_SPECIFIED = + Component.text("You must specify a command to be run.", NamedTextColor.RED); - private static String playerPlural(int num) { - return num == 1 ? num + " player is" : num + " players are"; - } + private static String playerPlural(int num) { + return num == 1 ? num + " player is" : num + " players are"; + } - @Subcommand("glist") - @CommandPermission("redisbungee.command.glist") - public void gList(CommandIssuer issuer, String[] args) { - plugin.executeAsync(() -> { - int count = plugin.getAbstractRedisBungeeApi().getPlayerCount(); - Component playersOnline = Component.text(playerPlural(count) + " currently online.", NamedTextColor.YELLOW); - if (args.length > 0 && args[0].equals("showall")) { - Multimap serverToPlayers = plugin.getAbstractRedisBungeeApi().getServerToPlayers(); - Multimap human = HashMultimap.create(); - serverToPlayers.forEach((key, value) -> { - // if for any reason UUID translation fails just return the uuid as name, to make command finish executing. - String playerName = plugin.getUuidTranslator().getNameFromUuid(value, false); - human.put(key, playerName != null ? playerName : value.toString()); + @Subcommand("glist") + @CommandPermission("redisbungee.command.glist") + public void gList(CommandIssuer issuer, String[] args) { + plugin.executeAsync( + () -> { + int count = plugin.getAbstractRedisBungeeApi().getPlayerCount(); + Component playersOnline = + Component.text(playerPlural(count) + " currently online.", NamedTextColor.YELLOW); + if (args.length > 0 && args[0].equals("showall")) { + Multimap serverToPlayers = + plugin.getAbstractRedisBungeeApi().getServerToPlayers(); + Multimap human = HashMultimap.create(); + serverToPlayers.forEach( + (key, value) -> { + // if for any reason UUID translation fails just return the uuid as name, to make + // command finish executing. + String playerName = plugin.getUuidTranslator().getNameFromUuid(value, false); + human.put(key, playerName != null ? playerName : value.toString()); }); - for (String server : new TreeSet<>(serverToPlayers.keySet())) { - Component serverName = Component.text("[" + server + "] ", NamedTextColor.GREEN); - Component serverCount = Component.text("(" + serverToPlayers.get(server).size() + "): ", NamedTextColor.YELLOW); - Component serverPlayers = Component.text(Joiner.on(", ").join(human.get(server)), NamedTextColor.WHITE); - sendMessage(issuer, Component.textOfChildren(serverName, serverCount, serverPlayers)); - } - sendMessage(issuer, playersOnline); - } else { - sendMessage(issuer, playersOnline); - sendMessage(issuer, Component.text("To see all players online, use /glist showall.", NamedTextColor.YELLOW)); + for (String server : new TreeSet<>(serverToPlayers.keySet())) { + Component serverName = Component.text("[" + server + "] ", NamedTextColor.GREEN); + Component serverCount = + Component.text( + "(" + serverToPlayers.get(server).size() + "): ", NamedTextColor.YELLOW); + Component serverPlayers = + Component.text(Joiner.on(", ").join(human.get(server)), NamedTextColor.WHITE); + sendMessage(issuer, Component.textOfChildren(serverName, serverCount, serverPlayers)); } - + sendMessage(issuer, playersOnline); + } else { + sendMessage(issuer, playersOnline); + sendMessage( + issuer, + Component.text( + "To see all players online, use /glist showall.", NamedTextColor.YELLOW)); + } }); - } + } - @Subcommand("find") - @CommandPermission("redisbungee.command.find") - public void find(CommandIssuer issuer, String[] args) { - plugin.executeAsync(() -> { - if (args.length > 0) { - UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); - if (uuid == null) { - sendMessage(issuer, PLAYER_NOT_FOUND); - return; - } - String proxyId = plugin.playerDataManager().getProxyFor(uuid); - if (proxyId != null) { - String serverId = plugin.playerDataManager().getServerFor(uuid); - Component message = Component.text(args[0] + " is on proxy " + proxyId + " on server " + serverId +".", NamedTextColor.BLUE); - sendMessage(issuer, message); - } else { - sendMessage(issuer, PLAYER_NOT_FOUND); - } + @Subcommand("find") + @CommandPermission("redisbungee.command.find") + public void find(CommandIssuer issuer, String[] args) { + plugin.executeAsync( + () -> { + if (args.length > 0) { + UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); + if (uuid == null) { + sendMessage(issuer, PLAYER_NOT_FOUND); + return; + } + String proxyId = plugin.playerDataManager().getProxyFor(uuid); + if (proxyId != null) { + String serverId = plugin.playerDataManager().getServerFor(uuid); + Component message = + Component.text( + args[0] + " is on proxy " + proxyId + " on server " + serverId + ".", + NamedTextColor.BLUE); + sendMessage(issuer, message); } else { - sendMessage(issuer, NO_PLAYER_SPECIFIED); + sendMessage(issuer, PLAYER_NOT_FOUND); } + } else { + sendMessage(issuer, NO_PLAYER_SPECIFIED); + } }); + } - } - - @Subcommand("lastseen") - @CommandPermission("redisbungee.command.lastseen") - public void lastSeen(CommandIssuer issuer, String[] args) { - plugin.executeAsync(() -> { - if (args.length > 0) { - UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); - if (uuid == null) { - sendMessage(issuer, PLAYER_NOT_FOUND); - return; - } - long secs = plugin.getAbstractRedisBungeeApi().getLastOnline(uuid); - TextComponent.Builder message = Component.text(); - if (secs == 0) { - message.color(NamedTextColor.GREEN); - message.content(args[0] + " is currently online."); - } else if (secs != -1) { - message.color(NamedTextColor.BLUE); - message.content(args[0] + " was last online on " + new SimpleDateFormat().format(secs) + "."); - } else { - message.color(NamedTextColor.RED); - message.content(args[0] + " has never been online."); - } - sendMessage(issuer, message.build()); + @Subcommand("lastseen") + @CommandPermission("redisbungee.command.lastseen") + public void lastSeen(CommandIssuer issuer, String[] args) { + plugin.executeAsync( + () -> { + if (args.length > 0) { + UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); + if (uuid == null) { + sendMessage(issuer, PLAYER_NOT_FOUND); + return; + } + long secs = plugin.getAbstractRedisBungeeApi().getLastOnline(uuid); + TextComponent.Builder message = Component.text(); + if (secs == 0) { + message.color(NamedTextColor.GREEN); + message.content(args[0] + " is currently online."); + } else if (secs != -1) { + message.color(NamedTextColor.BLUE); + message.content( + args[0] + " was last online on " + new SimpleDateFormat().format(secs) + "."); } else { - sendMessage(issuer, NO_PLAYER_SPECIFIED); + message.color(NamedTextColor.RED); + message.content(args[0] + " has never been online."); } - - + sendMessage(issuer, message.build()); + } else { + sendMessage(issuer, NO_PLAYER_SPECIFIED); + } }); - } + } - @Subcommand("ip") - @CommandPermission("redisbungee.command.ip") - public void ip(CommandIssuer issuer, String[] args) { - plugin.executeAsync(() -> { - if (args.length > 0) { - UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); - if (uuid == null) { - sendMessage(issuer, PLAYER_NOT_FOUND); - return; - } - InetAddress ia = plugin.getAbstractRedisBungeeApi().getPlayerIp(uuid); - if (ia != null) { - TextComponent message = Component.text(args[0] + " is connected from " + ia.toString() + ".", NamedTextColor.GREEN); - sendMessage(issuer, message); - } else { - sendMessage(issuer, PLAYER_NOT_FOUND); - } + @Subcommand("ip") + @CommandPermission("redisbungee.command.ip") + public void ip(CommandIssuer issuer, String[] args) { + plugin.executeAsync( + () -> { + if (args.length > 0) { + UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); + if (uuid == null) { + sendMessage(issuer, PLAYER_NOT_FOUND); + return; + } + InetAddress ia = plugin.getAbstractRedisBungeeApi().getPlayerIp(uuid); + if (ia != null) { + TextComponent message = + Component.text( + args[0] + " is connected from " + ia.toString() + ".", NamedTextColor.GREEN); + sendMessage(issuer, message); } else { - sendMessage(issuer, NO_PLAYER_SPECIFIED); + sendMessage(issuer, PLAYER_NOT_FOUND); } + } else { + sendMessage(issuer, NO_PLAYER_SPECIFIED); + } }); - } + } - @Subcommand("pproxy") - @CommandPermission("redisbungee.command.pproxy") - public void playerProxy(CommandIssuer issuer, String[] args) { - plugin.executeAsync(() -> { - if (args.length > 0) { - UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); - if (uuid == null) { - sendMessage(issuer, PLAYER_NOT_FOUND); - return; - } - String proxy = plugin.getAbstractRedisBungeeApi().getProxy(uuid); - if (proxy != null) { - TextComponent message = Component.text(args[0] + " is connected to " + proxy + ".", NamedTextColor.GREEN); - sendMessage(issuer, message); - } else { - sendMessage(issuer, PLAYER_NOT_FOUND); - } + @Subcommand("pproxy") + @CommandPermission("redisbungee.command.pproxy") + public void playerProxy(CommandIssuer issuer, String[] args) { + plugin.executeAsync( + () -> { + if (args.length > 0) { + UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); + if (uuid == null) { + sendMessage(issuer, PLAYER_NOT_FOUND); + return; + } + String proxy = plugin.getAbstractRedisBungeeApi().getProxy(uuid); + if (proxy != null) { + TextComponent message = + Component.text(args[0] + " is connected to " + proxy + ".", NamedTextColor.GREEN); + sendMessage(issuer, message); } else { - sendMessage(issuer, NO_PLAYER_SPECIFIED); + sendMessage(issuer, PLAYER_NOT_FOUND); } + } else { + sendMessage(issuer, NO_PLAYER_SPECIFIED); + } }); + } + @Subcommand("sendtoall") + @CommandPermission("redisbungee.command.sendtoall") + public void sendToAll(CommandIssuer issuer, String[] args) { + if (args.length > 0) { + String command = Joiner.on(" ").skipNulls().join(args); + plugin.getAbstractRedisBungeeApi().sendProxyCommand(command); + TextComponent message = + Component.text("Sent the command /" + command + " to all proxies.", NamedTextColor.GREEN); + sendMessage(issuer, message); + } else { + sendMessage(issuer, NO_COMMAND_SPECIFIED); } + } - @Subcommand("sendtoall") - @CommandPermission("redisbungee.command.sendtoall") - public void sendToAll(CommandIssuer issuer, String[] args) { - if (args.length > 0) { - String command = Joiner.on(" ").skipNulls().join(args); - plugin.getAbstractRedisBungeeApi().sendProxyCommand(command); - TextComponent message = Component.text("Sent the command /" + command + " to all proxies.", NamedTextColor.GREEN); - sendMessage(issuer, message); - } else { - sendMessage(issuer, NO_COMMAND_SPECIFIED); - } + @Subcommand("serverid") + @CommandPermission("redisbungee.command.serverid") + public void serverId(CommandIssuer issuer) { + sendMessage( + issuer, + Component.text( + "You are on " + plugin.getAbstractRedisBungeeApi().getProxyId() + ".", + NamedTextColor.YELLOW)); + } - } + @Subcommand("serverids") + @CommandPermission("redisbungee.command.serverids") + public void serverIds(CommandIssuer issuer) { + sendMessage( + issuer, + Component.text( + "All Proxies IDs: " + + Joiner.on(", ").join(plugin.getAbstractRedisBungeeApi().getAllProxies()), + NamedTextColor.YELLOW)); + } - @Subcommand("serverid") - @CommandPermission("redisbungee.command.serverid") - public void serverId(CommandIssuer issuer) { - sendMessage(issuer, Component.text("You are on " + plugin.getAbstractRedisBungeeApi().getProxyId() + ".", NamedTextColor.YELLOW)); - } - - @Subcommand("serverids") - @CommandPermission("redisbungee.command.serverids") - public void serverIds(CommandIssuer issuer) { - sendMessage(issuer, Component.text("All Proxies IDs: " + Joiner.on(", ").join(plugin.getAbstractRedisBungeeApi().getAllProxies()), NamedTextColor.YELLOW)); - } - - - @Subcommand("plist") - @CommandPermission("redisbungee.command.plist") - public void playerList(CommandIssuer issuer, String[] args) { - plugin.executeAsync(() -> { - String proxy = args.length >= 1 ? args[0] : plugin.configuration().getProxyId(); - if (!plugin.proxyDataManager().proxiesIds().contains(proxy)) { - sendMessage(issuer, Component.text(proxy + " is not a valid proxy. See /serverids for valid proxies.", NamedTextColor.RED)); - return; - } - Set players = plugin.getAbstractRedisBungeeApi().getPlayersOnProxy(proxy); - Component playersOnline = Component.text(playerPlural(players.size()) + " currently on proxy " + proxy + ".", NamedTextColor.YELLOW); - if (args.length >= 2 && args[1].equals("showall")) { - Multimap serverToPlayers = plugin.getAbstractRedisBungeeApi().getServerToPlayers(); - Multimap human = HashMultimap.create(); - serverToPlayers.forEach((key, value) -> { - if (players.contains(value)) { - human.put(key, plugin.getUuidTranslator().getNameFromUuid(value, false)); - } + @Subcommand("plist") + @CommandPermission("redisbungee.command.plist") + public void playerList(CommandIssuer issuer, String[] args) { + plugin.executeAsync( + () -> { + String proxy = args.length >= 1 ? args[0] : plugin.configuration().getProxyId(); + if (!plugin.proxyDataManager().proxiesIds().contains(proxy)) { + sendMessage( + issuer, + Component.text( + proxy + " is not a valid proxy. See /serverids for valid proxies.", + NamedTextColor.RED)); + return; + } + Set players = plugin.getAbstractRedisBungeeApi().getPlayersOnProxy(proxy); + Component playersOnline = + Component.text( + playerPlural(players.size()) + " currently on proxy " + proxy + ".", + NamedTextColor.YELLOW); + if (args.length >= 2 && args[1].equals("showall")) { + Multimap serverToPlayers = + plugin.getAbstractRedisBungeeApi().getServerToPlayers(); + Multimap human = HashMultimap.create(); + serverToPlayers.forEach( + (key, value) -> { + if (players.contains(value)) { + human.put(key, plugin.getUuidTranslator().getNameFromUuid(value, false)); + } }); - for (String server : new TreeSet<>(human.keySet())) { - TextComponent serverName = Component.text("[" + server + "] ", NamedTextColor.RED); - TextComponent serverCount = Component.text("(" + human.get(server).size() + "): ", NamedTextColor.YELLOW); - TextComponent serverPlayers = Component.text(Joiner.on(", ").join(human.get(server)), NamedTextColor.WHITE); - sendMessage(issuer, Component.textOfChildren(serverName, serverCount, serverPlayers)); - } - sendMessage(issuer, playersOnline); - } else { - sendMessage(issuer, playersOnline); - sendMessage(issuer, Component.text("To see all players online, use /plist " + proxy + " showall.", NamedTextColor.YELLOW)); + for (String server : new TreeSet<>(human.keySet())) { + TextComponent serverName = Component.text("[" + server + "] ", NamedTextColor.RED); + TextComponent serverCount = + Component.text("(" + human.get(server).size() + "): ", NamedTextColor.YELLOW); + TextComponent serverPlayers = + Component.text(Joiner.on(", ").join(human.get(server)), NamedTextColor.WHITE); + sendMessage(issuer, Component.textOfChildren(serverName, serverCount, serverPlayers)); } + sendMessage(issuer, playersOnline); + } else { + sendMessage(issuer, playersOnline); + sendMessage( + issuer, + Component.text( + "To see all players online, use /plist " + proxy + " showall.", + NamedTextColor.YELLOW)); + } }); - - } - -} \ No newline at end of file + } +} diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/AdventureBaseCommand.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/AdventureBaseCommand.java index 08a43c4..ac96a8f 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/AdventureBaseCommand.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/AdventureBaseCommand.java @@ -1,26 +1,22 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.utils; import co.aikar.commands.BaseCommand; import co.aikar.commands.CommandIssuer; import net.kyori.adventure.text.Component; -/** - * this just dumb class that wraps the adventure stuff into base command - */ +/** this just dumb class that wraps the adventure stuff into base command */ public abstract class AdventureBaseCommand extends BaseCommand { - protected void sendMessage(CommandIssuer issuer, Component component) { - CommandPlatformHelper.getPlatformHelper().sendMessage(issuer, component); - } - + protected void sendMessage(CommandIssuer issuer, Component component) { + CommandPlatformHelper.getPlatformHelper().sendMessage(issuer, component); + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/CommandPlatformHelper.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/CommandPlatformHelper.java index a951e9d..5f9b7c0 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/CommandPlatformHelper.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/CommandPlatformHelper.java @@ -1,36 +1,31 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.utils; import co.aikar.commands.CommandIssuer; -import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import net.kyori.adventure.text.Component; - public abstract class CommandPlatformHelper { - private static CommandPlatformHelper SINGLETON; + private static CommandPlatformHelper SINGLETON; - public abstract void sendMessage(CommandIssuer issuer, Component component); + public abstract void sendMessage(CommandIssuer issuer, Component component); - public static void init(CommandPlatformHelper platformHelper) { - if (SINGLETON != null) { - throw new IllegalStateException("tried to re init Platform Helper"); - } - SINGLETON = platformHelper; - } - - - public static CommandPlatformHelper getPlatformHelper() { - return SINGLETON; + public static void init(CommandPlatformHelper platformHelper) { + if (SINGLETON != null) { + throw new IllegalStateException("tried to re init Platform Helper"); } + SINGLETON = platformHelper; + } + public static CommandPlatformHelper getPlatformHelper() { + return SINGLETON; + } } diff --git a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/StopperUUIDCleanupTask.java b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/StopperUUIDCleanupTask.java index 06dbe85..e112c8f 100644 --- a/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/StopperUUIDCleanupTask.java +++ b/redisbungee/commands/src/main/java/com/imaginarycode/minecraft/redisbungee/commands/utils/StopperUUIDCleanupTask.java @@ -1,3 +1,12 @@ +/* +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.commands.utils; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; @@ -6,20 +15,20 @@ import redis.clients.jedis.UnifiedJedis; public class StopperUUIDCleanupTask extends UUIDCleanupTask { - public static boolean isRunning = false; + public static boolean isRunning = false; - public StopperUUIDCleanupTask(RedisBungeePlugin plugin) { - super(plugin); - } - - - @Override - public Void unifiedJedisTask(UnifiedJedis unifiedJedis) { - isRunning = true; - try { - super.unifiedJedisTask(unifiedJedis); - } catch (Exception ignored) {} - isRunning = false; - return null; + public StopperUUIDCleanupTask(RedisBungeePlugin plugin) { + super(plugin); + } + + @Override + public Void unifiedJedisTask(UnifiedJedis unifiedJedis) { + isRunning = true; + try { + super.unifiedJedisTask(unifiedJedis); + } catch (Exception ignored) { } + isRunning = false; + return null; + } } diff --git a/redisbungee/copyright_header.txt b/redisbungee/copyright_header.txt index aa3b10b..0a37ce7 100644 --- a/redisbungee/copyright_header.txt +++ b/redisbungee/copyright_header.txt @@ -1,7 +1,9 @@ -Copyright (c) 2013-present RedisBungee contributors - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -which accompanies this distribution, and is available at - -http://www.eclipse.org/legal/epl-v10.html +/* +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ \ No newline at end of file diff --git a/redisbungee/lang/build.gradle.kts b/redisbungee/lang/build.gradle.kts index a0593d3..0433b83 100644 --- a/redisbungee/lang/build.gradle.kts +++ b/redisbungee/lang/build.gradle.kts @@ -3,6 +3,9 @@ plugins { `maven-publish` } +version = property("redisbungee-version").toString() +group = property("redisbungee-group").toString() + dependencies { compileOnly(project(":RedisBungee-API")) compileOnly(libs.adventure.api) diff --git a/redisbungee/lang/src/main/java/net/limework/valiobungee/config/lang/LangConfigLoader.java b/redisbungee/lang/src/main/java/net/limework/valiobungee/config/lang/LangConfigLoader.java index 14cf449..11ad001 100644 --- a/redisbungee/lang/src/main/java/net/limework/valiobungee/config/lang/LangConfigLoader.java +++ b/redisbungee/lang/src/main/java/net/limework/valiobungee/config/lang/LangConfigLoader.java @@ -1,55 +1,63 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package net.limework.valiobungee.config.lang; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.api.config.loaders.GenericConfigLoader; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Locale; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.yaml.YAMLConfigurationLoader; -import java.io.IOException; -import java.nio.file.Path; -import java.util.Locale; - public interface LangConfigLoader extends GenericConfigLoader { - int CONFIG_VERSION = 1; + int CONFIG_VERSION = 1; - default void loadLangConfig(RedisBungeePlugin plugin, Path dataFolder) throws IOException { - Path configFile = createConfigFile(dataFolder, "lang.yml", "lang.yml"); - final YAMLConfigurationLoader yamlConfigurationFileLoader = YAMLConfigurationLoader.builder().setPath(configFile).build(); - ConfigurationNode node = yamlConfigurationFileLoader.load(); - if (node.getNode("config-version").getInt(0) != CONFIG_VERSION) { - handleOldConfig(dataFolder, "lang.yml", "lang.yml"); - node = yamlConfigurationFileLoader.load(); - } - // MINI message serializer - MiniMessage miniMessage = MiniMessage.miniMessage(); - - Component prefix = miniMessage.deserialize(node.getNode("prefix").getString("[RedisBungee]")); - Locale defaultLocale = Locale.forLanguageTag(node.getNode("default-locale").getString("en-us")); - boolean useClientLocale = node.getNode("use-client-locale").getBoolean(true); - LangConfiguration.Messages messages = new LangConfiguration.Messages(defaultLocale); - node.getNode("messages").getChildrenMap().forEach((key, childNode) -> childNode.getChildrenMap().forEach((childKey, childChildNode) -> { - messages.register(key.toString(), Locale.forLanguageTag(childKey.toString()), childChildNode.getString()); - })); - messages.test(defaultLocale); - - onLangConfigLoad(new LangConfiguration(prefix, defaultLocale, useClientLocale, messages)); + default void loadLangConfig(RedisBungeePlugin plugin, Path dataFolder) throws IOException { + Path configFile = createConfigFile(dataFolder, "lang.yml", "lang.yml"); + final YAMLConfigurationLoader yamlConfigurationFileLoader = + YAMLConfigurationLoader.builder().setPath(configFile).build(); + ConfigurationNode node = yamlConfigurationFileLoader.load(); + if (node.getNode("config-version").getInt(0) != CONFIG_VERSION) { + handleOldConfig(dataFolder, "lang.yml", "lang.yml"); + node = yamlConfigurationFileLoader.load(); } + // MINI message serializer + MiniMessage miniMessage = MiniMessage.miniMessage(); + Component prefix = + miniMessage.deserialize( + node.getNode("prefix").getString("[RedisBungee]")); + Locale defaultLocale = Locale.forLanguageTag(node.getNode("default-locale").getString("en-us")); + boolean useClientLocale = node.getNode("use-client-locale").getBoolean(true); + LangConfiguration.Messages messages = new LangConfiguration.Messages(defaultLocale); + node.getNode("messages") + .getChildrenMap() + .forEach( + (key, childNode) -> + childNode + .getChildrenMap() + .forEach( + (childKey, childChildNode) -> { + messages.register( + key.toString(), + Locale.forLanguageTag(childKey.toString()), + childChildNode.getString()); + })); + messages.test(defaultLocale); - void onLangConfigLoad(LangConfiguration langConfiguration); - + onLangConfigLoad(new LangConfiguration(prefix, defaultLocale, useClientLocale, messages)); + } + void onLangConfigLoad(LangConfiguration langConfiguration); } diff --git a/redisbungee/lang/src/main/java/net/limework/valiobungee/config/lang/LangConfiguration.java b/redisbungee/lang/src/main/java/net/limework/valiobungee/config/lang/LangConfiguration.java index 723f5d9..c7b303b 100644 --- a/redisbungee/lang/src/main/java/net/limework/valiobungee/config/lang/LangConfiguration.java +++ b/redisbungee/lang/src/main/java/net/limework/valiobungee/config/lang/LangConfiguration.java @@ -1,155 +1,164 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package net.limework.valiobungee.config.lang; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; - import java.util.HashMap; import java.util.Locale; import java.util.Map; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; /** - * This language support implementation is temporarily - * until I come up with better system but for now we will use Maps instead :/ - * Todo: possible usage of adventure api + * This language support implementation is temporarily until I come up with better system but for + * now we will use Maps instead :/ Todo: possible usage of adventure api */ public class LangConfiguration { - private interface RegistrableMessages { + private interface RegistrableMessages { - void register(String id, Locale locale, String miniMessage); + void register(String id, Locale locale, String miniMessage); - void test(Locale locale); + void test(Locale locale); - default void throwError(Locale locale, String where) { - throw new IllegalStateException("Language system in `" + where + "` found missing entries for " + locale.toString()); - } + default void throwError(Locale locale, String where) { + throw new IllegalStateException( + "Language system in `" + where + "` found missing entries for " + locale.toString()); + } + } + public static class Messages implements RegistrableMessages { + + private final Map LOGGED_IN_FROM_OTHER_LOCATION; + private final Map ALREADY_LOGGED_IN; + private final Map SERVER_CONNECTING; + private final Map SERVER_NOT_FOUND; + + private final Locale defaultLocale; + + public Messages(Locale defaultLocale) { + LOGGED_IN_FROM_OTHER_LOCATION = new HashMap<>(); + ALREADY_LOGGED_IN = new HashMap<>(); + SERVER_CONNECTING = new HashMap<>(); + SERVER_NOT_FOUND = new HashMap<>(); + this.defaultLocale = defaultLocale; } - public static class Messages implements RegistrableMessages{ - - private final Map LOGGED_IN_FROM_OTHER_LOCATION; - private final Map ALREADY_LOGGED_IN; - private final Map SERVER_CONNECTING; - private final Map SERVER_NOT_FOUND; - - private final Locale defaultLocale; - - public Messages(Locale defaultLocale) { - LOGGED_IN_FROM_OTHER_LOCATION = new HashMap<>(); - ALREADY_LOGGED_IN = new HashMap<>(); - SERVER_CONNECTING = new HashMap<>(); - SERVER_NOT_FOUND = new HashMap<>(); - this.defaultLocale = defaultLocale; - } - - public void register(String id, Locale locale, String miniMessage) { - switch (id) { - case "server-not-found" -> SERVER_NOT_FOUND.put(locale, miniMessage); - case "server-connecting" -> SERVER_CONNECTING.put(locale, miniMessage); - case "logged-in-other-location" -> LOGGED_IN_FROM_OTHER_LOCATION.put(locale, MiniMessage.miniMessage().deserialize(miniMessage)); - case "already-logged-in" -> ALREADY_LOGGED_IN.put(locale, MiniMessage.miniMessage().deserialize(miniMessage)); - } - } - - public Component alreadyLoggedIn(Locale locale) { - if (ALREADY_LOGGED_IN.containsKey(locale)) return ALREADY_LOGGED_IN.get(locale); - return ALREADY_LOGGED_IN.get(defaultLocale); - } - - // there is no way to know whats client locale during login so just default to use default locale MESSAGES. - public Component alreadyLoggedIn() { - return this.alreadyLoggedIn(this.defaultLocale); - } - - public Component loggedInFromOtherLocation(Locale locale) { - if (LOGGED_IN_FROM_OTHER_LOCATION.containsKey(locale)) return LOGGED_IN_FROM_OTHER_LOCATION.get(locale); - return LOGGED_IN_FROM_OTHER_LOCATION.get(defaultLocale); - } - - // there is no way to know what's client locale during login so just default to use default locale MESSAGES. - public Component loggedInFromOtherLocation() { - return this.loggedInFromOtherLocation(this.defaultLocale); - } - - public Component serverConnecting(Locale locale, String server) { - String miniMessage; - if (SERVER_CONNECTING.containsKey(locale)) { - miniMessage = SERVER_CONNECTING.get(locale); - } else { - miniMessage = SERVER_CONNECTING.get(defaultLocale); - } - return MiniMessage.miniMessage().deserialize(miniMessage, Placeholder.parsed("server", server)); - } - - public Component serverConnecting(String server) { - return this.serverConnecting(this.defaultLocale, server); - } - - public Component serverNotFound(Locale locale, String server) { - String miniMessage; - if (SERVER_NOT_FOUND.containsKey(locale)) { - miniMessage = SERVER_NOT_FOUND.get(locale); - } else { - miniMessage = SERVER_NOT_FOUND.get(defaultLocale); - } - return MiniMessage.miniMessage().deserialize(miniMessage, Placeholder.parsed("server", server)); - } - - public Component serverNotFound(String server) { - return this.serverNotFound(this.defaultLocale, server); - } - - - // tests locale if set CORRECTLY or just throw if not - public void test(Locale locale) { - if (!(LOGGED_IN_FROM_OTHER_LOCATION.containsKey(locale) && ALREADY_LOGGED_IN.containsKey(locale) && SERVER_CONNECTING.containsKey(locale) && SERVER_NOT_FOUND.containsKey(locale))) { - throwError(locale, "messages"); - } - } - + public void register(String id, Locale locale, String miniMessage) { + switch (id) { + case "server-not-found" -> SERVER_NOT_FOUND.put(locale, miniMessage); + case "server-connecting" -> SERVER_CONNECTING.put(locale, miniMessage); + case "logged-in-other-location" -> + LOGGED_IN_FROM_OTHER_LOCATION.put( + locale, MiniMessage.miniMessage().deserialize(miniMessage)); + case "already-logged-in" -> + ALREADY_LOGGED_IN.put(locale, MiniMessage.miniMessage().deserialize(miniMessage)); + } } - private final Component redisBungeePrefix; - - private final Locale defaultLanguage; - - private final boolean useClientLanguage; - - private final Messages messages; - - public LangConfiguration(Component redisBungeePrefix, Locale defaultLanguage, boolean useClientLanguage, Messages messages) { - this.redisBungeePrefix = redisBungeePrefix; - this.defaultLanguage = defaultLanguage; - this.useClientLanguage = useClientLanguage; - this.messages = messages; + public Component alreadyLoggedIn(Locale locale) { + if (ALREADY_LOGGED_IN.containsKey(locale)) return ALREADY_LOGGED_IN.get(locale); + return ALREADY_LOGGED_IN.get(defaultLocale); } - public Component redisBungeePrefix() { - return redisBungeePrefix; + // there is no way to know whats client locale during login so just default to use default + // locale MESSAGES. + public Component alreadyLoggedIn() { + return this.alreadyLoggedIn(this.defaultLocale); } - public Locale defaultLanguage() { - return defaultLanguage; + public Component loggedInFromOtherLocation(Locale locale) { + if (LOGGED_IN_FROM_OTHER_LOCATION.containsKey(locale)) + return LOGGED_IN_FROM_OTHER_LOCATION.get(locale); + return LOGGED_IN_FROM_OTHER_LOCATION.get(defaultLocale); } - public boolean useClientLanguage() { - return useClientLanguage; + // there is no way to know what's client locale during login so just default to use default + // locale MESSAGES. + public Component loggedInFromOtherLocation() { + return this.loggedInFromOtherLocation(this.defaultLocale); } - public Messages messages() { - return messages; + public Component serverConnecting(Locale locale, String server) { + String miniMessage; + if (SERVER_CONNECTING.containsKey(locale)) { + miniMessage = SERVER_CONNECTING.get(locale); + } else { + miniMessage = SERVER_CONNECTING.get(defaultLocale); + } + return MiniMessage.miniMessage() + .deserialize(miniMessage, Placeholder.parsed("server", server)); } + public Component serverConnecting(String server) { + return this.serverConnecting(this.defaultLocale, server); + } + + public Component serverNotFound(Locale locale, String server) { + String miniMessage; + if (SERVER_NOT_FOUND.containsKey(locale)) { + miniMessage = SERVER_NOT_FOUND.get(locale); + } else { + miniMessage = SERVER_NOT_FOUND.get(defaultLocale); + } + return MiniMessage.miniMessage() + .deserialize(miniMessage, Placeholder.parsed("server", server)); + } + + public Component serverNotFound(String server) { + return this.serverNotFound(this.defaultLocale, server); + } + + // tests locale if set CORRECTLY or just throw if not + public void test(Locale locale) { + if (!(LOGGED_IN_FROM_OTHER_LOCATION.containsKey(locale) + && ALREADY_LOGGED_IN.containsKey(locale) + && SERVER_CONNECTING.containsKey(locale) + && SERVER_NOT_FOUND.containsKey(locale))) { + throwError(locale, "messages"); + } + } + } + + private final Component redisBungeePrefix; + + private final Locale defaultLanguage; + + private final boolean useClientLanguage; + + private final Messages messages; + + public LangConfiguration( + Component redisBungeePrefix, + Locale defaultLanguage, + boolean useClientLanguage, + Messages messages) { + this.redisBungeePrefix = redisBungeePrefix; + this.defaultLanguage = defaultLanguage; + this.useClientLanguage = useClientLanguage; + this.messages = messages; + } + + public Component redisBungeePrefix() { + return redisBungeePrefix; + } + + public Locale defaultLanguage() { + return defaultLanguage; + } + + public boolean useClientLanguage() { + return useClientLanguage; + } + + public Messages messages() { + return messages; + } } diff --git a/redisbungee/proxies/bungeecord/build.gradle.kts b/redisbungee/proxies/bungeecord/build.gradle.kts index 7ad42d9..ba3baa1 100644 --- a/redisbungee/proxies/bungeecord/build.gradle.kts +++ b/redisbungee/proxies/bungeecord/build.gradle.kts @@ -3,6 +3,9 @@ plugins { alias(libs.plugins.shadow) } +version = property("redisbungee-version").toString() +group = property("redisbungee-group").toString() + dependencies { implementation(project(":RedisBungee-Bungee")) compileOnly(libs.platform.bungeecord) diff --git a/redisbungee/proxies/bungeecord/bungeecord-api/build.gradle.kts b/redisbungee/proxies/bungeecord/bungeecord-api/build.gradle.kts index 42f6042..00062b0 100644 --- a/redisbungee/proxies/bungeecord/bungeecord-api/build.gradle.kts +++ b/redisbungee/proxies/bungeecord/bungeecord-api/build.gradle.kts @@ -3,6 +3,9 @@ plugins { `maven-publish` } +version = property("redisbungee-version").toString() +group = property("redisbungee-group").toString() + dependencies { api(project(":RedisBungee-API")) compileOnly(libs.adventure.platforms.bungeecord) diff --git a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/ApiPlatformSupport.java b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/ApiPlatformSupport.java index 9bfe64b..46abbf9 100644 --- a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/ApiPlatformSupport.java +++ b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/ApiPlatformSupport.java @@ -1,22 +1,19 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; -import net.kyori.adventure.text.Component; - import java.util.UUID; +import net.kyori.adventure.text.Component; // this class used to redirect calls to keep the implementation and api separate public interface ApiPlatformSupport { - void kickPlayer(UUID player, Component message); - + void kickPlayer(UUID player, Component message); } diff --git a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeAPI.java b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeAPI.java index f349383..b7d1787 100644 --- a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeAPI.java +++ b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeAPI.java @@ -1,16 +1,17 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; +import java.util.List; +import java.util.UUID; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; import net.md_5.bungee.api.chat.BaseComponent; @@ -19,145 +20,140 @@ import net.md_5.bungee.api.plugin.Plugin; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.List; -import java.util.UUID; - /** - * This platform class exposes some internal RedisBungee functions. You obtain an instance of this object by invoking {@link RedisBungeeAPI#getRedisBungeeApi()} - * or somehow you got the Plugin instance by you can call the api using {@link RedisBungeePlugin#getAbstractRedisBungeeApi()}. + * This platform class exposes some internal RedisBungee functions. You obtain an instance of this + * object by invoking {@link RedisBungeeAPI#getRedisBungeeApi()} or somehow you got the Plugin + * instance by you can call the api using {@link RedisBungeePlugin#getAbstractRedisBungeeApi()}. * * @author tuxed * @since 0.2.3 | updated 0.8.0 */ public class RedisBungeeAPI extends AbstractRedisBungeeAPI { - private static RedisBungeeAPI redisBungeeApi; + private static RedisBungeeAPI redisBungeeApi; - private static final BungeeComponentSerializer BUNGEE_COMPONENT_SERIALIZER = BungeeComponentSerializer.get(); + private static final BungeeComponentSerializer BUNGEE_COMPONENT_SERIALIZER = + BungeeComponentSerializer.get(); - public RedisBungeeAPI(RedisBungeePlugin plugin) { - super(plugin); - if (redisBungeeApi == null) { - redisBungeeApi = this; - } + public RedisBungeeAPI(RedisBungeePlugin plugin) { + super(plugin); + if (redisBungeeApi == null) { + redisBungeeApi = this; } + } - /** - * Get the server where the specified player is playing. This function also deals with the case of local players - * as well, and will return local information on them. - * - * @param player a player uuid - * @return {@link ServerInfo} Can be null if proxy can't find it. - * @see #getServerNameFor(UUID) - */ - @Nullable - public final ServerInfo getServerFor(@NonNull UUID player) { - String serverName = this.getServerNameFor(player); - if (serverName == null) return null; - return ((Plugin) this.plugin).getProxy().getServerInfo(serverName); - } + /** + * Get the server where the specified player is playing. This function also deals with the case of + * local players as well, and will return local information on them. + * + * @param player a player uuid + * @return {@link ServerInfo} Can be null if proxy can't find it. + * @see #getServerNameFor(UUID) + */ + @Nullable + public final ServerInfo getServerFor(@NonNull UUID player) { + String serverName = this.getServerNameFor(player); + if (serverName == null) return null; + return ((Plugin) this.plugin).getProxy().getServerInfo(serverName); + } - /** - * Kicks a player from the network - * calls {@link #getUuidFromName(String)} to get uuid - * - * @param playerName player name - * @param message kick message that player will see on kick - * @since 0.13.0 - */ - public void kickPlayer(String playerName, BaseComponent[] message) { - kickPlayer(getUuidFromName(playerName), message); - } + /** + * Kicks a player from the network calls {@link #getUuidFromName(String)} to get uuid + * + * @param playerName player name + * @param message kick message that player will see on kick + * @since 0.13.0 + */ + public void kickPlayer(String playerName, BaseComponent[] message) { + kickPlayer(getUuidFromName(playerName), message); + } - /** - * Kicks a player from the network - * - * @param player player uuid - * @param message kick message that player will see on kick - * @since 0.13.0 - */ - public void kickPlayer(UUID player, BaseComponent[] message) { - kickPlayer(player, BUNGEE_COMPONENT_SERIALIZER.deserialize(message)); - } + /** + * Kicks a player from the network + * + * @param player player uuid + * @param message kick message that player will see on kick + * @since 0.13.0 + */ + public void kickPlayer(UUID player, BaseComponent[] message) { + kickPlayer(player, BUNGEE_COMPONENT_SERIALIZER.deserialize(message)); + } - /** - * Kicks a player from the network - * calls {@link #getUuidFromName(String)} to get uuid - * - * @param playerName player name - * @param message kick message that player will see on kick - * @since 0.12.0 - */ - public void kickPlayer(String playerName, Component message) { - kickPlayer(getUuidFromName(playerName), message); - } + /** + * Kicks a player from the network calls {@link #getUuidFromName(String)} to get uuid + * + * @param playerName player name + * @param message kick message that player will see on kick + * @since 0.12.0 + */ + public void kickPlayer(String playerName, Component message) { + kickPlayer(getUuidFromName(playerName), message); + } - /** - * Kicks a player from the network - * - * @param player player uuid - * @param message kick message that player will see on kick - * @since 0.12.0 - */ - public void kickPlayer(UUID player, Component message) { - ((ApiPlatformSupport) this.plugin).kickPlayer(player, message); - } + /** + * Kicks a player from the network + * + * @param player player uuid + * @param message kick message that player will see on kick + * @since 0.12.0 + */ + public void kickPlayer(UUID player, Component message) { + ((ApiPlatformSupport) this.plugin).kickPlayer(player, message); + } - /** - * Get the current BungeeCord / Velocity proxy ID for this server. - * - * @return the current server ID - * @see #getAllServers() - * @since 0.2.5 - * @deprecated to avoid confusion between A server and A proxy see #getProxyId() - */ - @Deprecated(forRemoval = true) - public final String getServerId() { - return getProxyId(); - } + /** + * Get the current BungeeCord / Velocity proxy ID for this server. + * + * @return the current server ID + * @see #getAllServers() + * @since 0.2.5 + * @deprecated to avoid confusion between A server and A proxy see #getProxyId() + */ + @Deprecated(forRemoval = true) + public final String getServerId() { + return getProxyId(); + } - /** - * Get all the linked proxies in this network. - * - * @return the list of all proxies - * @see #getServerId() - * @since 0.2.5 - * @deprecated to avoid confusion between A server and A proxy see see {@link #getAllProxies()} - */ - @Deprecated(forRemoval = true) - public final List getAllServers() { - return getAllProxies(); - } + /** + * Get all the linked proxies in this network. + * + * @return the list of all proxies + * @see #getServerId() + * @since 0.2.5 + * @deprecated to avoid confusion between A server and A proxy see see {@link #getAllProxies()} + */ + @Deprecated(forRemoval = true) + public final List getAllServers() { + return getAllProxies(); + } - /** - * Register (a) PubSub channel(s), so that you may handle PubSubMessageEvent for it. - * - * @param channels the channels to register - * @since 0.3 - * @deprecated No longer required - */ - @Deprecated(forRemoval = true) - public final void registerPubSubChannels(String... channels) { - } + /** + * Register (a) PubSub channel(s), so that you may handle PubSubMessageEvent for it. + * + * @param channels the channels to register + * @since 0.3 + * @deprecated No longer required + */ + @Deprecated(forRemoval = true) + public final void registerPubSubChannels(String... channels) {} - /** - * Unregister (a) PubSub channel(s). - * - * @param channels the channels to unregister - * @since 0.3 - * @deprecated No longer required - */ - @Deprecated(forRemoval = true) - public final void unregisterPubSubChannels(String... channels) { - } + /** + * Unregister (a) PubSub channel(s). + * + * @param channels the channels to unregister + * @since 0.3 + * @deprecated No longer required + */ + @Deprecated(forRemoval = true) + public final void unregisterPubSubChannels(String... channels) {} - /** - * Api instance - * - * @return the API instance. - * @since 0.6.5 - */ - public static RedisBungeeAPI getRedisBungeeApi() { - return redisBungeeApi; - } + /** + * Api instance + * + * @return the API instance. + * @since 0.6.5 + */ + public static RedisBungeeAPI getRedisBungeeApi() { + return redisBungeeApi; + } } diff --git a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java index a6b33f9..c05add7 100644 --- a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java +++ b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java @@ -1,52 +1,51 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.events; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerChangedServerNetworkEvent; -import net.md_5.bungee.api.plugin.Event; - import java.util.UUID; +import net.md_5.bungee.api.plugin.Event; /** * This event is sent when a player connects to a new server. RedisBungee sends the event only when * the proxy the player has been connected to is different than the local proxy. - *

- * This event corresponds to {@link net.md_5.bungee.api.event.ServerConnectedEvent}, and is fired + * + *

This event corresponds to {@link net.md_5.bungee.api.event.ServerConnectedEvent}, and is fired * asynchronously. * * @since 0.3.4 */ -public class PlayerChangedServerNetworkEvent extends Event implements IPlayerChangedServerNetworkEvent { - private final UUID uuid; - private final String previousServer; - private final String server; +public class PlayerChangedServerNetworkEvent extends Event + implements IPlayerChangedServerNetworkEvent { + private final UUID uuid; + private final String previousServer; + private final String server; - public PlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) { - this.uuid = uuid; - this.previousServer = previousServer; - this.server = server; - } + public PlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) { + this.uuid = uuid; + this.previousServer = previousServer; + this.server = server; + } - @Override - public UUID getUuid() { - return uuid; - } + @Override + public UUID getUuid() { + return uuid; + } - @Override - public String getServer() { - return server; - } + @Override + public String getServer() { + return server; + } - @Override - public String getPreviousServer() { - return previousServer; - } + @Override + public String getPreviousServer() { + return previousServer; + } } diff --git a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java index 51ff842..3579acc 100644 --- a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java +++ b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java @@ -1,38 +1,36 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.events; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEvent; +import java.util.UUID; import net.md_5.bungee.api.plugin.Event; -import java.util.UUID; - /** - * This event is sent when a player joins the network. RedisBungee sends the event only when - * the proxy the player has been connected to is different than the local proxy. - *

- * This event corresponds to {@link net.md_5.bungee.api.event.PostLoginEvent}, and is fired + * This event is sent when a player joins the network. RedisBungee sends the event only when the + * proxy the player has been connected to is different than the local proxy. + * + *

This event corresponds to {@link net.md_5.bungee.api.event.PostLoginEvent}, and is fired * asynchronously. * * @since 0.3.4 */ public class PlayerJoinedNetworkEvent extends Event implements IPlayerJoinedNetworkEvent { - private final UUID uuid; + private final UUID uuid; - public PlayerJoinedNetworkEvent(UUID uuid) { - this.uuid = uuid; - } + public PlayerJoinedNetworkEvent(UUID uuid) { + this.uuid = uuid; + } - @Override - public UUID getUuid() { - return uuid; - } + @Override + public UUID getUuid() { + return uuid; + } } diff --git a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java index 3edf2bb..f8e0dc3 100644 --- a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java +++ b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java @@ -1,38 +1,36 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.events; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent; +import java.util.UUID; import net.md_5.bungee.api.plugin.Event; -import java.util.UUID; - /** - * This event is sent when a player disconnects. RedisBungee sends the event only when - * the proxy the player has been connected to is different than the local proxy. - *

- * This event corresponds to {@link net.md_5.bungee.api.event.PlayerDisconnectEvent}, and is fired - * asynchronously. + * This event is sent when a player disconnects. RedisBungee sends the event only when the proxy the + * player has been connected to is different than the local proxy. + * + *

This event corresponds to {@link net.md_5.bungee.api.event.PlayerDisconnectEvent}, and is + * fired asynchronously. * * @since 0.3.4 */ public class PlayerLeftNetworkEvent extends Event implements IPlayerLeftNetworkEvent { - private final UUID uuid; + private final UUID uuid; - public PlayerLeftNetworkEvent(UUID uuid) { - this.uuid = uuid; - } + public PlayerLeftNetworkEvent(UUID uuid) { + this.uuid = uuid; + } - @Override - public UUID getUuid() { - return uuid; - } + @Override + public UUID getUuid() { + return uuid; + } } diff --git a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java index b328c40..919cc5b 100644 --- a/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java +++ b/redisbungee/proxies/bungeecord/bungeecord-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.events; import com.imaginarycode.minecraft.redisbungee.api.events.IPubSubMessageEvent; @@ -15,28 +14,27 @@ import net.md_5.bungee.api.plugin.Event; /** * This event is posted when a PubSub message is received. - *

- * Warning: This event is fired in a separate thread! + * + *

Warning: This event is fired in a separate thread! * * @since 0.2.6 */ - public class PubSubMessageEvent extends Event implements IPubSubMessageEvent { - private final String channel; - private final String message; + private final String channel; + private final String message; - public PubSubMessageEvent(String channel, String message) { - this.channel = channel; - this.message = message; - } + public PubSubMessageEvent(String channel, String message) { + this.channel = channel; + this.message = message; + } - @Override - public String getChannel() { - return channel; - } + @Override + public String getChannel() { + return channel; + } - @Override - public String getMessage() { - return message; - } + @Override + public String getMessage() { + return message; + } } diff --git a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/BungeeCommandPlatformHelper.java b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/BungeeCommandPlatformHelper.java index 019d06f..71960d8 100644 --- a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/BungeeCommandPlatformHelper.java +++ b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/BungeeCommandPlatformHelper.java @@ -1,3 +1,12 @@ +/* +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import co.aikar.commands.BungeeCommandIssuer; @@ -8,10 +17,9 @@ import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; public class BungeeCommandPlatformHelper extends CommandPlatformHelper { - @Override - public void sendMessage(CommandIssuer issuer, Component component) { - BungeeCommandIssuer bIssuer = (BungeeCommandIssuer) issuer; - bIssuer.getIssuer().sendMessage(BungeeComponentSerializer.get().serialize(component)); - } - + @Override + public void sendMessage(CommandIssuer issuer, Component component) { + BungeeCommandIssuer bIssuer = (BungeeCommandIssuer) issuer; + bIssuer.getIssuer().sendMessage(BungeeComponentSerializer.get().serialize(component)); + } } diff --git a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/BungeePlayerDataManager.java b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/BungeePlayerDataManager.java index e4f2fcb..3365537 100644 --- a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/BungeePlayerDataManager.java +++ b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/BungeePlayerDataManager.java @@ -1,25 +1,24 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import com.imaginarycode.minecraft.redisbungee.api.PlayerDataManager; -import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PlayerLeftNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent; +import java.util.UUID; +import java.util.concurrent.TimeUnit; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.api.event.PlayerDisconnectEvent; @@ -29,106 +28,115 @@ import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.event.EventHandler; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - - public class BungeePlayerDataManager extends PlayerDataManager implements Listener { - private final RedisBungee bPlugin; - public BungeePlayerDataManager(RedisBungee plugin) { - super(plugin); - bPlugin = plugin; + private final RedisBungee bPlugin; + + public BungeePlayerDataManager(RedisBungee plugin) { + super(plugin); + bPlugin = plugin; + } + + @EventHandler + public void onPlayerChangedServerNetworkEvent(PlayerChangedServerNetworkEvent event) { + super.handleNetworkPlayerServerChange(event); + } + + @EventHandler + public void onNetworkPlayerQuit(PlayerLeftNetworkEvent event) { + super.handleNetworkPlayerQuit(event); + } + + @EventHandler + public void onNetworkPlayerJoin(PlayerJoinedNetworkEvent event) { + super.handleNetworkPlayerJoin(event); + } + + @EventHandler + public void onPubSubMessageEvent(PubSubMessageEvent event) { + super.handlePubSubMessageEvent(event); + } + + @EventHandler + public void onServerConnectedEvent(ServerConnectedEvent event) { + final String currentServer = event.getServer().getInfo().getName(); + final String oldServer = + event.getPlayer().getServer() == null + ? null + : event.getPlayer().getServer().getInfo().getName(); + super.playerChangedServer(event.getPlayer().getUniqueId(), oldServer, currentServer); + } + + private final BungeeComponentSerializer BUNGEE_COMPONENT_SERIALIZER = + BungeeComponentSerializer.get(); + + private static final MiniMessage MINI_MESSAGE_SERIALIZER = MiniMessage.miniMessage(); + + @Override + public boolean handleSerializedKick(UUID uuid, String serializedMiniMessage) { + ProxiedPlayer player = plugin.getPlayer(uuid); + if (player == null) return false; + // decode the adventure component + if (serializedMiniMessage == null) { + // kick the player too even if the message is invalid + player.disconnect(BUNGEE_COMPONENT_SERIALIZER.serialize(Component.empty())); + plugin.logWarn("unable to decode serialized adventure component because its empty or null"); + } else { + Component message = MINI_MESSAGE_SERIALIZER.deserialize(serializedMiniMessage); + player.disconnect(BUNGEE_COMPONENT_SERIALIZER.serialize(message)); } + return true; + } - @EventHandler - public void onPlayerChangedServerNetworkEvent(PlayerChangedServerNetworkEvent event) { - super.handleNetworkPlayerServerChange(event); - } + public void kickPlayer(UUID player, Component message) { + serializedPlayerKick(player, MINI_MESSAGE_SERIALIZER.serialize(message)); + } - @EventHandler - public void onNetworkPlayerQuit(PlayerLeftNetworkEvent event) { - super.handleNetworkPlayerQuit(event); - } - - @EventHandler - public void onNetworkPlayerJoin(PlayerJoinedNetworkEvent event) { - super.handleNetworkPlayerJoin(event); - } - - @EventHandler - public void onPubSubMessageEvent(PubSubMessageEvent event) { - super.handlePubSubMessageEvent(event); - } - - @EventHandler - public void onServerConnectedEvent(ServerConnectedEvent event) { - final String currentServer = event.getServer().getInfo().getName(); - final String oldServer = event.getPlayer().getServer() == null ? null : event.getPlayer().getServer().getInfo().getName(); - super.playerChangedServer(event.getPlayer().getUniqueId(), oldServer, currentServer); - } - - private final BungeeComponentSerializer BUNGEE_COMPONENT_SERIALIZER = BungeeComponentSerializer.get(); - - private final static MiniMessage MINI_MESSAGE_SERIALIZER = MiniMessage.miniMessage(); - @Override - public boolean handleSerializedKick(UUID uuid, String serializedMiniMessage) { - ProxiedPlayer player = plugin.getPlayer(uuid); - if (player == null) return false; - // decode the adventure component - if (serializedMiniMessage == null) { - // kick the player too even if the message is invalid - player.disconnect(BUNGEE_COMPONENT_SERIALIZER.serialize(Component.empty())); - plugin.logWarn("unable to decode serialized adventure component because its empty or null"); - } else { - Component message = MINI_MESSAGE_SERIALIZER.deserialize(serializedMiniMessage); - player.disconnect(BUNGEE_COMPONENT_SERIALIZER.serialize(message)); - } - return true; - } - - public void kickPlayer(UUID player, Component message) { - serializedPlayerKick(player, MINI_MESSAGE_SERIALIZER.serialize(message)); - } - - @EventHandler - public void onLoginEvent(LoginEvent event) { - event.registerIntent((Plugin) plugin); - // check if online - if (getLastOnline(event.getConnection().getUniqueId()) == 0) { - // because something can go wrong and proxy somehow does not update player data correctly on shutdown - // we have to check proxy if it has the player - String proxyId = getProxyFor(event.getConnection().getUniqueId()); - if (proxyId == null || !plugin.proxyDataManager().isPlayerTrulyOnProxy(proxyId, event.getConnection().getUniqueId())) { - event.completeIntent((Plugin) plugin); - } else { - if (plugin.configuration().kickWhenOnline()) { - kickPlayer(event.getConnection().getUniqueId(), bPlugin.langConfiguration().messages().loggedInFromOtherLocation()); - // wait 3 seconds before releasing the event - plugin.executeAsyncAfter(() -> event.completeIntent((Plugin) plugin), TimeUnit.SECONDS, 3); - } else { - event.setCancelled(true); - event.setCancelReason(BungeeComponentSerializer.get().serialize(bPlugin.langConfiguration().messages().alreadyLoggedIn())); - event.completeIntent((Plugin) plugin); - } - } + @EventHandler + public void onLoginEvent(LoginEvent event) { + event.registerIntent((Plugin) plugin); + // check if online + if (getLastOnline(event.getConnection().getUniqueId()) == 0) { + // because something can go wrong and proxy somehow does not update player data correctly on + // shutdown + // we have to check proxy if it has the player + String proxyId = getProxyFor(event.getConnection().getUniqueId()); + if (proxyId == null + || !plugin + .proxyDataManager() + .isPlayerTrulyOnProxy(proxyId, event.getConnection().getUniqueId())) { + event.completeIntent((Plugin) plugin); + } else { + if (plugin.configuration().kickWhenOnline()) { + kickPlayer( + event.getConnection().getUniqueId(), + bPlugin.langConfiguration().messages().loggedInFromOtherLocation()); + // wait 3 seconds before releasing the event + plugin.executeAsyncAfter( + () -> event.completeIntent((Plugin) plugin), TimeUnit.SECONDS, 3); } else { - event.completeIntent((Plugin) plugin); + event.setCancelled(true); + event.setCancelReason( + BungeeComponentSerializer.get() + .serialize(bPlugin.langConfiguration().messages().alreadyLoggedIn())); + event.completeIntent((Plugin) plugin); } - - } - - - @EventHandler - public void onLoginEvent(PostLoginEvent event) { - super.addPlayer(event.getPlayer().getUniqueId(), event.getPlayer().getName(), event.getPlayer().getAddress().getAddress()); - } - - - @EventHandler - public void onDisconnectEvent(PlayerDisconnectEvent event) { - super.removePlayer(event.getPlayer().getUniqueId()); + } + } else { + event.completeIntent((Plugin) plugin); } + } + @EventHandler + public void onLoginEvent(PostLoginEvent event) { + super.addPlayer( + event.getPlayer().getUniqueId(), + event.getPlayer().getName(), + event.getPlayer().getAddress().getAddress()); + } + @EventHandler + public void onDisconnectEvent(PlayerDisconnectEvent event) { + super.removePlayer(event.getPlayer().getUniqueId()); + } } diff --git a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java index d39c6ed..dda19fc 100644 --- a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java +++ b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungee.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import co.aikar.commands.BungeeCommandManager; @@ -15,8 +14,8 @@ import com.imaginarycode.minecraft.redisbungee.api.PlayerDataManager; import com.imaginarycode.minecraft.redisbungee.api.ProxyDataManager; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeeMode; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; -import com.imaginarycode.minecraft.redisbungee.api.config.loaders.ConfigLoader; import com.imaginarycode.minecraft.redisbungee.api.config.RedisBungeeConfiguration; +import com.imaginarycode.minecraft.redisbungee.api.config.loaders.ConfigLoader; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerChangedServerNetworkEvent; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEvent; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent; @@ -31,6 +30,14 @@ import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetwork import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PlayerLeftNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.InetAddress; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.*; +import java.util.logging.Level; import net.kyori.adventure.text.Component; import net.limework.valiobungee.config.lang.LangConfigLoader; import net.limework.valiobungee.config.lang.LangConfiguration; @@ -43,327 +50,333 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import redis.clients.jedis.JedisPool; -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.InetAddress; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.*; -import java.util.logging.Level; +public class RedisBungee extends Plugin + implements RedisBungeePlugin, + ConfigLoader, + LangConfigLoader, + ApiPlatformSupport { + private static RedisBungeeAPI apiStatic; + private AbstractRedisBungeeAPI api; + private RedisBungeeMode redisBungeeMode; + private ProxyDataManager proxyDataManager; + private BungeePlayerDataManager playerDataManager; + private ScheduledTask heartbeatTask; + private ScheduledTask cleanupTask; + private Summoner summoner; + private UUIDTranslator uuidTranslator; + private RedisBungeeConfiguration configuration; + private LangConfiguration langConfiguration; + private BungeeCommandManager commandManager; -public class RedisBungee extends Plugin implements RedisBungeePlugin, ConfigLoader, LangConfigLoader, ApiPlatformSupport { + private final Logger logger = LoggerFactory.getLogger("RedisBungee"); - private static RedisBungeeAPI apiStatic; - private AbstractRedisBungeeAPI api; - private RedisBungeeMode redisBungeeMode; - private ProxyDataManager proxyDataManager; - private BungeePlayerDataManager playerDataManager; - private ScheduledTask heartbeatTask; - private ScheduledTask cleanupTask; - private Summoner summoner; - private UUIDTranslator uuidTranslator; - private RedisBungeeConfiguration configuration; - private LangConfiguration langConfiguration; - private BungeeCommandManager commandManager; + @Override + public RedisBungeeConfiguration configuration() { + return this.configuration; + } - private final Logger logger = LoggerFactory.getLogger("RedisBungee"); + public LangConfiguration langConfiguration() { + return this.langConfiguration; + } + @Override + public AbstractRedisBungeeAPI getAbstractRedisBungeeApi() { + return this.api; + } - @Override - public RedisBungeeConfiguration configuration() { - return this.configuration; + @Override + public ProxyDataManager proxyDataManager() { + return this.proxyDataManager; + } + + @Override + public PlayerDataManager playerDataManager() { + return this.playerDataManager; + } + + @Override + public UUIDTranslator getUuidTranslator() { + return this.uuidTranslator; + } + + @Override + public void fireEvent(Object event) { + this.getProxy().getPluginManager().callEvent((Event) event); + } + + @Override + public boolean isOnlineMode() { + return this.getProxy().getConfig().isOnlineMode(); + } + + @Override + public void logInfo(String msg) { + this.logger.info(msg); + } + + @Override + public void logInfo(String format, Object... object) { + this.logger.info(format, object); + } + + @Override + public void logWarn(String msg) { + this.logger.warn(msg); + } + + @Override + public void logWarn(String format, Object... object) { + this.logger.warn(format, object); + } + + @Override + public void logFatal(String msg) { + this.logger.error(msg); + } + + @Override + public void logFatal(String format, Throwable throwable) { + this.logger.error(format, throwable); + } + + @Override + public ProxiedPlayer getPlayer(UUID uuid) { + return this.getProxy().getPlayer(uuid); + } + + @Override + public ProxiedPlayer getPlayer(String name) { + return this.getProxy().getPlayer(name); + } + + @Override + public UUID getPlayerUUID(String player) { + return this.getProxy().getPlayer(player).getUniqueId(); + } + + @Override + public String getPlayerName(UUID player) { + return this.getProxy().getPlayer(player).getName(); + } + + @Override + public String getPlayerServerName(ProxiedPlayer player) { + return player.getServer().getInfo().getName(); + } + + @Override + public boolean isPlayerOnAServer(ProxiedPlayer player) { + return player.getServer() != null; + } + + @Override + public InetAddress getPlayerIp(ProxiedPlayer player) { + return player.getAddress().getAddress(); + } + + @Override + public void initialize() { + logInfo("Initializing RedisBungee....."); + logInfo("Version: {}", Constants.VERSION); + ThreadFactory factory = ((ThreadPoolExecutor) getExecutorService()).getThreadFactory(); + ScheduledExecutorService service = Executors.newScheduledThreadPool(24, factory); + try { + Field field = Plugin.class.getDeclaredField("service"); + field.setAccessible(true); + ExecutorService builtinService = (ExecutorService) field.get(this); + field.set(this, service); + builtinService.shutdownNow(); + } catch (IllegalAccessException | NoSuchFieldException e) { + getLogger().log(Level.WARNING, "Can't replace BungeeCord thread pool with our own"); + getLogger().log(Level.WARNING, "skipping replacement....."); } - - public LangConfiguration langConfiguration() { - return this.langConfiguration; + try { + loadConfig(this, getDataFolder().toPath()); + loadLangConfig(this, getDataFolder().toPath()); + } catch (IOException e) { + throw new RuntimeException("Unable to load/save config", e); } + // init the proxy data manager + this.proxyDataManager = + new ProxyDataManager(this) { + @Override + public Set getLocalOnlineUUIDs() { + HashSet uuids = new HashSet<>(); + ProxyServer.getInstance() + .getPlayers() + .forEach((proxiedPlayer) -> uuids.add(proxiedPlayer.getUniqueId())); + return uuids; + } - @Override - public AbstractRedisBungeeAPI getAbstractRedisBungeeApi() { - return this.api; - } - - @Override - public ProxyDataManager proxyDataManager() { - return this.proxyDataManager; - } - - @Override - public PlayerDataManager playerDataManager() { - return this.playerDataManager; - } - - @Override - public UUIDTranslator getUuidTranslator() { - return this.uuidTranslator; - } - - @Override - public void fireEvent(Object event) { - this.getProxy().getPluginManager().callEvent((Event) event); - } - - @Override - public boolean isOnlineMode() { - return this.getProxy().getConfig().isOnlineMode(); - } - - @Override - public void logInfo(String msg) { - this.logger.info(msg); - } - - @Override - public void logInfo(String format, Object... object) { - this.logger.info(format, object); - } - - @Override - public void logWarn(String msg) { - this.logger.warn(msg); - } - - @Override - public void logWarn(String format, Object... object) { - this.logger.warn(format, object); - } - - @Override - public void logFatal(String msg) { - this.logger.error(msg); - } - - @Override - public void logFatal(String format, Throwable throwable) { - this.logger.error(format, throwable); - } - - @Override - public ProxiedPlayer getPlayer(UUID uuid) { - return this.getProxy().getPlayer(uuid); - } - - @Override - public ProxiedPlayer getPlayer(String name) { - return this.getProxy().getPlayer(name); - } - - @Override - public UUID getPlayerUUID(String player) { - return this.getProxy().getPlayer(player).getUniqueId(); - } - - @Override - public String getPlayerName(UUID player) { - return this.getProxy().getPlayer(player).getName(); - } - - @Override - public String getPlayerServerName(ProxiedPlayer player) { - return player.getServer().getInfo().getName(); - } - - @Override - public boolean isPlayerOnAServer(ProxiedPlayer player) { - return player.getServer() != null; - } - - @Override - public InetAddress getPlayerIp(ProxiedPlayer player) { - return player.getAddress().getAddress(); - } - - - @Override - public void initialize() { - logInfo("Initializing RedisBungee....."); - logInfo("Version: {}", Constants.VERSION); - ThreadFactory factory = ((ThreadPoolExecutor) getExecutorService()).getThreadFactory(); - ScheduledExecutorService service = Executors.newScheduledThreadPool(24, factory); - try { - Field field = Plugin.class.getDeclaredField("service"); - field.setAccessible(true); - ExecutorService builtinService = (ExecutorService) field.get(this); - field.set(this, service); - builtinService.shutdownNow(); - } catch (IllegalAccessException | NoSuchFieldException e) { - getLogger().log(Level.WARNING, "Can't replace BungeeCord thread pool with our own"); - getLogger().log(Level.WARNING, "skipping replacement....."); - } - try { - loadConfig(this, getDataFolder().toPath()); - loadLangConfig(this, getDataFolder().toPath()); - } catch (IOException e) { - throw new RuntimeException("Unable to load/save config", e); - } - // init the proxy data manager - this.proxyDataManager = new ProxyDataManager(this) { - @Override - public Set getLocalOnlineUUIDs() { - HashSet uuids = new HashSet<>(); - ProxyServer.getInstance().getPlayers().forEach((proxiedPlayer) -> uuids.add(proxiedPlayer.getUniqueId())); - return uuids; - } - - @Override - protected void handlePlatformCommandExecution(String command) { - logInfo("Dispatching {}", command); - ProxyServer.getInstance().getPluginManager().dispatchCommand(RedisBungeeCommandSender.getSingleton(), command); - } + @Override + protected void handlePlatformCommandExecution(String command) { + logInfo("Dispatching {}", command); + ProxyServer.getInstance() + .getPluginManager() + .dispatchCommand(RedisBungeeCommandSender.getSingleton(), command); + } }; - this.playerDataManager = new BungeePlayerDataManager(this); + this.playerDataManager = new BungeePlayerDataManager(this); - getProxy().getPluginManager().registerListener(this, this.playerDataManager); - getProxy().getPluginManager().registerListener(this, new RedisBungeeListener(this)); - // start listening - getProxy().getScheduler().runAsync(this, proxyDataManager); - // heartbeat - this.heartbeatTask = getProxy().getScheduler().schedule(this, () -> this.proxyDataManager.publishHeartbeat(), 0, 1, TimeUnit.SECONDS); - // cleanup - this.cleanupTask = getProxy().getScheduler().schedule(this, () -> this.proxyDataManager.correctionTask(), 0, 60, TimeUnit.SECONDS); - // init the http lib - InitialUtils.checkRedisVersion(this); - uuidTranslator = new UUIDTranslator(this); + getProxy().getPluginManager().registerListener(this, this.playerDataManager); + getProxy().getPluginManager().registerListener(this, new RedisBungeeListener(this)); + // start listening + getProxy().getScheduler().runAsync(this, proxyDataManager); + // heartbeat + this.heartbeatTask = + getProxy() + .getScheduler() + .schedule(this, () -> this.proxyDataManager.publishHeartbeat(), 0, 1, TimeUnit.SECONDS); + // cleanup + this.cleanupTask = + getProxy() + .getScheduler() + .schedule(this, () -> this.proxyDataManager.correctionTask(), 0, 60, TimeUnit.SECONDS); + // init the http lib + InitialUtils.checkRedisVersion(this); + uuidTranslator = new UUIDTranslator(this); - // register plugin messages channel. - getProxy().registerChannel("legacy:redisbungee"); - getProxy().registerChannel("RedisBungee"); + // register plugin messages channel. + getProxy().registerChannel("legacy:redisbungee"); + getProxy().registerChannel("RedisBungee"); - // init the api - this.api = new RedisBungeeAPI(this); - apiStatic = (RedisBungeeAPI) this.api; + // init the api + this.api = new RedisBungeeAPI(this); + apiStatic = (RedisBungeeAPI) this.api; - // commands - CommandPlatformHelper.init(new BungeeCommandPlatformHelper()); - this.commandManager = new BungeeCommandManager(this); - CommandLoader.initCommands(this.commandManager, this); + // commands + CommandPlatformHelper.init(new BungeeCommandPlatformHelper()); + this.commandManager = new BungeeCommandManager(this); + CommandLoader.initCommands(this.commandManager, this); - logInfo("RedisBungee initialized successfully "); + logInfo("RedisBungee initialized successfully "); + } + + @Override + public void stop() { + logInfo("Turning off redis connections....."); + getProxy().getPluginManager().unregisterListeners(this); + + if (this.cleanupTask != null) { + this.cleanupTask.cancel(); } - - @Override - public void stop() { - logInfo("Turning off redis connections....."); - getProxy().getPluginManager().unregisterListeners(this); - - if (this.cleanupTask != null) { - this.cleanupTask.cancel(); - } - if (heartbeatTask != null) { - heartbeatTask.cancel(); - } - try { - this.proxyDataManager.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - try { - this.summoner.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - if (this.commandManager != null) { - this.commandManager.unregisterCommands(); - } - logInfo("RedisBungee shutdown successfully"); + if (heartbeatTask != null) { + heartbeatTask.cancel(); } - - @Override - public Summoner getSummoner() { - return this.summoner; + try { + this.proxyDataManager.close(); + } catch (Exception e) { + throw new RuntimeException(e); } - - @Override - public RedisBungeeMode getRedisBungeeMode() { - return this.redisBungeeMode; + try { + this.summoner.close(); + } catch (IOException e) { + throw new RuntimeException(e); } - - @Override - public void executeAsync(Runnable runnable) { - this.getProxy().getScheduler().runAsync(this, runnable); + if (this.commandManager != null) { + this.commandManager.unregisterCommands(); } + logInfo("RedisBungee shutdown successfully"); + } - @Override - public void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time) { - this.getProxy().getScheduler().schedule(this, runnable, time, timeUnit); + @Override + public Summoner getSummoner() { + return this.summoner; + } + + @Override + public RedisBungeeMode getRedisBungeeMode() { + return this.redisBungeeMode; + } + + @Override + public void executeAsync(Runnable runnable) { + this.getProxy().getScheduler().runAsync(this, runnable); + } + + @Override + public void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time) { + this.getProxy().getScheduler().schedule(this, runnable, time, timeUnit); + } + + @Override + public void onEnable() { + initialize(); + } + + @Override + public void onDisable() { + stop(); + } + + @Override + public IPlayerChangedServerNetworkEvent createPlayerChangedServerNetworkEvent( + UUID uuid, String previousServer, String server) { + return new PlayerChangedServerNetworkEvent(uuid, previousServer, server); + } + + @Override + public IPlayerJoinedNetworkEvent createPlayerJoinedNetworkEvent(UUID uuid) { + return new PlayerJoinedNetworkEvent(uuid); + } + + @Override + public IPlayerLeftNetworkEvent createPlayerLeftNetworkEvent(UUID uuid) { + return new PlayerLeftNetworkEvent(uuid); + } + + @Override + public IPubSubMessageEvent createPubSubEvent(String channel, String message) { + return new PubSubMessageEvent(channel, message); + } + + @Override + public void onConfigLoad( + RedisBungeeConfiguration configuration, Summoner summoner, RedisBungeeMode mode) { + this.configuration = configuration; + this.redisBungeeMode = mode; + this.summoner = summoner; + } + + @Override + public void onLangConfigLoad(LangConfiguration langConfiguration) { + this.langConfiguration = langConfiguration; + } + + @Override + public String platformId() { + return "bungeecord"; + } + + @Override + public void kickPlayer(UUID player, Component message) { + this.playerDataManager.kickPlayer(player, message); + } + + /** + * This returns an instance of {@link RedisBungeeAPI} + * + * @return the {@link AbstractRedisBungeeAPI} object instance. + * @deprecated Please use {@link RedisBungeeAPI#getRedisBungeeApi()} this class intended to for + * old plugins that no longer updated. + */ + @Deprecated + public static RedisBungeeAPI getApi() { + return apiStatic; + } + + @Deprecated + public JedisPool getPool() { + if (api.getMode() == RedisBungeeMode.SINGLE) { + JedisPool jedisPool = ((JedisPooledSummoner) getSummoner()).getCompatibilityJedisPool(); + if (jedisPool == null) { + throw new IllegalStateException( + "JedisPool compatibility mode is disabled, Please enable it in the RedisBungee config.yml"); + } + return jedisPool; + } else { + throw new IllegalStateException("Mode is not " + RedisBungeeMode.SINGLE); } - - @Override - public void onEnable() { - initialize(); - } - - @Override - public void onDisable() { - stop(); - } - - @Override - public IPlayerChangedServerNetworkEvent createPlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) { - return new PlayerChangedServerNetworkEvent(uuid, previousServer, server); - } - - @Override - public IPlayerJoinedNetworkEvent createPlayerJoinedNetworkEvent(UUID uuid) { - return new PlayerJoinedNetworkEvent(uuid); - } - - @Override - public IPlayerLeftNetworkEvent createPlayerLeftNetworkEvent(UUID uuid) { - return new PlayerLeftNetworkEvent(uuid); - } - - @Override - public IPubSubMessageEvent createPubSubEvent(String channel, String message) { - return new PubSubMessageEvent(channel, message); - } - - @Override - public void onConfigLoad(RedisBungeeConfiguration configuration, Summoner summoner, RedisBungeeMode mode) { - this.configuration = configuration; - this.redisBungeeMode = mode; - this.summoner = summoner; - } - - @Override - public void onLangConfigLoad(LangConfiguration langConfiguration) { - this.langConfiguration = langConfiguration; - } - - @Override - public String platformId() { - return "bungeecord"; - } - - @Override - public void kickPlayer(UUID player, Component message) { - this.playerDataManager.kickPlayer(player, message); - } - - /** - * This returns an instance of {@link RedisBungeeAPI} - * - * @return the {@link AbstractRedisBungeeAPI} object instance. - * @deprecated Please use {@link RedisBungeeAPI#getRedisBungeeApi()} this class intended to for old plugins that no longer updated. - */ - @Deprecated - public static RedisBungeeAPI getApi() { - return apiStatic; - } - - @Deprecated - public JedisPool getPool() { - if (api.getMode() == RedisBungeeMode.SINGLE) { - JedisPool jedisPool = ((JedisPooledSummoner) getSummoner()).getCompatibilityJedisPool(); - if (jedisPool == null) { - throw new IllegalStateException("JedisPool compatibility mode is disabled, Please enable it in the RedisBungee config.yml"); - } - return jedisPool; - } else { - throw new IllegalStateException("Mode is not " + RedisBungeeMode.SINGLE); - } - } - + } } diff --git a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSender.java b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSender.java index b8a3949..f367234 100644 --- a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSender.java +++ b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSender.java @@ -1,84 +1,68 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; -import net.md_5.bungee.api.CommandSender; -import net.md_5.bungee.api.chat.BaseComponent; - import java.util.Collection; import java.util.Collections; +import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.chat.BaseComponent; public class RedisBungeeCommandSender implements CommandSender { - private static final RedisBungeeCommandSender singleton; + private static final RedisBungeeCommandSender singleton; - static { - singleton = new RedisBungeeCommandSender(); - } + static { + singleton = new RedisBungeeCommandSender(); + } - public static RedisBungeeCommandSender getSingleton() { - return singleton; - } + public static RedisBungeeCommandSender getSingleton() { + return singleton; + } - @Override - public String getName() { - return "RedisBungee"; - } + @Override + public String getName() { + return "RedisBungee"; + } - @Override - public void sendMessage(String s) { + @Override + public void sendMessage(String s) {} - } + @Override + public void sendMessages(String... strings) {} - @Override - public void sendMessages(String... strings) { + @Override + public void sendMessage(BaseComponent... baseComponents) {} - } + @Override + public void sendMessage(BaseComponent baseComponent) {} - @Override - public void sendMessage(BaseComponent... baseComponents) { + @Override + public Collection getGroups() { + return null; + } - } + @Override + public void addGroups(String... strings) {} - @Override - public void sendMessage(BaseComponent baseComponent) { + @Override + public void removeGroups(String... strings) {} - } + @Override + public boolean hasPermission(String s) { + return true; + } - @Override - public Collection getGroups() { - return null; - } + @Override + public void setPermission(String s, boolean b) {} - @Override - public void addGroups(String... strings) { - - } - - @Override - public void removeGroups(String... strings) { - - } - - @Override - public boolean hasPermission(String s) { - return true; - } - - @Override - public void setPermission(String s, boolean b) { - - } - - @Override - public Collection getPermissions() { - return Collections.emptySet(); - } + @Override + public Collection getPermissions() { + return Collections.emptySet(); + } } diff --git a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java index 661dd73..19cb6f6 100644 --- a/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java +++ b/redisbungee/proxies/bungeecord/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java @@ -1,23 +1,24 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; +import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.MultiMapSerialization.*; + import com.google.common.base.Joiner; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; -import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.api.config.HandleMotdOrder; +import java.util.*; import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer; import net.md_5.bungee.api.AbstractReconnectHandler; import net.md_5.bungee.api.ProxyServer; @@ -31,162 +32,191 @@ import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.event.EventHandler; import net.md_5.bungee.event.EventPriority; -import java.util.*; - -import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.MultiMapSerialization.*; - public class RedisBungeeListener implements Listener { - private final RedisBungee plugin; + private final RedisBungee plugin; - public RedisBungeeListener(RedisBungee plugin) { - this.plugin = plugin; + public RedisBungeeListener(RedisBungee plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPingFirst(ProxyPingEvent event) { + if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.FIRST) { + return; } + onPing0(event); + } - @EventHandler(priority = EventPriority.LOWEST) - public void onPingFirst(ProxyPingEvent event) { - if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.FIRST) { - return; - } - onPing0(event); + @EventHandler(priority = EventPriority.NORMAL) + public void onPingNormal(ProxyPingEvent event) { + if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.NORMAL) { + return; } + onPing0(event); + } - @EventHandler(priority = EventPriority.NORMAL) - public void onPingNormal(ProxyPingEvent event) { - if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.NORMAL) { - return; - } - onPing0(event); + @EventHandler(priority = EventPriority.HIGHEST) + public void onPingLast(ProxyPingEvent event) { + if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.LAST) { + return; } + onPing0(event); + } - @EventHandler(priority = EventPriority.HIGHEST) - public void onPingLast(ProxyPingEvent event) { - if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.LAST) { - return; - } - onPing0(event); - } + private void onPing0(ProxyPingEvent event) { + if (!plugin.configuration().handleMotd()) return; + if (plugin + .configuration() + .getExemptAddresses() + .contains(event.getConnection().getAddress().getAddress())) return; + ServerInfo forced = AbstractReconnectHandler.getForcedHost(event.getConnection()); - private void onPing0(ProxyPingEvent event) { - if (!plugin.configuration().handleMotd()) return; - if (plugin.configuration().getExemptAddresses().contains(event.getConnection().getAddress().getAddress())) return; - ServerInfo forced = AbstractReconnectHandler.getForcedHost(event.getConnection()); + if (forced != null && event.getConnection().getListener().isPingPassthrough()) return; + event.getResponse().getPlayers().setOnline(plugin.proxyDataManager().totalNetworkPlayers()); + } - if (forced != null && event.getConnection().getListener().isPingPassthrough()) return; - event.getResponse().getPlayers().setOnline(plugin.proxyDataManager().totalNetworkPlayers()); - } + @SuppressWarnings("UnstableApiUsage") + @EventHandler + public void onPluginMessage(PluginMessageEvent event) { + if ((event.getTag().equals("legacy:redisbungee") || event.getTag().equals("RedisBungee")) + && event.getSender() instanceof Server) { + final String currentChannel = event.getTag(); + final byte[] data = Arrays.copyOf(event.getData(), event.getData().length); + plugin.executeAsync( + () -> { + ByteArrayDataInput in = ByteStreams.newDataInput(data); - @SuppressWarnings("UnstableApiUsage") - @EventHandler - public void onPluginMessage(PluginMessageEvent event) { - if ((event.getTag().equals("legacy:redisbungee") || event.getTag().equals("RedisBungee")) && event.getSender() instanceof Server) { - final String currentChannel = event.getTag(); - final byte[] data = Arrays.copyOf(event.getData(), event.getData().length); - plugin.executeAsync(() -> { - ByteArrayDataInput in = ByteStreams.newDataInput(data); + String subchannel = in.readUTF(); + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + String type; - String subchannel = in.readUTF(); - ByteArrayDataOutput out = ByteStreams.newDataOutput(); - String type; - - switch (subchannel) { - case "PlayerList" -> { - out.writeUTF("PlayerList"); - Set original = Collections.emptySet(); - type = in.readUTF(); - if (type.equals("ALL")) { - out.writeUTF("ALL"); - original = plugin.proxyDataManager().networkPlayers(); - } else { - out.writeUTF(type); - try { - original = plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type); - } catch (IllegalArgumentException ignored) { - } - } - Set players = new HashSet<>(); - for (UUID uuid : original) - players.add(plugin.getUuidTranslator().getNameFromUuid(uuid, false)); - out.writeUTF(Joiner.on(',').join(players)); - } - case "PlayerCount" -> { - out.writeUTF("PlayerCount"); - type = in.readUTF(); - if (type.equals("ALL")) { - out.writeUTF("ALL"); - out.writeInt(plugin.proxyDataManager().totalNetworkPlayers()); - } else { - out.writeUTF(type); - try { - out.writeInt(plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type).size()); - } catch (IllegalArgumentException e) { - out.writeInt(0); - } - } - } - case "LastOnline" -> { - String user = in.readUTF(); - out.writeUTF("LastOnline"); - out.writeUTF(user); - out.writeLong(plugin.getAbstractRedisBungeeApi().getLastOnline(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(user, true)))); - } - case "ServerPlayers" -> { - String type1 = in.readUTF(); - out.writeUTF("ServerPlayers"); - Multimap multimap = plugin.getAbstractRedisBungeeApi().getServerToPlayers(); - boolean includesUsers; - switch (type1) { - case "COUNT" -> includesUsers = false; - case "PLAYERS" -> includesUsers = true; - default -> { - // TODO: Should I raise an error? - return; - } - } - out.writeUTF(type1); - if (includesUsers) { - Multimap human = HashMultimap.create(); - for (Map.Entry entry : multimap.entries()) { - human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false)); - } - serializeMultimap(human, true, out); - } else { - serializeMultiset(multimap.keys(), out); - } - } - case "Proxy" -> { - out.writeUTF("Proxy"); - out.writeUTF(plugin.configuration().getProxyId()); - } - case "PlayerProxy" -> { - String username = in.readUTF(); - out.writeUTF("PlayerProxy"); - out.writeUTF(username); - out.writeUTF(plugin.getAbstractRedisBungeeApi().getProxy(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(username, true)))); - } - default -> { - return; - } + switch (subchannel) { + case "PlayerList" -> { + out.writeUTF("PlayerList"); + Set original = Collections.emptySet(); + type = in.readUTF(); + if (type.equals("ALL")) { + out.writeUTF("ALL"); + original = plugin.proxyDataManager().networkPlayers(); + } else { + out.writeUTF(type); + try { + original = plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type); + } catch (IllegalArgumentException ignored) { + } } - - ((Server) event.getSender()).sendData(currentChannel, out.toByteArray()); - }); - } - } - - @EventHandler - public void onServerConnectEvent(ServerConnectEvent event) { - if (event.getReason() == ServerConnectEvent.Reason.JOIN_PROXY && plugin.configuration().handleReconnectToLastServer()) { - ProxiedPlayer player = event.getPlayer(); - String lastServer = plugin.playerDataManager().getLastServerFor(event.getPlayer().getUniqueId()); - if (lastServer == null) return; - player.sendMessage(BungeeComponentSerializer.get().serialize(plugin.langConfiguration().messages().serverConnecting(player.getLocale(), lastServer))); - ServerInfo serverInfo = ProxyServer.getInstance().getServerInfo(lastServer); - if (serverInfo == null) { - player.sendMessage(BungeeComponentSerializer.get().serialize(plugin.langConfiguration().messages().serverNotFound(player.getLocale(), lastServer))); + Set players = new HashSet<>(); + for (UUID uuid : original) + players.add(plugin.getUuidTranslator().getNameFromUuid(uuid, false)); + out.writeUTF(Joiner.on(',').join(players)); + } + case "PlayerCount" -> { + out.writeUTF("PlayerCount"); + type = in.readUTF(); + if (type.equals("ALL")) { + out.writeUTF("ALL"); + out.writeInt(plugin.proxyDataManager().totalNetworkPlayers()); + } else { + out.writeUTF(type); + try { + out.writeInt( + plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type).size()); + } catch (IllegalArgumentException e) { + out.writeInt(0); + } + } + } + case "LastOnline" -> { + String user = in.readUTF(); + out.writeUTF("LastOnline"); + out.writeUTF(user); + out.writeLong( + plugin + .getAbstractRedisBungeeApi() + .getLastOnline( + Objects.requireNonNull( + plugin.getUuidTranslator().getTranslatedUuid(user, true)))); + } + case "ServerPlayers" -> { + String type1 = in.readUTF(); + out.writeUTF("ServerPlayers"); + Multimap multimap = + plugin.getAbstractRedisBungeeApi().getServerToPlayers(); + boolean includesUsers; + switch (type1) { + case "COUNT" -> includesUsers = false; + case "PLAYERS" -> includesUsers = true; + default -> { + // TODO: Should I raise an error? + return; + } + } + out.writeUTF(type1); + if (includesUsers) { + Multimap human = HashMultimap.create(); + for (Map.Entry entry : multimap.entries()) { + human.put( + entry.getKey(), + plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false)); + } + serializeMultimap(human, true, out); + } else { + serializeMultiset(multimap.keys(), out); + } + } + case "Proxy" -> { + out.writeUTF("Proxy"); + out.writeUTF(plugin.configuration().getProxyId()); + } + case "PlayerProxy" -> { + String username = in.readUTF(); + out.writeUTF("PlayerProxy"); + out.writeUTF(username); + out.writeUTF( + plugin + .getAbstractRedisBungeeApi() + .getProxy( + Objects.requireNonNull( + plugin.getUuidTranslator().getTranslatedUuid(username, true)))); + } + default -> { return; + } } - event.setTarget(serverInfo); - } + + ((Server) event.getSender()).sendData(currentChannel, out.toByteArray()); + }); } + } + + @EventHandler + public void onServerConnectEvent(ServerConnectEvent event) { + if (event.getReason() == ServerConnectEvent.Reason.JOIN_PROXY + && plugin.configuration().handleReconnectToLastServer()) { + ProxiedPlayer player = event.getPlayer(); + String lastServer = + plugin.playerDataManager().getLastServerFor(event.getPlayer().getUniqueId()); + if (lastServer == null) return; + player.sendMessage( + BungeeComponentSerializer.get() + .serialize( + plugin + .langConfiguration() + .messages() + .serverConnecting(player.getLocale(), lastServer))); + ServerInfo serverInfo = ProxyServer.getInstance().getServerInfo(lastServer); + if (serverInfo == null) { + player.sendMessage( + BungeeComponentSerializer.get() + .serialize( + plugin + .langConfiguration() + .messages() + .serverNotFound(player.getLocale(), lastServer))); + return; + } + event.setTarget(serverInfo); + } + } } diff --git a/redisbungee/proxies/velocity/build.gradle.kts b/redisbungee/proxies/velocity/build.gradle.kts index b422ab9..91cdd4f 100644 --- a/redisbungee/proxies/velocity/build.gradle.kts +++ b/redisbungee/proxies/velocity/build.gradle.kts @@ -4,6 +4,9 @@ plugins { alias(libs.plugins.run.velocity) } +version = property("redisbungee-version").toString() +group = property("redisbungee-group").toString() + dependencies { implementation(project(":RedisBungee-Velocity")) compileOnly(libs.platform.velocity) diff --git a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSource.java b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSource.java index 9f04ac1..59cbfc1 100644 --- a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSource.java +++ b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeCommandSource.java @@ -1,45 +1,43 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; - import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.permission.Tristate; import net.kyori.adventure.permission.PermissionChecker; public class RedisBungeeCommandSource implements CommandSource { - private static final RedisBungeeCommandSource singleton; - private final PermissionChecker permissionChecker = PermissionChecker.always(net.kyori.adventure.util.TriState.TRUE); + private static final RedisBungeeCommandSource singleton; + private final PermissionChecker permissionChecker = + PermissionChecker.always(net.kyori.adventure.util.TriState.TRUE); - static { - singleton = new RedisBungeeCommandSource(); - } + static { + singleton = new RedisBungeeCommandSource(); + } - public static RedisBungeeCommandSource getSingleton() { - return singleton; - } + public static RedisBungeeCommandSource getSingleton() { + return singleton; + } + @Override + public boolean hasPermission(String permission) { + return this.permissionChecker.test(permission); + } - @Override - public boolean hasPermission(String permission) { - return this.permissionChecker.test(permission); - } + @Override + public Tristate getPermissionValue(String s) { + return Tristate.TRUE; + } - @Override - public Tristate getPermissionValue(String s) { - return Tristate.TRUE; - } - - @Override - public PermissionChecker getPermissionChecker() { - return this.permissionChecker; - } + @Override + public PermissionChecker getPermissionChecker() { + return this.permissionChecker; + } } diff --git a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java index 8d6afcf..8d57776 100644 --- a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java +++ b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeListener.java @@ -1,22 +1,23 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; +import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.MultiMapSerialization.serializeMultimap; +import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.MultiMapSerialization.serializeMultiset; + import com.google.common.base.Joiner; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.io.ByteArrayDataInput; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; -import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.imaginarycode.minecraft.redisbungee.api.config.HandleMotdOrder; import com.velocitypowered.api.event.PostOrder; import com.velocitypowered.api.event.Subscribe; @@ -27,173 +28,196 @@ import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerPing; - import java.util.*; import java.util.stream.Collectors; -import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.MultiMapSerialization.serializeMultimap; -import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.MultiMapSerialization.serializeMultiset; - public class RedisBungeeListener { - private final RedisBungeeVelocityPlugin plugin; + private final RedisBungeeVelocityPlugin plugin; - public RedisBungeeListener(RedisBungeeVelocityPlugin plugin) { - this.plugin = plugin; + public RedisBungeeListener(RedisBungeeVelocityPlugin plugin) { + this.plugin = plugin; + } + + @Subscribe(order = PostOrder.FIRST) + public void onPingFirst(ProxyPingEvent event) { + if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.FIRST) { + return; + } + onPing0(event); + } + + @Subscribe(order = PostOrder.NORMAL) + public void onPingNormal(ProxyPingEvent event) { + if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.NORMAL) { + return; + } + onPing0(event); + } + + @Subscribe(order = PostOrder.LAST) + public void onPingLast(ProxyPingEvent event) { + if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.LAST) { + return; + } + onPing0(event); + } + + private void onPing0(ProxyPingEvent event) { + if (!plugin.configuration().handleMotd()) return; + if (plugin + .configuration() + .getExemptAddresses() + .contains(event.getConnection().getRemoteAddress().getAddress())) return; + + ServerPing.Builder ping = event.getPing().asBuilder(); + ping.onlinePlayers(plugin.proxyDataManager().totalNetworkPlayers()); + event.setPing(ping.build()); + } + + @Subscribe + public void onPluginMessage(PluginMessageEvent event) { + if (!(event.getSource() instanceof ServerConnection) + || !RedisBungeeVelocityPlugin.IDENTIFIERS.contains(event.getIdentifier())) { + return; } - @Subscribe(order = PostOrder.FIRST) - public void onPingFirst(ProxyPingEvent event) { - if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.FIRST) { - return; - } - onPing0(event); - } + event.setResult(PluginMessageEvent.ForwardResult.handled()); - @Subscribe(order = PostOrder.NORMAL) - public void onPingNormal(ProxyPingEvent event) { - if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.NORMAL) { - return; - } - onPing0(event); - } + plugin.executeAsync( + () -> { + ByteArrayDataInput in = event.dataAsDataStream(); - @Subscribe(order = PostOrder.LAST) - public void onPingLast(ProxyPingEvent event) { - if (plugin.configuration().handleMotdOrder() != HandleMotdOrder.LAST) { - return; - } - onPing0(event); - } + String subchannel = in.readUTF(); + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + String type; - private void onPing0(ProxyPingEvent event) { - if (!plugin.configuration().handleMotd()) return; - if (plugin.configuration().getExemptAddresses().contains(event.getConnection().getRemoteAddress().getAddress())) return; - - ServerPing.Builder ping = event.getPing().asBuilder(); - ping.onlinePlayers(plugin.proxyDataManager().totalNetworkPlayers()); - event.setPing(ping.build()); - } - - @Subscribe - public void onPluginMessage(PluginMessageEvent event) { - if (!(event.getSource() instanceof ServerConnection) || !RedisBungeeVelocityPlugin.IDENTIFIERS.contains(event.getIdentifier())) { - return; - } - - event.setResult(PluginMessageEvent.ForwardResult.handled()); - - plugin.executeAsync(() -> { - ByteArrayDataInput in = event.dataAsDataStream(); - - String subchannel = in.readUTF(); - ByteArrayDataOutput out = ByteStreams.newDataOutput(); - String type; - - switch (subchannel) { - case "PlayerList" -> { - out.writeUTF("PlayerList"); - Set original = Collections.emptySet(); - type = in.readUTF(); - if (type.equals("ALL")) { - out.writeUTF("ALL"); - original = plugin.proxyDataManager().networkPlayers(); - } else { - out.writeUTF(type); - try { - original = plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type); - } catch (IllegalArgumentException ignored) { - } - } - Set players = original.stream() - .map(uuid -> plugin.getUuidTranslator().getNameFromUuid(uuid, false)) - .collect(Collectors.toSet()); - out.writeUTF(Joiner.on(',').join(players)); + switch (subchannel) { + case "PlayerList" -> { + out.writeUTF("PlayerList"); + Set original = Collections.emptySet(); + type = in.readUTF(); + if (type.equals("ALL")) { + out.writeUTF("ALL"); + original = plugin.proxyDataManager().networkPlayers(); + } else { + out.writeUTF(type); + try { + original = plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type); + } catch (IllegalArgumentException ignored) { } - case "PlayerCount" -> { - out.writeUTF("PlayerCount"); - type = in.readUTF(); - if (type.equals("ALL")) { - out.writeUTF("ALL"); - out.writeInt(plugin.proxyDataManager().totalNetworkPlayers()); - } else { - out.writeUTF(type); - try { - out.writeInt(plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type).size()); - } catch (IllegalArgumentException e) { - out.writeInt(0); - } - } - } - case "LastOnline" -> { - String user = in.readUTF(); - out.writeUTF("LastOnline"); - out.writeUTF(user); - out.writeLong(plugin.getAbstractRedisBungeeApi().getLastOnline(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(user, true)))); - } - case "ServerPlayers" -> { - String type1 = in.readUTF(); - out.writeUTF("ServerPlayers"); - Multimap multimap = plugin.getAbstractRedisBungeeApi().getServerToPlayers(); - boolean includesUsers; - switch (type1) { - case "COUNT" -> includesUsers = false; - case "PLAYERS" -> includesUsers = true; - default -> { - // TODO: Should I raise an error? - return; - } - } - out.writeUTF(type1); - if (includesUsers) { - Multimap human = HashMultimap.create(); - for (Map.Entry entry : multimap.entries()) { - human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false)); - } - serializeMultimap(human, true, out); - } else { - serializeMultiset(multimap.keys(), out); - } - } - case "Proxy" -> { - out.writeUTF("Proxy"); - out.writeUTF(plugin.configuration().getProxyId()); - } - case "PlayerProxy" -> { - String username = in.readUTF(); - out.writeUTF("PlayerProxy"); - out.writeUTF(username); - out.writeUTF(plugin.getAbstractRedisBungeeApi().getProxy(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(username, true)))); + } + Set players = + original.stream() + .map(uuid -> plugin.getUuidTranslator().getNameFromUuid(uuid, false)) + .collect(Collectors.toSet()); + out.writeUTF(Joiner.on(',').join(players)); + } + case "PlayerCount" -> { + out.writeUTF("PlayerCount"); + type = in.readUTF(); + if (type.equals("ALL")) { + out.writeUTF("ALL"); + out.writeInt(plugin.proxyDataManager().totalNetworkPlayers()); + } else { + out.writeUTF(type); + try { + out.writeInt(plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type).size()); + } catch (IllegalArgumentException e) { + out.writeInt(0); } + } + } + case "LastOnline" -> { + String user = in.readUTF(); + out.writeUTF("LastOnline"); + out.writeUTF(user); + out.writeLong( + plugin + .getAbstractRedisBungeeApi() + .getLastOnline( + Objects.requireNonNull( + plugin.getUuidTranslator().getTranslatedUuid(user, true)))); + } + case "ServerPlayers" -> { + String type1 = in.readUTF(); + out.writeUTF("ServerPlayers"); + Multimap multimap = + plugin.getAbstractRedisBungeeApi().getServerToPlayers(); + boolean includesUsers; + switch (type1) { + case "COUNT" -> includesUsers = false; + case "PLAYERS" -> includesUsers = true; default -> { - return; + // TODO: Should I raise an error? + return; } + } + out.writeUTF(type1); + if (includesUsers) { + Multimap human = HashMultimap.create(); + for (Map.Entry entry : multimap.entries()) { + human.put( + entry.getKey(), + plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false)); + } + serializeMultimap(human, true, out); + } else { + serializeMultiset(multimap.keys(), out); + } } - try { - // ServerConnection throws IllegalStateException when connection dies somehow so just ignore :/ - ((ServerConnection) event.getSource()).sendPluginMessage(event.getIdentifier(), out.toByteArray()); - } catch (IllegalStateException ignored) { + case "Proxy" -> { + out.writeUTF("Proxy"); + out.writeUTF(plugin.configuration().getProxyId()); } + case "PlayerProxy" -> { + String username = in.readUTF(); + out.writeUTF("PlayerProxy"); + out.writeUTF(username); + out.writeUTF( + plugin + .getAbstractRedisBungeeApi() + .getProxy( + Objects.requireNonNull( + plugin.getUuidTranslator().getTranslatedUuid(username, true)))); + } + default -> { + return; + } + } + try { + // ServerConnection throws IllegalStateException when connection dies somehow so just + // ignore :/ + ((ServerConnection) event.getSource()) + .sendPluginMessage(event.getIdentifier(), out.toByteArray()); + } catch (IllegalStateException ignored) { + } }); + } + @Subscribe + public void onPlayerChooseInitialServerEvent(PlayerChooseInitialServerEvent event) { + if (plugin.configuration().handleReconnectToLastServer()) { + Player player = event.getPlayer(); + String lastServer = plugin.playerDataManager().getLastServerFor(player.getUniqueId()); + if (lastServer == null) return; + player.sendMessage( + plugin + .langConfiguration() + .messages() + .serverConnecting(player.getPlayerSettings().getLocale(), lastServer)); + Optional optionalRegisteredServer = + ((RedisBungeeVelocityPlugin) plugin).getProxy().getServer(lastServer); + if (optionalRegisteredServer.isEmpty()) { + player.sendMessage( + plugin + .langConfiguration() + .messages() + .serverNotFound(player.getPlayerSettings().getLocale(), lastServer)); + return; + } + RegisteredServer server = optionalRegisteredServer.get(); + event.setInitialServer(server); } - - @Subscribe - public void onPlayerChooseInitialServerEvent(PlayerChooseInitialServerEvent event) { - if (plugin.configuration().handleReconnectToLastServer()) { - Player player = event.getPlayer(); - String lastServer = plugin.playerDataManager().getLastServerFor(player.getUniqueId()); - if (lastServer == null) return; - player.sendMessage(plugin.langConfiguration().messages().serverConnecting(player.getPlayerSettings().getLocale(), lastServer)); - Optional optionalRegisteredServer = ((RedisBungeeVelocityPlugin) plugin).getProxy().getServer(lastServer); - if (optionalRegisteredServer.isEmpty()) { - player.sendMessage(plugin.langConfiguration().messages().serverNotFound(player.getPlayerSettings().getLocale(), lastServer)); - return; - } - RegisteredServer server = optionalRegisteredServer.get(); - event.setInitialServer(server); - } - } - - + } } diff --git a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeVelocityPlugin.java b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeVelocityPlugin.java index 3d92d81..79b0a34 100644 --- a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeVelocityPlugin.java +++ b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeVelocityPlugin.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import co.aikar.commands.VelocityCommandManager; @@ -16,10 +15,8 @@ import com.imaginarycode.minecraft.redisbungee.api.PlayerDataManager; import com.imaginarycode.minecraft.redisbungee.api.ProxyDataManager; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeeMode; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; -import com.imaginarycode.minecraft.redisbungee.commands.CommandLoader; -import com.imaginarycode.minecraft.redisbungee.commands.utils.CommandPlatformHelper; -import com.imaginarycode.minecraft.redisbungee.api.config.loaders.ConfigLoader; import com.imaginarycode.minecraft.redisbungee.api.config.RedisBungeeConfiguration; +import com.imaginarycode.minecraft.redisbungee.api.config.loaders.ConfigLoader; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerChangedServerNetworkEvent; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEvent; import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent; @@ -27,6 +24,8 @@ import com.imaginarycode.minecraft.redisbungee.api.events.IPubSubMessageEvent; import com.imaginarycode.minecraft.redisbungee.api.summoners.Summoner; import com.imaginarycode.minecraft.redisbungee.api.util.InitialUtils; import com.imaginarycode.minecraft.redisbungee.api.util.uuid.UUIDTranslator; +import com.imaginarycode.minecraft.redisbungee.commands.CommandLoader; +import com.imaginarycode.minecraft.redisbungee.commands.utils.CommandPlatformHelper; import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PlayerLeftNetworkEvent; @@ -43,12 +42,6 @@ import com.velocitypowered.api.proxy.messages.ChannelIdentifier; import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import com.velocitypowered.api.scheduler.ScheduledTask; -import net.kyori.adventure.text.Component; -import net.limework.valiobungee.config.lang.LangConfiguration; -import net.limework.valiobungee.config.lang.LangConfigLoader; -import org.slf4j.Logger; -import redis.clients.jedis.exceptions.JedisConnectionException; - import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; @@ -59,307 +52,333 @@ import java.util.List; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; +import net.kyori.adventure.text.Component; +import net.limework.valiobungee.config.lang.LangConfigLoader; +import net.limework.valiobungee.config.lang.LangConfiguration; +import org.slf4j.Logger; +import redis.clients.jedis.exceptions.JedisConnectionException; -@Plugin(id = "redisbungee", name = "RedisBungee", version = Constants.VERSION, url = "https://github.com/ProxioDev/RedisBungee", authors = {"astei", "ProxioDev"}) -public class RedisBungeeVelocityPlugin implements RedisBungeePlugin, ConfigLoader, LangConfigLoader, ApiPlatformSupport { - private final ProxyServer server; - private final Logger logger; - private final Path dataFolder; - private final AbstractRedisBungeeAPI api; - private Summoner jedisSummoner; - private RedisBungeeMode redisBungeeMode; - private final UUIDTranslator uuidTranslator; - private RedisBungeeConfiguration configuration; - private LangConfiguration langConfiguration; +@Plugin( + id = "redisbungee", + name = "RedisBungee", + version = Constants.VERSION, + url = "https://github.com/ProxioDev/RedisBungee", + authors = {"astei", "ProxioDev"}) +public class RedisBungeeVelocityPlugin + implements RedisBungeePlugin, ConfigLoader, LangConfigLoader, ApiPlatformSupport { + private final ProxyServer server; + private final Logger logger; + private final Path dataFolder; + private final AbstractRedisBungeeAPI api; + private Summoner jedisSummoner; + private RedisBungeeMode redisBungeeMode; + private final UUIDTranslator uuidTranslator; + private RedisBungeeConfiguration configuration; + private LangConfiguration langConfiguration; - private final ProxyDataManager proxyDataManager; + private final ProxyDataManager proxyDataManager; - private final VelocityPlayerDataManager playerDataManager; + private final VelocityPlayerDataManager playerDataManager; - private ScheduledTask cleanUpTask; - private ScheduledTask heartbeatTask; + private ScheduledTask cleanUpTask; + private ScheduledTask heartbeatTask; - public static final List IDENTIFIERS = List.of( - MinecraftChannelIdentifier.create("legacy", "redisbungee"), - new LegacyChannelIdentifier("RedisBungee"), - // This is needed for clients before 1.13 - new LegacyChannelIdentifier("legacy:redisbungee") - ); + public static final List IDENTIFIERS = + List.of( + MinecraftChannelIdentifier.create("legacy", "redisbungee"), + new LegacyChannelIdentifier("RedisBungee"), + // This is needed for clients before 1.13 + new LegacyChannelIdentifier("legacy:redisbungee")); - private VelocityCommandManager commandManager; + private VelocityCommandManager commandManager; - @Inject - public RedisBungeeVelocityPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { - this.server = server; - this.logger = logger; - this.dataFolder = dataDirectory; - logInfo("Version: {}", Constants.VERSION); - try { - loadConfig(this, dataDirectory); - loadLangConfig(this, dataDirectory); - } catch (IOException e) { - throw new RuntimeException("Unable to load/save config", e); - } catch (JedisConnectionException e) { - throw new RuntimeException("Unable to connect to your Redis server!", e); - } - this.api = new RedisBungeeAPI(this); - InitialUtils.checkRedisVersion(this); - this.proxyDataManager = new ProxyDataManager(this) { - @Override - public Set getLocalOnlineUUIDs() { - HashSet players = new HashSet<>(); - server.getAllPlayers().forEach(player -> players.add(player.getUniqueId())); - return players; - } + @Inject + public RedisBungeeVelocityPlugin( + ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { + this.server = server; + this.logger = logger; + this.dataFolder = dataDirectory; + logInfo("Version: {}", Constants.VERSION); + try { + loadConfig(this, dataDirectory); + loadLangConfig(this, dataDirectory); + } catch (IOException e) { + throw new RuntimeException("Unable to load/save config", e); + } catch (JedisConnectionException e) { + throw new RuntimeException("Unable to connect to your Redis server!", e); + } + this.api = new RedisBungeeAPI(this); + InitialUtils.checkRedisVersion(this); + this.proxyDataManager = + new ProxyDataManager(this) { + @Override + public Set getLocalOnlineUUIDs() { + HashSet players = new HashSet<>(); + server.getAllPlayers().forEach(player -> players.add(player.getUniqueId())); + return players; + } - @Override - protected void handlePlatformCommandExecution(String command) { - server.getCommandManager().executeAsync(RedisBungeeCommandSource.getSingleton(), command); - } + @Override + protected void handlePlatformCommandExecution(String command) { + server + .getCommandManager() + .executeAsync(RedisBungeeCommandSource.getSingleton(), command); + } }; - this.playerDataManager = new VelocityPlayerDataManager(this); - uuidTranslator = new UUIDTranslator(this); + this.playerDataManager = new VelocityPlayerDataManager(this); + uuidTranslator = new UUIDTranslator(this); + } + + @Override + public Summoner getSummoner() { + return this.jedisSummoner; + } + + @Override + public AbstractRedisBungeeAPI getAbstractRedisBungeeApi() { + return this.api; + } + + @Override + public ProxyDataManager proxyDataManager() { + return this.proxyDataManager; + } + + @Override + public PlayerDataManager playerDataManager() { + return this.playerDataManager; + } + + @Override + public UUIDTranslator getUuidTranslator() { + return this.uuidTranslator; + } + + @Override + public void executeAsync(Runnable runnable) { + this.getProxy().getScheduler().buildTask(this, runnable).schedule(); + } + + @Override + public void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time) { + this.getProxy().getScheduler().buildTask(this, runnable).delay(time, timeUnit).schedule(); + } + + @Override + public void fireEvent(Object event) { + this.getProxy().getEventManager().fireAndForget(event); + } + + @Override + public boolean isOnlineMode() { + return this.getProxy().getConfiguration().isOnlineMode(); + } + + @Override + public void logInfo(String msg) { + this.getLogger().info(msg); + } + + @Override + public void logInfo(String format, Object... object) { + logger.info(format, object); + } + + @Override + public void logWarn(String msg) { + this.getLogger().warn(msg); + } + + @Override + public void logWarn(String format, Object... object) { + logger.warn(format, object); + } + + @Override + public void logFatal(String msg) { + this.getLogger().error(msg); + } + + @Override + public void logFatal(String format, Throwable throwable) { + logger.error(format, throwable); + } + + @Override + public RedisBungeeConfiguration configuration() { + return this.configuration; + } + + public LangConfiguration langConfiguration() { + return this.langConfiguration; + } + + @Override + public Player getPlayer(UUID uuid) { + return this.getProxy().getPlayer(uuid).orElse(null); + } + + @Override + public Player getPlayer(String name) { + return this.getProxy().getPlayer(name).orElse(null); + } + + @Override + public UUID getPlayerUUID(String player) { + return this.getProxy().getPlayer(player).map(Player::getUniqueId).orElse(null); + } + + @Override + public String getPlayerName(UUID player) { + return this.getProxy().getPlayer(player).map(Player::getUsername).orElse(null); + } + + @Override + public String getPlayerServerName(Player player) { + return player + .getCurrentServer() + .map(serverConnection -> serverConnection.getServerInfo().getName()) + .orElse(null); + } + + @Override + public boolean isPlayerOnAServer(Player player) { + return player.getCurrentServer().isPresent(); + } + + @Override + public InetAddress getPlayerIp(Player player) { + return player.getRemoteAddress().getAddress(); + } + + @Override + public void initialize() { + logInfo("Initializing RedisBungee....."); + // start heartbeat task + // heartbeat and clean up + this.heartbeatTask = + server + .getScheduler() + .buildTask(this, this.proxyDataManager::publishHeartbeat) + .repeat(Duration.ofSeconds(1)) + .schedule(); + this.cleanUpTask = + server + .getScheduler() + .buildTask(this, this.proxyDataManager::correctionTask) + .repeat(Duration.ofSeconds(60)) + .schedule(); + + server.getEventManager().register(this, this.playerDataManager); + server.getEventManager().register(this, new RedisBungeeListener(this)); + + // subscribe + server.getScheduler().buildTask(this, this.proxyDataManager).schedule(); + + // register plugin messages + IDENTIFIERS.forEach(getProxy().getChannelRegistrar()::register); + + // load commands + CommandPlatformHelper.init(new VelocityCommandPlatformHelper()); + this.commandManager = new VelocityCommandManager(this.getProxy(), this); + CommandLoader.initCommands(this.commandManager, this); + + logInfo("RedisBungee initialized successfully "); + } + + @Override + public void stop() { + logInfo("Turning off redis connections....."); + // Poison the PubSub listener + if (cleanUpTask != null) { + cleanUpTask.cancel(); + } + if (heartbeatTask != null) { + heartbeatTask.cancel(); + } + try { + this.proxyDataManager.close(); + this.jedisSummoner.close(); + } catch (Exception e) { + throw new RuntimeException(e); } + if (commandManager != null) commandManager.unregisterCommands(); + logInfo("RedisBungee shutdown complete"); + } - @Override - public Summoner getSummoner() { - return this.jedisSummoner; - } + @Override + public void onConfigLoad( + RedisBungeeConfiguration configuration, Summoner summoner, RedisBungeeMode mode) { + this.jedisSummoner = summoner; + this.configuration = configuration; + this.redisBungeeMode = mode; + } - @Override - public AbstractRedisBungeeAPI getAbstractRedisBungeeApi() { - return this.api; - } + @Override + public void onLangConfigLoad(LangConfiguration langConfiguration) { + this.langConfiguration = langConfiguration; + } - @Override - public ProxyDataManager proxyDataManager() { - return this.proxyDataManager; - } + @Override + public RedisBungeeMode getRedisBungeeMode() { + return this.redisBungeeMode; + } - @Override - public PlayerDataManager playerDataManager() { - return this.playerDataManager; - } + @Subscribe(order = PostOrder.FIRST) + public void onProxyInitializeEvent(ProxyInitializeEvent event) { + initialize(); + } - @Override - public UUIDTranslator getUuidTranslator() { - return this.uuidTranslator; - } + @Subscribe(order = PostOrder.LAST) + public void onProxyShutdownEvent(ProxyShutdownEvent event) { + stop(); + } + @Override + public IPlayerChangedServerNetworkEvent createPlayerChangedServerNetworkEvent( + UUID uuid, String previousServer, String server) { + return new PlayerChangedServerNetworkEvent(uuid, previousServer, server); + } - @Override - public void executeAsync(Runnable runnable) { - this.getProxy().getScheduler().buildTask(this, runnable).schedule(); - } + @Override + public IPlayerJoinedNetworkEvent createPlayerJoinedNetworkEvent(UUID uuid) { + return new PlayerJoinedNetworkEvent(uuid); + } - @Override - public void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time) { - this.getProxy().getScheduler().buildTask(this, runnable).delay(time, timeUnit).schedule(); - } + @Override + public IPlayerLeftNetworkEvent createPlayerLeftNetworkEvent(UUID uuid) { + return new PlayerLeftNetworkEvent(uuid); + } - @Override - public void fireEvent(Object event) { - this.getProxy().getEventManager().fireAndForget(event); - } + @Override + public IPubSubMessageEvent createPubSubEvent(String channel, String message) { + return new PubSubMessageEvent(channel, message); + } - @Override - public boolean isOnlineMode() { - return this.getProxy().getConfiguration().isOnlineMode(); - } + public ProxyServer getProxy() { + return server; + } - @Override - public void logInfo(String msg) { - this.getLogger().info(msg); - } + @Override + public void kickPlayer(UUID player, Component message) { + this.playerDataManager.kickPlayer(player, message); + } - @Override - public void logInfo(String format, Object... object) { - logger.info(format, object); - } + public Logger getLogger() { + return logger; + } - @Override - public void logWarn(String msg) { - this.getLogger().warn(msg); - } + public Path getDataFolder() { + return this.dataFolder; + } - @Override - public void logWarn(String format, Object... object) { - logger.warn(format, object); - } + public InputStream getResourceAsStream(String name) { + return this.getClass().getClassLoader().getResourceAsStream(name); + } - @Override - public void logFatal(String msg) { - this.getLogger().error(msg); - } - - @Override - public void logFatal(String format, Throwable throwable) { - logger.error(format, throwable); - } - - @Override - public RedisBungeeConfiguration configuration() { - return this.configuration; - } - - public LangConfiguration langConfiguration() { - return this.langConfiguration; - } - - @Override - public Player getPlayer(UUID uuid) { - return this.getProxy().getPlayer(uuid).orElse(null); - } - - @Override - public Player getPlayer(String name) { - return this.getProxy().getPlayer(name).orElse(null); - } - - @Override - public UUID getPlayerUUID(String player) { - return this.getProxy().getPlayer(player).map(Player::getUniqueId).orElse(null); - } - - @Override - public String getPlayerName(UUID player) { - return this.getProxy().getPlayer(player).map(Player::getUsername).orElse(null); - } - - @Override - public String getPlayerServerName(Player player) { - return player.getCurrentServer().map(serverConnection -> serverConnection.getServerInfo().getName()).orElse(null); - } - - @Override - public boolean isPlayerOnAServer(Player player) { - return player.getCurrentServer().isPresent(); - } - - @Override - public InetAddress getPlayerIp(Player player) { - return player.getRemoteAddress().getAddress(); - } - - @Override - public void initialize() { - logInfo("Initializing RedisBungee....."); - // start heartbeat task - // heartbeat and clean up - this.heartbeatTask = server.getScheduler().buildTask(this, this.proxyDataManager::publishHeartbeat).repeat(Duration.ofSeconds(1)).schedule(); - this.cleanUpTask = server.getScheduler().buildTask(this, this.proxyDataManager::correctionTask).repeat(Duration.ofSeconds(60)).schedule(); - - server.getEventManager().register(this, this.playerDataManager); - server.getEventManager().register(this, new RedisBungeeListener(this)); - - // subscribe - server.getScheduler().buildTask(this, this.proxyDataManager).schedule(); - - // register plugin messages - IDENTIFIERS.forEach(getProxy().getChannelRegistrar()::register); - - // load commands - CommandPlatformHelper.init(new VelocityCommandPlatformHelper()); - this.commandManager = new VelocityCommandManager(this.getProxy(), this); - CommandLoader.initCommands(this.commandManager, this); - - logInfo("RedisBungee initialized successfully "); - } - - @Override - public void stop() { - logInfo("Turning off redis connections....."); - // Poison the PubSub listener - if (cleanUpTask != null) { - cleanUpTask.cancel(); - } - if (heartbeatTask != null) { - heartbeatTask.cancel(); - } - try { - this.proxyDataManager.close(); - this.jedisSummoner.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - - if (commandManager != null) commandManager.unregisterCommands(); - logInfo("RedisBungee shutdown complete"); - } - - @Override - public void onConfigLoad(RedisBungeeConfiguration configuration, Summoner summoner, RedisBungeeMode mode) { - this.jedisSummoner = summoner; - this.configuration = configuration; - this.redisBungeeMode = mode; - } - - @Override - public void onLangConfigLoad(LangConfiguration langConfiguration) { - this.langConfiguration = langConfiguration; - } - - @Override - public RedisBungeeMode getRedisBungeeMode() { - return this.redisBungeeMode; - } - - - @Subscribe(order = PostOrder.FIRST) - public void onProxyInitializeEvent(ProxyInitializeEvent event) { - initialize(); - } - - @Subscribe(order = PostOrder.LAST) - public void onProxyShutdownEvent(ProxyShutdownEvent event) { - stop(); - } - - - @Override - public IPlayerChangedServerNetworkEvent createPlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) { - return new PlayerChangedServerNetworkEvent(uuid, previousServer, server); - } - - @Override - public IPlayerJoinedNetworkEvent createPlayerJoinedNetworkEvent(UUID uuid) { - return new PlayerJoinedNetworkEvent(uuid); - } - - @Override - public IPlayerLeftNetworkEvent createPlayerLeftNetworkEvent(UUID uuid) { - return new PlayerLeftNetworkEvent(uuid); - } - - @Override - public IPubSubMessageEvent createPubSubEvent(String channel, String message) { - return new PubSubMessageEvent(channel, message); - } - - public ProxyServer getProxy() { - return server; - } - - @Override - public void kickPlayer(UUID player, Component message) { - this.playerDataManager.kickPlayer(player, message); - } - - public Logger getLogger() { - return logger; - } - - public Path getDataFolder() { - return this.dataFolder; - } - - public InputStream getResourceAsStream(String name) { - return this.getClass().getClassLoader().getResourceAsStream(name); - } - - @Override - public String platformId() { - return "velocity"; - } + @Override + public String platformId() { + return "velocity"; + } } diff --git a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/VelocityCommandPlatformHelper.java b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/VelocityCommandPlatformHelper.java index 07cd9de..b850776 100644 --- a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/VelocityCommandPlatformHelper.java +++ b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/VelocityCommandPlatformHelper.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import co.aikar.commands.CommandIssuer; @@ -17,10 +16,9 @@ import net.kyori.adventure.text.Component; public class VelocityCommandPlatformHelper extends CommandPlatformHelper { - @Override - public void sendMessage(CommandIssuer issuer, Component component) { - VelocityCommandIssuer vIssuer = (VelocityCommandIssuer) issuer; - vIssuer.getIssuer().sendMessage(component); - } - + @Override + public void sendMessage(CommandIssuer issuer, Component component) { + VelocityCommandIssuer vIssuer = (VelocityCommandIssuer) issuer; + vIssuer.getIssuer().sendMessage(component); + } } diff --git a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/VelocityPlayerDataManager.java b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/VelocityPlayerDataManager.java index 2efd115..0cc1e7c 100644 --- a/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/VelocityPlayerDataManager.java +++ b/redisbungee/proxies/velocity/src/main/java/com/imaginarycode/minecraft/redisbungee/VelocityPlayerDataManager.java @@ -1,13 +1,12 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import com.imaginarycode.minecraft.redisbungee.api.PlayerDataManager; @@ -23,108 +22,119 @@ import com.velocitypowered.api.event.connection.LoginEvent; import com.velocitypowered.api.event.connection.PostLoginEvent; import com.velocitypowered.api.event.player.ServerConnectedEvent; import com.velocitypowered.api.proxy.Player; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; - import java.util.UUID; import java.util.concurrent.TimeUnit; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; public class VelocityPlayerDataManager extends PlayerDataManager { - private final RedisBungeeVelocityPlugin vplugin; + private final RedisBungeeVelocityPlugin vplugin; - public VelocityPlayerDataManager(RedisBungeeVelocityPlugin plugin) { - super(plugin); - this.vplugin = plugin; + public VelocityPlayerDataManager(RedisBungeeVelocityPlugin plugin) { + super(plugin); + this.vplugin = plugin; + } + + @Subscribe + public void onPlayerChangedServerNetworkEvent(PlayerChangedServerNetworkEvent event) { + handleNetworkPlayerServerChange(event); + } + + @Subscribe + public void onNetworkPlayerQuit(PlayerLeftNetworkEvent event) { + handleNetworkPlayerQuit(event); + } + + @Subscribe + public void onNetworkPlayerJoin(PlayerJoinedNetworkEvent event) { + handleNetworkPlayerJoin(event); + } + + @Subscribe + public void onPubSubMessageEvent(PubSubMessageEvent event) { + handlePubSubMessageEvent(event); + } + + @Subscribe + public void onServerConnectedEvent(ServerConnectedEvent event) { + final String currentServer = event.getServer().getServerInfo().getName(); + final String oldServer; + if (event.getPreviousServer().isPresent()) { + oldServer = event.getPreviousServer().get().getServerInfo().getName(); + } else { + oldServer = null; } + super.playerChangedServer(event.getPlayer().getUniqueId(), oldServer, currentServer); + } - @Subscribe - public void onPlayerChangedServerNetworkEvent(PlayerChangedServerNetworkEvent event) { - handleNetworkPlayerServerChange(event); + private static final MiniMessage MINI_MESSAGE_SERIALIZER = MiniMessage.miniMessage(); + + @Override + public boolean handleSerializedKick(UUID uuid, String serializedMiniMessage) { + Player player = plugin.getPlayer(uuid); + if (player == null) return false; + // decode the adventure component + if (serializedMiniMessage == null) { + // kick the player too even if the message is invalid + player.disconnect(Component.empty()); + plugin.logWarn("unable to decode serialized adventure component because its empty or null"); + } else { + Component message = MINI_MESSAGE_SERIALIZER.deserialize(serializedMiniMessage); + player.disconnect(message); } + return true; + } - @Subscribe - public void onNetworkPlayerQuit(PlayerLeftNetworkEvent event) { - handleNetworkPlayerQuit(event); - } + public void kickPlayer(UUID player, Component message) { + serializedPlayerKick(player, MINI_MESSAGE_SERIALIZER.serialize(message)); + } - @Subscribe - public void onNetworkPlayerJoin(PlayerJoinedNetworkEvent event) { - handleNetworkPlayerJoin(event); - } - - @Subscribe - public void onPubSubMessageEvent(PubSubMessageEvent event) { - handlePubSubMessageEvent(event); - } - - @Subscribe - public void onServerConnectedEvent(ServerConnectedEvent event) { - final String currentServer = event.getServer().getServerInfo().getName(); - final String oldServer; - if (event.getPreviousServer().isPresent()) { - oldServer = event.getPreviousServer().get().getServerInfo().getName(); + @Subscribe + public void onLoginEvent(LoginEvent event, Continuation continuation) { + // check if online + if (getLastOnline(event.getPlayer().getUniqueId()) == 0) { + // because something can go wrong and proxy somehow does not update player data correctly on + // shutdown + // we have to check proxy if it has the player + String proxyId = getProxyFor(event.getPlayer().getUniqueId()); + if (proxyId == null + || !plugin + .proxyDataManager() + .isPlayerTrulyOnProxy(proxyId, event.getPlayer().getUniqueId())) { + continuation.resume(); + } else { + if (plugin.configuration().kickWhenOnline()) { + kickPlayer( + event.getPlayer().getUniqueId(), + vplugin.langConfiguration().messages().loggedInFromOtherLocation()); + // wait 3 seconds before releasing the event + plugin.executeAsyncAfter(continuation::resume, TimeUnit.SECONDS, 3); } else { - oldServer = null; + event.setResult( + ResultedEvent.ComponentResult.denied( + vplugin.langConfiguration().messages().alreadyLoggedIn())); + continuation.resume(); } - super.playerChangedServer(event.getPlayer().getUniqueId(), oldServer, currentServer); + } + } else { + continuation.resume(); } + } - private final static MiniMessage MINI_MESSAGE_SERIALIZER = MiniMessage.miniMessage(); - @Override - public boolean handleSerializedKick(UUID uuid, String serializedMiniMessage) { - Player player = plugin.getPlayer(uuid); - if (player == null) return false; - // decode the adventure component - if (serializedMiniMessage == null) { - // kick the player too even if the message is invalid - player.disconnect(Component.empty()); - plugin.logWarn("unable to decode serialized adventure component because its empty or null"); - } else { - Component message = MINI_MESSAGE_SERIALIZER.deserialize(serializedMiniMessage); - player.disconnect(message); - } - return true; - } + @Subscribe + public void onLoginEvent(PostLoginEvent event) { + addPlayer( + event.getPlayer().getUniqueId(), + event.getPlayer().getUsername(), + event.getPlayer().getRemoteAddress().getAddress()); + } - public void kickPlayer(UUID player, Component message) { - serializedPlayerKick(player, MINI_MESSAGE_SERIALIZER.serialize(message)); - } - - @Subscribe - public void onLoginEvent(LoginEvent event, Continuation continuation) { - // check if online - if (getLastOnline(event.getPlayer().getUniqueId()) == 0) { - // because something can go wrong and proxy somehow does not update player data correctly on shutdown - // we have to check proxy if it has the player - String proxyId = getProxyFor(event.getPlayer().getUniqueId()); - if (proxyId == null || !plugin.proxyDataManager().isPlayerTrulyOnProxy(proxyId, event.getPlayer().getUniqueId())) { - continuation.resume(); - } else { - if (plugin.configuration().kickWhenOnline()) { - kickPlayer(event.getPlayer().getUniqueId(), vplugin.langConfiguration().messages().loggedInFromOtherLocation()); - // wait 3 seconds before releasing the event - plugin.executeAsyncAfter(continuation::resume, TimeUnit.SECONDS, 3); - } else { - event.setResult(ResultedEvent.ComponentResult.denied(vplugin.langConfiguration().messages().alreadyLoggedIn())); - continuation.resume(); - } - } - } else { - continuation.resume(); - } - } - - @Subscribe - public void onLoginEvent(PostLoginEvent event) { - addPlayer(event.getPlayer().getUniqueId(), event.getPlayer().getUsername(), event.getPlayer().getRemoteAddress().getAddress()); - } - - @Subscribe - public void onDisconnectEvent(DisconnectEvent event) { - if (event.getLoginStatus() == DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN || event.getLoginStatus() == DisconnectEvent.LoginStatus.PRE_SERVER_JOIN) { - removePlayer(event.getPlayer().getUniqueId()); - } + @Subscribe + public void onDisconnectEvent(DisconnectEvent event) { + if (event.getLoginStatus() == DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN + || event.getLoginStatus() == DisconnectEvent.LoginStatus.PRE_SERVER_JOIN) { + removePlayer(event.getPlayer().getUniqueId()); } + } } diff --git a/redisbungee/proxies/velocity/velocity-api/build.gradle.kts b/redisbungee/proxies/velocity/velocity-api/build.gradle.kts index 46dd2fb..2cc4406 100644 --- a/redisbungee/proxies/velocity/velocity-api/build.gradle.kts +++ b/redisbungee/proxies/velocity/velocity-api/build.gradle.kts @@ -3,6 +3,9 @@ plugins { `maven-publish` } +version = property("redisbungee-version").toString() +group = property("redisbungee-group").toString() + dependencies { api(project(":RedisBungee-API")) { // Since velocity already includes guava / configurate / guava exlude them diff --git a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/ApiPlatformSupport.java b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/ApiPlatformSupport.java index 7edb1bf..668bddc 100644 --- a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/ApiPlatformSupport.java +++ b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/ApiPlatformSupport.java @@ -1,25 +1,22 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import com.velocitypowered.api.proxy.ProxyServer; -import net.kyori.adventure.text.Component; - import java.util.UUID; +import net.kyori.adventure.text.Component; // this class used to redirect calls to keep the implementation and api separate public interface ApiPlatformSupport { - ProxyServer getProxy(); - - void kickPlayer(UUID player, Component message); + ProxyServer getProxy(); + void kickPlayer(UUID player, Component message); } diff --git a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeAPI.java b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeAPI.java index 5368bc0..9311caf 100644 --- a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeAPI.java +++ b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/RedisBungeeAPI.java @@ -1,89 +1,89 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee; import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.proxy.server.ServerInfo; +import java.util.UUID; import net.kyori.adventure.text.Component; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.UUID; - /** - * This platform class exposes some internal RedisBungee functions. You obtain an instance of this object by invoking {@link RedisBungeeAPI#getRedisBungeeApi()} - * or somehow you got the Plugin instance by you can call the api using {@link RedisBungeePlugin#getAbstractRedisBungeeApi()}. + * This platform class exposes some internal RedisBungee functions. You obtain an instance of this + * object by invoking {@link RedisBungeeAPI#getRedisBungeeApi()} or somehow you got the Plugin + * instance by you can call the api using {@link RedisBungeePlugin#getAbstractRedisBungeeApi()}. * * @author tuxed * @since 0.2.3 */ public class RedisBungeeAPI extends AbstractRedisBungeeAPI { - private static RedisBungeeAPI redisBungeeApi; - - public RedisBungeeAPI(RedisBungeePlugin plugin) { - super(plugin); - if (redisBungeeApi == null) { - redisBungeeApi = this; - } + private static RedisBungeeAPI redisBungeeApi; + public RedisBungeeAPI(RedisBungeePlugin plugin) { + super(plugin); + if (redisBungeeApi == null) { + redisBungeeApi = this; } + } - /** - * Get the server where the specified player is playing. This function also deals with the case of local players - * as well, and will return local information on them. - * - * @param player a player uuid - * @return {@link ServerInfo} Can be null if proxy can't find it. - * @see #getServerNameFor(UUID) - */ - @Nullable - public final ServerInfo getServerFor(@NonNull UUID player) { - String serverName = this.getServerNameFor(player); - if (serverName == null) return null; - return ((ApiPlatformSupport) this.plugin).getProxy().getServer(serverName).map((RegisteredServer::getServerInfo)).orElse(null); - } + /** + * Get the server where the specified player is playing. This function also deals with the case of + * local players as well, and will return local information on them. + * + * @param player a player uuid + * @return {@link ServerInfo} Can be null if proxy can't find it. + * @see #getServerNameFor(UUID) + */ + @Nullable + public final ServerInfo getServerFor(@NonNull UUID player) { + String serverName = this.getServerNameFor(player); + if (serverName == null) return null; + return ((ApiPlatformSupport) this.plugin) + .getProxy() + .getServer(serverName) + .map((RegisteredServer::getServerInfo)) + .orElse(null); + } - /** - * Kicks a player from the network - * calls {@link #getUuidFromName(String)} to get uuid - * - * @param playerName player name - * @param message kick message that player will see on kick - * @since 0.12.0 - */ - public void kickPlayer(String playerName, Component message) { - kickPlayer(getUuidFromName(playerName), message); - } + /** + * Kicks a player from the network calls {@link #getUuidFromName(String)} to get uuid + * + * @param playerName player name + * @param message kick message that player will see on kick + * @since 0.12.0 + */ + public void kickPlayer(String playerName, Component message) { + kickPlayer(getUuidFromName(playerName), message); + } - /** - * Kicks a player from the network - * - * @param playerUUID player name - * @param message kick message that player will see on kick - * @since 0.12.0 - */ - public void kickPlayer(UUID playerUUID, Component message) { - ((ApiPlatformSupport) this.plugin).kickPlayer(playerUUID, message); - } + /** + * Kicks a player from the network + * + * @param playerUUID player name + * @param message kick message that player will see on kick + * @since 0.12.0 + */ + public void kickPlayer(UUID playerUUID, Component message) { + ((ApiPlatformSupport) this.plugin).kickPlayer(playerUUID, message); + } - - /** - * Api instance - * - * @return the API instance. - * @since 0.6.5 - */ - public static RedisBungeeAPI getRedisBungeeApi() { - return redisBungeeApi; - } + /** + * Api instance + * + * @return the API instance. + * @since 0.6.5 + */ + public static RedisBungeeAPI getRedisBungeeApi() { + return redisBungeeApi; + } } diff --git a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java index 0ba58ca..3912709 100644 --- a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java +++ b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerChangedServerNetworkEvent.java @@ -1,52 +1,49 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.events; - import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerChangedServerNetworkEvent; - import java.util.UUID; /** * This event is sent when a player connects to a new server. RedisBungee sends the event only when * the proxy the player has been connected to is different than the local proxy. - *

- * This event corresponds to {@link com.velocitypowered.api.event.player.ServerConnectedEvent}, and is fired - * asynchronously. + * + *

This event corresponds to {@link com.velocitypowered.api.event.player.ServerConnectedEvent}, + * and is fired asynchronously. * * @since 0.3.4 */ public class PlayerChangedServerNetworkEvent implements IPlayerChangedServerNetworkEvent { - private final UUID uuid; - private final String previousServer; - private final String server; + private final UUID uuid; + private final String previousServer; + private final String server; - public PlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) { - this.uuid = uuid; - this.previousServer = previousServer; - this.server = server; - } + public PlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) { + this.uuid = uuid; + this.previousServer = previousServer; + this.server = server; + } - @Override - public UUID getUuid() { - return uuid; - } + @Override + public UUID getUuid() { + return uuid; + } - @Override - public String getServer() { - return server; - } + @Override + public String getServer() { + return server; + } - @Override - public String getPreviousServer() { - return previousServer; - } + @Override + public String getPreviousServer() { + return previousServer; + } } diff --git a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java index f60adb0..01fbd68 100644 --- a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java +++ b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerJoinedNetworkEvent.java @@ -1,38 +1,35 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.events; - import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEvent; - import java.util.UUID; /** - * This event is sent when a player joins the network. RedisBungee sends the event only when - * the proxy the player has been connected to is different than the local proxy. - *

- * This event corresponds to {@link com.velocitypowered.api.event.connection.PostLoginEvent}, and is fired - * asynchronously. + * This event is sent when a player joins the network. RedisBungee sends the event only when the + * proxy the player has been connected to is different than the local proxy. + * + *

This event corresponds to {@link com.velocitypowered.api.event.connection.PostLoginEvent}, and + * is fired asynchronously. * * @since 0.3.4 */ public class PlayerJoinedNetworkEvent implements IPlayerJoinedNetworkEvent { - private final UUID uuid; + private final UUID uuid; - public PlayerJoinedNetworkEvent(UUID uuid) { - this.uuid = uuid; - } + public PlayerJoinedNetworkEvent(UUID uuid) { + this.uuid = uuid; + } - @Override - public UUID getUuid() { - return uuid; - } + @Override + public UUID getUuid() { + return uuid; + } } diff --git a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java index 745c777..2b1f94a 100644 --- a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java +++ b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PlayerLeftNetworkEvent.java @@ -1,38 +1,35 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.events; - import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent; - import java.util.UUID; /** - * This event is sent when a player disconnects. RedisBungee sends the event only when - * the proxy the player has been connected to is different than the local proxy. - *

- * This event corresponds to {@link com.velocitypowered.api.event.connection.DisconnectEvent}, and is fired - * asynchronously. + * This event is sent when a player disconnects. RedisBungee sends the event only when the proxy the + * player has been connected to is different than the local proxy. + * + *

This event corresponds to {@link com.velocitypowered.api.event.connection.DisconnectEvent}, + * and is fired asynchronously. * * @since 0.3.4 */ public class PlayerLeftNetworkEvent implements IPlayerLeftNetworkEvent { - private final UUID uuid; + private final UUID uuid; - public PlayerLeftNetworkEvent(UUID uuid) { - this.uuid = uuid; - } + public PlayerLeftNetworkEvent(UUID uuid) { + this.uuid = uuid; + } - @Override - public UUID getUuid() { - return uuid; - } + @Override + public UUID getUuid() { + return uuid; + } } diff --git a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java index 1ceaa53..25c5826 100644 --- a/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java +++ b/redisbungee/proxies/velocity/velocity-api/src/main/java/com/imaginarycode/minecraft/redisbungee/events/PubSubMessageEvent.java @@ -1,42 +1,39 @@ /* - * Copyright (c) 2013-present RedisBungee contributors - * - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * - * http://www.eclipse.org/legal/epl-v10.html - */ - +* Copyright (c) 2026 RedisBungee contributors +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* +* http://www.eclipse.org/legal/epl-v10.html +*/ package com.imaginarycode.minecraft.redisbungee.events; - import com.imaginarycode.minecraft.redisbungee.api.events.IPubSubMessageEvent; /** * This event is posted when a PubSub message is received. - *

- * Warning: This event is fired in a separate thread! + * + *

Warning: This event is fired in a separate thread! * * @since 0.2.6 */ - public class PubSubMessageEvent implements IPubSubMessageEvent { - private final String channel; - private final String message; + private final String channel; + private final String message; - public PubSubMessageEvent(String channel, String message) { - this.channel = channel; - this.message = message; - } + public PubSubMessageEvent(String channel, String message) { + this.channel = channel; + this.message = message; + } - @Override - public String getChannel() { - return channel; - } + @Override + public String getChannel() { + return channel; + } - @Override - public String getMessage() { - return message; - } + @Override + public String getMessage() { + return message; + } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 44f6fb5..07554c0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,10 +9,12 @@ rootProject.name = "ValioBungee" fun configureProject(name: String) { val projectName = ":valiobungee-$name" - include(projectName) - project(projectName).projectDir = file(name) + configureProject(projectName,name) +} +fun configureProject(name: String, path: String) { + include(name) + project(name).projectDir = file(path) } - dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) @@ -24,4 +26,15 @@ dependencyResolutionManagement { } } -sequenceOf("core", "api").forEach{configureProject(it)} \ No newline at end of file +// main project stuff +sequenceOf("core", "api").forEach{configureProject(it)} +// RedisBunggee Project +configureProject(":RedisBungee-API", "redisbungee/api") +configureProject(":RedisBungee-Lang", "redisbungee/lang") +configureProject(":RedisBungee-Commands", "redisbungee/commands") + +configureProject(":RedisBungee-Bungee", "redisbungee/proxies/bungeecord/bungeecord-api") +configureProject(":RedisBungee-Proxy-Bungee", "redisbungee/proxies/bungeecord") + +configureProject(":RedisBungee-Velocity", "redisbungee/proxies/velocity/velocity-api") +configureProject(":RedisBungee-Proxy-Velocity", "redisbungee/proxies/velocity") \ No newline at end of file