From 65e4ebeb6d26246daee237ac9b6eee42a97f74b8 Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sat, 11 Dec 2021 16:55:36 +0100 Subject: [PATCH 1/2] Spigot 1.18 Support --- .../de/steamwar/core/FlatteningWrapper14.java | 6 +- SpigotCore_18/build.gradle | 50 ++++ SpigotCore_18/settings.gradle | 20 ++ .../steamwar/core/CraftbukkitWrapper18.java | 42 +++ SpigotCore_Main/build.gradle | 5 +- .../comphenix/tinyprotocol/Reflection.java | 104 +++---- .../comphenix/tinyprotocol/TinyProtocol.java | 261 +++++------------- .../src/de/steamwar/core/Core.java | 33 ++- .../core/authlib/AuthlibInjector.java | 2 +- .../steamwar/core/events/ChunkListener.java | 31 +-- .../de/steamwar/scoreboard/SWScoreboard.java | 20 +- build.gradle | 9 + settings.gradle | 1 + 13 files changed, 260 insertions(+), 324 deletions(-) create mode 100644 SpigotCore_18/build.gradle create mode 100644 SpigotCore_18/settings.gradle create mode 100644 SpigotCore_18/src/de/steamwar/core/CraftbukkitWrapper18.java diff --git a/SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java b/SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java index 3a28106..2092669 100644 --- a/SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java +++ b/SpigotCore_14/src/de/steamwar/core/FlatteningWrapper14.java @@ -222,15 +222,15 @@ public class FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper renamedLegacy.put("RECORD_12", Material.MUSIC_DISC_WAIT); } - private static final Reflection.FieldAccessor scoreboardName = Reflection.getField(SWScoreboard.scoreboardObjective, Reflection.getClass("{nms}.IChatBaseComponent"), 0); - private static final Reflection.ConstructorInvoker chatComponentConstructor = Reflection.getConstructor(Reflection.getClass("{nms}.ChatComponentText"), String.class); + private static final Reflection.FieldAccessor scoreboardName = Reflection.getField(SWScoreboard.scoreboardObjective, Reflection.getClass("{nms.network.chat}.IChatBaseComponent"), 0); + private static final Reflection.ConstructorInvoker chatComponentConstructor = Reflection.getConstructor(Reflection.getClass("{nms.network.chat}.ChatComponentText"), String.class); @Override public void setScoreboardTitle(Object packet, String title) { scoreboardName.set(packet, chatComponentConstructor.invoke(title)); } - private static final Class scoreActionEnum = Reflection.getClass("{nms}.ScoreboardServer$Action"); + private static final Class scoreActionEnum = Reflection.getClass("{nms.server}.ScoreboardServer$Action"); private static final Reflection.FieldAccessor scoreAction = Reflection.getField(SWScoreboard.scoreboardScore, scoreActionEnum, 0); private static final Object scoreActionChange = scoreActionEnum.getEnumConstants()[0]; diff --git a/SpigotCore_18/build.gradle b/SpigotCore_18/build.gradle new file mode 100644 index 0000000..c6185e9 --- /dev/null +++ b/SpigotCore_18/build.gradle @@ -0,0 +1,50 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +plugins { + id 'base' + id 'java' +} + +group 'steamwar' +version '1.0' + +compileJava.options.encoding = 'UTF-8' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +sourceSets { + main { + java { + srcDirs = ['src/'] + } + resources { + srcDirs = ['src/'] + exclude '**/*.java', '**/*.kt' + } + } +} + +dependencies { + implementation project(":SpigotCore_Main") + + compileOnly 'org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT' + compileOnly files("${project.rootDir}/lib/Spigot-1.18.jar") +} diff --git a/SpigotCore_18/settings.gradle b/SpigotCore_18/settings.gradle new file mode 100644 index 0000000..8943e4f --- /dev/null +++ b/SpigotCore_18/settings.gradle @@ -0,0 +1,20 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +rootProject.name = 'SpigotCore_18' \ No newline at end of file diff --git a/SpigotCore_18/src/de/steamwar/core/CraftbukkitWrapper18.java b/SpigotCore_18/src/de/steamwar/core/CraftbukkitWrapper18.java new file mode 100644 index 0000000..594fbac --- /dev/null +++ b/SpigotCore_18/src/de/steamwar/core/CraftbukkitWrapper18.java @@ -0,0 +1,42 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2021 SteamWar.de-Serverteam + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +package de.steamwar.core; + +import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.level.chunk.Chunk; +import org.bukkit.craftbukkit.v1_18_R1.CraftChunk; +import org.bukkit.craftbukkit.v1_18_R1.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class CraftbukkitWrapper18 implements CraftbukkitWrapper.ICraftbukkitWrapper { + + @Override + public void sendChunk(Player p, int chunkX, int chunkZ) { + Chunk chunk = ((CraftChunk)p.getWorld().getChunkAt(chunkX, chunkZ)).getHandle(); + ((CraftPlayer)p).getHandle().b.a(new ClientboundLevelChunkWithLightPacket(chunk, chunk.q.l_(), null, null, false)); + } + + @Override + @SuppressWarnings("deprecation") + public double[] getSpigotTPS() { + return MinecraftServer.getServer().recentTps; + } +} diff --git a/SpigotCore_Main/build.gradle b/SpigotCore_Main/build.gradle index 746d01e..1eb2599 100644 --- a/SpigotCore_Main/build.gradle +++ b/SpigotCore_Main/build.gradle @@ -43,7 +43,10 @@ sourceSets { } dependencies { - compileOnly files("${project.rootDir}/lib/Spigot-1.15.jar") + compileOnly 'org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT' + compileOnly 'io.netty:netty-all:4.1.68.Final' + compileOnly 'com.mojang:authlib:1.5.25' + compileOnly 'mysql:mysql-connector-java:5.1.49' compileOnly files("${project.rootDir}/lib/WorldEdit-1.12.jar") implementation 'net.wesjd:anvilgui:1.4.0-SNAPSHOT' diff --git a/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java b/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java index 1e18232..e13db9a 100644 --- a/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java +++ b/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java @@ -1,5 +1,6 @@ package com.comphenix.tinyprotocol; +import de.steamwar.core.Core; import org.bukkit.Bukkit; import java.lang.reflect.Constructor; @@ -25,7 +26,7 @@ public final class Reflection { * @param arguments - the arguments to pass to the constructor. * @return The constructed object. */ - public Object invoke(Object... arguments); + Object invoke(Object... arguments); } /** @@ -39,7 +40,7 @@ public final class Reflection { * @param arguments - the arguments to pass to the method. * @return The return value, or NULL if is void. */ - public Object invoke(Object target, Object... arguments); + Object invoke(Object target, Object... arguments); } /** @@ -54,7 +55,7 @@ public final class Reflection { * @param target - the target object, or NULL for a static field. * @return The value of the field. */ - public T get(Object target); + T get(Object target); /** * Set the content of a field. @@ -62,7 +63,7 @@ public final class Reflection { * @param target - the target object, or NULL for a static field. * @param value - the new value of the field. */ - public void set(Object target, Object value); + void set(Object target, Object value); /** * Determine if the given object has this field. @@ -70,16 +71,16 @@ public final class Reflection { * @param target - the object to test. * @return TRUE if it does, FALSE otherwise. */ - public boolean hasField(Object target); + boolean hasField(Object target); } // Deduce the net.minecraft.server.v* package - private static String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName(); - private static String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server"); - private static String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", ""); + private static final String OBC_PREFIX = Bukkit.getServer().getClass().getPackage().getName(); + private static final String NMS_PREFIX = OBC_PREFIX.replace("org.bukkit.craftbukkit", "net.minecraft.server"); + private static final String VERSION = OBC_PREFIX.replace("org.bukkit.craftbukkit", "").replace(".", ""); // Variable replacement - private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}"); + private static final Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}"); private Reflection() { // Seal class @@ -148,7 +149,7 @@ public final class Reflection { try { return (T) field.get(target); } catch (IllegalAccessException e) { - throw new RuntimeException("Cannot access reflection.", e); + throw new IllegalArgumentException("Cannot access reflection.", e); } } @@ -157,7 +158,7 @@ public final class Reflection { try { field.set(target, value); } catch (IllegalAccessException e) { - throw new RuntimeException("Cannot access reflection.", e); + throw new IllegalArgumentException("Cannot access reflection.", e); } } @@ -220,17 +221,12 @@ public final class Reflection { && Arrays.equals(method.getParameterTypes(), params)) { method.setAccessible(true); - return new MethodInvoker() { - - @Override - public Object invoke(Object target, Object... arguments) { - try { - return method.invoke(target, arguments); - } catch (Exception e) { - throw new RuntimeException("Cannot invoke method " + method, e); - } + return (target, arguments) -> { + try { + return method.invoke(target, arguments); + } catch (Exception e) { + throw new IllegalArgumentException("Cannot invoke method " + method, e); } - }; } } @@ -267,17 +263,12 @@ public final class Reflection { if (Arrays.equals(constructor.getParameterTypes(), params)) { constructor.setAccessible(true); - return new ConstructorInvoker() { - - @Override - public Object invoke(Object... arguments) { - try { - return constructor.newInstance(arguments); - } catch (Exception e) { - throw new RuntimeException("Cannot invoke constructor " + constructor, e); - } + return arguments -> { + try { + return constructor.newInstance(arguments); + } catch (Exception e) { + throw new IllegalArgumentException("Cannot invoke constructor " + constructor, e); } - }; } } @@ -290,8 +281,7 @@ public final class Reflection { *

* This is useful when looking up fields by a NMS or OBC type. *

- * - * @see {@link #getClass()} for more information. + * * @param lookupName - the class name with variables. * @return The class. */ @@ -330,40 +320,10 @@ public final class Reflection { * @throws IllegalArgumentException If a variable or class could not be found. */ public static Class getClass(String lookupName) { - return getCanonicalClass(expandVariables(lookupName)); - } - - /** - * Retrieve a class in the net.minecraft.server.VERSION.* package. - * - * @param name - the name of the class, excluding the package. - * @throws IllegalArgumentException If the class doesn't exist. - */ - public static Class getMinecraftClass(String name) { - return getCanonicalClass(NMS_PREFIX + "." + name); - } - - /** - * Retrieve a class in the org.bukkit.craftbukkit.VERSION.* package. - * - * @param name - the name of the class, excluding the package. - * @throws IllegalArgumentException If the class doesn't exist. - */ - public static Class getCraftBukkitClass(String name) { - return getCanonicalClass(OBC_PREFIX + "." + name); - } - - /** - * Retrieve a class by its canonical name. - * - * @param canonicalName - the canonical name. - * @return The class. - */ - private static Class getCanonicalClass(String canonicalName) { try { - return Class.forName(canonicalName); + return Class.forName(expandVariables(lookupName)); } catch (ClassNotFoundException e) { - throw new IllegalArgumentException("Cannot find " + canonicalName, e); + throw new IllegalArgumentException("Cannot find " + expandVariables(lookupName), e); } } @@ -379,14 +339,17 @@ public final class Reflection { while (matcher.find()) { String variable = matcher.group(1); - String replacement = ""; + String replacement; // Expand all detected variables - if ("nms".equalsIgnoreCase(variable)) - replacement = NMS_PREFIX; - else if ("obc".equalsIgnoreCase(variable)) + if (variable.startsWith("nms")) { + if(Core.getVersion() >= 17) + replacement = NMS_PREFIX; + else + replacement = "net.minecraft" + variable.substring(3); + } else if ("obc".equals(variable)) replacement = OBC_PREFIX; - else if ("version".equalsIgnoreCase(variable)) + else if ("version".equals(variable)) replacement = VERSION; else throw new IllegalArgumentException("Unknown variable: " + variable); @@ -401,6 +364,7 @@ public final class Reflection { return output.toString(); } + @SuppressWarnings("deprecation") public static Object newInstance(Class clazz) { try { return clazz.newInstance(); diff --git a/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java index 3d2e41a..1718efc 100644 --- a/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java @@ -5,6 +5,7 @@ import com.comphenix.tinyprotocol.Reflection.MethodInvoker; import com.google.common.collect.Lists; import com.google.common.collect.MapMaker; import com.mojang.authlib.GameProfile; +import de.steamwar.core.Core; import io.netty.channel.*; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -28,18 +29,20 @@ import java.util.logging.Level; * * @author Kristian */ -public abstract class TinyProtocol { +public class TinyProtocol { private static final AtomicInteger ID = new AtomicInteger(0); // Used in order to lookup a channel private static final MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle"); - private static final FieldAccessor getConnection = Reflection.getField("{nms}.EntityPlayer", "playerConnection", Object.class); - private static final FieldAccessor getManager = Reflection.getField("{nms}.PlayerConnection", "networkManager", Object.class); - private static final FieldAccessor getChannel = Reflection.getField("{nms}.NetworkManager", Channel.class, 0); + private static final Class playerConnection = Reflection.getUntypedClass("{nms.network}.PlayerConnection"); + private static final FieldAccessor getConnection = Reflection.getField("{nms.server.level}.EntityPlayer", playerConnection, 0); + private static final Class networkManager = Reflection.getUntypedClass("{nms.network}.NetworkManager"); + private static final FieldAccessor getManager = Reflection.getField(playerConnection, networkManager, 0); + private static final FieldAccessor getChannel = Reflection.getField(networkManager, Channel.class, 0); // Looking up ServerConnection - private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms}.MinecraftServer"); - private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms}.ServerConnection"); + private static final Class minecraftServerClass = Reflection.getUntypedClass("{nms.server}.MinecraftServer"); + private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms.server.network}.ServerConnection"); private static final FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0); private static final FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0); private static final MethodInvoker getNetworkMarkers; @@ -54,46 +57,65 @@ public abstract class TinyProtocol { } // Packets we have to intercept - private static final Class PACKET_LOGIN_IN_START = Reflection.getMinecraftClass("PacketLoginInStart"); + private static final Class PACKET_LOGIN_IN_START = Reflection.getClass("{nms.network.protocol.login}.PacketLoginInStart"); private static final FieldAccessor getGameProfile = Reflection.getField(PACKET_LOGIN_IN_START, GameProfile.class, 0); // Speedup channel lookup - private Map channelLookup = new MapMaker().weakValues().makeMap(); - private Listener listener; + private final Map channelLookup = new MapMaker().weakValues().makeMap(); + private final Listener listener; // Channels that have already been removed - private Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); + private final Set uninjectedChannels = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap()); // List of network markers private Collection networkManagers; // Injected channel handlers - private List serverChannels = Lists.newArrayList(); + private final List serverChannels = Lists.newArrayList(); private ChannelInboundHandlerAdapter serverChannelHandler; private ChannelInitializer beginInitProtocol; private ChannelInitializer endInitProtocol; // Current handler name - private String handlerName; + private final String handlerName; + private volatile boolean closed; + private final Plugin plugin; - protected volatile boolean closed; - protected Plugin plugin; + private PacketFilter inFilter = (player, channel, packet) -> packet; + private PacketFilter outFilter = (player, channel, packet) -> packet; + + public static final TinyProtocol instance = new TinyProtocol(Core.getInstance()); - /** - * Construct a new instance of TinyProtocol, and start intercepting packets for all connected clients and future clients. - *

- * You can construct multiple instances per plugin. - * - * @param plugin - the plugin. - */ public TinyProtocol(final Plugin plugin) { this.plugin = plugin; // Compute handler name - this.handlerName = getHandlerName(); + this.handlerName = "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); // Prepare existing players - registerBukkitEvents(); + listener = new Listener() { + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerLogin(PlayerLoginEvent e) { + if (closed) + return; + + Channel channel = getChannel(e.getPlayer()); + + // Don't inject players that have been explicitly uninjected + if (!uninjectedChannels.contains(channel)) { + injectPlayer(e.getPlayer()); + } + } + + @EventHandler + public void onPluginDisable(PluginDisableEvent e) { + if (e.getPlugin().equals(plugin)) { + close(); + } + } + }; + plugin.getServer().getPluginManager().registerEvents(listener, plugin); try { registerChannelHandler(); @@ -158,37 +180,6 @@ public abstract class TinyProtocol { }; } - /** - * Register bukkit events. - */ - private void registerBukkitEvents() { - listener = new Listener() { - - @EventHandler(priority = EventPriority.LOWEST) - public final void onPlayerLogin(PlayerLoginEvent e) { - if (closed) - return; - - Channel channel = getChannel(e.getPlayer()); - - // Don't inject players that have been explicitly uninjected - if (!uninjectedChannels.contains(channel)) { - injectPlayer(e.getPlayer()); - } - } - - @EventHandler - public final void onPluginDisable(PluginDisableEvent e) { - if (e.getPlugin().equals(plugin)) { - close(); - } - } - - }; - - plugin.getServer().getPluginManager().registerEvents(listener, plugin); - } - @SuppressWarnings("unchecked") private void registerChannelHandler() { Object mcServer = getMinecraftServer.get(Bukkit.getServer()); @@ -204,7 +195,7 @@ public abstract class TinyProtocol { List list = Reflection.getField(serverConnection.getClass(), List.class, i).get(serverConnection); for (Object item : list) { - if (!ChannelFuture.class.isInstance(item)) + if (!(item instanceof ChannelFuture)) break; // Channel future that contains the server connection @@ -225,17 +216,12 @@ public abstract class TinyProtocol { final ChannelPipeline pipeline = serverChannel.pipeline(); // Remove channel handler - serverChannel.eventLoop().execute(new Runnable() { - - @Override - public void run() { - try { - pipeline.remove(serverChannelHandler); - } catch (NoSuchElementException e) { - // That's fine - } + serverChannel.eventLoop().execute(() -> { + try { + pipeline.remove(serverChannelHandler); + } catch (NoSuchElementException e) { + // That's fine } - }); } } @@ -246,120 +232,46 @@ public abstract class TinyProtocol { } } - /** - * Invoked when the server is starting to send a packet to a player. - *

- * Note that this is not executed on the main thread. - * - * @param receiver - the receiving player, NULL for early login/status packets. - * @param channel - the channel that received the packet. Never NULL. - * @param packet - the packet being sent. - * @return The packet to send instead, or NULL to cancel the transmission. - */ public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { - return packet; + return outFilter.onPacket(receiver, channel, packet); } - /** - * Invoked when the server has received a packet from a given player. - *

- * Use {@link Channel#remoteAddress()} to get the remote address of the client. - * - * @param sender - the player that sent the packet, NULL for early login/status packets. - * @param channel - channel that received the packet. Never NULL. - * @param packet - the packet being received. - * @return The packet to recieve instead, or NULL to cancel. - */ public Object onPacketInAsync(Player sender, Channel channel, Object packet) { - return packet; + return inFilter.onPacket(sender, channel, packet); + } + + public void setInFilter(PacketFilter filter) { + inFilter = filter; + } + + public void setOutFilter(PacketFilter filter) { + outFilter = filter; } - /** - * Send a packet to a particular player. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param player - the destination player. - * @param packet - the packet to send. - */ public void sendPacket(Player player, Object packet) { sendPacket(getChannel(player), packet); } - /** - * Send a packet to a particular client. - *

- * Note that {@link #onPacketOutAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet to send. - */ public void sendPacket(Channel channel, Object packet) { channel.pipeline().writeAndFlush(packet); } - /** - * Pretend that a given packet has been received from a player. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param player - the player that sent the packet. - * @param packet - the packet that will be received by the server. - */ public void receivePacket(Player player, Object packet) { receivePacket(getChannel(player), packet); } - /** - * Pretend that a given packet has been received from a given client. - *

- * Note that {@link #onPacketInAsync(Player, Channel, Object)} will be invoked with this packet. - * - * @param channel - client identified by a channel. - * @param packet - the packet that will be received by the server. - */ public void receivePacket(Channel channel, Object packet) { channel.pipeline().context("encoder").fireChannelRead(packet); } - /** - * Retrieve the name of the channel injector, default implementation is "tiny-" + plugin name + "-" + a unique ID. - *

- * Note that this method will only be invoked once. It is no longer necessary to override this to support multiple instances. - * - * @return A unique channel handler name. - */ - protected String getHandlerName() { - return "tiny-" + plugin.getName() + "-" + ID.incrementAndGet(); - } - - /** - * Add a custom channel handler to the given player's channel pipeline, allowing us to intercept sent and received packets. - *

- * This will automatically be called when a player has logged in. - * - * @param player - the player to inject. - */ public void injectPlayer(Player player) { injectChannelInternal(getChannel(player)).player = player; } - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - * @return The intercepted channel, or NULL if it has already been injected. - */ public void injectChannel(Channel channel) { injectChannelInternal(channel); } - /** - * Add a custom channel handler to the given channel. - * - * @param channel - the channel to inject. - * @return The packet interceptor. - */ private PacketInterceptor injectChannelInternal(Channel channel) { try { PacketInterceptor interceptor = (PacketInterceptor) channel.pipeline().get(handlerName); @@ -378,12 +290,6 @@ public abstract class TinyProtocol { } } - /** - * Retrieve the Netty channel associated with a player. This is cached. - * - * @param player - the player. - * @return The Netty channel. - */ public Channel getChannel(Player player) { Channel channel = channelLookup.get(player.getName()); @@ -398,22 +304,10 @@ public abstract class TinyProtocol { return channel; } - /** - * Uninject a specific player. - * - * @param player - the injected player. - */ public void uninjectPlayer(Player player) { uninjectChannel(getChannel(player)); } - /** - * Uninject a specific channel. - *

- * This will also disable the automatic channel injection that occurs when a player has properly logged in. - * - * @param channel - the injected channel. - */ public void uninjectChannel(final Channel channel) { // No need to guard against this if we're closing if (!closed) { @@ -421,39 +315,17 @@ public abstract class TinyProtocol { } // See ChannelInjector in ProtocolLib, line 590 - channel.eventLoop().execute(new Runnable() { - - @Override - public void run() { - channel.pipeline().remove(handlerName); - } - - }); + channel.eventLoop().execute(() -> channel.pipeline().remove(handlerName)); } - /** - * Determine if the given player has been injected by TinyProtocol. - * - * @param player - the player. - * @return TRUE if it is, FALSE otherwise. - */ public boolean hasInjected(Player player) { return hasInjected(getChannel(player)); } - /** - * Determine if the given channel has been injected by TinyProtocol. - * - * @param channel - the channel. - * @return TRUE if it is, FALSE otherwise. - */ public boolean hasInjected(Channel channel) { return channel.pipeline().get(handlerName) != null; } - /** - * Cease listening for packets. This is called automatically when your plugin is disabled. - */ public final void close() { if (!closed) { closed = true; @@ -469,11 +341,10 @@ public abstract class TinyProtocol { } } - /** - * Channel handler that is inserted into the player's channel pipeline, allowing us to intercept sent and received packets. - * - * @author Kristian - */ + public interface PacketFilter { + Object onPacket(Player player, Channel channel, Object packet); + } + private final class PacketInterceptor extends ChannelDuplexHandler { // Updated by the login event public volatile Player player; diff --git a/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore_Main/src/de/steamwar/core/Core.java index 82f0705..2bc3194 100644 --- a/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -19,10 +19,10 @@ package de.steamwar.core; +import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.comms.BungeeReceiver; import de.steamwar.core.authlib.AuthlibInjector; import de.steamwar.core.events.ChattingEvent; -import de.steamwar.core.events.ChunkListener; import de.steamwar.core.events.PlayerJoinedEvent; import de.steamwar.core.events.WorldLoadEvent; import de.steamwar.message.Message; @@ -38,25 +38,31 @@ import java.util.logging.Level; public class Core extends JavaPlugin{ + private static final int VERSION; + public static final Message MESSAGE; private static Core instance; - private static final int version; - public static Message MESSAGE; static{ String packageName = Bukkit.getServer().getClass().getPackage().getName(); - if(packageName.contains("1_15")) - version = 15; + if(packageName.contains("1_18")) + VERSION = 18; + else if(packageName.contains("1_15")) + VERSION = 15; else if(packageName.contains("1_14")) - version = 14; + VERSION = 14; + else if(packageName.contains("1_12")) + VERSION = 12; else if(packageName.contains("1_10")) - version = 10; + VERSION = 10; else if(packageName.contains("1_9")) - version = 9; + VERSION = 9; else if(packageName.contains("1_8")) - version = 8; + VERSION = 8; else - version = 12; + VERSION = 18; + + MESSAGE = new Message("SpigotCore", Core.class.getClassLoader()); } private ErrorHandler errorHandler; @@ -75,20 +81,17 @@ public class Core extends JavaPlugin{ Bukkit.getPluginManager().registerEvents(new WorldLoadEvent(), this); getServer().getMessenger().registerIncomingPluginChannel(this, "sw:bridge", new BungeeReceiver()); getServer().getMessenger().registerOutgoingPluginChannel(this, "sw:bridge"); - ChunkListener.init(); AuthlibInjector.inject(); try { Bukkit.getLogger().log(Level.INFO, "Running on: " + new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream())).readLine()); } catch (IOException e) { throw new SecurityException("Could not load Hostname", e); } - - MESSAGE = new Message("SpigotCore", getClassLoader()); } @Override public void onDisable() { - ChunkListener.protocol.close(); + TinyProtocol.instance.close(); errorHandler.unregister(); SQL.close(); } @@ -98,7 +101,7 @@ public class Core extends JavaPlugin{ } public static int getVersion(){ - return version; + return VERSION; } private static void setInstance(Core instance) { diff --git a/SpigotCore_Main/src/de/steamwar/core/authlib/AuthlibInjector.java b/SpigotCore_Main/src/de/steamwar/core/authlib/AuthlibInjector.java index ace4936..0c9c188 100644 --- a/SpigotCore_Main/src/de/steamwar/core/authlib/AuthlibInjector.java +++ b/SpigotCore_Main/src/de/steamwar/core/authlib/AuthlibInjector.java @@ -27,7 +27,7 @@ public class AuthlibInjector { private AuthlibInjector() {} public static void inject() { - Class minecraftServerClass = Reflection.getClass("{nms}.MinecraftServer"); + Class minecraftServerClass = Reflection.getClass("{nms.server}.MinecraftServer"); Reflection.FieldAccessor gameProfile = Reflection.getField(minecraftServerClass, GameProfileRepository.class, 0); Object minecraftServer = Reflection.getTypedMethod(minecraftServerClass, "getServer", minecraftServerClass).invoke(null); gameProfile.set(minecraftServer, new SteamwarGameProfileRepository((YggdrasilGameProfileRepository) gameProfile.get(minecraftServer))); diff --git a/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java b/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java index fe285fe..9e51366 100644 --- a/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java +++ b/SpigotCore_Main/src/de/steamwar/core/events/ChunkListener.java @@ -19,41 +19,14 @@ package de.steamwar.core.events; -import com.comphenix.tinyprotocol.Reflection; -import com.comphenix.tinyprotocol.TinyProtocol; -import de.steamwar.core.Core; import de.steamwar.core.CraftbukkitWrapper; -import de.steamwar.sql.SteamwarUser; -import io.netty.channel.Channel; import org.bukkit.entity.Player; +@Deprecated public class ChunkListener { private ChunkListener(){} - private static final Class mapChunkPacket = Reflection.getClass("{nms}.PacketPlayOutMapChunk"); - private static final Reflection.FieldAccessor fullChunk = Reflection.getField(mapChunkPacket, boolean.class, 0); - private static final Reflection.FieldAccessor chunkX = Reflection.getField(mapChunkPacket, int.class, 0); - private static final Reflection.FieldAccessor chunkZ = Reflection.getField(mapChunkPacket, int.class, 1); - - public static final TinyProtocol protocol = new TinyProtocol(Core.getInstance()){ - @Override - public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { - if ( - !mapChunkPacket.isInstance(packet) || - !SteamwarUser.get(receiver.getUniqueId()).isBedrock() || - fullChunk.get(packet) - ) - return packet; - - CraftbukkitWrapper.impl.sendChunk(receiver, chunkX.get(packet), chunkZ.get(packet)); - return null; - } - }; - - public static void init(){ - //triggering - } - + @Deprecated public static void sendChunk(Player p, int chunkX, int chunkZ) { CraftbukkitWrapper.impl.sendChunk(p, chunkX, chunkZ); } diff --git a/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java b/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java index 67cbeaa..9cde7bc 100644 --- a/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java +++ b/SpigotCore_Main/src/de/steamwar/scoreboard/SWScoreboard.java @@ -20,9 +20,9 @@ package de.steamwar.scoreboard; import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.core.Core; import de.steamwar.core.FlatteningWrapper; -import de.steamwar.core.events.ChunkListener; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -32,14 +32,14 @@ import java.util.Map; public class SWScoreboard { private SWScoreboard() {} - public static final Class scoreboardObjective = Reflection.getClass("{nms}.PacketPlayOutScoreboardObjective"); + public static final Class scoreboardObjective = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutScoreboardObjective"); private static final Reflection.FieldAccessor scoreboardName = Reflection.getField(scoreboardObjective, String.class, 0); private static final Reflection.FieldAccessor scoreboardAction = Reflection.getField(scoreboardObjective, int.class, 0); - private static final Class scoreboardDisplayEnum = Reflection.getClass("{nms}.IScoreboardCriteria$EnumScoreboardHealthDisplay"); + private static final Class scoreboardDisplayEnum = Reflection.getClass("{nms.world.scores.criteria}.IScoreboardCriteria$EnumScoreboardHealthDisplay"); private static final Reflection.FieldAccessor scoreboardDisplayType = Reflection.getField(scoreboardObjective, scoreboardDisplayEnum, 0); private static final Object displayTypeIntegers = scoreboardDisplayEnum.getEnumConstants()[0]; - public static final Class scoreboardScore = Reflection.getClass("{nms}.PacketPlayOutScoreboardScore"); + public static final Class scoreboardScore = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutScoreboardScore"); private static final Reflection.FieldAccessor scoreName = Reflection.getField(scoreboardScore, String.class, 0); private static final Reflection.FieldAccessor scoreScoreboardName = Reflection.getField(scoreboardScore, String.class, 1); private static final Reflection.FieldAccessor scoreValue = Reflection.getField(scoreboardScore, int.class, 0); @@ -52,7 +52,7 @@ public class SWScoreboard { private static final Object[] DISPLAY_SIDEBAR = new Object[2]; static { - Class scoreboardDisplayObjective = Reflection.getClass("{nms}.PacketPlayOutScoreboardDisplayObjective"); + Class scoreboardDisplayObjective = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutScoreboardDisplayObjective"); Reflection.FieldAccessor scoreboardDisplayName = Reflection.getField(scoreboardDisplayObjective, String.class, 0); Reflection.FieldAccessor scoreboardDisplaySlot = Reflection.getField(scoreboardDisplayObjective, int.class, 0); for(int id = 0; id < 2; id++) { @@ -72,16 +72,16 @@ public class SWScoreboard { Player player = scoreboard.getKey(); ScoreboardCallback callback = scoreboard.getValue(); - ChunkListener.protocol.sendPacket(player, DELETE_SCOREBOARD[toggle]); - ChunkListener.protocol.sendPacket(player, createSidebarPacket(callback.getTitle())); + TinyProtocol.instance.sendPacket(player, DELETE_SCOREBOARD[toggle]); + TinyProtocol.instance.sendPacket(player, createSidebarPacket(callback.getTitle())); for(Map.Entry score : callback.getData().entrySet()){ - ChunkListener.protocol.sendPacket(player, createScorePacket(score.getKey(), score.getValue())); + TinyProtocol.instance.sendPacket(player, createScorePacket(score.getKey(), score.getValue())); } Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> { if(!player.isOnline()) return; - ChunkListener.protocol.sendPacket(player, DISPLAY_SIDEBAR[toggle]); + TinyProtocol.instance.sendPacket(player, DISPLAY_SIDEBAR[toggle]); }, 2); } }, 10, 5); @@ -96,7 +96,7 @@ public class SWScoreboard { if(playerBoards.remove(player) == null || !player.isOnline()) return; - ChunkListener.protocol.sendPacket(player, DELETE_SCOREBOARD[toggle]); + TinyProtocol.instance.sendPacket(player, DELETE_SCOREBOARD[toggle]); } private static Object createSidebarPacket(String name){ diff --git a/build.gradle b/build.gradle index 2230e6a..52eae83 100644 --- a/build.gradle +++ b/build.gradle @@ -74,6 +74,14 @@ allprojects { maven { url = uri("https://repo.codemc.io/repository/maven-snapshots/") } + + maven { + url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/') + } + + maven { + url = uri('https://libraries.minecraft.net') + } } } @@ -85,6 +93,7 @@ dependencies { implementation project(":SpigotCore_12") implementation project(":SpigotCore_14") implementation project(":SpigotCore_15") + implementation project(":SpigotCore_18") } task buildProject { diff --git a/settings.gradle b/settings.gradle index 44cbeeb..0bd9de2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -20,6 +20,7 @@ rootProject.name = 'SpigotCore' include 'SpigotCore_Main' +include 'SpigotCore_18' include 'SpigotCore_15' include 'SpigotCore_14' include 'SpigotCore_12' From 1ba50faad314431cfd5d6214eb7312f064b5b72b Mon Sep 17 00:00:00 2001 From: Lixfel Date: Sun, 12 Dec 2021 09:56:15 +0100 Subject: [PATCH 2/2] Bugfixes --- .../comphenix/tinyprotocol/Reflection.java | 4 ++-- .../comphenix/tinyprotocol/TinyProtocol.java | 19 +++++++------------ .../src/de/steamwar/core/Core.java | 1 + SpigotCore_Main/src/plugin.yml | 3 ++- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java b/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java index e13db9a..1742df4 100644 --- a/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java +++ b/SpigotCore_Main/src/com/comphenix/tinyprotocol/Reflection.java @@ -344,9 +344,9 @@ public final class Reflection { // Expand all detected variables if (variable.startsWith("nms")) { if(Core.getVersion() >= 17) - replacement = NMS_PREFIX; - else replacement = "net.minecraft" + variable.substring(3); + else + replacement = NMS_PREFIX; } else if ("obc".equals(variable)) replacement = OBC_PREFIX; else if ("version".equals(variable)) diff --git a/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java index 1718efc..c526594 100644 --- a/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java +++ b/SpigotCore_Main/src/com/comphenix/tinyprotocol/TinyProtocol.java @@ -34,7 +34,7 @@ public class TinyProtocol { // Used in order to lookup a channel private static final MethodInvoker getPlayerHandle = Reflection.getMethod("{obc}.entity.CraftPlayer", "getHandle"); - private static final Class playerConnection = Reflection.getUntypedClass("{nms.network}.PlayerConnection"); + private static final Class playerConnection = Reflection.getUntypedClass("{nms.server.network}.PlayerConnection"); private static final FieldAccessor getConnection = Reflection.getField("{nms.server.level}.EntityPlayer", playerConnection, 0); private static final Class networkManager = Reflection.getUntypedClass("{nms.network}.NetworkManager"); private static final FieldAccessor getManager = Reflection.getField(playerConnection, networkManager, 0); @@ -45,16 +45,7 @@ public class TinyProtocol { private static final Class serverConnectionClass = Reflection.getUntypedClass("{nms.server.network}.ServerConnection"); private static final FieldAccessor getMinecraftServer = Reflection.getField("{obc}.CraftServer", minecraftServerClass, 0); private static final FieldAccessor getServerConnection = Reflection.getField(minecraftServerClass, serverConnectionClass, 0); - private static final MethodInvoker getNetworkMarkers; - static { - MethodInvoker networkMarkers; - try { - networkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, List.class, serverConnectionClass); - } catch (IllegalStateException e) { // Paper, wtf why. - networkMarkers = Reflection.getTypedMethod(serverConnectionClass, null, Queue.class, serverConnectionClass); - } - getNetworkMarkers = networkMarkers; - } + private static final FieldAccessor getNetworkMarkers = Reflection.getField(serverConnectionClass, Collection.class, 1); // Packets we have to intercept private static final Class PACKET_LOGIN_IN_START = Reflection.getClass("{nms.network.protocol.login}.PacketLoginInStart"); @@ -86,6 +77,10 @@ public class TinyProtocol { public static final TinyProtocol instance = new TinyProtocol(Core.getInstance()); + public static void init() { + //enforce init + } + public TinyProtocol(final Plugin plugin) { this.plugin = plugin; @@ -187,7 +182,7 @@ public class TinyProtocol { boolean looking = true; // We need to synchronize against this list - networkManagers = (Collection) getNetworkMarkers.invoke(null, serverConnection); + networkManagers = getNetworkMarkers.get(serverConnection); createServerChannelHandler(); // Find the correct list, or implicitly throw an exception diff --git a/SpigotCore_Main/src/de/steamwar/core/Core.java b/SpigotCore_Main/src/de/steamwar/core/Core.java index 2bc3194..5cb4e64 100644 --- a/SpigotCore_Main/src/de/steamwar/core/Core.java +++ b/SpigotCore_Main/src/de/steamwar/core/Core.java @@ -82,6 +82,7 @@ public class Core extends JavaPlugin{ getServer().getMessenger().registerIncomingPluginChannel(this, "sw:bridge", new BungeeReceiver()); getServer().getMessenger().registerOutgoingPluginChannel(this, "sw:bridge"); AuthlibInjector.inject(); + TinyProtocol.init(); try { Bukkit.getLogger().log(Level.INFO, "Running on: " + new BufferedReader(new InputStreamReader(Runtime.getRuntime().exec("hostname").getInputStream())).readLine()); } catch (IOException e) { diff --git a/SpigotCore_Main/src/plugin.yml b/SpigotCore_Main/src/plugin.yml index 8eee87b..115baf6 100644 --- a/SpigotCore_Main/src/plugin.yml +++ b/SpigotCore_Main/src/plugin.yml @@ -7,4 +7,5 @@ softdepend: - WorldEdit main: de.steamwar.core.Core -commands: \ No newline at end of file +libraries: + - mysql:mysql-connector-java:5.1.49 \ No newline at end of file