mirror of
https://github.com/proxiodev/RedisBungee.git
synced 2026-04-07 23:50:27 +00:00
redo module system
This commit is contained in:
82
proxies/bungeecord/build.gradle.kts
Normal file
82
proxies/bungeecord/build.gradle.kts
Normal file
@@ -0,0 +1,82 @@
|
||||
plugins {
|
||||
java
|
||||
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||
id("xyz.jpenilla.run-waterfall") version "2.0.0"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":RedisBungee-Bungee"))
|
||||
compileOnly(libs.platform.bungeecord) {
|
||||
exclude("com.google.guava", "guava")
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("net.kyori","adventure-api")
|
||||
}
|
||||
implementation(libs.adventure.platforms.bungeecord)
|
||||
implementation(libs.adventure.gson)
|
||||
implementation(libs.acf.bungeecord)
|
||||
implementation(project(":RedisBungee-Commands"))
|
||||
}
|
||||
|
||||
description = "RedisBungee Bungeecord implementation"
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
|
||||
tasks {
|
||||
withType<Javadoc> {
|
||||
dependsOn(project(":RedisBungee-API").getTasksByName("javadoc", false))
|
||||
val options = options as StandardJavadocDocletOptions
|
||||
options.use()
|
||||
options.isDocFilesSubDirs = true
|
||||
options.links(
|
||||
"https://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/", // bungeecord api
|
||||
)
|
||||
val apiDocs = File(rootProject.projectDir, "RedisBungee-API/build/docs/javadoc")
|
||||
options.linksOffline("https://ci.limework.net/RedisBungee/RedisBungee-API/build/docs/javadoc", apiDocs.path)
|
||||
}
|
||||
runWaterfall {
|
||||
waterfallVersion("1.20")
|
||||
environment["REDISBUNGEE_PROXY_ID"] = "bungeecord-1"
|
||||
environment["REDISBUNGEE_NETWORK_ID"] = "dev"
|
||||
}
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(17)
|
||||
}
|
||||
javadoc {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
processResources {
|
||||
filteringCharset = Charsets.UTF_8.name()
|
||||
filesMatching("plugin.yml") {
|
||||
filter {
|
||||
it.replace("*{redisbungee.version}*", "$version", false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
shadowJar {
|
||||
relocate("redis.clients.jedis", "com.imaginarycode.minecraft.redisbungee.internal.jedis")
|
||||
relocate("redis.clients.util", "com.imaginarycode.minecraft.redisbungee.internal.jedisutil")
|
||||
relocate("org.apache.commons.pool", "com.imaginarycode.minecraft.redisbungee.internal.commonspool")
|
||||
relocate("com.squareup.okhttp", "com.imaginarycode.minecraft.redisbungee.internal.okhttp")
|
||||
relocate("okio", "com.imaginarycode.minecraft.redisbungee.internal.okio")
|
||||
relocate("org.json", "com.imaginarycode.minecraft.redisbungee.internal.json")
|
||||
// configurate shade
|
||||
relocate("ninja.leaping.configurate", "com.imaginarycode.minecraft.redisbungee.internal.configurate")
|
||||
relocate("org.yaml", "com.imaginarycode.minecraft.redisbungee.internal.yml")
|
||||
relocate("com.google.common", "com.imaginarycode.minecraft.redisbungee.internal.com.google.common")
|
||||
relocate("com.google.errorprone", "com.imaginarycode.minecraft.redisbungee.internal.com.google.errorprone")
|
||||
relocate("com.google.gson", "com.imaginarycode.minecraft.redisbungee.internal.com.google.gson")
|
||||
relocate("com.google.j2objc", "com.imaginarycode.minecraft.redisbungee.internal.com.google.j2objc")
|
||||
relocate("com.google.thirdparty", "com.imaginarycode.minecraft.redisbungee.internal.com.google.thirdparty")
|
||||
relocate("com.github.benmanes.caffeine", "com.imaginarycode.minecraft.redisbungee.internal.caffeine")
|
||||
// acf shade
|
||||
relocate("co.aikar.commands", "com.imaginarycode.minecraft.redisbungee.internal.acf.commands")
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
51
proxies/bungeecord/bungeecord-api/build.gradle.kts
Normal file
51
proxies/bungeecord/bungeecord-api/build.gradle.kts
Normal file
@@ -0,0 +1,51 @@
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":RedisBungee-API"))
|
||||
compileOnly(libs.platform.bungeecord) {
|
||||
exclude("com.google.guava", "guava")
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("net.kyori","adventure-api")
|
||||
}
|
||||
}
|
||||
|
||||
description = "RedisBungee Bungeecord API"
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
|
||||
tasks {
|
||||
withType<Javadoc> {
|
||||
dependsOn(project(":RedisBungee-API").getTasksByName("javadoc", false))
|
||||
val path = project(":RedisBungee-API").path
|
||||
val options = options as StandardJavadocDocletOptions
|
||||
options.use()
|
||||
options.isDocFilesSubDirs = true
|
||||
options.links(
|
||||
"https://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/", // bungeecord api
|
||||
)
|
||||
val apiDocs = File(rootProject.projectDir, "$path/build/docs/javadoc")
|
||||
options.linksOffline("https://ci.limework.net/ValioBungee/api/build/docs/javadoc", apiDocs.path)
|
||||
}
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(17)
|
||||
}
|
||||
javadoc {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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
|
||||
*/
|
||||
|
||||
package com.imaginarycode.minecraft.redisbungee;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
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.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()}.
|
||||
*
|
||||
* @author tuxed
|
||||
* @since 0.2.3 | updated 0.8.0
|
||||
*/
|
||||
public class RedisBungeeAPI extends AbstractRedisBungeeAPI {
|
||||
|
||||
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 ((Plugin) this.plugin).getProxy().getServerInfo(serverName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Api instance
|
||||
*
|
||||
* @return the API instance.
|
||||
* @since 0.6.5
|
||||
*/
|
||||
public static RedisBungeeAPI getRedisBungeeApi() {
|
||||
return redisBungeeApi;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerChangedServerNetworkEvent;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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 PlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) {
|
||||
this.uuid = uuid;
|
||||
this.previousServer = previousServer;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreviousServer() {
|
||||
return previousServer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEvent;
|
||||
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.
|
||||
* <p>
|
||||
* 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;
|
||||
|
||||
public PlayerJoinedNetworkEvent(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent;
|
||||
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.
|
||||
* <p>
|
||||
* 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;
|
||||
|
||||
public PlayerLeftNetworkEvent(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPubSubMessageEvent;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
/**
|
||||
* This event is posted when a PubSub message is received.
|
||||
* <p>
|
||||
* <strong>Warning</strong>: 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;
|
||||
|
||||
public PubSubMessageEvent(String channel, String message) {
|
||||
this.channel = channel;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.imaginarycode.minecraft.redisbungee;
|
||||
|
||||
import co.aikar.commands.BungeeCommandIssuer;
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import com.imaginarycode.minecraft.redisbungee.commands.utils.CommandPlatformHelper;
|
||||
import net.kyori.adventure.text.Component;
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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.PlayerLeftNetworkEvent;
|
||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.LoginEvent;
|
||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectedEvent;
|
||||
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.concurrent.TimeUnit;
|
||||
|
||||
|
||||
public class BungeePlayerDataManager extends PlayerDataManager<ProxiedPlayer, PostLoginEvent, PlayerDisconnectEvent, PubSubMessageEvent, PlayerChangedServerNetworkEvent, PlayerLeftNetworkEvent, ServerConnectedEvent> implements Listener {
|
||||
|
||||
public BungeePlayerDataManager(RedisBungeePlugin<ProxiedPlayer> plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
@EventHandler
|
||||
public void onPlayerChangedServerNetworkEvent(PlayerChangedServerNetworkEvent event) {
|
||||
super.handleNetworkPlayerServerChange(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@EventHandler
|
||||
public void onNetworkPlayerQuit(PlayerLeftNetworkEvent event) {
|
||||
super.handleNetworkPlayerQuit(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@EventHandler
|
||||
public void onPubSubMessageEvent(PubSubMessageEvent event) {
|
||||
super.handlePubSubMessageEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@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);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLoginEvent(LoginEvent event) {
|
||||
event.registerIntent((Plugin) plugin);
|
||||
// check if online
|
||||
if (getLastOnline(event.getConnection().getUniqueId()) == 0) {
|
||||
if (plugin.configuration().kickWhenOnline()) {
|
||||
kickPlayer(event.getConnection().getUniqueId(), plugin.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(plugin.langConfiguration().messages().alreadyLoggedIn()));
|
||||
event.completeIntent((Plugin) plugin);
|
||||
}
|
||||
} else {
|
||||
event.completeIntent((Plugin) plugin);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@EventHandler
|
||||
public void onLoginEvent(PostLoginEvent event) {
|
||||
super.addPlayer(event.getPlayer().getUniqueId(), event.getPlayer().getName(), event.getPlayer().getAddress().getAddress());
|
||||
}
|
||||
|
||||
@Override
|
||||
@EventHandler
|
||||
public void onDisconnectEvent(PlayerDisconnectEvent event) {
|
||||
super.removePlayer(event.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import co.aikar.commands.BungeeCommandManager;
|
||||
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.LangConfiguration;
|
||||
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.LangConfigLoader;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerChangedServerNetworkEvent;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEvent;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent;
|
||||
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.NameFetcher;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.util.uuid.UUIDFetcher;
|
||||
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;
|
||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||
import com.squareup.okhttp.Dispatcher;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import net.md_5.bungee.api.scheduler.ScheduledTask;
|
||||
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.sql.Date;
|
||||
import java.time.Instant;
|
||||
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<ProxiedPlayer>, ConfigLoader, LangConfigLoader {
|
||||
|
||||
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 OkHttpClient httpClient;
|
||||
private BungeeCommandManager commandManager;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger("RedisBungee");
|
||||
|
||||
|
||||
@Override
|
||||
public RedisBungeeConfiguration configuration() {
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LangConfiguration langConfiguration() {
|
||||
return this.langConfiguration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRedisBungeeAPI getAbstractRedisBungeeApi() {
|
||||
return this.api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProxyDataManager proxyDataManager() {
|
||||
return this.proxyDataManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerDataManager<ProxiedPlayer, ?, ?, ?, ?, ?, ?> 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 boolean handlePlatformKick(UUID uuid, Component message) {
|
||||
ProxiedPlayer player = getPlayer(uuid);
|
||||
if (player == null) return false;
|
||||
if (!player.isConnected()) return false;
|
||||
player.disconnect(BungeeComponentSerializer.get().serialize(message));
|
||||
return true;
|
||||
}
|
||||
|
||||
@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<UUID> getLocalOnlineUUIDs() {
|
||||
HashSet<UUID> 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);
|
||||
}
|
||||
};
|
||||
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
|
||||
httpClient = new OkHttpClient();
|
||||
Dispatcher dispatcher = new Dispatcher(getExecutorService());
|
||||
httpClient.setDispatcher(dispatcher);
|
||||
NameFetcher.setHttpClient(httpClient);
|
||||
UUIDFetcher.setHttpClient(httpClient);
|
||||
InitialUtils.checkRedisVersion(this);
|
||||
uuidTranslator = new UUIDTranslator(this);
|
||||
|
||||
// register plugin messages channel.
|
||||
getProxy().registerChannel("legacy:redisbungee");
|
||||
getProxy().registerChannel("RedisBungee");
|
||||
|
||||
// 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);
|
||||
|
||||
logInfo("RedisBungee initialized successfully ");
|
||||
}
|
||||
|
||||
@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");
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
return api.getJedisPool();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onLangConfigLoad(LangConfiguration langConfiguration) {
|
||||
this.langConfiguration = langConfiguration;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +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
|
||||
*/
|
||||
|
||||
package com.imaginarycode.minecraft.redisbungee;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
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.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()}.
|
||||
*
|
||||
* @author tuxed
|
||||
* @since 0.2.3 | updated 0.8.0
|
||||
*/
|
||||
public class RedisBungeeAPI extends AbstractRedisBungeeAPI {
|
||||
|
||||
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 ((Plugin) this.plugin).getProxy().getServerInfo(serverName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Api instance
|
||||
*
|
||||
* @return the API instance.
|
||||
* @since 0.6.5
|
||||
*/
|
||||
public static RedisBungeeAPI getRedisBungeeApi() {
|
||||
return redisBungeeApi;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class RedisBungeeCommandSender implements CommandSender {
|
||||
private static final RedisBungeeCommandSender singleton;
|
||||
|
||||
static {
|
||||
singleton = new RedisBungeeCommandSender();
|
||||
}
|
||||
|
||||
public static RedisBungeeCommandSender getSingleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "RedisBungee";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(String s) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessages(String... strings) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent... baseComponents) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(BaseComponent baseComponent) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getGroups() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@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<String> getPermissions() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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 net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
|
||||
import net.md_5.bungee.api.AbstractReconnectHandler;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.connection.Server;
|
||||
import net.md_5.bungee.api.event.PluginMessageEvent;
|
||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.MultiMapSerialization.*;
|
||||
|
||||
public class RedisBungeeListener implements Listener {
|
||||
|
||||
private final RedisBungeePlugin<ProxiedPlayer> plugin;
|
||||
|
||||
public RedisBungeeListener(RedisBungeePlugin<ProxiedPlayer> plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPing(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());
|
||||
}
|
||||
|
||||
@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;
|
||||
|
||||
switch (subchannel) {
|
||||
case "PlayerList" -> {
|
||||
out.writeUTF("PlayerList");
|
||||
Set<UUID> 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<String> 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<String, UUID> 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<String, String> human = HashMultimap.create();
|
||||
for (Map.Entry<String, UUID> 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;
|
||||
}
|
||||
}
|
||||
|
||||
((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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerChangedServerNetworkEvent;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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 PlayerChangedServerNetworkEvent(UUID uuid, String previousServer, String server) {
|
||||
this.uuid = uuid;
|
||||
this.previousServer = previousServer;
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreviousServer() {
|
||||
return previousServer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEvent;
|
||||
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.
|
||||
* <p>
|
||||
* 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;
|
||||
|
||||
public PlayerJoinedNetworkEvent(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent;
|
||||
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.
|
||||
* <p>
|
||||
* 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;
|
||||
|
||||
public PlayerLeftNetworkEvent(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPubSubMessageEvent;
|
||||
import net.md_5.bungee.api.plugin.Event;
|
||||
|
||||
/**
|
||||
* This event is posted when a PubSub message is received.
|
||||
* <p>
|
||||
* <strong>Warning</strong>: 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;
|
||||
|
||||
public PubSubMessageEvent(String channel, String message) {
|
||||
this.channel = channel;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
6
proxies/bungeecord/src/main/resources/plugin.yml
Normal file
6
proxies/bungeecord/src/main/resources/plugin.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
name: RedisBungee
|
||||
main: com.imaginarycode.minecraft.redisbungee.RedisBungee
|
||||
version: *{redisbungee.version}*
|
||||
author: "astei, ProxioDev"
|
||||
# This is used so that we can automatically override default BungeeCord behavior.
|
||||
softDepends: ["cmd_find", "cmd_list"]
|
||||
45
proxies/velocity/build.gradle.kts
Normal file
45
proxies/velocity/build.gradle.kts
Normal file
@@ -0,0 +1,45 @@
|
||||
plugins {
|
||||
java
|
||||
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||
id("xyz.jpenilla.run-velocity") version "2.0.0"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(":RedisBungee-Velocity"))
|
||||
compileOnly(libs.platform.velocity)
|
||||
annotationProcessor(libs.platform.velocity)
|
||||
implementation(project(":RedisBungee-Commands"))
|
||||
implementation(libs.acf.velocity)
|
||||
|
||||
}
|
||||
|
||||
description = "RedisBungee Velocity implementation"
|
||||
|
||||
|
||||
tasks {
|
||||
runVelocity {
|
||||
velocityVersion("3.3.0-SNAPSHOT")
|
||||
environment["REDISBUNGEE_PROXY_ID"] = "velocity-1"
|
||||
environment["REDISBUNGEE_NETWORK_ID"] = "dev"
|
||||
}
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(17)
|
||||
}
|
||||
processResources {
|
||||
filteringCharset = Charsets.UTF_8.name()
|
||||
}
|
||||
shadowJar {
|
||||
relocate("redis.clients.jedis", "com.imaginarycode.minecraft.redisbungee.internal.jedis")
|
||||
relocate("redis.clients.util", "com.imaginarycode.minecraft.redisbungee.internal.jedisutil")
|
||||
relocate("org.apache.commons.pool", "com.imaginarycode.minecraft.redisbungee.internal.commonspool")
|
||||
relocate("com.squareup.okhttp", "com.imaginarycode.minecraft.redisbungee.internal.okhttp")
|
||||
relocate("okio", "com.imaginarycode.minecraft.redisbungee.internal.okio")
|
||||
relocate("org.json", "com.imaginarycode.minecraft.redisbungee.internal.json")
|
||||
relocate("com.github.benmanes.caffeine", "com.imaginarycode.minecraft.redisbungee.internal.caffeine")
|
||||
// acf shade
|
||||
relocate("co.aikar.commands", "com.imaginarycode.minecraft.redisbungee.internal.acf.commands")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
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);
|
||||
|
||||
static {
|
||||
singleton = new RedisBungeeCommandSource();
|
||||
}
|
||||
|
||||
public static RedisBungeeCommandSource getSingleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
return this.permissionChecker.test(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tristate getPermissionValue(String s) {
|
||||
return Tristate.TRUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermissionChecker getPermissionChecker() {
|
||||
return this.permissionChecker;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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.velocitypowered.api.event.PostOrder;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.PluginMessageEvent;
|
||||
import com.velocitypowered.api.event.player.PlayerChooseInitialServerEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyPingEvent;
|
||||
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 net.kyori.adventure.text.Component;
|
||||
|
||||
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 RedisBungeePlugin<Player> plugin;
|
||||
|
||||
public RedisBungeeListener(RedisBungeePlugin<Player> plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Subscribe(order = PostOrder.LAST) // some plugins changes it online players so we need to be executed as last
|
||||
public void onPing(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<UUID> 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<String> 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<String, UUID> 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<String, String> human = HashMultimap.create();
|
||||
for (Map.Entry<String, UUID> 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;
|
||||
}
|
||||
}
|
||||
|
||||
((ServerConnection) event.getSource()).sendPluginMessage(event.getIdentifier(), out.toByteArray());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@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<RegisteredServer> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import co.aikar.commands.VelocityCommandManager;
|
||||
import com.google.inject.Inject;
|
||||
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.LangConfiguration;
|
||||
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.LangConfigLoader;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerChangedServerNetworkEvent;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerJoinedNetworkEvent;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPlayerLeftNetworkEvent;
|
||||
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.NameFetcher;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.util.uuid.UUIDFetcher;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.util.uuid.UUIDTranslator;
|
||||
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 com.squareup.okhttp.Dispatcher;
|
||||
import com.squareup.okhttp.OkHttpClient;
|
||||
import com.velocitypowered.api.event.PostOrder;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||
import com.velocitypowered.api.plugin.Plugin;
|
||||
import com.velocitypowered.api.plugin.annotation.DataDirectory;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
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 org.slf4j.Logger;
|
||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.Date;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Plugin(id = "redisbungee", name = "RedisBungee", version = Constants.VERSION, url = "https://github.com/ProxioDev/RedisBungee", authors = {"astei", "ProxioDev"})
|
||||
public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player>, ConfigLoader, LangConfigLoader, ServerObjectFetcher {
|
||||
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 OkHttpClient httpClient;
|
||||
|
||||
private final ProxyDataManager proxyDataManager;
|
||||
|
||||
private final VelocityPlayerDataManager playerDataManager;
|
||||
|
||||
private ScheduledTask cleanUpTask;
|
||||
private ScheduledTask heartbeatTask;
|
||||
|
||||
public static final List<ChannelIdentifier> 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;
|
||||
|
||||
@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<UUID> getLocalOnlineUUIDs() {
|
||||
HashSet<UUID> 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);
|
||||
}
|
||||
};
|
||||
this.playerDataManager = new VelocityPlayerDataManager(this);
|
||||
uuidTranslator = new UUIDTranslator(this);
|
||||
this.httpClient = new OkHttpClient();
|
||||
Dispatcher dispatcher = new Dispatcher(Executors.newFixedThreadPool(6));
|
||||
this.httpClient.setDispatcher(dispatcher);
|
||||
NameFetcher.setHttpClient(httpClient);
|
||||
UUIDFetcher.setHttpClient(httpClient);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Summoner<?> getSummoner() {
|
||||
return this.jedisSummoner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractRedisBungeeAPI getAbstractRedisBungeeApi() {
|
||||
return this.api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProxyDataManager proxyDataManager() {
|
||||
return this.proxyDataManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerDataManager<Player, ?, ?, ?, ?, ?, ?> 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;
|
||||
}
|
||||
|
||||
@Override
|
||||
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 boolean handlePlatformKick(UUID uuid, Component message) {
|
||||
Player player = getPlayer(uuid);
|
||||
if (player == null) return false;
|
||||
player.disconnect(message);
|
||||
return true;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
this.httpClient.getDispatcher().getExecutorService().shutdown();
|
||||
try {
|
||||
logInfo("waiting for httpclient thread-pool termination.....");
|
||||
this.httpClient.getDispatcher().getExecutorService().awaitTermination(20, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException 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;
|
||||
}
|
||||
|
||||
public Logger getLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public Path getDataFolder() {
|
||||
return this.dataFolder;
|
||||
}
|
||||
|
||||
public InputStream getResourceAsStream(String name) {
|
||||
return this.getClass().getClassLoader().getResourceAsStream(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import co.aikar.commands.CommandIssuer;
|
||||
import co.aikar.commands.VelocityCommandIssuer;
|
||||
import com.imaginarycode.minecraft.redisbungee.commands.utils.CommandPlatformHelper;
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.PlayerDataManager;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin;
|
||||
import com.imaginarycode.minecraft.redisbungee.api.config.RedisBungeeConfiguration;
|
||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent;
|
||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerLeftNetworkEvent;
|
||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||
import com.velocitypowered.api.event.Continuation;
|
||||
import com.velocitypowered.api.event.ResultedEvent;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
||||
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 java.util.concurrent.TimeUnit;
|
||||
|
||||
public class VelocityPlayerDataManager extends PlayerDataManager<Player, PostLoginEvent, DisconnectEvent, PubSubMessageEvent, PlayerChangedServerNetworkEvent, PlayerLeftNetworkEvent, ServerConnectedEvent> {
|
||||
public VelocityPlayerDataManager(RedisBungeePlugin<Player> plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Subscribe
|
||||
public void onPlayerChangedServerNetworkEvent(PlayerChangedServerNetworkEvent event) {
|
||||
handleNetworkPlayerServerChange(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Subscribe
|
||||
public void onNetworkPlayerQuit(PlayerLeftNetworkEvent event) {
|
||||
handleNetworkPlayerQuit(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Subscribe
|
||||
public void onPubSubMessageEvent(PubSubMessageEvent event) {
|
||||
handlePubSubMessageEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
@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 onLoginEvent(LoginEvent event, Continuation continuation) {
|
||||
// check if online
|
||||
if (getLastOnline(event.getPlayer().getUniqueId()) == 0) {
|
||||
if (plugin.configuration().kickWhenOnline()) {
|
||||
kickPlayer(event.getPlayer().getUniqueId(), plugin.langConfiguration().messages().loggedInFromOtherLocation());
|
||||
// wait 3 seconds before releasing the event
|
||||
plugin.executeAsyncAfter(continuation::resume, TimeUnit.SECONDS, 3);
|
||||
} else {
|
||||
event.setResult(ResultedEvent.ComponentResult.denied(plugin.langConfiguration().messages().alreadyLoggedIn()));
|
||||
continuation.resume();
|
||||
}
|
||||
} else {
|
||||
continuation.resume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Subscribe
|
||||
public void onLoginEvent(PostLoginEvent event) {
|
||||
addPlayer(event.getPlayer().getUniqueId(), event.getPlayer().getUsername(), event.getPlayer().getRemoteAddress().getAddress());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Subscribe
|
||||
public void onDisconnectEvent(DisconnectEvent event) {
|
||||
if (event.getLoginStatus() == DisconnectEvent.LoginStatus.SUCCESSFUL_LOGIN || event.getLoginStatus() == DisconnectEvent.LoginStatus.PRE_SERVER_JOIN) {
|
||||
removePlayer(event.getPlayer().getUniqueId());
|
||||
}
|
||||
}
|
||||
}
|
||||
62
proxies/velocity/velocity-api/build.gradle.kts
Normal file
62
proxies/velocity/velocity-api/build.gradle.kts
Normal file
@@ -0,0 +1,62 @@
|
||||
plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":RedisBungee-API")) {
|
||||
// Since velocity already includes guava / configurate exlude them
|
||||
exclude("com.google.guava", "guava")
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("org.spongepowered", "configurate-yaml")
|
||||
// exclude also adventure api
|
||||
exclude("net.kyori", "adventure-api")
|
||||
exclude("net.kyori", "adventure-text-serializer-gson")
|
||||
exclude("net.kyori", "adventure-text-serializer-legacy")
|
||||
exclude("net.kyori", "adventure-text-serializer-plain")
|
||||
exclude("net.kyori", "adventure-text-minimessage")
|
||||
}
|
||||
compileOnly(libs.platform.velocity)
|
||||
|
||||
}
|
||||
|
||||
description = "RedisBungee Velocity API"
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
tasks {
|
||||
withType<Javadoc> {
|
||||
dependsOn(project(":RedisBungee-API").getTasksByName("javadoc", false))
|
||||
val path = project(":RedisBungee-API").path;
|
||||
val options = options as StandardJavadocDocletOptions
|
||||
options.use()
|
||||
options.isDocFilesSubDirs = true
|
||||
options.links(
|
||||
"https://jd.papermc.io/velocity/3.0.0/", // velocity api
|
||||
)
|
||||
val apiDocs = File(rootProject.projectDir, "$path/build/docs/javadoc")
|
||||
options.linksOffline("https://ci.limework.net/ValioBungee/api/build/docs/javadoc", apiDocs.path)
|
||||
}
|
||||
compileJava {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
options.release.set(17)
|
||||
}
|
||||
javadoc {
|
||||
options.encoding = Charsets.UTF_8.name()
|
||||
}
|
||||
processResources {
|
||||
filteringCharset = Charsets.UTF_8.name()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
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()}.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ((ServerObjectFetcher) this.plugin).getProxy().getServer(serverName).map((RegisteredServer::getServerInfo)).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Api instance
|
||||
*
|
||||
* @return the API instance.
|
||||
* @since 0.6.5
|
||||
*/
|
||||
public static RedisBungeeAPI getRedisBungeeApi() {
|
||||
return redisBungeeApi;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.imaginarycode.minecraft.redisbungee;
|
||||
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
|
||||
public interface ServerObjectFetcher {
|
||||
|
||||
ProxyServer getProxy();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.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.
|
||||
* <p>
|
||||
* 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;
|
||||
|
||||
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 String getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreviousServer() {
|
||||
return previousServer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.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.
|
||||
* <p>
|
||||
* 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;
|
||||
|
||||
public PlayerJoinedNetworkEvent(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.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.
|
||||
* <p>
|
||||
* 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;
|
||||
|
||||
public PlayerLeftNetworkEvent(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.events;
|
||||
|
||||
|
||||
import com.imaginarycode.minecraft.redisbungee.api.events.IPubSubMessageEvent;
|
||||
|
||||
/**
|
||||
* This event is posted when a PubSub message is received.
|
||||
* <p>
|
||||
* <strong>Warning</strong>: 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;
|
||||
|
||||
public PubSubMessageEvent(String channel, String message) {
|
||||
this.channel = channel;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user