From a1d8ec806f5480afdea12762f821851674f1f825 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 16 Jun 2024 04:04:05 +0200 Subject: [PATCH] Copy over Code --- build.gradle | 2 + .../bungeecore/listeners/PluginMessage.java | 127 +++++++++-------- src/de/steamwar/bungeecore/mods/Badlion.java | 12 +- .../steamwar/bungeecore/mods/Controlify.java | 14 +- src/de/steamwar/bungeecore/mods/FML.java | 89 ++++++++---- src/de/steamwar/bungeecore/mods/FML2.java | 128 +++++++++--------- .../bungeecore/mods/FabricModSender.java | 53 +++++--- src/de/steamwar/bungeecore/mods/Feather.java | 10 +- src/de/steamwar/bungeecore/mods/Hostname.java | 28 ++-- src/de/steamwar/bungeecore/mods/LabyMod.java | 29 ++-- src/de/steamwar/bungeecore/mods/Lunar.java | 30 ++-- src/de/steamwar/bungeecore/mods/ModUtils.java | 39 +++--- .../steamwar/bungeecore/mods/ReplayMod.java | 2 +- .../steamwar/bungeecore/mods/Schematica.java | 9 +- .../bungeecore/mods/ServerListPing.java | 62 ++++++--- .../bungeecore/mods/WorldDownloader.java | 6 +- .../network/handlers/FightInfoHandler.java | 13 +- .../bungeecore/tablist/TablistManager.java | 24 ++-- 18 files changed, 378 insertions(+), 299 deletions(-) diff --git a/build.gradle b/build.gradle index 35c7ac9..ef6e3b8 100644 --- a/build.gradle +++ b/build.gradle @@ -96,6 +96,7 @@ dependencies { compileOnly 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT' annotationProcessor 'com.velocitypowered:velocity-api:3.3.0-SNAPSHOT' + // TODO: Add velocity-proxy as a compileOnly dependency to steamwar-maven //compileOnly 'com.velocitypowered:velocity-proxy:3.3.0-SNAPSHOT' //implementation 'org.reflections:reflections:0.10.2' @@ -105,6 +106,7 @@ dependencies { implementation 'org.yaml:snakeyaml:2.2' + // TODO: Monorepo? compileOnly files('persistentvelocitycore.jar') implementation("net.dv8tion:JDA:4.4.0_352") { exclude module: 'opus-java' diff --git a/src/de/steamwar/bungeecore/listeners/PluginMessage.java b/src/de/steamwar/bungeecore/listeners/PluginMessage.java index d3c96a8..db63762 100644 --- a/src/de/steamwar/bungeecore/listeners/PluginMessage.java +++ b/src/de/steamwar/bungeecore/listeners/PluginMessage.java @@ -19,27 +19,25 @@ package de.steamwar.bungeecore.listeners; +import com.google.inject.Inject; import com.lunarclient.apollo.ApolloManager; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.network.ProtocolVersion; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ServerConnection; +import com.velocitypowered.api.proxy.messages.ChannelMessageSource; +import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; +import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import de.steamwar.bungeecore.VelocityCore; -import de.steamwar.messages.Message; import de.steamwar.bungeecore.commands.TeamCommand; import de.steamwar.bungeecore.mods.*; import de.steamwar.bungeecore.network.ServerMetaInfo; -import de.steamwar.messages.Chatter; import de.steamwar.network.packets.NetworkPacket; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.Unpooled; -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.Connection; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.connection.Server; -import net.md_5.bungee.api.event.PluginMessageEvent; -import net.md_5.bungee.connection.InitialHandler; -import net.md_5.bungee.event.EventHandler; -import net.md_5.bungee.protocol.DefinedPacket; +import net.kyori.adventure.text.Component; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; @@ -48,16 +46,21 @@ import java.util.*; import java.util.function.Consumer; import java.util.logging.Level; -public class PluginMessage extends BasicListener { +public class PluginMessage { - public static void send(ProxiedPlayer player, String legacyChannel, String channel, byte[] data) { + private final Lunar lunar; + private final LabyMod labyMod; + private final WorldDownloader wdl; + private final FabricModSender fms; + private final FML flm; + + public static void send(Player player, String legacyChannel, String channel, byte[] data) { // 1.12 format change - send(player, player.getPendingConnection().getVersion() > 340 ? channel : legacyChannel, data); + send(player, player.getProtocolVersion().getProtocol() > 340 ? channel : legacyChannel, data); } - public static void send(ProxiedPlayer player, String channel, byte[] data) { - if(((InitialHandler)player.getPendingConnection()).getRegisteredChannels().contains(channel)) - player.sendData(channel, data); + public static void send(Player player, String channel, byte[] data) { + player.sendPluginMessage(MinecraftChannelIdentifier.from(channel), data); } public static byte[] genBufPacket(Consumer generator) { @@ -86,20 +89,25 @@ public class PluginMessage extends BasicListener { void accept(DataOutputStream out) throws IOException; } - private static final Parser UNKNOWN = event -> VelocityCore.getLogger().log(Level.WARNING, () -> "Undefined PluginMessage on channel " + event.getTag() + " from " + event.getSender() + " received.\n" + new String(event.getData()) + "\n" + Arrays.toString(event.getData())); - private static final Parser PASS_THROUGH = event -> event.setCancelled(false); - private static final Parser DROP = event -> {}; - - private final Lunar lunar = new Lunar(); + private static final Parser UNKNOWN = event -> { + VelocityCore.get().getLogger().log(Level.WARNING, () -> "Undefined PluginMessage on channel " + event.getIdentifier().getId() + " from " + (event.getSource() instanceof Player pl ? pl.getUsername() : event.getSource().toString()) + " received.\n" + new String(event.getData()) + "\n" + Arrays.toString(event.getData())); + event.setResult(PluginMessageEvent.ForwardResult.handled()); + }; + private static final Parser PASS_THROUGH = event -> event.setResult(PluginMessageEvent.ForwardResult.forward()); + private static final Parser DROP = event -> event.setResult(PluginMessageEvent.ForwardResult.handled()); private final Set knownBrands = new HashSet<>(); - private final Map> channelRegisterHandlers = new HashMap<>(); + private final Map> channelRegisterHandlers = new HashMap<>(); private final Map handlers = new HashMap<>(); public PluginMessage() { - //TODO interface generalisation - LabyMod labyMod = new LabyMod(); - WorldDownloader wdl = new WorldDownloader(); + ModUtils utils = new ModUtils(); + + this.lunar = new Lunar(utils); + this.labyMod = new LabyMod(utils); + this.wdl = new WorldDownloader(); + this.fms = new FabricModSender(utils); + this.flm = new FML(utils); knownBrands.addAll(Arrays.asList("vanilla", "fabric", "quilt", "forge", "optifine", "Geyser", "labymod", "Feather Fabric")); @@ -107,7 +115,7 @@ public class PluginMessage extends BasicListener { "fabric:container/open", "fabric:registry/sync/direct", "fabric:registry/sync", "fabric-screen-handler-api-v1:open_screen", - FML.CHANNEL, "fml:loginwrapper", "fml:handshake", "fml:play", "forge:tier_sorting", "forge:split", + FML.CHANNEL.getId(), "fml:loginwrapper", "fml:handshake", "fml:play", "forge:tier_sorting", "forge:split", "forge:login", "forge:handshake", "labymod3:main", "labymod:neo", @@ -145,16 +153,18 @@ public class PluginMessage extends BasicListener { "noxesium-v1:reset", "noxesium-v1:change_server_rules", "noxesium-v1:server_info", "noxesium-v1:mcc_server", "noxesium-v1:mcc_game_state", "noxesium-v1:reset_server_rules", "noxesium-v1:stop_sound", "noxesium-v1:start_sound", "noxesium-v1:modify_sound" - )) - channelRegisterHandlers.put(channel, player -> {}); + )) { + channelRegisterHandlers.put(channel, player -> { + }); + } channelRegisterHandlers.put(ApolloManager.PLUGIN_MESSAGE_CHANNEL, lunar::sendRestrictions); - channelRegisterHandlers.put(Feather.CHANNEL, new Feather()::sendRestrictions); - channelRegisterHandlers.put("xaerominimap:main", player -> player.sendMessage(ChatMessageType.SYSTEM, new TextComponent("§n§o§m§i§n§i§m§a§p"))); //https://www.curseforge.com/minecraft/mc-mods/xaeros-minimap - channelRegisterHandlers.put("litemoretica:init_easy_place", player -> player.disconnect(Chatter.of(player).parse(false, new Message("MOD_YELLOW_SING", "litematica")))); //https://github.com/Earthcomputer/litemoretica/tree/master - channelRegisterHandlers.put("voxelmap:settings", player -> player.disconnect(Chatter.of(player).parse(false, new Message("MOD_YELLOW_SING", "voxelmap")))); //https://modrinth.com/mod/voxelmap-updated undocumented - channelRegisterHandlers.put("worldinfo:world_id", player -> player.disconnect(Chatter.of(player).parse(false, new Message("MOD_YELLOW_SING", "minimap")))); // JourneyMap and VoxelMap - channelRegisterHandlers.put(Controlify.CHANNEL, new Controlify()::onRegister); + channelRegisterHandlers.put(Feather.CHANNEL.getId(), new Feather()::sendRestrictions); + channelRegisterHandlers.put("xaerominimap:main", player -> player.sendMessage(Component.text("§n§o§m§i§n§i§m§a§p"))); //https://www.curseforge.com/minecraft/mc-mods/xaeros-minimap + channelRegisterHandlers.put("litemoretica:init_easy_place", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "litematica")))); //https://github.com/Earthcomputer/litemoretica/tree/master + channelRegisterHandlers.put("voxelmap:settings", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "voxelmap")))); //https://modrinth.com/mod/voxelmap-updated undocumented + channelRegisterHandlers.put("worldinfo:world_id", player -> player.disconnect(ChatSender.of(player).parseToComponent(false, new Message("MOD_YELLOW_SING", "minimap")))); // JourneyMap and VoxelMap + channelRegisterHandlers.put(Controlify.CHANNEL.getId(), new Controlify()::onRegister); registerBiDirPassthrough("worldedit:cui"); @@ -194,9 +204,9 @@ public class PluginMessage extends BasicListener { register("minecraft:brand", false, directional(this::steamWarBrand, this::userBrand)); //Needs to be registered cause paper refuses to send PluginMessages on unregistered channels... - register("sw:bridge", true, directional(onlySWSource(async(event -> NetworkPacket.handle(new ServerMetaInfo(((Server) event.getSender()).getInfo()), event.getData()))), UNKNOWN)); + register("sw:bridge", true, directional(onlySWSource(async(event -> NetworkPacket.handle(new ServerMetaInfo(((ServerConnection) event.getSource()).getServer()), event.getData()))), UNKNOWN)); register("sw:hotkeys", false, directional(UNKNOWN, PASS_THROUGH)); - register("fabricmodsender:mods", true, directional(UNKNOWN, async(new FabricModSender()::handlePluginMessage))); + register("fabricmodsender:mods", true, directional(UNKNOWN, async(fms::handlePluginMessage))); register("WDL|INIT", true, directional(UNKNOWN, wdl::handlePluginMessage)); register("wdl:init", true, directional(UNKNOWN, wdl::handlePluginMessage)); @@ -205,7 +215,7 @@ public class PluginMessage extends BasicListener { register("LMC", true, directional(UNKNOWN, async(labyMod::handlePluginMessage))); register("labymod3:main", true, directional(UNKNOWN, async(labyMod::handlePluginMessage))); register("labymod:neo", false, directional(UNKNOWN, DROP)); //undocumented, JSON format "0" byte, packetlängen byte, {"version":"4.1.25"} - register(FML.CHANNEL, true, directional(UNKNOWN, async(new FML()::handlePluginMessage))); + register(FML.CHANNEL.getId(), true, directional(UNKNOWN, async(flm::handlePluginMessage))); //vanilla does not register any channels (sends only one minecraft:brand vanilla, nothing else (potential spoofed client detection)) //Forge interestingly registers all channels the server registers @@ -214,12 +224,12 @@ public class PluginMessage extends BasicListener { // Hackclientlike modsuppressor for labymod: https://github.com/Neocraftr/LabyMod-NeoEssentials (Potentially recognizable from NO Addons/NO Mods?) https://github.com/Neocraftr/LabyMod-NeoEssentials/blob/master/src/main/java/de/neocraftr/neoessentials/utils/BytecodeMethods.java } - @EventHandler + @Subscribe public void onPluginMessage(PluginMessageEvent event) { - event.setCancelled(true); + event.setResult(PluginMessageEvent.ForwardResult.handled()); try { - handlers.getOrDefault(event.getTag(), UNKNOWN).handle(event); + handlers.getOrDefault(event.getIdentifier().getId(), UNKNOWN).handle(event); } catch (Exception e) { throw new SecurityException("PluginMessage handling exception: " + event + "\n" + Arrays.toString(event.getData()), e); } @@ -247,34 +257,34 @@ public class PluginMessage extends BasicListener { private void register(String channel, boolean clientSideRegister, Parser handler) { handlers.put(channel, handler); if(clientSideRegister) - ProxyServer.getInstance().registerChannel(channel); + VelocityCore.get().getProxyServer().getChannelRegistrar().register(MinecraftChannelIdentifier.from(channel)); } private void clientRegistersChannel(PluginMessageEvent event) { - ProxiedPlayer player = (ProxiedPlayer) event.getSender(); + Player player = (Player) event.getSource(); for(String channel : new String(event.getData()).split("\0")) { - channelRegisterHandlers.getOrDefault(channel, p -> VelocityCore.getLogger().log(Level.WARNING, () -> p.getName() + " registered unknown channel " + channel)).accept(player); + channelRegisterHandlers.getOrDefault(channel, p -> VelocityCore.get().getLogger().log(Level.WARNING, () -> p.getUsername() + " registered unknown channel " + channel)).accept(player); } PASS_THROUGH.handle(event); } private void serverRegistersChannel(PluginMessageEvent event) { - ProxiedPlayer player = (ProxiedPlayer)event.getReceiver(); + Player player = (Player) event.getTarget(); List channels = new ArrayList<>(Arrays.asList(new String(event.getData()).split("\0"))); channels.removeIf(channel -> channel.equals("sw:bridge")); - player.sendData((player).getPendingConnection().getVersion() > 340 ? "minecraft:register" : "REGISTER", String.join("\0", channels).getBytes()); + player.sendPluginMessage((player).getProtocolVersion().greaterThan(ProtocolVersion.MINECRAFT_1_12_2) ? MinecraftChannelIdentifier.from("minecraft:register") : new LegacyChannelIdentifier("REGISTER"), String.join("\0", channels).getBytes()); } private void userBrand(PluginMessageEvent event) { - ProxiedPlayer player = (ProxiedPlayer) event.getSender(); + Player player = (Player) event.getSource(); ByteBuf buf = Unpooled.wrappedBuffer(event.getData()); - String brand = DefinedPacket.readString(buf); + String brand = ProtocolUtils.readString(buf); boolean lunarclient = brand.startsWith("lunarclient:"); - VelocityCore.getLogger().log(knownBrands.contains(brand) || lunarclient ? Level.INFO : Level.WARNING, () -> player.getName() + " joins with brand: " + brand); + VelocityCore.get().getLogger().log(knownBrands.contains(brand) || lunarclient ? Level.INFO : Level.WARNING, () -> player.getUsername() + " joins with brand: " + brand); if(lunarclient) lunar.sendRestrictions(player); @@ -282,30 +292,29 @@ public class PluginMessage extends BasicListener { } private void steamWarBrand(PluginMessageEvent event) { - ProxiedPlayer player = (ProxiedPlayer) event.getReceiver(); - String brandString = Chatter.of(player).parseToLegacy("STEAMWAR_BRAND", ProxyServer.getInstance().getName(), player.getServer().getInfo().getName(), new String(event.getData(), 1, event.getData().length - 1)); + Player player = (Player) event.getTarget(); + String brandString = ChatSender.of(player).parseToLegacy("STEAMWAR_BRAND", "Velocity", player.getCurrentServer().map(serverConnection -> serverConnection.getServerInfo().getName()).orElse(""), new String(event.getData(), 1, event.getData().length - 1)); ByteBuf brand = ByteBufAllocator.DEFAULT.heapBuffer(); - DefinedPacket.writeString(brandString, brand); - player.sendData(event.getTag(), DefinedPacket.toArray(brand)); + ProtocolUtils.writeString(brand, brandString); + player.sendPluginMessage(event.getIdentifier(), brand.array()); brand.release(); } private Parser directional(Parser fromServer, Parser fromPlayer) { return event -> { - if(event.getSender() instanceof ProxiedPlayer) + if(event.getSource() instanceof Player) fromPlayer.handle(event); else fromServer.handle(event); }; } - @SuppressWarnings("deprecation") private Parser onlySWSource(Parser parser) { return event -> { - Connection sender = event.getSender(); - if(TeamCommand.isLocalhost(sender instanceof ProxiedPlayer ? IPSanitizer.getTrueAddress(((ProxiedPlayer) sender).getPendingConnection()) : sender.getAddress().getAddress())) + ChannelMessageSource sender = event.getSource(); + if(TeamCommand.isLocalhost(sender instanceof Player player ? IPSanitizer.getTrueAddress((player)) : ((ServerConnection) sender).getServerInfo().getAddress().getAddress())) parser.handle(event); else UNKNOWN.handle(event); @@ -313,7 +322,7 @@ public class PluginMessage extends BasicListener { } private Parser async(Parser parser) { - return event -> ProxyServer.getInstance().getScheduler().runAsync(VelocityCore.get(), () -> parser.handle(event)); + return event -> VelocityCore.get().getProxyServer().getScheduler().buildTask(VelocityCore.get(), () -> parser.handle(event)).schedule(); } private interface Parser { diff --git a/src/de/steamwar/bungeecore/mods/Badlion.java b/src/de/steamwar/bungeecore/mods/Badlion.java index 4a58f0f..145783c 100644 --- a/src/de/steamwar/bungeecore/mods/Badlion.java +++ b/src/de/steamwar/bungeecore/mods/Badlion.java @@ -20,11 +20,11 @@ package de.steamwar.bungeecore.mods; import com.google.gson.JsonObject; -import de.steamwar.bungeecore.listeners.BasicListener; -import net.md_5.bungee.api.event.PostLoginEvent; -import net.md_5.bungee.event.EventHandler; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.PostLoginEvent; +import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; -public class Badlion extends BasicListener { +public class Badlion { // https://github.com/BadlionClient/BadlionClientModAPI private final byte[] packet; @@ -50,8 +50,8 @@ public class Badlion extends BasicListener { packet = json.toString().getBytes(); } - @EventHandler + @Subscribe public void onPostLogin(PostLoginEvent event) { - event.getPlayer().sendData("badlion:mods", packet); + event.getPlayer().sendPluginMessage(MinecraftChannelIdentifier.from("badlion:mods"), packet); } } diff --git a/src/de/steamwar/bungeecore/mods/Controlify.java b/src/de/steamwar/bungeecore/mods/Controlify.java index 2c24017..6dfded4 100644 --- a/src/de/steamwar/bungeecore/mods/Controlify.java +++ b/src/de/steamwar/bungeecore/mods/Controlify.java @@ -19,16 +19,18 @@ package de.steamwar.bungeecore.mods; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; +import com.velocitypowered.proxy.protocol.ProtocolUtils; import de.steamwar.bungeecore.listeners.PluginMessage; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.protocol.DefinedPacket; public class Controlify { //https://modrinth.com/mod/controlify //https://github.com/isXander/Controlify/blob/1.20.x/dev/src/main/java/dev/isxander/controlify/server/ServerPolicyPacket.java //https://github.com/isXander/Controlify/blob/1.20.x/dev/src/main/java/dev/isxander/controlify/server/ServerPolicies.java - public static final String CHANNEL = "controlify:server_policy"; + public static final ChannelIdentifier CHANNEL = MinecraftChannelIdentifier.from("controlify:server_policy"); private final byte[][] packets; public Controlify() { @@ -40,13 +42,13 @@ public class Controlify { private byte[] restrict(String name) { return PluginMessage.genBufPacket(buf -> { - DefinedPacket.writeString(name, buf); + ProtocolUtils.writeString(buf, name); buf.writeBoolean(false); }); } - public void onRegister(ProxiedPlayer player) { + public void onRegister(Player player) { for(byte[] packet : packets) - player.sendData(CHANNEL, packet); + player.sendPluginMessage(CHANNEL, packet); } } diff --git a/src/de/steamwar/bungeecore/mods/FML.java b/src/de/steamwar/bungeecore/mods/FML.java index aaa7c90..337c833 100644 --- a/src/de/steamwar/bungeecore/mods/FML.java +++ b/src/de/steamwar/bungeecore/mods/FML.java @@ -19,32 +19,68 @@ package de.steamwar.bungeecore.mods; +import com.google.inject.Inject; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.ConnectionHandshakeEvent; +import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.event.connection.PostLoginEvent; +import com.velocitypowered.api.proxy.LoginPhaseConnection; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; +import com.velocitypowered.proxy.connection.ConnectionType; +import com.velocitypowered.proxy.connection.ConnectionTypes; +import com.velocitypowered.proxy.connection.client.ConnectedPlayer; +import com.velocitypowered.proxy.connection.client.InitialInboundConnection; +import com.velocitypowered.proxy.connection.client.LoginInboundConnection; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import com.velocitypowered.proxy.protocol.packet.HandshakePacket; import de.steamwar.bungeecore.VelocityCore; -import de.steamwar.bungeecore.listeners.BasicListener; -import de.steamwar.messages.Chatter; +import de.steamwar.bungeecore.util.annotations.Create; import de.steamwar.sql.Mod; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.connection.PendingConnection; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PluginMessageEvent; -import net.md_5.bungee.api.event.PostLoginEvent; -import net.md_5.bungee.connection.InitialHandler; -import net.md_5.bungee.event.EventHandler; -import net.md_5.bungee.protocol.DefinedPacket; +import lombok.SneakyThrows; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.TimeUnit; -public class FML extends BasicListener { +@Create +public class FML { // https://wiki.vg/Minecraft_Forge_Handshake#FML_protocol_.281.7_-_1.12.29 - public static boolean isFML(PendingConnection connection, String type) { - return ((InitialHandler)connection).getExtraDataInHandshake().equals("\0" + type); + private static final Field delegateField; + private static final Field handshakeField; + + static { + try { + delegateField = LoginInboundConnection.class.getDeclaredField("delegate"); + handshakeField = InitialInboundConnection.class.getDeclaredField("handshake"); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } } - public static final String CHANNEL = "FML|HS"; + private final ModUtils utils; + private final ProxyServer proxyServer; + private final VelocityCore core; + + @Inject + public FML(ModUtils utils) { + this.utils = utils; + this.proxyServer = VelocityCore.getProxy(); + this.core = VelocityCore.get(); + } + + @SneakyThrows + public static boolean isFML(LoginPhaseConnection connection, String type) { + return handshakeField.get(delegateField.get(connection)) instanceof HandshakePacket packet && packet.getServerAddress().endsWith("\0" + type); + } + + public static final ChannelIdentifier CHANNEL = MinecraftChannelIdentifier.from("FML|HS"); private final byte[] helloPacket = new byte[]{ /* Packet type: ServerHello */ 0, /* FML protocol version */ 2, @@ -53,9 +89,9 @@ public class FML extends BasicListener { private static final Set unlocked = new HashSet<>(); - @EventHandler + @Subscribe public void onPostLogin(PostLoginEvent event) { - ProxiedPlayer player = event.getPlayer(); + Player player = event.getPlayer(); synchronized (unlocked) { if(unlocked.contains(player.getUniqueId())){ @@ -64,35 +100,36 @@ public class FML extends BasicListener { } } - if(isFML(player.getPendingConnection(), "FML\0")) - player.sendData(CHANNEL, helloPacket); + if(((ConnectedPlayer) event.getPlayer()).getConnection().getType() == ConnectionTypes.LEGACY_FORGE) { + player.sendPluginMessage(CHANNEL, helloPacket); + } } public void handlePluginMessage(PluginMessageEvent event) { - ProxiedPlayer p = (ProxiedPlayer) event.getSender(); + Player p = (Player) event.getSource(); ByteBuf buf = Unpooled.wrappedBuffer(event.getData()); if (buf.readByte() == /* ModList */ 2) { - int numMods = DefinedPacket.readVarInt(buf); + int numMods = ProtocolUtils.readVarInt(buf); List mods = new ArrayList<>(); for(int i = 0; i < numMods; i++) { - String name = DefinedPacket.readString(buf); - DefinedPacket.readString(buf); // version + String name = ProtocolUtils.readString(buf); + ProtocolUtils.readString(buf); // version mods.add(Mod.getOrCreate(name, Mod.Platform.FORGE)); } - if (ModUtils.handleMods(p, mods)) { + if (utils.handleMods(p, mods)) { synchronized (unlocked) { unlocked.add(p.getUniqueId()); } - Chatter.disconnect(p).system("MODS_CHECKED"); - ProxyServer.getInstance().getScheduler().schedule(VelocityCore.get(), () -> { + p.disconnect(LegacyComponentSerializer.legacySection().deserialize("§7Deine installierten Mods wurden überprüft\n§aDu kannst nun §eSteam§8War §abetreten")); + proxyServer.getScheduler().buildTask(core, () -> { synchronized (unlocked) { unlocked.remove(p.getUniqueId()); } - }, 30, TimeUnit.SECONDS); + }).delay(30, TimeUnit.SECONDS); } } } diff --git a/src/de/steamwar/bungeecore/mods/FML2.java b/src/de/steamwar/bungeecore/mods/FML2.java index 800dbbf..6d00f9e 100644 --- a/src/de/steamwar/bungeecore/mods/FML2.java +++ b/src/de/steamwar/bungeecore/mods/FML2.java @@ -19,29 +19,29 @@ package de.steamwar.bungeecore.mods; +import com.google.inject.Inject; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.PreLoginEvent; +import com.velocitypowered.api.proxy.LoginPhaseConnection; +import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; +import com.velocitypowered.proxy.connection.client.LoginInboundConnection; +import com.velocitypowered.proxy.protocol.ProtocolUtils; +import com.velocitypowered.proxy.protocol.StateRegistry; import de.steamwar.bungeecore.VelocityCore; -import de.steamwar.bungeecore.listeners.BasicListener; import de.steamwar.bungeecore.listeners.IPSanitizer; import de.steamwar.bungeecore.listeners.PluginMessage; +import de.steamwar.bungeecore.util.annotations.Create; import de.steamwar.sql.Mod; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.PendingConnection; -import net.md_5.bungee.api.event.LoginEvent; -import net.md_5.bungee.event.EventHandler; -import net.md_5.bungee.netty.HandlerBoss; -import net.md_5.bungee.netty.PacketHandler; -import net.md_5.bungee.protocol.DefinedPacket; -import net.md_5.bungee.protocol.packet.LoginPayloadRequest; -import net.md_5.bungee.protocol.packet.LoginPayloadResponse; +import org.checkerframework.checker.nullness.qual.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; +import java.util.*; import java.util.logging.Level; -public class FML2 extends BasicListener { +public class FML2 { + + protected final ModUtils modUtils; // FML2: https://wiki.vg/Minecraft_Forge_Handshake#FML2_protocol_.281.13_-_Current.29 // FML3: https://github.com/adde0109/Ambassador/tree/non-api/src/main/java/org/adde0109/ambassador/forge @@ -54,24 +54,25 @@ public class FML2 extends BasicListener { private final byte[] forgeModListPacket; public FML2() { + this.modUtils = modUtils; fml2ModListPacket = generateModListPacket(false); fml3ModListPacket = generateModListPacket(true); forgeModListPacket = PluginMessage.genBufPacket(buf -> { buf.writeByte(0); // Login wrapper packet - DefinedPacket.writeString("forge:handshake", buf); + ProtocolUtils.writeString(buf, "forge:handshake"); ByteBuf packet = Unpooled.buffer(); packet.writeByte(1); // Mod list packet - DefinedPacket.writeVarInt(0, packet); // Mod amount + ProtocolUtils.writeVarInt(packet, 0); // Mod amount - DefinedPacket.writeVarInt(packet.readableBytes(), buf); + ProtocolUtils.writeVarInt(buf, packet.readableBytes()); buf.writeBytes(packet); }); } - @EventHandler - public void onLogin(LoginEvent event) { - PendingConnection connection = event.getConnection(); + @Subscribe + public void onLogin(PreLoginEvent event) { + LoginInboundConnection connection = (LoginInboundConnection) event.getConnection(); boolean fml2 = FML.isFML(connection, "FML2\0"); boolean fml3 = FML.isFML(connection, "FML3\0"); @@ -79,45 +80,49 @@ public class FML2 extends BasicListener { if(!fml2 && !fml3 && !forge) return; - IPSanitizer.getChannelWrapper(connection).getHandle().pipeline().get(HandlerBoss.class).setHandler(new FML2LoginHandler(event)); + FML2LoginHandler handler = new FML2LoginHandler(connection, event.getUniqueId(), forge); - event.registerIntent(VelocityCore.get()); - if(forge) - connection.unsafe().sendPacket(new LoginPayloadRequest(1, "forge:login", forgeModListPacket)); - else - connection.unsafe().sendPacket(new LoginPayloadRequest(1, "fml:loginwrapper", fml3 ? fml3ModListPacket : fml2ModListPacket)); + if(forge) { + ((LoginInboundConnection) event.getConnection()).sendLoginPluginMessage(MinecraftChannelIdentifier.from("forge:login"), forgeModListPacket, handler); + } else { + ((LoginInboundConnection) event.getConnection()).sendLoginPluginMessage(MinecraftChannelIdentifier.from("fml:loginwrapper"), fml3 ? fml3ModListPacket : fml2ModListPacket, handler); + } } private byte[] generateModListPacket(boolean fml3) { return PluginMessage.genBufPacket(buf -> { - DefinedPacket.writeString("fml:handshake", buf); + ProtocolUtils.writeString(buf, "fml:handshake"); ByteBuf packet = Unpooled.buffer(); packet.writeByte(1); // Mod list packet - DefinedPacket.writeVarInt(0, packet); // Mod amount + ProtocolUtils.writeVarInt(packet, 0); // Mod amount if(fml3) { - DefinedPacket.writeVarInt(1, packet); // Channel amount - DefinedPacket.writeString("forge:tier_sorting", packet); - DefinedPacket.writeString("1.0", packet); + ProtocolUtils.writeVarInt(packet,1); // Channel amount + ProtocolUtils.writeString(packet, "forge:tier_sorting"); + ProtocolUtils.writeString(packet, "1.0"); } else { - DefinedPacket.writeVarInt(0, packet); // Channel amount + ProtocolUtils.writeVarInt(packet, 0); // Channel amount } - DefinedPacket.writeVarInt(0, packet); // Registries amount + ProtocolUtils.writeVarInt(packet, 0); // Registries amount if(fml3) - DefinedPacket.writeVarInt(0, packet); // DataPacks amount + ProtocolUtils.writeVarInt(packet, 0); // DataPacks amount - DefinedPacket.writeVarInt(packet.readableBytes(), buf); + ProtocolUtils.writeVarInt(buf, packet.readableBytes()); buf.writeBytes(packet); }); } - private static class FML2LoginHandler extends PacketHandler { - private final LoginEvent event; + private class FML2LoginHandler implements LoginPhaseConnection.MessageConsumer { + private final LoginInboundConnection connection; + private final UUID uuid; + private final boolean forge; - public FML2LoginHandler(LoginEvent event) { - this.event = event; + private FML2LoginHandler(LoginInboundConnection connection, UUID uuid, boolean forge) { + this.connection = connection; + this.uuid = uuid; + this.forge = forge; } @Override @@ -125,59 +130,52 @@ public class FML2 extends BasicListener { return "SteamWar Forge Handler"; } + private void abort(byte[] response, String error) { + + VelocityCore.get().getLogger().log(Level.SEVERE, () -> error + "\n" + Base64.getEncoder().encodeToString(response)); + } + @Override - public void handle(LoginPayloadResponse response) { - boolean forge = FML.isFML(event.getConnection(), "FORGE"); - byte[] data = response.getData(); + public void onMessageResponse(byte @Nullable [] data) { if(data == null) { - abort(response, "Not FML2/3 client"); + abort(null, "Not FML2/3 client"); return; } ByteBuf buf = Unpooled.wrappedBuffer(data); if(forge && buf.readByte() != 0) { - abort(response, "Not FORGE login wrapper"); + abort(data, "Not FORGE login wrapper"); return; } - if(!DefinedPacket.readString(buf).equals(forge ? "forge:handshake" : "fml:handshake")) { - abort(response, "Not FML2/3/FORGE handshake response"); + if(!ProtocolUtils.readString(buf).equals(forge ? "forge:handshake" : "fml:handshake")) { + abort(data, "Not FML2/3/FORGE handshake response"); return; } - if(DefinedPacket.readVarInt(buf) != buf.readableBytes()) { - abort(response, "FML2/3/FORGE packet size mismatch"); + if(ProtocolUtils.readVarInt(buf) != buf.readableBytes()) { + abort(data, "FML2/3/FORGE packet size mismatch"); return; } - if(DefinedPacket.readVarInt(buf) != (forge ? /* Mod Versions */ 1 : /* Mod List Reply */ 2)) { - abort(response, "Not FML2/3/FORGE mod list reply"); + if(ProtocolUtils.readVarInt(buf) != (forge ? /* Mod Versions */ 1 : /* Mod List Reply */ 2)) { + abort(data, "Not FML2/3/FORGE mod list reply"); return; } List mods = new ArrayList<>(); - int modCount = DefinedPacket.readVarInt(buf); + int modCount = ProtocolUtils.readVarInt(buf); for(int i = 0; i < modCount; i++) { - mods.add(Mod.getOrCreate(DefinedPacket.readString(buf), Mod.Platform.FORGE)); + mods.add(Mod.getOrCreate(ProtocolUtils.readString(buf), Mod.Platform.FORGE)); if(forge) { - DefinedPacket.readString(buf); // Human readable name - DefinedPacket.readString(buf); // Version + ProtocolUtils.readString(buf); // Human readable name + ProtocolUtils.readString(buf); // Version } } - if(!ModUtils.handleMods(event.getConnection().getUniqueId(), Locale.getDefault(), event::setReason, mods)) - event.setCancelled(true); - - event.completeIntent(VelocityCore.get()); - } - - private void abort(LoginPayloadResponse response, String error) { - event.setReason(TextComponent.fromLegacy(error)); - event.setCancelled(true); - event.completeIntent(VelocityCore.get()); - VelocityCore.getLogger().log(Level.SEVERE, () -> error + "\n" + response); + modUtils.handleMods(uuid, Locale.getDefault(), connection::disconnect, mods); } } } diff --git a/src/de/steamwar/bungeecore/mods/FabricModSender.java b/src/de/steamwar/bungeecore/mods/FabricModSender.java index 93f54fa..170006f 100644 --- a/src/de/steamwar/bungeecore/mods/FabricModSender.java +++ b/src/de/steamwar/bungeecore/mods/FabricModSender.java @@ -22,31 +22,40 @@ package de.steamwar.bungeecore.mods; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; +import com.google.inject.Inject; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.DisconnectEvent; +import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.event.player.ServerConnectedEvent; +import com.velocitypowered.api.event.player.ServerPostConnectEvent; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.proxy.protocol.ProtocolUtils; import de.steamwar.bungeecore.VelocityCore; import de.steamwar.bungeecore.Storage; -import de.steamwar.bungeecore.listeners.BasicListener; +import de.steamwar.bungeecore.util.annotations.Create; import de.steamwar.sql.Mod; import de.steamwar.sql.SWException; import de.steamwar.sql.SteamwarUser; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PlayerDisconnectEvent; -import net.md_5.bungee.api.event.PluginMessageEvent; -import net.md_5.bungee.api.event.ServerSwitchEvent; -import net.md_5.bungee.event.EventHandler; -import net.md_5.bungee.protocol.DefinedPacket; import java.util.*; import java.util.concurrent.TimeUnit; -public class FabricModSender extends BasicListener { +@Create +public class FabricModSender { + + private final ModUtils utils; + private final ProxyServer proxyServer; private final Set neededFabricMods = new HashSet<>(); private final Set neededQuiltMods = new HashSet<>(); - public FabricModSender() { + @Inject + public FabricModSender(ModUtils utils) { + this.utils = utils; + this.proxyServer = VelocityCore.getProxy(); neededFabricMods.add("java"); neededFabricMods.add("minecraft"); neededFabricMods.add("steamwarmodsender"); @@ -55,9 +64,9 @@ public class FabricModSender extends BasicListener { neededFabricMods.add("fabricloader"); neededQuiltMods.add("quilt_loader"); - BungeeCord.getInstance().getScheduler().schedule(VelocityCore.get(), () -> { + proxyServer.getScheduler().buildTask(VelocityCore.get(), () -> { synchronized (Storage.fabricExpectPluginMessage) { - for (Map.Entry entry : Storage.fabricExpectPluginMessage.entrySet()) { + for (Map.Entry entry : Storage.fabricExpectPluginMessage.entrySet()) { if (!Storage.fabricCheckedPlayers.containsKey(entry.getKey())) { continue; } @@ -67,11 +76,11 @@ public class FabricModSender extends BasicListener { } } } - }, 0, 1, TimeUnit.SECONDS); + }).repeat(1, TimeUnit.SECONDS); } public void handlePluginMessage(PluginMessageEvent e){ - ProxiedPlayer player = (ProxiedPlayer) e.getSender(); + Player player = (Player) e.getSource(); SteamwarUser user = SteamwarUser.get(player.getUniqueId()); if (!Storage.fabricCheckedPlayers.containsKey(player)) { @@ -87,7 +96,7 @@ public class FabricModSender extends BasicListener { List mods = new ArrayList<>(); ByteBuf buf = Unpooled.wrappedBuffer(e.getData()); - String data = DefinedPacket.readString(buf, 1024*1024); + String data = ProtocolUtils.readString(buf, 1024*1024); if(buf.readableBytes() > 0) { logMessage(user, "Invalid message length", Arrays.toString(e.getData())); return; @@ -104,7 +113,7 @@ public class FabricModSender extends BasicListener { return; } - if(!ModUtils.handleMods(player,mods)) + if(!utils.handleMods(player,mods)) return; if (!Storage.fabricCheckedPlayers.containsKey(player)) { @@ -114,17 +123,17 @@ public class FabricModSender extends BasicListener { } } - @EventHandler - public void onServerSwitchEvent(ServerSwitchEvent e) { - if (e.getFrom() == null) return; + @Subscribe + public void onServerSwitchEvent(ServerConnectedEvent e) { + if (e.getPreviousServer().isEmpty()) return; synchronized (Storage.fabricExpectPluginMessage) { Storage.fabricExpectPluginMessage.put(e.getPlayer(), System.currentTimeMillis()); } } - @EventHandler - public void onDisconnect(PlayerDisconnectEvent e) { - ProxiedPlayer player = e.getPlayer(); + @Subscribe + public void onDisconnect(DisconnectEvent e) { + Player player = e.getPlayer(); Storage.fabricCheckedPlayers.remove(player); synchronized (Storage.fabricExpectPluginMessage) { diff --git a/src/de/steamwar/bungeecore/mods/Feather.java b/src/de/steamwar/bungeecore/mods/Feather.java index c7d2b65..1325ffb 100644 --- a/src/de/steamwar/bungeecore/mods/Feather.java +++ b/src/de/steamwar/bungeecore/mods/Feather.java @@ -21,12 +21,14 @@ package de.steamwar.bungeecore.mods; import com.google.gson.JsonArray; import com.google.gson.JsonObject; -import net.md_5.bungee.api.connection.ProxiedPlayer; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; public class Feather { //https://github.com/Koupah/Feather-Client-API/blob/main/src/club/koupah/feather/packets/FeatherMod.java //https://archive.org/details/feather-server-api - public static final String CHANNEL = "feather:client"; + public static final ChannelIdentifier CHANNEL = MinecraftChannelIdentifier.from("feather:client"); private final byte[] packet; public Feather() { @@ -50,7 +52,7 @@ public class Feather { packet = obj.toString().getBytes(); } - public void sendRestrictions(ProxiedPlayer player) { - player.sendData(CHANNEL, packet); + public void sendRestrictions(Player player) { + player.sendPluginMessage(CHANNEL, packet); } } diff --git a/src/de/steamwar/bungeecore/mods/Hostname.java b/src/de/steamwar/bungeecore/mods/Hostname.java index 23820b5..f6d9f23 100644 --- a/src/de/steamwar/bungeecore/mods/Hostname.java +++ b/src/de/steamwar/bungeecore/mods/Hostname.java @@ -19,20 +19,19 @@ package de.steamwar.bungeecore.mods; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.proxy.ProxyPingEvent; import de.steamwar.bungeecore.VelocityCore; -import de.steamwar.bungeecore.listeners.BasicListener; -import net.md_5.bungee.api.event.PlayerHandshakeEvent; -import net.md_5.bungee.connection.InitialHandler; -import net.md_5.bungee.event.EventHandler; +import de.steamwar.bungeecore.util.annotations.Create; import java.util.HashSet; import java.util.Set; import java.util.logging.Level; -public class Hostname extends BasicListener { +@Create +public class Hostname { private final Set knownHostnames = new HashSet<>(); - private final Set knownExtraData = new HashSet<>(); public Hostname() { knownHostnames.add("steamwar.de"); @@ -45,22 +44,13 @@ public class Hostname extends BasicListener { knownHostnames.add("wtf.mynx.lol"); //https://discord.com/invite/serverseeker knownHostnames.add("masscan"); knownHostnames.add("aaa"); - - knownExtraData.add(""); - knownExtraData.add("\0FML\0"); - knownExtraData.add("\0FML2\0"); - knownExtraData.add("\0FML3\0"); - knownExtraData.add("\0FORGE"); } - @EventHandler - public void onHandshake(PlayerHandshakeEvent event) { - String hostname = event.getHandshake().getHost().toLowerCase(); - String extraDataInHandshake = ((InitialHandler) event.getConnection()).getExtraDataInHandshake(); + @Subscribe + public void onHandshake(ProxyPingEvent event) { + String hostname = event.getConnection().getVirtualHost().map(inetSocketAddress -> inetSocketAddress.getHostName()).orElse(""); if (!knownHostnames.contains(hostname) && !hostname.endsWith(".steamwar.de")) { - VelocityCore.getLogger().log(Level.WARNING, () -> event.getConnection().getSocketAddress() + " connected with unknown hostname " + event.getHandshake() + " " + extraDataInHandshake); - } else if (!knownExtraData.contains(extraDataInHandshake)) { - VelocityCore.getLogger().log(Level.WARNING, () -> event.getConnection().getSocketAddress() + " connected with unknown extra data " + event.getHandshake() + " " + extraDataInHandshake); + VelocityCore.get().getLogger().log(Level.WARNING, () -> event.getConnection().getRemoteAddress().toString() + " connected with unknown hostname '" + hostname + "'"); } } } diff --git a/src/de/steamwar/bungeecore/mods/LabyMod.java b/src/de/steamwar/bungeecore/mods/LabyMod.java index 6cc1900..8ac12ec 100644 --- a/src/de/steamwar/bungeecore/mods/LabyMod.java +++ b/src/de/steamwar/bungeecore/mods/LabyMod.java @@ -22,48 +22,53 @@ package de.steamwar.bungeecore.mods; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.proxy.protocol.ProtocolUtils; import de.steamwar.bungeecore.VelocityCore; import de.steamwar.bungeecore.listeners.PluginMessage; +import de.steamwar.bungeecore.util.annotations.Create; import de.steamwar.sql.Mod; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PluginMessageEvent; -import net.md_5.bungee.protocol.DefinedPacket; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; +@Create public class LabyMod { // https://docs.labymod.net/pages/server/introduction/ // https://github.com/LabyMod/labymod-server-api // https://dl.labymod.net/addons.json + private final ModUtils utils; + private final byte[] gameInfoPacket; - public LabyMod() { + public LabyMod(ModUtils utils) { + this.utils = utils; gameInfoPacket = PluginMessage.genBufPacket(buf -> { - DefinedPacket.writeString("discord_rpc", buf); + ProtocolUtils.writeString(buf, "discord_rpc"); JsonObject json = new JsonObject(); json.addProperty("hasGame", true); json.addProperty("game_mode", "steamwar.de"); json.addProperty("game_startTime", 0); json.addProperty("game_endTime", 0); - DefinedPacket.writeString(json.toString(), buf); + ProtocolUtils.writeString(buf, json.toString()); }); } public void handlePluginMessage(PluginMessageEvent event) { - ProxiedPlayer player = (ProxiedPlayer) event.getSender(); - player.sendData(event.getTag(), gameInfoPacket); + Player player = (Player) event.getSource(); + player.sendPluginMessage(event.getIdentifier(), gameInfoPacket); ByteBuf buf = Unpooled.wrappedBuffer(event.getData()); - String purpose = DefinedPacket.readString(buf); + String purpose = ProtocolUtils.readString(buf); if(!"INFO".equals(purpose)) return; - JsonObject message = JsonParser.parseString(DefinedPacket.readString(buf)).getAsJsonObject(); + JsonObject message = JsonParser.parseString(ProtocolUtils.readString(buf)).getAsJsonObject(); List mods = new LinkedList<>(); if(message.has("addons")) { @@ -74,7 +79,7 @@ public class LabyMod { } if(message.has("mods")) { - VelocityCore.getLogger().log(Level.WARNING, () -> "LabyMod External Mods for debugging: " + message.getAsJsonArray("mods")); + VelocityCore.get().getLogger().log(Level.WARNING, () -> "LabyMod External Mods for debugging: " + message.getAsJsonArray("mods")); for(JsonElement element : message.getAsJsonArray("mods")) { JsonObject addon = element.getAsJsonObject(); //TODO observe: FORGE and FABRIC mods available, do they always and with .jar? (would equal new mod platform) @@ -82,6 +87,6 @@ public class LabyMod { } } - ModUtils.handleMods(player, mods); + utils.handleMods(player, mods); } } diff --git a/src/de/steamwar/bungeecore/mods/Lunar.java b/src/de/steamwar/bungeecore/mods/Lunar.java index 6c260a6..9b8f147 100644 --- a/src/de/steamwar/bungeecore/mods/Lunar.java +++ b/src/de/steamwar/bungeecore/mods/Lunar.java @@ -32,11 +32,14 @@ import com.lunarclient.apollo.option.Options; import com.lunarclient.apollo.player.AbstractApolloPlayer; import com.lunarclient.apollo.player.v1.ModMessage; import com.lunarclient.apollo.player.v1.PlayerHandshakeMessage; +import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.messages.ChannelIdentifier; +import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import de.steamwar.bungeecore.VelocityCore; +import de.steamwar.bungeecore.util.annotations.Create; import de.steamwar.sql.Mod; import lombok.AllArgsConstructor; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PluginMessageEvent; import java.util.ArrayList; import java.util.List; @@ -44,13 +47,16 @@ import java.util.UUID; import java.util.function.Consumer; import java.util.logging.Level; +@Create public class Lunar { // https://lunarclient.dev/apollo/introduction // https://github.com/LunarClient/Apollo private final ApolloModuleManager manager = new ApolloModuleManagerImpl().addModule(ModSettingModule.class); - public Lunar() { //TODO seems defunct + private final ModUtils utils; + + public Lunar(ModUtils utils) { //TODO seems defunct Options modSettings = manager.getModule(ModSettingModule.class).getOptions(); modSettings.set(ModReplaymod.ENABLED, false); // TODO check if restrictions working modSettings.set(ModFreelook.ENABLED, false); @@ -60,14 +66,16 @@ public class Lunar { modSettings.set(ModTeamView.ENABLED, false); modSettings.set(ModTntCountdown.ENABLED, false); modSettings.set(ModToggleSneak.TOGGLE_SNEAK_CONTAINER, false); + + this.utils = utils; } - public void sendRestrictions(ProxiedPlayer player) { + public void sendRestrictions(Player player) { NetworkOptions.sendOptions(manager.getModules(), true, new SWApolloPlayer(player)); } public void handlePluginMessage(PluginMessageEvent event) { - ProxiedPlayer player = (ProxiedPlayer) event.getSender(); + Player player = (Player) event.getSource(); Any packet; try { @@ -94,12 +102,12 @@ public class Lunar { case TYPE_UNSPECIFIED: case UNRECOGNIZED: default: - VelocityCore.getLogger().log(Level.INFO, () -> player.getName() + " uses Lunar mod with unknown type " + mod); + VelocityCore.get().getLogger().log(Level.INFO, () -> player.getUsername() + " uses Lunar mod with unknown type " + mod); break; } } - ModUtils.handleMods(player, mods); + utils.handleMods(player, mods); }); } @@ -112,7 +120,9 @@ public class Lunar { @AllArgsConstructor private static class SWApolloPlayer extends AbstractApolloPlayer { - private final ProxiedPlayer player; + private static final ChannelIdentifier CHANNEL = MinecraftChannelIdentifier.from(ApolloManager.PLUGIN_MESSAGE_CHANNEL); + + private final Player player; @Override public void sendPacket(Message message) { @@ -121,11 +131,11 @@ public class Lunar { @Override public void sendPacket(byte[] bytes) { - player.sendData(ApolloManager.PLUGIN_MESSAGE_CHANNEL, bytes); + player.sendPluginMessage(CHANNEL, bytes); } @Override public UUID getUniqueId() { return player.getUniqueId(); } - @Override public String getName() { return player.getName(); } + @Override public String getName() { return player.getUsername(); } @Override public boolean hasPermission(String s) { return player.hasPermission(s); } @Override public Object getPlayer() { return player; } } diff --git a/src/de/steamwar/bungeecore/mods/ModUtils.java b/src/de/steamwar/bungeecore/mods/ModUtils.java index 8df8a36..7ff804a 100644 --- a/src/de/steamwar/bungeecore/mods/ModUtils.java +++ b/src/de/steamwar/bungeecore/mods/ModUtils.java @@ -19,18 +19,17 @@ package de.steamwar.bungeecore.mods; +import com.velocitypowered.api.proxy.Player; import de.steamwar.bungeecore.VelocityCore; import de.steamwar.bungeecore.commands.PunishmentCommand; -import de.steamwar.messages.Chatter; +import de.steamwar.messages.Message; +import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.Mod; import de.steamwar.sql.Mod.ModType; -import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.UserPerm; import lombok.Getter; -import lombok.experimental.UtilityClass; -import net.md_5.bungee.api.chat.BaseComponent; -import net.md_5.bungee.api.chat.TextComponent; -import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import java.sql.Timestamp; import java.time.Instant; @@ -38,23 +37,27 @@ import java.time.temporal.ChronoUnit; import java.util.*; import java.util.function.Consumer; import java.util.logging.Level; +import java.util.logging.Logger; import java.util.stream.Collectors; -@UtilityClass public class ModUtils { + private final Logger logger; @Getter - private static final Map> playerModMap = new HashMap<>(); + private final Map> playerModMap = new HashMap<>(); - public static boolean handleMods(ProxiedPlayer player, List mods) { - return handleMods(player.getUniqueId(), Chatter.of(player).getLocale(), player::disconnect, mods); + public ModUtils() { + this.logger = VelocityCore.getLogger(); } - public static boolean handleMods(UUID uuid, Locale locale, Consumer disconnect, List mods){ - Chatter sender = Chatter.of(uuid); - SteamwarUser user = sender.user(); + public boolean handleMods(Player player, List mods) { + return handleMods(player.getUniqueId(), ChatSender.of(player).getLocale(), player::disconnect, mods); + } + + public boolean handleMods(UUID uuid, Locale locale, Consumer disconnect, List mods){ + SteamwarUser user = SteamwarUser.get(uuid); playerModMap.put(uuid,new ArrayList<>(mods)); - VelocityCore.getLogger().log(Level.INFO, user.getUserName() + " declares mods: " + mods.stream().map(mod -> mod.getPlatform() + ":" + mod.getModName()).collect(Collectors.joining(" "))); + VelocityCore.get().getLogger().log(Level.INFO, user.getUserName() + " declares mods: " + mods.stream().map(mod -> mod.getPlatform() + ":" + mod.getModName()).collect(Collectors.joining(" "))); ModType max = ModType.YELLOW; Iterator it = mods.iterator(); @@ -76,17 +79,17 @@ public class ModUtils { String message; if(mods.size() == 1) { - message = sender.parseToLegacy(max == ModType.RED ? "MOD_RED_SING" : "MOD_YELLOW_SING", locale, modList); + message = Message.parse(max == ModType.RED ? "MOD_RED_SING" : "MOD_YELLOW_SING", locale, modList); } else { - message = sender.parseToLegacy(max == ModType.RED ? "MOD_RED_PLUR" : "MOD_YELLOW_PLUR", locale, modList); + message = Message.parse(max == ModType.RED ? "MOD_RED_PLUR" : "MOD_YELLOW_PLUR", locale, modList); } if(max == ModType.RED) { PunishmentCommand.ban(user, Timestamp.from(Instant.now().plus(7, ChronoUnit.DAYS)), message, SteamwarUser.get(-1), false); - VelocityCore.getLogger().log(Level.SEVERE, user.getUserName() + " " + user.getId() + " wurde automatisch wegen der Mods " + modList + " gebannt."); + logger.log(Level.SEVERE, user.getUserName() + " " + user.getId() + " wurde automatisch wegen der Mods " + modList + " gebannt."); } - disconnect.accept(TextComponent.fromLegacy(message)); + disconnect.accept(LegacyComponentSerializer.legacySection().deserialize(message)); return false; } } diff --git a/src/de/steamwar/bungeecore/mods/ReplayMod.java b/src/de/steamwar/bungeecore/mods/ReplayMod.java index d09eb6e..a12efed 100644 --- a/src/de/steamwar/bungeecore/mods/ReplayMod.java +++ b/src/de/steamwar/bungeecore/mods/ReplayMod.java @@ -55,7 +55,7 @@ public class ReplayMod extends BasicListener { public void onPlayerJoin(ServerSwitchEvent event) { ProxiedPlayer player = event.getPlayer(); ServerInfo server = player.getServer().getInfo(); - if(ProxyServer.getInstance().getServerInfo(VelocityCore.get().getConfig().getLobbyserver()) == server) + if(ProxyServer.getInstance().getServerInfo(VelocityCore.LOBBY_SERVER) == server) return; Subserver subserver = Subserver.getSubserver(server); diff --git a/src/de/steamwar/bungeecore/mods/Schematica.java b/src/de/steamwar/bungeecore/mods/Schematica.java index c39ad59..20b33a7 100644 --- a/src/de/steamwar/bungeecore/mods/Schematica.java +++ b/src/de/steamwar/bungeecore/mods/Schematica.java @@ -19,9 +19,10 @@ package de.steamwar.bungeecore.mods; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.PostLoginEvent; +import com.velocitypowered.api.proxy.messages.LegacyChannelIdentifier; import de.steamwar.bungeecore.listeners.BasicListener; -import net.md_5.bungee.api.event.PostLoginEvent; -import net.md_5.bungee.event.EventHandler; public class Schematica extends BasicListener { // https://github.com/Lunatrius/SchematicaPlugin/blob/master/src/main/java/com/github/lunatrius/schematica/plugin/SchematicaPlugin.java @@ -33,8 +34,8 @@ public class Schematica extends BasicListener { /* PERM_LOAD */ 1 }; - @EventHandler + @Subscribe public void onPostLogin(PostLoginEvent event) { - event.getPlayer().sendData("schematica", packet); + event.getPlayer().sendPluginMessage(new LegacyChannelIdentifier("schematica"), packet); } } diff --git a/src/de/steamwar/bungeecore/mods/ServerListPing.java b/src/de/steamwar/bungeecore/mods/ServerListPing.java index e774794..f465903 100644 --- a/src/de/steamwar/bungeecore/mods/ServerListPing.java +++ b/src/de/steamwar/bungeecore/mods/ServerListPing.java @@ -20,44 +20,64 @@ package de.steamwar.bungeecore.mods; import com.google.gson.*; -import de.steamwar.bungeecore.listeners.BasicListener; -import net.md_5.bungee.BungeeCord; -import net.md_5.bungee.api.ServerPing; +import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.api.proxy.server.ServerPing; +import de.steamwar.bungeecore.VelocityCore; import java.lang.reflect.Field; import java.lang.reflect.Type; -public class ServerListPing extends BasicListener implements JsonSerializer, JsonDeserializer { +public class ServerListPing { // https://github.com/Aizistral-Studios/No-Chat-Reports/discussions/206 // https://github.com/Aizistral-Studios/No-Chat-Reports/wiki/How-to-Get-Safe-Server-Status - private final Gson gson; + @SuppressWarnings("unused") + private final ProxyServer proxyServer; + + private static final String[] FIELDS_TO_OVERRIDE = new String[] { + "PRE_1_16_PING_SERIALIZER", + "PRE_1_20_3_PING_SERIALIZER", + "MODERN_PING_SERIALIZER" + }; public ServerListPing() { - BungeeCord bungeeCord = BungeeCord.getInstance(); - gson = bungeeCord.gson; + this.proxyServer = VelocityCore.getProxy(); try { - Field gsonField = BungeeCord.class.getDeclaredField("gson"); - gsonField.setAccessible(true); - gsonField.set(bungeeCord, gson.newBuilder().registerTypeAdapter(ServerPing.class, this).create()); + for (String fieldName : FIELDS_TO_OVERRIDE) { + Field field = proxyServer.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + Object obj = field.get(null); + if (obj instanceof Gson gsonOld) { + Gson gsonNew = new GsonBuilder() + .registerTypeAdapter(ServerPing.class, new ServerListPingSerializer(gsonOld)) + .create(); + field.set(null, gsonNew); + } else { + throw new SecurityException("Failed to inject ServerListPing in " + fieldName); + } + } } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { throw new SecurityException("Failed to inject ServerListPing", e); } } - @Override - public JsonElement serialize(ServerPing ping, Type type, JsonSerializationContext context) { - JsonElement element = gson.toJsonTree(ping, type); + private record ServerListPingSerializer( + Gson gson) implements JsonSerializer, JsonDeserializer { - JsonObject object = element.getAsJsonObject(); - object.addProperty("preventsChatReports", true); + @Override + public JsonElement serialize(ServerPing ping, Type type, JsonSerializationContext context) { + JsonElement element = gson.toJsonTree(ping, type); - return element; - } + JsonObject object = element.getAsJsonObject(); + object.addProperty("preventsChatReports", true); - @Override - public ServerPing deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { - return gson.fromJson(element, ServerPing.class); - } + return element; + } + + @Override + public ServerPing deserialize(JsonElement element, Type type, JsonDeserializationContext context) throws JsonParseException { + return gson.fromJson(element, ServerPing.class); + } + } } diff --git a/src/de/steamwar/bungeecore/mods/WorldDownloader.java b/src/de/steamwar/bungeecore/mods/WorldDownloader.java index d18be4c..45e2f04 100644 --- a/src/de/steamwar/bungeecore/mods/WorldDownloader.java +++ b/src/de/steamwar/bungeecore/mods/WorldDownloader.java @@ -19,9 +19,9 @@ package de.steamwar.bungeecore.mods; +import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.proxy.Player; import de.steamwar.bungeecore.listeners.PluginMessage; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PluginMessageEvent; public class WorldDownloader { // https://wiki.vg/Plugin_channels/World_downloader @@ -43,6 +43,6 @@ public class WorldDownloader { } public void handlePluginMessage(PluginMessageEvent event) { - PluginMessage.send((ProxiedPlayer) event.getSender(), "WDL|CONTROL", "wdl:control", controlPacket); + PluginMessage.send((Player) event.getSource(), "WDL|CONTROL", "wdl:control", controlPacket); } } diff --git a/src/de/steamwar/bungeecore/network/handlers/FightInfoHandler.java b/src/de/steamwar/bungeecore/network/handlers/FightInfoHandler.java index 64a30da..2b6fbba 100644 --- a/src/de/steamwar/bungeecore/network/handlers/FightInfoHandler.java +++ b/src/de/steamwar/bungeecore/network/handlers/FightInfoHandler.java @@ -21,13 +21,12 @@ package de.steamwar.bungeecore.network.handlers; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.server.RegisteredServer; +import com.velocitypowered.api.proxy.server.ServerInfo; import de.steamwar.bungeecore.network.NetworkSender; import de.steamwar.bungeecore.network.ServerMetaInfo; import de.steamwar.bungeecore.tablist.TablistManager; import de.steamwar.network.packets.PacketHandler; import de.steamwar.network.packets.common.FightInfoPacket; -import net.md_5.bungee.api.config.ServerInfo; -import net.md_5.bungee.api.connection.ProxiedPlayer; import java.util.HashSet; import java.util.Iterator; @@ -47,16 +46,16 @@ public class FightInfoHandler extends PacketHandler { @Handler public void handle(FightInfoPacket packet) { - ServerInfo info = ((ServerMetaInfo) packet.getMetaInfos()).getSender(); + RegisteredServer info = ((ServerMetaInfo) packet.getMetaInfos()).getSender().getServer(); - FightInfoPacket lobbyPacket = packet.withServerName(info.getName()); + FightInfoPacket lobbyPacket = packet.withServerName(info.getServerInfo().getName()); TablistManager.newFightInfo(info, packet); - Iterator lobbyIt = lobbys.iterator(); + Iterator lobbyIt = lobbys.iterator(); while(lobbyIt.hasNext()) { - ServerInfo lobby = lobbyIt.next(); - Iterator it = lobby.getPlayers().iterator(); + RegisteredServer lobby = lobbyIt.next(); + Iterator it = lobby.getPlayersConnected().iterator(); if(!it.hasNext()){ lobbyIt.remove(); continue; diff --git a/src/de/steamwar/bungeecore/tablist/TablistManager.java b/src/de/steamwar/bungeecore/tablist/TablistManager.java index 4e56855..ea47b95 100644 --- a/src/de/steamwar/bungeecore/tablist/TablistManager.java +++ b/src/de/steamwar/bungeecore/tablist/TablistManager.java @@ -19,40 +19,32 @@ package de.steamwar.bungeecore.tablist; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.server.RegisteredServer; import de.steamwar.bungeecore.VelocityCore; -import de.steamwar.bungeecore.Servertype; -import de.steamwar.bungeecore.Storage; -import de.steamwar.bungeecore.Subserver; import de.steamwar.bungeecore.listeners.BasicListener; import de.steamwar.network.packets.common.FightInfoPacket; -import net.md_5.bungee.api.ProxyServer; -import net.md_5.bungee.api.config.ServerInfo; -import net.md_5.bungee.api.connection.ProxiedPlayer; -import net.md_5.bungee.api.event.PlayerDisconnectEvent; -import net.md_5.bungee.api.event.PostLoginEvent; -import net.md_5.bungee.api.event.ServerSwitchEvent; -import net.md_5.bungee.event.EventHandler; import java.util.*; import java.util.concurrent.TimeUnit; public class TablistManager extends BasicListener { - private static final Map fightInfos = new HashMap<>(); + private static final Map fightInfos = new HashMap<>(); - public static synchronized void newFightInfo(ServerInfo info, FightInfoPacket packet) { + public static synchronized void newFightInfo(RegisteredServer info, FightInfoPacket packet) { fightInfos.put(info, packet); - fightInfos.keySet().removeIf(serverInfo -> serverInfo.getPlayers().isEmpty()); + fightInfos.keySet().removeIf(serverInfo -> serverInfo.getPlayersConnected().isEmpty()); } - private final Map tablists = new HashMap<>(); + private final Map tablists = new HashMap<>(); private int seconds = 0; public TablistManager() { - ProxyServer.getInstance().getScheduler().schedule(VelocityCore.get(), this::updateTablist, 1, 1, TimeUnit.SECONDS); + VelocityCore.schedule(this::updateTablist).repeat(1, TimeUnit.SECONDS); synchronized (tablists) { - ProxyServer.getInstance().getPlayers().forEach(player -> tablists.put(player, new Tablist(player))); + VelocityCore.getProxy().getAllPlayers().forEach(player -> tablists.put(player, new Tablist(player))); } }