From 443e3c2d444a6708c74e3bbe8a1a3cdd18df089b Mon Sep 17 00:00:00 2001 From: ME1312 Date: Wed, 19 Aug 2020 15:24:05 -0400 Subject: [PATCH] Favor new connections over the old ones This is a change to the rules that govern what happens when the same UUID connects to the same network more than once. It is now more BungeeCord like in nature. --- .../Packet/PacketDisconnectPlayer.java | 85 +++++++++++++++++++ .../Packet/PacketExDisconnectPlayer.java | 62 ++++++++++++++ .../Network/Packet/PacketExSyncPlayer.java | 50 ++++++----- .../Bungee/Network/SubProtocol.java | 6 +- .../ME1312/SubServers/Bungee/SubProxy.java | 38 ++++++--- .../net/ME1312/SubServers/Sync/ExProxy.java | 42 +++++---- .../Packet/PacketDisconnectPlayer.java | 62 ++++++++++++++ .../Packet/PacketExDisconnectPlayer.java | 73 ++++++++++++++++ .../Network/Packet/PacketExSyncPlayer.java | 34 +++++--- .../SubServers/Sync/Network/SubProtocol.java | 9 +- 10 files changed, 390 insertions(+), 71 deletions(-) create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketDisconnectPlayer.java create mode 100644 SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketExDisconnectPlayer.java create mode 100644 SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketDisconnectPlayer.java create mode 100644 SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketExDisconnectPlayer.java diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketDisconnectPlayer.java b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketDisconnectPlayer.java new file mode 100644 index 00000000..4af621b7 --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketDisconnectPlayer.java @@ -0,0 +1,85 @@ +package net.ME1312.SubServers.Bungee.Network.Packet; + +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.SubData.Server.Protocol.PacketObjectIn; +import net.ME1312.SubData.Server.Protocol.PacketObjectOut; +import net.ME1312.SubData.Server.SubDataClient; +import net.ME1312.SubServers.Bungee.Host.RemotePlayer; +import net.ME1312.SubServers.Bungee.Host.Server; +import net.ME1312.SubServers.Bungee.Host.SubServer; +import net.ME1312.SubServers.Bungee.SubProxy; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.Map; +import java.util.UUID; + +/** + * Disconnect Player Packet + */ +public class PacketDisconnectPlayer implements PacketObjectIn, PacketObjectOut { + private SubProxy plugin; + private int response; + private UUID tracker; + + /** + * New PacketDisconnectPlayer (In) + * + * @param plugin SubPlugin + */ + public PacketDisconnectPlayer(SubProxy plugin) { + if (Util.isNull(plugin)) throw new NullPointerException(); + this.plugin = plugin; + } + + /** + * New PacketDisconnectPlayer (Out) + * + * @param response Response ID + * @param tracker Receiver ID + */ + public PacketDisconnectPlayer(int response, UUID tracker) { + this.response = response; + this.tracker = tracker; + } + + @Override + public ObjectMap send(SubDataClient client) { + ObjectMap json = new ObjectMap(); + if (tracker != null) json.set(0x0000, tracker); + json.set(0x0001, response); + return json; + } + + @Override + public void receive(SubDataClient client, ObjectMap data) { + UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null); + try { + UUID id = data.getUUID(0x0001); + + ProxiedPlayer local; + RemotePlayer remote; + if ((local = plugin.getPlayer(id)) != null) { + if (data.contains(0x0002)) { + local.disconnect(data.getRawString(0x0002)); + } else { + local.disconnect(); + } + client.sendPacket(new PacketDisconnectPlayer(2, tracker)); + } else if ((remote = plugin.api.getGlobalPlayer(id)) != null) { + + client.sendPacket(new PacketDisconnectPlayer(2, tracker)); + } else { + client.sendPacket(new PacketDisconnectPlayer(3, tracker)); + } + } catch (Throwable e) { + client.sendPacket(new PacketDisconnectPlayer(2, tracker)); + e.printStackTrace(); + } + } + + @Override + public int version() { + return 0x0001; + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketExDisconnectPlayer.java b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketExDisconnectPlayer.java new file mode 100644 index 00000000..feff246f --- /dev/null +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketExDisconnectPlayer.java @@ -0,0 +1,62 @@ +package net.ME1312.SubServers.Bungee.Network.Packet; + +import net.ME1312.Galaxi.Library.Callback.Callback; +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.SubData.Server.Protocol.PacketObjectIn; +import net.ME1312.SubData.Server.Protocol.PacketObjectOut; +import net.ME1312.SubData.Server.SubDataClient; + +import java.util.HashMap; +import java.util.UUID; + +/** + * Disconnect External Player Packet + */ +public class PacketExDisconnectPlayer implements PacketObjectIn, PacketObjectOut { + private static HashMap>[]> callbacks = new HashMap>[]>(); + private UUID player; + private String reason; + private UUID id; + + /** + * New PacketExDisconnectPlayer (In) + */ + public PacketExDisconnectPlayer() {} + + /** + * New PacketExDisconnectPlayer (Out) + * + * @param player Player + * @param reason Reason + * @param callback Callbacks + */ + @SafeVarargs + public PacketExDisconnectPlayer(UUID player, String reason, Callback>... callback) { + if (Util.isNull(player, callback)) throw new NullPointerException(); + this.player = player; + this.reason = reason; + this.id = Util.getNew(callbacks.keySet(), UUID::randomUUID); + callbacks.put(id, callback); + } + + @Override + public ObjectMap send(SubDataClient client) { + ObjectMap data = new ObjectMap(); + data.set(0x0000, id); + data.set(0x0001, player); + if (reason != null) data.set(0x0002, reason); + return data; + } + + @Override + public void receive(SubDataClient client, ObjectMap data) { + for (Callback> callback : callbacks.get(data.getUUID(0x0000))) callback.run(data); + callbacks.remove(data.getUUID(0x0000)); + } + + @Override + public int version() { + return 0x0001; + } +} diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketExSyncPlayer.java b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketExSyncPlayer.java index 5566c320..a7b05926 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketExSyncPlayer.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/Packet/PacketExSyncPlayer.java @@ -71,30 +71,38 @@ public class PacketExSyncPlayer implements PacketObjectIn, PacketObject plugin.rPlayers.remove(id); } } - if (data.getBoolean(0x0001) != Boolean.FALSE) { - if (data.contains(0x0002)) for (Map object : (List>) data.getObjectList(0x0002)) { - Server server = (object.getOrDefault("server", null) != null)?plugin.api.getServer(object.get("server").toString()):null; - RemotePlayer player = new RemotePlayer(object.get("name").toString(), UUID.fromString(object.get("id").toString()), (Proxy) client.getHandler(), server, - new InetSocketAddress(object.get("address").toString().split(":")[0], Integer.parseInt(object.get("address").toString().split(":")[1]))); + synchronized (plugin.rPlayers) { + if (data.getBoolean(0x0001) != Boolean.FALSE) { + if (data.contains(0x0002)) for (Map object : (List>) data.getObjectList(0x0002)) { + Server server = (object.getOrDefault("server", null) != null)?plugin.api.getServer(object.get("server").toString()):null; + RemotePlayer player = new RemotePlayer(object.get("name").toString(), UUID.fromString(object.get("id").toString()), (Proxy) client.getHandler(), server, + new InetSocketAddress(object.get("address").toString().split(":")[0], Integer.parseInt(object.get("address").toString().split(":")[1]))); - forward.add(player); - plugin.rPlayers.put(player.getUniqueId(), player); - plugin.rPlayerLinkP.put(player.getUniqueId(), (Proxy) client.getHandler()); - if (server != null) plugin.rPlayerLinkS.put(player.getUniqueId(), server); - } - } else { - if (data.contains(0x0002)) for (Map object : (List>) data.getObjectList(0x0002)) { - UUID id = UUID.fromString(object.get("id").toString()); - RemotePlayer player = plugin.rPlayers.get(id); + forward.add(player); + plugin.rPlayerLinkP.put(player.getUniqueId(), (Proxy) client.getHandler()); + plugin.rPlayers.put(player.getUniqueId(), player); + if (server != null) plugin.rPlayerLinkS.put(player.getUniqueId(), server); + } + } else { + if (data.contains(0x0002)) for (Map object : (List>) data.getObjectList(0x0002)) { + UUID id = UUID.fromString(object.get("id").toString()); + RemotePlayer player = plugin.rPlayers.get(id); - if (player != null) forward.add(player); - plugin.rPlayerLinkS.remove(id); - plugin.rPlayerLinkP.remove(id); - plugin.rPlayers.remove(id); + // Don't accept removal requests from non-managing proxies + if (player == null || player.getProxy() == null || client.getHandler().equals(plugin.rPlayerLinkP.get(id))) { + if (player != null) forward.add(player); + plugin.rPlayerLinkS.remove(id); + plugin.rPlayerLinkP.remove(id); + plugin.rPlayers.remove(id); + } + } + } + + if (data.getBoolean(0x0001) == null || forward.size() > 0) { + for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null && proxy != client.getHandler()) { + ((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketExSyncPlayer(((Proxy) client.getHandler()).getName(), data.getBoolean(0x0001), forward.toArray(new RemotePlayer[0]))); + } } - } - for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null && proxy != client.getHandler()) { - ((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketExSyncPlayer(((Proxy) client.getHandler()).getName(), data.getBoolean(0x0001), forward.toArray(new RemotePlayer[0]))); } } } diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/SubProtocol.java b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/SubProtocol.java index cacdef83..80e7a63d 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/SubProtocol.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/Network/SubProtocol.java @@ -75,7 +75,7 @@ public class SubProtocol extends SubDataProtocol { registerPacket(0x0039, PacketDeleteServer.class); //registerPacket(0x003A, PacketRestoreServer.class); // TODO //registerPacket(0x003B, PacketTeleportPlayer.class); - //registerPacket(0x003C, PacketTeleportPlayerResponse.class); + registerPacket(0x003C, PacketDisconnectPlayer.class); registerPacket(0x0030, new PacketCreateServer(plugin)); registerPacket(0x0031, new PacketAddServer(plugin)); @@ -89,7 +89,7 @@ public class SubProtocol extends SubDataProtocol { registerPacket(0x0039, new PacketDeleteServer(plugin)); //registerPacket(0x003A, new PacketRestoreServer(plugin)); // TODO //registerPacket(0x003B, new PacketTeleportPlayer(plugin)); - //registerPacket(0x003C, new PacketTeleportPlayerResponse(plugin)); + registerPacket(0x003C, new PacketDisconnectPlayer(plugin)); // 50-6F: External Host Packets @@ -124,12 +124,14 @@ public class SubProtocol extends SubDataProtocol { registerPacket(0x0072, PacketOutExReload.class); registerPacket(0x0073, PacketOutExUpdateWhitelist.class); registerPacket(0x0074, PacketExSyncPlayer.class); + registerPacket(0x0076, PacketExDisconnectPlayer.class); //registerPacket(0x0070, new PacketOutRunEvent()); //registerPacket(0x0071, new PacketOutReset()); //registerPacket(0x0072, new PacketOutReload()); //registerPacket(0x0073, new PacketOutExUpdateWhitelist()); registerPacket(0x0074, new PacketExSyncPlayer(plugin)); + registerPacket(0x0076, new PacketExDisconnectPlayer()); } @SuppressWarnings("deprecation") diff --git a/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/SubProxy.java b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/SubProxy.java index da59ec8b..1555e128 100644 --- a/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/SubProxy.java +++ b/SubServers.Bungee/src/net/ME1312/SubServers/Bungee/SubProxy.java @@ -26,6 +26,7 @@ import net.ME1312.SubServers.Bungee.Library.Exception.InvalidHostException; import net.ME1312.SubServers.Bungee.Library.Exception.InvalidServerException; import net.ME1312.Galaxi.Library.Version.Version; import net.ME1312.SubServers.Bungee.Network.Packet.PacketExSyncPlayer; +import net.ME1312.SubServers.Bungee.Network.Packet.PacketExDisconnectPlayer; import net.ME1312.SubServers.Bungee.Network.Packet.PacketOutExReload; import net.ME1312.SubServers.Bungee.Network.SubProtocol; import net.md_5.bungee.BungeeCord; @@ -849,8 +850,13 @@ public final class SubProxy extends BungeeCord implements Listener { @EventHandler(priority = Byte.MIN_VALUE) public void login(LoginEvent e) { if (rPlayers.containsKey(e.getConnection().getUniqueId())) { - e.setCancelled(true); - e.setCancelReason(new TextComponent(getTranslation("already_connected_proxy"))); + Logger.get("SubServers").info(e.getConnection().getName() + " connected, but already had a database entry"); + RemotePlayer player = rPlayers.get(e.getConnection().getUniqueId()); + if (player.getProxy() == null || player.getProxy().isMaster()) { + getPlayer(player.getUniqueId()).disconnect(new TextComponent(getTranslation("already_connected_proxy"))); + } else { + ((SubDataClient) player.getProxy().getSubData()[0]).sendPacket(new PacketExDisconnectPlayer(player.getUniqueId(), getTranslation("already_connected_proxy"))); + } } } @@ -897,12 +903,14 @@ public final class SubProxy extends BungeeCord implements Listener { @SuppressWarnings("deprecation") @EventHandler(priority = Byte.MAX_VALUE) public void connected(ServerConnectedEvent e) { - RemotePlayer player = new RemotePlayer(e.getPlayer().getName(), e.getPlayer().getUniqueId(), mProxy, (e.getServer().getInfo() instanceof Server)?(Server) e.getServer().getInfo():null, e.getPlayer().getAddress()); - rPlayers.put(player.getUniqueId(), player); - rPlayerLinkP.put(player.getUniqueId(), player.getProxy()); - if (player.getServer() != null) rPlayerLinkS.put(player.getUniqueId(), player.getServer()); - for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) { - ((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketExSyncPlayer(mProxy.getName(), true, player)); + synchronized (rPlayers) { + RemotePlayer player = new RemotePlayer(e.getPlayer().getName(), e.getPlayer().getUniqueId(), mProxy, (e.getServer().getInfo() instanceof Server)?(Server) e.getServer().getInfo():null, e.getPlayer().getAddress()); + rPlayerLinkP.put(player.getUniqueId(), player.getProxy()); + rPlayers.put(player.getUniqueId(), player); + if (player.getServer() != null) rPlayerLinkS.put(player.getUniqueId(), player.getServer()); + for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) { + ((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketExSyncPlayer(mProxy.getName(), true, player)); + } } @@ -950,13 +958,15 @@ public final class SubProxy extends BungeeCord implements Listener { fallbackLimbo.remove(e.getPlayer().getUniqueId()); SubCommand.players.remove(e.getPlayer().getUniqueId()); - if (rPlayers.containsKey(e.getPlayer().getUniqueId())) { - for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) { - ((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketExSyncPlayer(mProxy.getName(), false, rPlayers.get(e.getPlayer().getUniqueId()))); + synchronized (rPlayers) { + if (rPlayers.containsKey(e.getPlayer().getUniqueId()) && (!rPlayerLinkP.containsKey(e.getPlayer().getUniqueId()) || rPlayerLinkP.get(e.getPlayer().getUniqueId()).isMaster())) { + for (Proxy proxy : SubAPI.getInstance().getProxies().values()) if (proxy.getSubData()[0] != null) { + ((SubDataClient) proxy.getSubData()[0]).sendPacket(new PacketExSyncPlayer(mProxy.getName(), false, rPlayers.get(e.getPlayer().getUniqueId()))); + } + rPlayerLinkS.remove(e.getPlayer().getUniqueId()); + rPlayerLinkP.remove(e.getPlayer().getUniqueId()); + rPlayers.remove(e.getPlayer().getUniqueId()); } - rPlayerLinkS.remove(e.getPlayer().getUniqueId()); - rPlayerLinkP.remove(e.getPlayer().getUniqueId()); - rPlayers.remove(e.getPlayer().getUniqueId()); } } diff --git a/SubServers.Sync/src/net/ME1312/SubServers/Sync/ExProxy.java b/SubServers.Sync/src/net/ME1312/SubServers/Sync/ExProxy.java index c19ac150..076010ae 100644 --- a/SubServers.Sync/src/net/ME1312/SubServers/Sync/ExProxy.java +++ b/SubServers.Sync/src/net/ME1312/SubServers/Sync/ExProxy.java @@ -23,6 +23,7 @@ import net.ME1312.Galaxi.Library.Version.Version; import net.ME1312.SubData.Client.SubDataClient; import net.ME1312.SubServers.Sync.Library.ConfigUpdater; import net.ME1312.SubServers.Sync.Network.API.RemotePlayer; +import net.ME1312.SubServers.Sync.Network.Packet.PacketDisconnectPlayer; import net.ME1312.SubServers.Sync.Network.Packet.PacketExSyncPlayer; import net.ME1312.SubServers.Sync.Network.SubProtocol; import net.ME1312.SubServers.Sync.Server.ServerImpl; @@ -373,8 +374,13 @@ public final class ExProxy extends BungeeCord implements Listener { @EventHandler(priority = Byte.MIN_VALUE) public void login(LoginEvent e) { if (rPlayers.containsKey(e.getConnection().getUniqueId())) { - e.setCancelled(true); - e.setCancelReason(new TextComponent(getTranslation("already_connected_proxy"))); + Logger.get("SubServers").info(e.getConnection().getName() + " connected, but already had a database entry"); + RemotePlayer player = rPlayers.get(e.getConnection().getUniqueId()); + if (player.getProxy() != null && player.getProxy().equalsIgnoreCase(api.getName())) { + getPlayer(player.getUniqueId()).disconnect(new TextComponent(getTranslation("already_connected_proxy"))); + } else { + ((SubDataClient) api.getSubDataNetwork()[0]).sendPacket(new PacketDisconnectPlayer(player.getUniqueId(), getTranslation("already_connected_proxy"))); + } } } @@ -421,14 +427,16 @@ public final class ExProxy extends BungeeCord implements Listener { @SuppressWarnings("deprecation") @EventHandler(priority = Byte.MAX_VALUE) public void connected(ServerConnectedEvent e) { - ObjectMap raw = RemotePlayer.translate(e.getPlayer()); - raw.set("server", e.getServer().getInfo().getName()); - RemotePlayer player = new RemotePlayer(raw); - rPlayers.put(player.getUniqueId(), player); - rPlayerLinkP.put(player.getUniqueId(), player.getProxy().toLowerCase()); - if (e.getServer().getInfo() instanceof ServerImpl) rPlayerLinkS.put(player.getUniqueId(), (ServerImpl) e.getServer().getInfo()); - if (api.getSubDataNetwork()[0] != null) { - ((SubDataClient) api.getSubDataNetwork()[0]).sendPacket(new PacketExSyncPlayer(true, player)); + synchronized (rPlayers) { + ObjectMap raw = RemotePlayer.translate(e.getPlayer()); + raw.set("server", e.getServer().getInfo().getName()); + RemotePlayer player = new RemotePlayer(raw); + rPlayerLinkP.put(player.getUniqueId(), player.getProxy().toLowerCase()); + rPlayers.put(player.getUniqueId(), player); + if (e.getServer().getInfo() instanceof ServerImpl) rPlayerLinkS.put(player.getUniqueId(), (ServerImpl) e.getServer().getInfo()); + if (api.getSubDataNetwork()[0] != null) { + ((SubDataClient) api.getSubDataNetwork()[0]).sendPacket(new PacketExSyncPlayer(true, player)); + } } @@ -476,13 +484,15 @@ public final class ExProxy extends BungeeCord implements Listener { fallbackLimbo.remove(e.getPlayer().getUniqueId()); SubCommand.permitted.remove(e.getPlayer().getUniqueId()); - if (rPlayers.containsKey(e.getPlayer().getUniqueId())) { - if (api.getSubDataNetwork()[0] != null) { - ((SubDataClient) api.getSubDataNetwork()[0]).sendPacket(new PacketExSyncPlayer(false, rPlayers.get(e.getPlayer().getUniqueId()))); + synchronized (rPlayers) { + if (rPlayers.containsKey(e.getPlayer().getUniqueId()) && (!rPlayerLinkP.containsKey(e.getPlayer().getUniqueId()) || rPlayerLinkP.get(e.getPlayer().getUniqueId()).equalsIgnoreCase(api.getName()))) { + if (api.getSubDataNetwork()[0] != null) { + ((SubDataClient) api.getSubDataNetwork()[0]).sendPacket(new PacketExSyncPlayer(false, rPlayers.get(e.getPlayer().getUniqueId()))); + } + rPlayerLinkS.remove(e.getPlayer().getUniqueId()); + rPlayerLinkP.remove(e.getPlayer().getUniqueId()); + rPlayers.remove(e.getPlayer().getUniqueId()); } - rPlayerLinkS.remove(e.getPlayer().getUniqueId()); - rPlayerLinkP.remove(e.getPlayer().getUniqueId()); - rPlayers.remove(e.getPlayer().getUniqueId()); } } diff --git a/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketDisconnectPlayer.java b/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketDisconnectPlayer.java new file mode 100644 index 00000000..0a8eb798 --- /dev/null +++ b/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketDisconnectPlayer.java @@ -0,0 +1,62 @@ +package net.ME1312.SubServers.Sync.Network.Packet; + +import net.ME1312.Galaxi.Library.Callback.Callback; +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.Galaxi.Library.Util; +import net.ME1312.SubData.Client.Protocol.PacketObjectIn; +import net.ME1312.SubData.Client.Protocol.PacketObjectOut; +import net.ME1312.SubData.Client.SubDataSender; + +import java.util.HashMap; +import java.util.UUID; + +/** + * Disconnect Player Packet + */ +public class PacketDisconnectPlayer implements PacketObjectIn, PacketObjectOut { + private static HashMap>[]> callbacks = new HashMap>[]>(); + private UUID player; + private String reason; + private UUID id; + + /** + * New PacketDisconnectPlayer (In) + */ + public PacketDisconnectPlayer() {} + + /** + * New PacketDisconnectPlayer (Out) + * + * @param player Player + * @param reason Reason + * @param callback Callbacks + */ + @SafeVarargs + public PacketDisconnectPlayer(UUID player, String reason, Callback>... callback) { + if (Util.isNull(player, callback)) throw new NullPointerException(); + this.player = player; + this.reason = reason; + this.id = Util.getNew(callbacks.keySet(), UUID::randomUUID); + callbacks.put(id, callback); + } + + @Override + public ObjectMap send(SubDataSender client) { + ObjectMap data = new ObjectMap(); + data.set(0x0000, id); + data.set(0x0001, player); + if (reason != null) data.set(0x0002, reason); + return data; + } + + @Override + public void receive(SubDataSender client, ObjectMap data) { + for (Callback> callback : callbacks.get(data.getUUID(0x0000))) callback.run(data); + callbacks.remove(data.getUUID(0x0000)); + } + + @Override + public int version() { + return 0x0001; + } +} diff --git a/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketExDisconnectPlayer.java b/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketExDisconnectPlayer.java new file mode 100644 index 00000000..b04fddea --- /dev/null +++ b/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketExDisconnectPlayer.java @@ -0,0 +1,73 @@ +package net.ME1312.SubServers.Sync.Network.Packet; + +import net.ME1312.Galaxi.Library.Map.ObjectMap; +import net.ME1312.SubData.Client.Protocol.PacketObjectIn; +import net.ME1312.SubData.Client.Protocol.PacketObjectOut; +import net.ME1312.SubData.Client.SubDataSender; +import net.ME1312.SubServers.Sync.ExProxy; +import net.md_5.bungee.api.connection.ProxiedPlayer; + +import java.util.UUID; + +/** + * Disconnect External Player Packet + */ +public class PacketExDisconnectPlayer implements PacketObjectIn, PacketObjectOut { + private ExProxy plugin; + private int response; + private UUID tracker; + + /** + * New PacketExDisconnectPlayer (In) + */ + public PacketExDisconnectPlayer(ExProxy plugin) { + this.plugin = plugin; + } + + /** + * New PacketExDisconnectPlayer (Out) + * + * @param response Response ID + * @param tracker Receiver ID + */ + public PacketExDisconnectPlayer(int response, UUID tracker) { + this.response = response; + this.tracker = tracker; + } + + @Override + public ObjectMap send(SubDataSender client) { + ObjectMap json = new ObjectMap(); + if (tracker != null) json.set(0x0000, tracker); + json.set(0x0001, response); + return json; + } + + @Override + public void receive(SubDataSender client, ObjectMap data) { + UUID tracker = (data.contains(0x0000)?data.getUUID(0x0000):null); + try { + UUID id = data.getUUID(0x0001); + + ProxiedPlayer local; + if ((local = plugin.getPlayer(id)) != null) { + if (data.contains(0x0002)) { + local.disconnect(data.getRawString(0x0002)); + } else { + local.disconnect(); + } + client.sendPacket(new PacketExDisconnectPlayer(2, tracker)); + } else { + client.sendPacket(new PacketExDisconnectPlayer(3, tracker)); + } + } catch (Throwable e) { + client.sendPacket(new PacketExDisconnectPlayer(2, tracker)); + e.printStackTrace(); + } + } + + @Override + public int version() { + return 0x0001; + } +} diff --git a/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketExSyncPlayer.java b/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketExSyncPlayer.java index 9a3c8c12..2a3cffc3 100644 --- a/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketExSyncPlayer.java +++ b/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/Packet/PacketExSyncPlayer.java @@ -63,21 +63,27 @@ public class PacketExSyncPlayer implements PacketObjectIn, PacketObject plugin.rPlayers.remove(id); } } - if (data.getBoolean(0x0001) != Boolean.FALSE) { - if (data.contains(0x0002)) for (Map object : (List>) data.getObjectList(0x0002)) { - ServerImpl server = (object.getOrDefault("server", null) != null)?plugin.servers.getOrDefault(object.get("server").toString().toLowerCase(), null):null; - RemotePlayer player = new RemotePlayer(new ObjectMap<>(object)); + synchronized (plugin.rPlayers) { + if (data.getBoolean(0x0001) != Boolean.FALSE) { + if (data.contains(0x0002)) for (Map object : (List>) data.getObjectList(0x0002)) { + ServerImpl server = (object.getOrDefault("server", null) != null)?plugin.servers.getOrDefault(object.get("server").toString().toLowerCase(), null):null; + RemotePlayer player = new RemotePlayer(new ObjectMap<>(object)); - plugin.rPlayers.put(player.getUniqueId(), player); - plugin.rPlayerLinkP.put(player.getUniqueId(), proxy); - if (server != null) plugin.rPlayerLinkS.put(player.getUniqueId(), server); - } - } else { - if (data.contains(0x0002)) for (Map object : (List>) data.getObjectList(0x0002)) { - UUID id = UUID.fromString(object.get("id").toString()); - plugin.rPlayerLinkS.remove(id); - plugin.rPlayerLinkP.remove(id); - plugin.rPlayers.remove(id); + plugin.rPlayerLinkP.put(player.getUniqueId(), proxy); + plugin.rPlayers.put(player.getUniqueId(), player); + if (server != null) plugin.rPlayerLinkS.put(player.getUniqueId(), server); + } + } else { + if (data.contains(0x0002)) for (Map object : (List>) data.getObjectList(0x0002)) { + UUID id = UUID.fromString(object.get("id").toString()); + + // Don't accept removal requests when we're managing players + if ((!plugin.rPlayerLinkP.containsKey(id) || !plugin.rPlayerLinkP.get(id).equalsIgnoreCase(plugin.api.getName()))) { + plugin.rPlayerLinkS.remove(id); + plugin.rPlayerLinkP.remove(id); + plugin.rPlayers.remove(id); + } + } } } } diff --git a/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/SubProtocol.java b/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/SubProtocol.java index 2722eaad..b4280eec 100644 --- a/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/SubProtocol.java +++ b/SubServers.Sync/src/net/ME1312/SubServers/Sync/Network/SubProtocol.java @@ -5,7 +5,6 @@ import net.ME1312.Galaxi.Library.Map.ObjectMap; import net.ME1312.Galaxi.Library.Container.NamedContainer; import net.ME1312.Galaxi.Library.Util; import net.ME1312.Galaxi.Library.Version.Version; -import net.ME1312.SubData.Client.Library.DisconnectReason; import net.ME1312.SubData.Client.SubDataClient; import net.ME1312.SubData.Client.SubDataProtocol; import net.ME1312.SubServers.Sync.Event.SubNetworkConnectEvent; @@ -21,10 +20,8 @@ import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.conf.Configuration; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.net.InetAddress; import java.util.*; -import java.util.concurrent.TimeUnit; import java.util.logging.Logger; /** @@ -79,6 +76,7 @@ public class SubProtocol extends SubDataProtocol { registerPacket(0x0037, PacketStopServer.class); registerPacket(0x0038, PacketRemoveServer.class); registerPacket(0x0039, PacketDeleteServer.class); + registerPacket(0x003C, PacketDisconnectPlayer.class); registerPacket(0x0030, new PacketCreateServer()); registerPacket(0x0031, new PacketAddServer()); @@ -90,6 +88,7 @@ public class SubProtocol extends SubDataProtocol { registerPacket(0x0037, new PacketStopServer()); registerPacket(0x0038, new PacketRemoveServer()); registerPacket(0x0039, new PacketDeleteServer()); + registerPacket(0x003C, new PacketDisconnectPlayer()); // 70-7F: External Misc Packets @@ -97,11 +96,13 @@ public class SubProtocol extends SubDataProtocol { //registerPacket(0x0071, PacketInExReset.class); //registerPacket(0x0073, PacketInExReload.class); registerPacket(0x0074, PacketExSyncPlayer.class); + registerPacket(0x0076, PacketExDisconnectPlayer.class); registerPacket(0x0070, new PacketInExRunEvent(plugin)); registerPacket(0x0071, new PacketInExReset()); registerPacket(0x0073, new PacketInExUpdateWhitelist(plugin)); registerPacket(0x0074, new PacketExSyncPlayer(plugin)); + registerPacket(0x0076, new PacketExDisconnectPlayer(plugin)); } public static SubProtocol get() { @@ -181,8 +182,8 @@ public class SubProtocol extends SubDataProtocol { plugin.api.getGlobalPlayers(players -> { for (RemotePlayer player : players.values()) { - plugin.rPlayers.put(player.getUniqueId(), player); plugin.rPlayerLinkP.put(player.getUniqueId(), player.getProxy().toLowerCase()); + plugin.rPlayers.put(player.getUniqueId(), player); ServerInfo server = plugin.getServerInfo(player.getServer()); if (server instanceof ServerImpl)