2022-04-13 13:14:08 +00:00
|
|
|
package com.imaginarycode.minecraft.redisbungee;
|
|
|
|
|
2022-04-13 16:22:07 +00:00
|
|
|
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;
|
2022-07-17 03:41:18 +00:00
|
|
|
import com.imaginarycode.minecraft.redisbungee.api.AbstractRedisBungeeListener;
|
2022-07-26 08:49:44 +00:00
|
|
|
import com.imaginarycode.minecraft.redisbungee.api.util.player.PlayerUtils;
|
2022-07-17 03:41:18 +00:00
|
|
|
import com.imaginarycode.minecraft.redisbungee.api.RedisBungeePlugin;
|
|
|
|
import com.imaginarycode.minecraft.redisbungee.api.tasks.RedisTask;
|
2022-07-19 11:30:45 +00:00
|
|
|
import com.imaginarycode.minecraft.redisbungee.api.util.payload.PayloadUtils;
|
2022-04-14 11:59:02 +00:00
|
|
|
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
2022-04-13 16:22:07 +00:00
|
|
|
import net.md_5.bungee.api.AbstractReconnectHandler;
|
|
|
|
import net.md_5.bungee.api.config.ServerInfo;
|
2022-04-13 13:14:08 +00:00
|
|
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
2022-04-13 16:22:07 +00:00
|
|
|
import net.md_5.bungee.api.connection.Server;
|
2022-04-13 13:14:08 +00:00
|
|
|
import net.md_5.bungee.api.event.*;
|
|
|
|
import net.md_5.bungee.api.plugin.Listener;
|
|
|
|
import net.md_5.bungee.api.plugin.Plugin;
|
|
|
|
import net.md_5.bungee.event.EventHandler;
|
2022-07-26 13:47:18 +00:00
|
|
|
import redis.clients.jedis.UnifiedJedis;
|
2022-04-13 13:14:08 +00:00
|
|
|
|
|
|
|
import java.net.InetAddress;
|
2022-04-13 16:22:07 +00:00
|
|
|
import java.util.*;
|
2022-04-13 13:14:08 +00:00
|
|
|
|
2022-07-30 18:36:29 +00:00
|
|
|
import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.Serializations.serializeMultimap;
|
|
|
|
import static com.imaginarycode.minecraft.redisbungee.api.util.serialize.Serializations.serializeMultiset;
|
2022-09-14 04:09:43 +00:00
|
|
|
import static net.md_5.bungee.event.EventPriority.HIGHEST;
|
2022-07-30 18:36:29 +00:00
|
|
|
|
2022-07-14 23:05:53 +00:00
|
|
|
public class RedisBungeeBungeeListener extends AbstractRedisBungeeListener<LoginEvent, PostLoginEvent, PlayerDisconnectEvent, ServerConnectedEvent, ProxyPingEvent, PluginMessageEvent, PubSubMessageEvent> implements Listener {
|
2022-04-13 13:14:08 +00:00
|
|
|
|
|
|
|
|
2022-07-14 23:05:53 +00:00
|
|
|
public RedisBungeeBungeeListener(RedisBungeePlugin<?> plugin, List<InetAddress> exemptAddresses) {
|
2022-04-13 13:14:08 +00:00
|
|
|
super(plugin, exemptAddresses);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-09-14 04:09:43 +00:00
|
|
|
@EventHandler (priority = HIGHEST)
|
2022-04-13 13:14:08 +00:00
|
|
|
public void onLogin(LoginEvent event) {
|
|
|
|
event.registerIntent((Plugin) plugin);
|
2022-07-17 03:41:18 +00:00
|
|
|
plugin.executeAsync(new RedisTask<Void>(plugin) {
|
2022-04-13 13:14:08 +00:00
|
|
|
@Override
|
2022-07-26 13:47:18 +00:00
|
|
|
public Void unifiedJedisTask(UnifiedJedis unifiedJedis) {
|
2022-04-13 13:14:08 +00:00
|
|
|
try {
|
|
|
|
if (event.isCancelled()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We make sure they aren't trying to use an existing player's name.
|
|
|
|
// This is problematic for online-mode servers as they always disconnect old clients.
|
|
|
|
if (plugin.isOnlineMode()) {
|
|
|
|
ProxiedPlayer player = (ProxiedPlayer) plugin.getPlayer(event.getConnection().getName());
|
|
|
|
|
|
|
|
if (player != null) {
|
|
|
|
event.setCancelled(true);
|
|
|
|
// TODO: Make it accept a BaseComponent[] like everything else.
|
|
|
|
event.setCancelReason(ONLINE_MODE_RECONNECT);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-17 11:38:00 +00:00
|
|
|
for (String s : plugin.getProxiesIds()) {
|
2022-07-26 13:47:18 +00:00
|
|
|
if (unifiedJedis.sismember("proxy:" + s + ":usersOnline", event.getConnection().getUniqueId().toString())) {
|
2022-07-17 03:41:18 +00:00
|
|
|
event.setCancelled(true);
|
|
|
|
// TODO: Make it accept a BaseComponent[] like everything else.
|
|
|
|
event.setCancelReason(ALREADY_LOGGED_IN);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
} finally {
|
|
|
|
event.completeIntent((Plugin) plugin);
|
|
|
|
}
|
|
|
|
}
|
2022-04-13 13:14:08 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@EventHandler
|
|
|
|
public void onPostLogin(PostLoginEvent event) {
|
2022-07-17 03:41:18 +00:00
|
|
|
plugin.executeAsync(new RedisTask<Void>(plugin) {
|
2022-04-13 13:14:08 +00:00
|
|
|
@Override
|
2022-07-26 13:47:18 +00:00
|
|
|
public Void unifiedJedisTask(UnifiedJedis unifiedJedis) {
|
|
|
|
plugin.getUuidTranslator().persistInfo(event.getPlayer().getName(), event.getPlayer().getUniqueId(), unifiedJedis);
|
|
|
|
BungeePlayerUtils.createPlayer(event.getPlayer(), unifiedJedis, true);
|
2022-04-13 13:14:08 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@EventHandler
|
|
|
|
public void onPlayerDisconnect(PlayerDisconnectEvent event) {
|
2022-07-17 03:41:18 +00:00
|
|
|
plugin.executeAsync(new RedisTask<Void>(plugin) {
|
2022-04-13 13:14:08 +00:00
|
|
|
@Override
|
2022-07-26 13:47:18 +00:00
|
|
|
public Void unifiedJedisTask(UnifiedJedis unifiedJedis) {
|
|
|
|
PlayerUtils.cleanUpPlayer(event.getPlayer().getUniqueId().toString(), unifiedJedis, true);
|
2022-07-17 03:41:18 +00:00
|
|
|
return null;
|
|
|
|
}
|
2022-04-13 13:14:08 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@EventHandler
|
|
|
|
public void onServerChange(ServerConnectedEvent event) {
|
2022-07-20 09:25:26 +00:00
|
|
|
final String currentServer = event.getServer().getInfo().getName();
|
2022-07-20 08:32:04 +00:00
|
|
|
final String oldServer = event.getPlayer().getServer() == null ? null : event.getPlayer().getServer().getInfo().getName();
|
2022-07-17 03:41:18 +00:00
|
|
|
plugin.executeAsync(new RedisTask<Void>(plugin) {
|
2022-04-13 16:22:07 +00:00
|
|
|
@Override
|
2022-07-26 13:47:18 +00:00
|
|
|
public Void unifiedJedisTask(UnifiedJedis unifiedJedis) {
|
|
|
|
unifiedJedis.hset("player:" + event.getPlayer().getUniqueId().toString(), "server", event.getServer().getInfo().getName());
|
|
|
|
PayloadUtils.playerServerChangePayload(event.getPlayer().getUniqueId(), unifiedJedis, currentServer, oldServer);
|
2022-07-16 05:18:33 +00:00
|
|
|
return null;
|
|
|
|
}
|
2022-04-13 16:22:07 +00:00
|
|
|
});
|
2022-04-13 13:14:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@EventHandler
|
|
|
|
public void onPing(ProxyPingEvent event) {
|
2022-04-13 16:22:07 +00:00
|
|
|
if (exemptAddresses.contains(event.getConnection().getAddress().getAddress())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ServerInfo forced = AbstractReconnectHandler.getForcedHost(event.getConnection());
|
2022-04-13 13:14:08 +00:00
|
|
|
|
2022-04-13 16:22:07 +00:00
|
|
|
if (forced != null && event.getConnection().getListener().isPingPassthrough()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event.getResponse().getPlayers().setOnline(plugin.getCount());
|
2022-04-13 13:14:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2022-04-13 16:22:07 +00:00
|
|
|
@SuppressWarnings("UnstableApiUsage")
|
2022-04-13 13:14:08 +00:00
|
|
|
@EventHandler
|
|
|
|
public void onPluginMessage(PluginMessageEvent event) {
|
2022-07-14 21:43:22 +00:00
|
|
|
if ((event.getTag().equals("legacy:redisbungee") || event.getTag().equals("RedisBungee")) && event.getSender() instanceof Server) {
|
2022-04-13 16:22:07 +00:00
|
|
|
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;
|
2022-04-13 13:14:08 +00:00
|
|
|
|
2022-04-13 16:22:07 +00:00
|
|
|
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 {
|
2022-07-27 13:43:51 +00:00
|
|
|
original = plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type);
|
2022-04-13 16:22:07 +00:00
|
|
|
} 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 {
|
2022-07-27 13:43:51 +00:00
|
|
|
out.writeInt(plugin.getAbstractRedisBungeeApi().getPlayersOnServer(type).size());
|
2022-04-13 16:22:07 +00:00
|
|
|
} catch (IllegalArgumentException e) {
|
|
|
|
out.writeInt(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "LastOnline":
|
|
|
|
String user = in.readUTF();
|
|
|
|
out.writeUTF("LastOnline");
|
|
|
|
out.writeUTF(user);
|
2022-07-27 13:43:51 +00:00
|
|
|
out.writeLong(plugin.getAbstractRedisBungeeApi().getLastOnline(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(user, true))));
|
2022-04-13 16:22:07 +00:00
|
|
|
break;
|
|
|
|
case "ServerPlayers":
|
|
|
|
String type1 = in.readUTF();
|
|
|
|
out.writeUTF("ServerPlayers");
|
2022-07-27 13:43:51 +00:00
|
|
|
Multimap<String, UUID> multimap = plugin.getAbstractRedisBungeeApi().getServerToPlayers();
|
2022-04-13 16:22:07 +00:00
|
|
|
|
|
|
|
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");
|
2022-07-17 11:38:00 +00:00
|
|
|
out.writeUTF(plugin.getConfiguration().getProxyId());
|
2022-04-13 16:22:07 +00:00
|
|
|
break;
|
|
|
|
case "PlayerProxy":
|
|
|
|
String username = in.readUTF();
|
|
|
|
out.writeUTF("PlayerProxy");
|
|
|
|
out.writeUTF(username);
|
2022-07-27 13:43:51 +00:00
|
|
|
out.writeUTF(plugin.getAbstractRedisBungeeApi().getProxy(Objects.requireNonNull(plugin.getUuidTranslator().getTranslatedUuid(username, true))));
|
2022-04-13 16:22:07 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
((Server) event.getSender()).sendData(currentChannel, out.toByteArray());
|
|
|
|
});
|
|
|
|
}
|
2022-04-13 13:14:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@EventHandler
|
|
|
|
public void onPubSubMessage(PubSubMessageEvent event) {
|
2022-07-27 13:43:51 +00:00
|
|
|
if (event.getChannel().equals("redisbungee-allservers") || event.getChannel().equals("redisbungee-" + plugin.getAbstractRedisBungeeApi().getProxyId())) {
|
2022-04-13 13:14:08 +00:00
|
|
|
String message = event.getMessage();
|
|
|
|
if (message.startsWith("/"))
|
|
|
|
message = message.substring(1);
|
|
|
|
plugin.logInfo("Invoking command via PubSub: /" + message);
|
2022-06-29 14:11:19 +00:00
|
|
|
((Plugin) plugin).getProxy().getPluginManager().dispatchCommand(RedisBungeeCommandSender.getSingleton(), message);
|
2022-04-13 13:14:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|