2
0
mirror of https://github.com/proxiodev/RedisBungee.git synced 2024-11-23 04:28:01 +00:00

re-implement the commands, right usage of logger, general improvements to the listener (#39)

Co-authored-by: mohammed jasem alaajel <xrambad@gmail.com>
This commit is contained in:
Adrian 2022-07-15 01:52:53 -05:00 committed by GitHub
parent 5f07ba6b66
commit 21f6cdeaeb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 404 additions and 364 deletions

View File

@ -12,8 +12,8 @@
<artifactId>RedisBungee-Velocity</artifactId> <artifactId>RedisBungee-Velocity</artifactId>
<properties> <properties>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target> <maven.compiler.target>11</maven.compiler.target>
</properties> </properties>
<repositories> <repositories>
<repository> <repository>
@ -48,8 +48,8 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version> <version>3.8.1</version>
<configuration> <configuration>
<source>1.8</source> <source>11</source>
<target>1.8</target> <target>11</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
@ -130,7 +130,7 @@
<dependency> <dependency>
<groupId>com.velocitypowered</groupId> <groupId>com.velocitypowered</groupId>
<artifactId>velocity-api</artifactId> <artifactId>velocity-api</artifactId>
<version>3.1.0</version> <version>3.1.2-SNAPSHOT</version>
<type>jar</type> <type>jar</type>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>

View File

@ -4,13 +4,10 @@ package com.imaginarycode.minecraft.redisbungee;
import com.velocitypowered.api.command.CommandSource; import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.permission.Tristate; import com.velocitypowered.api.permission.Tristate;
import net.kyori.adventure.permission.PermissionChecker; import net.kyori.adventure.permission.PermissionChecker;
import net.kyori.adventure.util.TriState;
import java.util.Collection;
import java.util.Collections;
public class RedisBungeeCommandSource implements CommandSource { public class RedisBungeeCommandSource implements CommandSource {
private static final RedisBungeeCommandSource singleton; private static final RedisBungeeCommandSource singleton;
private final PermissionChecker permissionChecker = PermissionChecker.always(net.kyori.adventure.util.TriState.TRUE);
static { static {
singleton = new RedisBungeeCommandSource(); singleton = new RedisBungeeCommandSource();
@ -23,16 +20,16 @@ public class RedisBungeeCommandSource implements CommandSource {
@Override @Override
public boolean hasPermission(String permission) { public boolean hasPermission(String permission) {
return true; return this.permissionChecker.test(permission);
} }
@Override @Override
public Tristate getPermissionValue(String s) { public Tristate getPermissionValue(String s) {
return null; return Tristate.TRUE;
} }
@Override @Override
public PermissionChecker getPermissionChecker() { public PermissionChecker getPermissionChecker() {
return PermissionChecker.always(TriState.TRUE); return this.permissionChecker;
} }
} }

View File

@ -20,21 +20,23 @@ import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.event.connection.LoginEvent; import com.velocitypowered.api.event.connection.LoginEvent;
import com.velocitypowered.api.event.connection.PluginMessageEvent; import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.event.connection.PostLoginEvent; import com.velocitypowered.api.event.connection.PostLoginEvent;
import com.velocitypowered.api.event.connection.PluginMessageEvent.ForwardResult;
import com.velocitypowered.api.event.player.ServerConnectedEvent; import com.velocitypowered.api.event.player.ServerConnectedEvent;
import com.velocitypowered.api.event.proxy.ProxyPingEvent; import com.velocitypowered.api.event.proxy.ProxyPingEvent;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection; import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier;
import com.velocitypowered.api.proxy.server.ServerPing; import com.velocitypowered.api.proxy.server.ServerPing;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline; import redis.clients.jedis.Pipeline;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
public class RedisBungeeVelocityListener extends AbstractRedisBungeeListener<LoginEvent, PostLoginEvent, DisconnectEvent, ServerConnectedEvent, ProxyPingEvent, PluginMessageEvent, PubSubMessageEvent> { public class RedisBungeeVelocityListener extends AbstractRedisBungeeListener<LoginEvent, PostLoginEvent, DisconnectEvent, ServerConnectedEvent, ProxyPingEvent, PluginMessageEvent, PubSubMessageEvent> {
// Some messages are using legacy characters
private final LegacyComponentSerializer serializer = LegacyComponentSerializer.legacySection();
public RedisBungeeVelocityListener(RedisBungeePlugin<?> plugin, List<InetAddress> exemptAddresses) { public RedisBungeeVelocityListener(RedisBungeePlugin<?> plugin, List<InetAddress> exemptAddresses) {
super(plugin, exemptAddresses); super(plugin, exemptAddresses);
@ -56,14 +58,14 @@ public class RedisBungeeVelocityListener extends AbstractRedisBungeeListener<Log
Player player = (Player) plugin.getPlayer(event.getPlayer().getUsername()); Player player = (Player) plugin.getPlayer(event.getPlayer().getUsername());
if (player != null) { if (player != null) {
event.setResult(ResultedEvent.ComponentResult.denied(Component.text(ONLINE_MODE_RECONNECT))); event.setResult(ResultedEvent.ComponentResult.denied(serializer.deserialize(ONLINE_MODE_RECONNECT)));
return null; return null;
} }
} }
for (String s : plugin.getServerIds()) { for (String s : plugin.getServerIds()) {
if (jedis.sismember("proxy:" + s + ":usersOnline", event.getPlayer().getUniqueId().toString())) { if (jedis.sismember("proxy:" + s + ":usersOnline", event.getPlayer().getUniqueId().toString())) {
event.setResult(ResultedEvent.ComponentResult.denied(Component.text(ALREADY_LOGGED_IN))); event.setResult(ResultedEvent.ComponentResult.denied(serializer.deserialize(ALREADY_LOGGED_IN)));
return null; return null;
} }
} }
@ -136,114 +138,115 @@ public class RedisBungeeVelocityListener extends AbstractRedisBungeeListener<Log
if (exemptAddresses.contains(event.getConnection().getRemoteAddress().getAddress())) { if (exemptAddresses.contains(event.getConnection().getRemoteAddress().getAddress())) {
return; return;
} }
ServerPing oldPing = event.getPing(); ServerPing.Builder ping = event.getPing().asBuilder();
int max = oldPing.getPlayers().map(ServerPing.Players::getMax).orElse(0); ping.onlinePlayers(plugin.getCount());
List<ServerPing.SamplePlayer> list = oldPing.getPlayers().map(ServerPing.Players::getSample).orElse(Collections.emptyList()); event.setPing(ping.build());
event.setPing(new ServerPing(oldPing.getVersion(), new ServerPing.Players(plugin.getCount(), max, list), oldPing.getDescriptionComponent(), oldPing.getFavicon().orElse(null)));
} }
@Override @Override
@SuppressWarnings("UnstableApiUsage")
@Subscribe @Subscribe
public void onPluginMessage(PluginMessageEvent event) { public void onPluginMessage(PluginMessageEvent event) {
if ((event.getIdentifier().getId().equals("legacy:redisbungee") || event.getIdentifier().getId().equals("RedisBungee")) && event.getSource() instanceof ServerConnection) { if(!(event.getSource() instanceof ServerConnection) || !RedisBungeeVelocityPlugin.IDENTIFIERS.contains(event.getIdentifier())) {
final String currentChannel = event.getIdentifier().getId(); return;
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.getPlayers();
} else {
try {
original = plugin.getApi().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));
break;
case "PlayerCount":
out.writeUTF("PlayerCount");
type = in.readUTF();
if (type.equals("ALL")) {
out.writeUTF("ALL");
out.writeInt(plugin.getCount());
} else {
out.writeUTF(type);
try {
out.writeInt(plugin.getApi().getPlayersOnServer(type).size());
} catch (IllegalArgumentException e) {
out.writeInt(0);
}
}
break;
case "LastOnline":
String user = in.readUTF();
out.writeUTF("LastOnline");
out.writeUTF(user);
out.writeLong(plugin.getApi().getLastOnline(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(user, true))));
break;
case "ServerPlayers":
String type1 = in.readUTF();
out.writeUTF("ServerPlayers");
Multimap<String, UUID> multimap = plugin.getApi().getServerToPlayers();
boolean includesUsers;
switch (type1) {
case "COUNT":
includesUsers = false;
break;
case "PLAYERS":
includesUsers = true;
break;
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);
}
break;
case "Proxy":
out.writeUTF("Proxy");
out.writeUTF(plugin.getConfiguration().getServerId());
break;
case "PlayerProxy":
String username = in.readUTF();
out.writeUTF("PlayerProxy");
out.writeUTF(username);
out.writeUTF(plugin.getApi().getProxy(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(username, true))));
break;
default:
return;
}
((ServerConnection) event.getSource()).sendPluginMessage(new LegacyChannelIdentifier(currentChannel), out.toByteArray());
});
} }
event.setResult(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.getPlayers();
} else {
try {
original = plugin.getApi().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));
break;
case "PlayerCount":
out.writeUTF("PlayerCount");
type = in.readUTF();
if (type.equals("ALL")) {
out.writeUTF("ALL");
out.writeInt(plugin.getCount());
} else {
out.writeUTF(type);
try {
out.writeInt(plugin.getApi().getPlayersOnServer(type).size());
} catch (IllegalArgumentException e) {
out.writeInt(0);
}
}
break;
case "LastOnline":
String user = in.readUTF();
out.writeUTF("LastOnline");
out.writeUTF(user);
out.writeLong(plugin.getApi().getLastOnline(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(user, true))));
break;
case "ServerPlayers":
String type1 = in.readUTF();
out.writeUTF("ServerPlayers");
Multimap<String, UUID> multimap = plugin.getApi().getServerToPlayers();
boolean includesUsers;
switch (type1) {
case "COUNT":
includesUsers = false;
break;
case "PLAYERS":
includesUsers = true;
break;
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);
}
break;
case "Proxy":
out.writeUTF("Proxy");
out.writeUTF(plugin.getConfiguration().getServerId());
break;
case "PlayerProxy":
String username = in.readUTF();
out.writeUTF("PlayerProxy");
out.writeUTF(username);
out.writeUTF(plugin.getApi().getProxy(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(username, true))));
break;
default:
return;
}
((ServerConnection) event.getSource()).sendPluginMessage(event.getIdentifier(), out.toByteArray());
});
} }
@ -255,7 +258,7 @@ public class RedisBungeeVelocityListener extends AbstractRedisBungeeListener<Log
if (message.startsWith("/")) if (message.startsWith("/"))
message = message.substring(1); message = message.substring(1);
plugin.logInfo("Invoking command via PubSub: /" + message); plugin.logInfo("Invoking command via PubSub: /" + message);
((RedisBungeeVelocityPlugin) plugin).getProxy().getCommandManager().executeAsync(RedisBungeeCommandSource.getSingleton(), message);//.dispatchCommand(RedisBungeeCommandSource.getSingleton(), message); ((RedisBungeeVelocityPlugin)plugin).getProxy().getCommandManager().executeAsync(RedisBungeeCommandSource.getSingleton(), message);
} }
} }

View File

@ -6,9 +6,9 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.io.ByteStreams;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.imaginarycode.minecraft.redisbungee.commands.RedisBungeeCommands;
import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent;
import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent; import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent; import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
@ -29,6 +29,7 @@ import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer; 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.LegacyChannelIdentifier;
import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier;
import com.velocitypowered.api.scheduler.ScheduledTask; import com.velocitypowered.api.scheduler.ScheduledTask;
@ -48,6 +49,7 @@ import java.io.*;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -56,7 +58,7 @@ import java.util.concurrent.atomic.AtomicInteger;
public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> { public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
private final ProxyServer server; private final ProxyServer server;
private final Logger logger; private final Logger logger;
private final File dataFolder; private final Path dataFolder;
private final RedisBungeeAPI api; private final RedisBungeeAPI api;
private final PubSubListener psl; private final PubSubListener psl;
private JedisSummoner jedisSummoner; private JedisSummoner jedisSummoner;
@ -73,6 +75,10 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
private LuaManager.Script getPlayerCountScript; private LuaManager.Script getPlayerCountScript;
private static final Object SERVER_TO_PLAYERS_KEY = new Object(); private static final Object SERVER_TO_PLAYERS_KEY = new Object();
public static final List<ChannelIdentifier> IDENTIFIERS = List.of(
MinecraftChannelIdentifier.create("legacy", "redisbungee"),
new LegacyChannelIdentifier("RedisBungee")
);
private final Cache<Object, Multimap<String, UUID>> serverToPlayersCache = CacheBuilder.newBuilder() private final Cache<Object, Multimap<String, UUID>> serverToPlayersCache = CacheBuilder.newBuilder()
.expireAfterWrite(5, TimeUnit.SECONDS) .expireAfterWrite(5, TimeUnit.SECONDS)
.build(); .build();
@ -82,7 +88,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
public RedisBungeeVelocityPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { public RedisBungeeVelocityPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
this.server = server; this.server = server;
this.logger = logger; this.logger = logger;
this.dataFolder = dataDirectory.toFile(); this.dataFolder = dataDirectory;
try { try {
loadConfig(); loadConfig();
} catch (IOException e) { } catch (IOException e) {
@ -107,9 +113,9 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
for (String s : info.split("\r\n")) { for (String s : info.split("\r\n")) {
if (s.startsWith("redis_version:")) { if (s.startsWith("redis_version:")) {
String version = s.split(":")[1]; String version = s.split(":")[1];
getLogger().info(version + " <- redis version"); getLogger().info("{} <- redis version", version);
if (!RedisUtil.isRedisVersionRight(version)) { if (!RedisUtil.isRedisVersionRight(version)) {
getLogger().error("Your version of Redis (" + version + ") is not at least version 6.0 RedisBungee requires a newer version of Redis."); getLogger().error("Your version of Redis ({}) is not at least version 6.0 RedisBungee requires a newer version of Redis.", version);
throw new RuntimeException("Unsupported Redis version detected"); throw new RuntimeException("Unsupported Redis version detected");
} else { } else {
LuaManager manager = new LuaManager(this); LuaManager manager = new LuaManager(this);
@ -272,7 +278,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
if (lagged ? time >= stamp + 30 : time <= stamp + 30) if (lagged ? time >= stamp + 30 : time <= stamp + 30)
servers.add(entry.getKey()); servers.add(entry.getKey());
else if (nag && nagTime <= 0) { else if (nag && nagTime <= 0) {
getLogger().warn(entry.getKey() + " is " + (time - stamp) + " seconds behind! (Time not synchronized or server down?) and was removed from heartbeat."); getLogger().warn("{} is {} seconds behind! (Time not synchronized or server down?) and was removed from heartbeat.", entry.getKey(), (time - stamp));
jedis.hdel("heartbeats", entry.getKey()); jedis.hdel("heartbeats", entry.getKey());
} }
} catch (NumberFormatException ignored) { } catch (NumberFormatException ignored) {
@ -308,12 +314,12 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
@Override @Override
public void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time) { public void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time) {
this.getProxy().getScheduler().buildTask(this, runnable).delay(time, timeUnit); this.getProxy().getScheduler().buildTask(this, runnable).delay(time, timeUnit).schedule();
} }
@Override @Override
public void callEvent(Object event) { public void callEvent(Object event) {
this.getProxy().getEventManager().fire(event); this.getProxy().getEventManager().fireAndForget(event);
} }
@Override @Override
@ -425,7 +431,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
Set<String> laggedPlayers = tmpRsc.smembers("proxy:" + s + ":usersOnline"); Set<String> laggedPlayers = tmpRsc.smembers("proxy:" + s + ":usersOnline");
tmpRsc.del("proxy:" + s + ":usersOnline"); tmpRsc.del("proxy:" + s + ":usersOnline");
if (!laggedPlayers.isEmpty()) { if (!laggedPlayers.isEmpty()) {
getLogger().info("Cleaning up lagged proxy " + s + " (" + laggedPlayers.size() + " players)..."); getLogger().info("Cleaning up lagged proxy {} ({} players)...", s, laggedPlayers.size());
for (String laggedPlayer : laggedPlayers) { for (String laggedPlayer : laggedPlayers) {
RedisUtil.cleanUpPlayer(laggedPlayer, tmpRsc); RedisUtil.cleanUpPlayer(laggedPlayer, tmpRsc);
} }
@ -449,10 +455,10 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
} }
if (!found) { if (!found) {
RedisUtil.cleanUpPlayer(member, tmpRsc); RedisUtil.cleanUpPlayer(member, tmpRsc);
getLogger().warn("Player found in set that was not found locally and globally: " + member); getLogger().warn("Player found in set that was not found locally and globally: {}", member);
} else { } else {
tmpRsc.srem("proxy:" + configuration.getServerId() + ":usersOnline", member); tmpRsc.srem("proxy:" + configuration.getServerId() + ":usersOnline", member);
getLogger().warn("Player found in set that was not found locally, but is on another proxy: " + member); getLogger().warn("Player found in set that was not found locally, but is on another proxy: {}", member);
} }
} }
@ -460,7 +466,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
for (String player : absentInRedis) { for (String player : absentInRedis) {
// Player not online according to Redis but not BungeeCord. // Player not online according to Redis but not BungeeCord.
getLogger().warn("Player " + player + " is on the proxy but not in Redis."); getLogger().warn("Player {} is on the proxy but not in Redis.", player);
Player playerProxied = getProxy().getPlayer(UUID.fromString(player)).orElse(null); Player playerProxied = getProxy().getPlayer(UUID.fromString(player)).orElse(null);
if (playerProxied == null) if (playerProxied == null)
@ -475,24 +481,23 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
} }
}).repeat(1, TimeUnit.MINUTES).schedule(); }).repeat(1, TimeUnit.MINUTES).schedule();
// register plugin messages
IDENTIFIERS.forEach(getProxy().getChannelRegistrar()::register);
getProxy().getChannelRegistrar().register(new LegacyChannelIdentifier("RedisBungee"));
getProxy().getChannelRegistrar().register(new LegacyChannelIdentifier("legacy:redisbungee"));
getProxy().getChannelRegistrar().register(MinecraftChannelIdentifier.create("legacy", "redisbungee"));
// register commands // register commands
// those still bungeecord commands will migrate them later. // Override Velocity commands
// if (configuration.doOverrideBungeeCommands()) { if (configuration.doOverrideBungeeCommands()) {
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.GlistCommand(this)); getProxy().getCommandManager().register("glist", new RedisBungeeCommands.GlistCommand(this), "redisbungee", "rglist");
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.FindCommand(this)); }
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.LastSeenCommand(this));
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.IpCommand(this)); getProxy().getCommandManager().register("sendtoall", new RedisBungeeCommands.SendToAll(this), "rsendtoall");
// getProxy().getCommandManager().register("serverid", new RedisBungeeCommands.ServerId(this), "rserverid");
// } getProxy().getCommandManager().register("serverids", new RedisBungeeCommands.ServerIds(this));
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.SendToAll(this)); getProxy().getCommandManager().register("pproxy", new RedisBungeeCommands.PlayerProxyCommand(this));
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.ServerId(this)); getProxy().getCommandManager().register("plist", new RedisBungeeCommands.PlistCommand(this), "rplist");
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.ServerIds(this)); getProxy().getCommandManager().register("lastseen", new RedisBungeeCommands.LastSeenCommand(this), "rlastseen");
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.PlayerProxyCommand(this)); getProxy().getCommandManager().register("ip", new RedisBungeeCommands.IpCommand(this), "playerip", "rip", "rplayerip");
// getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.PlistCommand(this)); getProxy().getCommandManager().register("find", new RedisBungeeCommands.FindCommand(this), "rfind");
} }
@Override @Override
@ -526,18 +531,26 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
@Override @Override
public void loadConfig() throws IOException { public void loadConfig() throws IOException {
if (!getDataFolder().exists() && getDataFolder().mkdir()) { if (Files.notExists(getDataFolder())) {
getLogger().info("data folder was created"); try {
Files.createDirectory(getDataFolder());
getLogger().info("data folder was created");
} catch (IOException e) {
getLogger().error("Cannot create data folder", e);
}
} }
File file = new File(getDataFolder(), "config.yml"); Path file = getDataFolder().resolve("config.yml");
if (!file.exists() && file.createNewFile()) { if (Files.notExists(file)) {
getLogger().info("config file was created"); try (InputStream in = getResourceAsStream("example_config.yml")) {
try (InputStream in = getResourceAsStream("example_config.yml"); Files.createFile(file);
OutputStream out = Files.newOutputStream(file.toPath())) { Files.copy(in, file, StandardCopyOption.REPLACE_EXISTING);
ByteStreams.copy(in, out); getLogger().info("config file was created");
} catch (IOException e) {
getLogger().error("Cannot create configuration", e);
} }
} }
final YAMLConfigurationLoader yamlConfiguration = YAMLConfigurationLoader.builder().setFile(file).build(); final YAMLConfigurationLoader yamlConfiguration = YAMLConfigurationLoader.builder().setPath(file).build();
ConfigurationNode node = yamlConfiguration.load(); ConfigurationNode node = yamlConfiguration.load();
final String redisServer = node.getNode("redis-server").getString(); final String redisServer = node.getNode("redis-server").getString();
final int redisPort = node.getNode("redis-port").getInt(); final int redisPort = node.getNode("redis-port").getInt();
@ -560,12 +573,12 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
* I think due snake yaml limitations so as todo: write our own yaml parser? * I think due snake yaml limitations so as todo: write our own yaml parser?
*/ */
String genId = UUID.randomUUID().toString(); String genId = UUID.randomUUID().toString();
getLogger().info("Generated server id " + genId + " and saving it to config."); getLogger().info("Generated server id {} and saving it to config.", genId);
node.getNode("server-id").setValue(genId); node.getNode("server-id").setValue(genId);
yamlConfiguration.save(node); yamlConfiguration.save(node);
getLogger().info("Server id was generated: " + serverId); getLogger().info("Server id was generated: {}", serverId);
} else { } else {
getLogger().info("Loaded server id " + serverId + '.'); getLogger().info("Loaded server id {}.", serverId);
} }
try { try {
this.configuration = new RedisBungeeConfiguration(serverId, node.getNode("exempt-ip-addresses").getList(TypeToken.of(String.class)), node.getNode("register-bungee-commands").getBoolean()); this.configuration = new RedisBungeeConfiguration(serverId, node.getNode("exempt-ip-addresses").getList(TypeToken.of(String.class)), node.getNode("register-bungee-commands").getBoolean());
@ -587,9 +600,15 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
try (Jedis rsc = requestJedis()) { try (Jedis rsc = requestJedis()) {
rsc.ping(); rsc.ping();
// If that worked, now we can check for an existing, alive Bungee: // If that worked, now we can check for an existing, alive Bungee:
File crashFile = new File(getDataFolder(), "restarted_from_crash.txt"); Path crashFile = getDataFolder().resolve("restarted_from_crash.txt");
if (crashFile.exists() && crashFile.delete()) { if (Files.exists(crashFile)) {
getLogger().info("crash file was deleted"); try {
Files.delete(crashFile);
getLogger().info("crash file was deleted");
} catch (IOException e) {
getLogger().error("Cannot delete crash file", e);
}
} else if (rsc.hexists("heartbeats", serverId)) { } else if (rsc.hexists("heartbeats", serverId)) {
try { try {
long value = Long.parseLong(rsc.hget("heartbeats", serverId)); long value = Long.parseLong(rsc.hget("heartbeats", serverId));
@ -653,7 +672,7 @@ public class RedisBungeeVelocityPlugin implements RedisBungeePlugin<Player> {
return logger; return logger;
} }
public File getDataFolder() { public Path getDataFolder() {
return this.dataFolder; return this.dataFolder;
} }

View File

@ -1,6 +1,25 @@
package com.imaginarycode.minecraft.redisbungee.commands; package com.imaginarycode.minecraft.redisbungee.commands;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import com.google.common.base.Joiner;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI; import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
import com.imaginarycode.minecraft.redisbungee.RedisBungeeVelocityPlugin;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.proxy.server.ServerInfo;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.NamedTextColor;
/** /**
@ -12,316 +31,318 @@ import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
* @since 0.2.3 * @since 0.2.3
*/ */
public class RedisBungeeCommands { public class RedisBungeeCommands {
/*
private static final BaseComponent[] NO_PLAYER_SPECIFIED = private static final Component NO_PLAYER_SPECIFIED =
new ComponentBuilder("You must specify a player name.").color(ChatColor.RED).create(); Component.text("You must specify a player name.", NamedTextColor.RED);
private static final BaseComponent[] PLAYER_NOT_FOUND = private static final Component PLAYER_NOT_FOUND =
new ComponentBuilder("No such player found.").color(ChatColor.RED).create(); Component.text("No such player found.", NamedTextColor.RED);
private static final BaseComponent[] NO_COMMAND_SPECIFIED = private static final Component NO_COMMAND_SPECIFIED =
new ComponentBuilder("You must specify a command to be run.").color(ChatColor.RED).create(); Component.text("You must specify a command to be run.", NamedTextColor.RED);
private static String playerPlural(int num) { private static String playerPlural(int num) {
return num == 1 ? num + " player is" : num + " players are"; return num == 1 ? num + " player is" : num + " players are";
} }
public static class GlistCommand extends Command { public static class GlistCommand implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public GlistCommand(RedisBungeeVelocityPlugin plugin) { public GlistCommand(RedisBungeeVelocityPlugin plugin) {
super("glist", "bungeecord.command.list", "redisbungee", "rglist");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public void execute(final CommandSender sender, final String[] args) { public void execute(final Invocation invocation) {
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() { plugin.getProxy().getScheduler().buildTask(plugin, () -> {
@Override int count = plugin.getApi().getPlayerCount();
public void run() { Component playersOnline = Component.text(playerPlural(count) + " currently online.", NamedTextColor.YELLOW);
int count = plugin.getApi().getPlayerCount(); CommandSource sender = invocation.source();
BaseComponent[] playersOnline = new ComponentBuilder("").color(ChatColor.YELLOW) if (invocation.arguments().length > 0 && invocation.arguments()[0].equals("showall")) {
.append(playerPlural(count) + " currently online.").create(); Multimap<String, UUID> serverToPlayers = plugin.getApi().getServerToPlayers();
if (args.length > 0 && args[0].equals("showall")) { Multimap<String, String> human = HashMultimap.create();
Multimap<String, UUID> serverToPlayers = plugin.getApi().getServerToPlayers(); serverToPlayers.forEach((key, value) -> human.put(key, plugin.getUuidTranslator().getNameFromUuid(value, false)));
Multimap<String, String> human = HashMultimap.create(); for (String server : new TreeSet<>(serverToPlayers.keySet())) {
for (Map.Entry<String, UUID> entry : serverToPlayers.entries()) { Component serverName = Component.text("[" + server + "] ", NamedTextColor.GREEN);
human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false)); Component serverCount = Component.text("(" + serverToPlayers.get(server).size() + "): ", NamedTextColor.YELLOW);
} Component serverPlayers = Component.text(Joiner.on(", ").join(human.get(server)), NamedTextColor.WHITE);
for (String server : new TreeSet<>(serverToPlayers.keySet())) { sender.sendMessage(Component.textOfChildren(serverName, serverCount, serverPlayers));
TextComponent serverName = new TextComponent();
serverName.setColor(ChatColor.GREEN);
serverName.setText("[" + server + "] ");
TextComponent serverCount = new TextComponent();
serverCount.setColor(ChatColor.YELLOW);
serverCount.setText("(" + serverToPlayers.get(server).size() + "): ");
TextComponent serverPlayers = new TextComponent();
serverPlayers.setColor(ChatColor.WHITE);
serverPlayers.setText(Joiner.on(", ").join(human.get(server)));
sender.sendMessage(serverName, serverCount, serverPlayers);
}
sender.sendMessage(playersOnline);
} else {
sender.sendMessage(playersOnline);
sender.sendMessage(new ComponentBuilder("To see all players online, use /glist showall.").color(ChatColor.YELLOW).create());
} }
sender.sendMessage(playersOnline);
} else {
sender.sendMessage(playersOnline);
sender.sendMessage(Component.text("To see all players online, use /glist showall.", NamedTextColor.YELLOW));
} }
}); }).schedule();
}
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("velocity.command.server");
} }
} }
public static class FindCommand extends Command { public static class FindCommand implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public FindCommand(RedisBungeeVelocityPlugin plugin) { public FindCommand(RedisBungeeVelocityPlugin plugin) {
super("find", "bungeecord.command.find", "rfind");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public void execute(final CommandSender sender, final String[] args) { public void execute(final Invocation invocation) {
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() { plugin.getProxy().getScheduler().buildTask(plugin, () -> {
@Override String[] args = invocation.arguments();
public void run() { CommandSource sender = invocation.source();
if (args.length > 0) { if (args.length > 0) {
UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
if (uuid == null) { if (uuid == null) {
sender.sendMessage(PLAYER_NOT_FOUND); sender.sendMessage(PLAYER_NOT_FOUND);
return; return;
}
ServerInfo si = plugin.getProxy().getServerInfo(plugin.getApi().getServerFor(uuid));
if (si != null) {
TextComponent message = new TextComponent();
message.setColor(ChatColor.BLUE);
message.setText(args[0] + " is on " + si.getName() + ".");
sender.sendMessage(message);
} else {
sender.sendMessage(PLAYER_NOT_FOUND);
}
} else {
sender.sendMessage(NO_PLAYER_SPECIFIED);
} }
ServerInfo si = plugin.getProxy().getServer(plugin.getApi().getServerFor(uuid)).map(RegisteredServer::getServerInfo).orElse(null);
if (si != null) {
Component message = Component.text(args[0] + " is on " + si.getName() + ".", NamedTextColor.BLUE);
sender.sendMessage(message);
} else {
sender.sendMessage(PLAYER_NOT_FOUND);
}
} else {
sender.sendMessage(NO_PLAYER_SPECIFIED);
} }
}); }).schedule();
}
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("redisbungee.command.find");
} }
} }
public static class LastSeenCommand extends Command { public static class LastSeenCommand implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public LastSeenCommand(RedisBungeeVelocityPlugin plugin) { public LastSeenCommand(RedisBungeeVelocityPlugin plugin) {
super("lastseen", "redisbungee.command.lastseen", "rlastseen");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public void execute(final CommandSender sender, final String[] args) { public void execute(final Invocation invocation) {
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() { plugin.getProxy().getScheduler().buildTask(plugin, () -> {
@Override String[] args = invocation.arguments();
public void run() { CommandSource sender = invocation.source();
if (args.length > 0) { if (args.length > 0) {
UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
if (uuid == null) { if (uuid == null) {
sender.sendMessage(PLAYER_NOT_FOUND); sender.sendMessage(PLAYER_NOT_FOUND);
return; return;
}
long secs = plugin.getApi().getLastOnline(uuid);
TextComponent message = new TextComponent();
if (secs == 0) {
message.setColor(ChatColor.GREEN);
message.setText(args[0] + " is currently online.");
} else if (secs != -1) {
message.setColor(ChatColor.BLUE);
message.setText(args[0] + " was last online on " + new SimpleDateFormat().format(secs) + ".");
} else {
message.setColor(ChatColor.RED);
message.setText(args[0] + " has never been online.");
}
sender.sendMessage(message);
} else {
sender.sendMessage(NO_PLAYER_SPECIFIED);
} }
long secs = plugin.getApi().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.");
}
sender.sendMessage(message.build());
} else {
sender.sendMessage(NO_PLAYER_SPECIFIED);
} }
}); }).schedule();
}
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("redisbungee.command.lastseen");
} }
} }
public static class IpCommand extends Command { public static class IpCommand implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public IpCommand(RedisBungeeVelocityPlugin plugin) { public IpCommand(RedisBungeeVelocityPlugin plugin) {
super("ip", "redisbungee.command.ip", "playerip", "rip", "rplayerip");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public void execute(final CommandSender sender, final String[] args) { public void execute(final Invocation invocation) {
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() { CommandSource sender = invocation.source();
@Override String[] args = invocation.arguments();
public void run() { plugin.getProxy().getScheduler().buildTask(plugin, () -> {
if (args.length > 0) { if (args.length > 0) {
UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
if (uuid == null) { if (uuid == null) {
sender.sendMessage(PLAYER_NOT_FOUND); sender.sendMessage(PLAYER_NOT_FOUND);
return; return;
}
InetAddress ia = plugin.getApi().getPlayerIp(uuid);
if (ia != null) {
TextComponent message = new TextComponent();
message.setColor(ChatColor.GREEN);
message.setText(args[0] + " is connected from " + ia.toString() + ".");
sender.sendMessage(message);
} else {
sender.sendMessage(PLAYER_NOT_FOUND);
}
} else {
sender.sendMessage(NO_PLAYER_SPECIFIED);
} }
InetAddress ia = plugin.getApi().getPlayerIp(uuid);
if (ia != null) {
TextComponent message = Component.text(args[0] + " is connected from " + ia.toString() + ".", NamedTextColor.GREEN);
sender.sendMessage(message);
} else {
sender.sendMessage(PLAYER_NOT_FOUND);
}
} else {
sender.sendMessage(NO_PLAYER_SPECIFIED);
} }
}); }).schedule();
}
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("redisbungee.command.ip");
} }
} }
public static class PlayerProxyCommand extends Command { public static class PlayerProxyCommand implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public PlayerProxyCommand(RedisBungeeVelocityPlugin plugin) { public PlayerProxyCommand(RedisBungeeVelocityPlugin plugin) {
super("pproxy", "redisbungee.command.pproxy");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public void execute(final CommandSender sender, final String[] args) { public void execute(final Invocation invocation) {
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() { CommandSource sender = invocation.source();
@Override String[] args = invocation.arguments();
public void run() { plugin.getProxy().getScheduler().buildTask(plugin, () -> {
if (args.length > 0) { if (args.length > 0) {
UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true); UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
if (uuid == null) { if (uuid == null) {
sender.sendMessage(PLAYER_NOT_FOUND); sender.sendMessage(PLAYER_NOT_FOUND);
return; return;
}
String proxy = plugin.getApi().getProxy(uuid);
if (proxy != null) {
TextComponent message = new TextComponent();
message.setColor(ChatColor.GREEN);
message.setText(args[0] + " is connected to " + proxy + ".");
sender.sendMessage(message);
} else {
sender.sendMessage(PLAYER_NOT_FOUND);
}
} else {
sender.sendMessage(NO_PLAYER_SPECIFIED);
} }
String proxy = plugin.getApi().getProxy(uuid);
if (proxy != null) {
TextComponent message = Component.text(args[0] + " is connected to " + proxy + ".", NamedTextColor.GREEN);
sender.sendMessage(message);
} else {
sender.sendMessage(PLAYER_NOT_FOUND);
}
} else {
sender.sendMessage(NO_PLAYER_SPECIFIED);
} }
}); }).schedule();
}
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("redisbungee.command.pproxy");
} }
} }
public static class SendToAll extends Command { public static class SendToAll implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public SendToAll(RedisBungeeVelocityPlugin plugin) { public SendToAll(RedisBungeeVelocityPlugin plugin) {
super("sendtoall", "redisbungee.command.sendtoall", "rsendtoall"); //super("sendtoall", "redisbungee.command.sendtoall", "rsendtoall");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public void execute(CommandSender sender, String[] args) { public void execute(final Invocation invocation) {
String[] args = invocation.arguments();
CommandSource sender = invocation.source();
if (args.length > 0) { if (args.length > 0) {
String command = Joiner.on(" ").skipNulls().join(args); String command = Joiner.on(" ").skipNulls().join(args);
plugin.getApi().sendProxyCommand(command); plugin.getApi().sendProxyCommand(command);
TextComponent message = new TextComponent(); TextComponent message = Component.text("Sent the command /" + command + " to all proxies.", NamedTextColor.GREEN);
message.setColor(ChatColor.GREEN);
message.setText("Sent the command /" + command + " to all proxies.");
sender.sendMessage(message); sender.sendMessage(message);
} else { } else {
sender.sendMessage(NO_COMMAND_SPECIFIED); sender.sendMessage(NO_COMMAND_SPECIFIED);
} }
} }
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("redisbungee.command.sendtoall");
}
} }
public static class ServerId extends Command { public static class ServerId implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public ServerId(RedisBungeeVelocityPlugin plugin) { public ServerId(RedisBungeeVelocityPlugin plugin) {
super("serverid", "redisbungee.command.serverid", "rserverid");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public void execute(CommandSender sender, String[] args) { public void execute(Invocation invocation) {
TextComponent textComponent = new TextComponent(); invocation.source().sendMessage(Component.text("You are on " + plugin.getApi().getServerId() + ".", NamedTextColor.YELLOW));
textComponent.setText("You are on " + plugin.getApi().getServerId() + "."); }
textComponent.setColor(ChatColor.YELLOW);
sender.sendMessage(textComponent); @Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("redisbungee.command.serverid");
} }
} }
public static class ServerIds extends Command { public static class ServerIds implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public ServerIds(RedisBungeeVelocityPlugin plugin) { public ServerIds(RedisBungeeVelocityPlugin plugin) {
super("serverids", "redisbungee.command.serverids");
this.plugin =plugin; this.plugin =plugin;
} }
@Override @Override
public void execute(CommandSender sender, String[] strings) { public void execute(Invocation invocation) {
TextComponent textComponent = new TextComponent(); invocation.source().sendMessage(
textComponent.setText("All server IDs: " + Joiner.on(", ").join(plugin.getApi().getAllServers())); Component.text("All server IDs: " + Joiner.on(", ").join(plugin.getApi().getAllServers()), NamedTextColor.YELLOW));
textComponent.setColor(ChatColor.YELLOW); }
sender.sendMessage(textComponent);
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("redisbungee.command.serverids");
} }
} }
public static class PlistCommand extends Command { public static class PlistCommand implements SimpleCommand {
private final RedisBungeeVelocityPlugin plugin; private final RedisBungeeVelocityPlugin plugin;
public PlistCommand(RedisBungeeVelocityPlugin plugin) { public PlistCommand(RedisBungeeVelocityPlugin plugin) {
super("plist", "redisbungee.command.plist", "rplist");
this.plugin = plugin; this.plugin = plugin;
} }
@Override @Override
public void execute(final CommandSender sender, final String[] args) { public void execute(Invocation invocation) {
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() { CommandSource sender= invocation.source();
@Override String[] args = invocation.arguments();
public void run() { plugin.getProxy().getScheduler().buildTask(plugin, () -> {
String proxy = args.length >= 1 ? args[0] : plugin.getConfiguration().getServerId(); String proxy = args.length >= 1 ? args[0] : plugin.getConfiguration().getServerId();
if (!plugin.getServerIds().contains(proxy)) { if (!plugin.getServerIds().contains(proxy)) {
sender.sendMessage(new ComponentBuilder(proxy + " is not a valid proxy. See /serverids for valid proxies.").color(ChatColor.RED).create()); sender.sendMessage(Component.text(proxy + " is not a valid proxy. See /serverids for valid proxies.", NamedTextColor.RED));
return; return;
}
Set<UUID> players = plugin.getApi().getPlayersOnProxy(proxy);
BaseComponent[] playersOnline = new ComponentBuilder("").color(ChatColor.YELLOW)
.append(playerPlural(players.size()) + " currently on proxy " + proxy + ".").create();
if (args.length >= 2 && args[1].equals("showall")) {
Multimap<String, UUID> serverToPlayers = plugin.getApi().getServerToPlayers();
Multimap<String, String> human = HashMultimap.create();
for (Map.Entry<String, UUID> entry : serverToPlayers.entries()) {
if (players.contains(entry.getValue())) {
human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false));
}
}
for (String server : new TreeSet<>(human.keySet())) {
TextComponent serverName = new TextComponent();
serverName.setColor(ChatColor.RED);
serverName.setText("[" + server + "] ");
TextComponent serverCount = new TextComponent();
serverCount.setColor(ChatColor.YELLOW);
serverCount.setText("(" + human.get(server).size() + "): ");
TextComponent serverPlayers = new TextComponent();
serverPlayers.setColor(ChatColor.WHITE);
serverPlayers.setText(Joiner.on(", ").join(human.get(server)));
sender.sendMessage(serverName, serverCount, serverPlayers);
}
sender.sendMessage(playersOnline);
} else {
sender.sendMessage(playersOnline);
sender.sendMessage(new ComponentBuilder("To see all players online, use /plist " + proxy + " showall.").color(ChatColor.YELLOW).create());
}
} }
}); Set<UUID> players = plugin.getApi().getPlayersOnProxy(proxy);
Component playersOnline = Component.text(playerPlural(players.size()) + " currently on proxy " + proxy + ".", NamedTextColor.YELLOW);
if (args.length >= 2 && args[1].equals("showall")) {
Multimap<String, UUID> serverToPlayers = plugin.getApi().getServerToPlayers();
Multimap<String, String> 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);
sender.sendMessage(Component.textOfChildren(serverName, serverCount, serverPlayers));
}
sender.sendMessage(playersOnline);
} else {
sender.sendMessage(playersOnline);
sender.sendMessage(Component.text("To see all players online, use /plist " + proxy + " showall.", NamedTextColor.YELLOW));
}
}).schedule();
}
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("redisbungee.command.plist");
} }
} }
*/
} }