From 0195f7edf60fe6c24dc24b74009abecef54a4338 Mon Sep 17 00:00:00 2001 From: SBDeveloper Date: Tue, 27 Sep 2022 20:43:54 +0200 Subject: [PATCH 1/2] Removed ProtocolLib dependency, untested --- pom.xml | 32 +-- .../mapreflectionapi/MapReflectionAPI.java | 9 +- .../listeners/PacketListener.java | 185 +++++++++++------- .../utils/ReflectionUtil.java | 9 + src/main/resources/plugin.yml | 1 - 5 files changed, 145 insertions(+), 91 deletions(-) diff --git a/pom.xml b/pom.xml index c0c8e2e..17a47bb 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ tech.sbdevelopment MapReflectionAPI - 1.3 + 1.4 jar MapReflectionAPI @@ -188,13 +188,7 @@ org.spigotmc spigot-api - 1.19.1-R0.1-SNAPSHOT - provided - - - com.comphenix.protocol - ProtocolLib - 5.0.0-SNAPSHOT + 1.19.2-R0.1-SNAPSHOT provided @@ -204,19 +198,25 @@ provided - - - org.jetbrains - annotations-java5 - 23.0.0 - provided - - org.bstats bstats-bukkit 3.0.0 compile + + + + org.jetbrains + annotations-java5 + 23.0.0 + provided + + + io.netty + netty-transport + 4.1.77.Final + provided + \ No newline at end of file diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java index d4a0555..df43435 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java @@ -19,7 +19,6 @@ package tech.sbdevelopment.mapreflectionapi; import com.bergerkiller.bukkit.common.map.MapColorPalette; -import com.comphenix.protocol.ProtocolLibrary; import org.bstats.bukkit.Metrics; import org.bstats.charts.SingleLineChart; import org.bukkit.Bukkit; @@ -84,12 +83,6 @@ public class MapReflectionAPI extends JavaPlugin { } MapColorPalette.getColor(0, 0, 0); //Initializes the class - if (!Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) { - getLogger().severe("MapReflectionAPI requires ProtocolLib to function!"); - Bukkit.getPluginManager().disablePlugin(this); - return; - } - getLogger().info("Loading the configuration..."); Configuration.init(this); @@ -120,7 +113,7 @@ public class MapReflectionAPI extends JavaPlugin { getLogger().info("Registering the listeners..."); Bukkit.getPluginManager().registerEvents(new MapListener(), this); - ProtocolLibrary.getProtocolManager().addPacketListener(new PacketListener(this)); + Bukkit.getPluginManager().registerEvents(new PacketListener(), this); getLogger().info("Loading metrics..."); Metrics metrics = new Metrics(this, 16033); diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java index 24f8c12..7887358 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java @@ -18,90 +18,143 @@ package tech.sbdevelopment.mapreflectionapi.listeners; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.wrappers.EnumWrappers; -import com.comphenix.protocol.wrappers.WrappedEnumEntityUseAction; +import io.netty.channel.Channel; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.Plugin; import org.bukkit.util.Vector; import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; import tech.sbdevelopment.mapreflectionapi.api.events.CreateInventoryMapUpdateEvent; import tech.sbdevelopment.mapreflectionapi.api.events.MapCancelEvent; import tech.sbdevelopment.mapreflectionapi.api.events.MapInteractEvent; +import tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil; -public class PacketListener extends PacketAdapter { - public PacketListener(Plugin plugin) { - super(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MAP, PacketType.Play.Client.USE_ENTITY, PacketType.Play.Client.SET_CREATIVE_SLOT); +import java.util.concurrent.TimeUnit; + +import static tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil.*; + +public class PacketListener implements Listener { + private static final Class packetPlayOutMapClass = getNMSClass("network.protocol.game", "PacketPlayOutMap"); + private static final Class packetPlayInUseEntityClass = getNMSClass("network.protocol.game", "PacketPlayInUseEntity"); + private static final Class packetPlayInSetCreativeSlotClass = getNMSClass("network.protocol.game", "packetPlayInSetCreativeSlot"); + private static final Class vec3DClass = getNMSClass("world.phys", "Vec3D"); + private static final Class craftStackClass = getCraftClass("CraftItemStack"); + + @EventHandler + public void onJoin(PlayerJoinEvent e) { + injectPlayer(e.getPlayer()); } - @Override - public void onPacketSending(PacketEvent event) { - if (event.getPacketType() == PacketType.Play.Server.MAP) { - handleOUTMapPacket(event); - } + @EventHandler + public void onQuit(PlayerQuitEvent e) { + removePlayer(e.getPlayer()); } - @Override - public void onPacketReceiving(PacketEvent event) { - if (event.getPacketType() == PacketType.Play.Client.USE_ENTITY) { - handleINUseEntityPacket(event); - } else if (event.getPacketType() == PacketType.Play.Client.SET_CREATIVE_SLOT) { - handleINSetCreativeSlotPacket(event); - } + private void injectPlayer(Player player) { + ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { + @Override + public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { + if (packet.getClass().isAssignableFrom(packetPlayOutMapClass)) { + Object packetPlayOutMap = packetPlayOutMapClass.cast(packet); + + int id = (int) getDeclaredField(packetPlayOutMap, "a"); + if (id < 0) { + int newId = -id; + setDeclaredField(packetPlayOutMap, "a", newId); + } else { + boolean async = !MapReflectionAPI.getInstance().getServer().isPrimaryThread(); + MapCancelEvent event = new MapCancelEvent(player, id, async); + if (MapReflectionAPI.getMapManager().isIdUsedBy(player, id)) event.setCancelled(true); + if (event.getHandlers().getRegisteredListeners().length > 0) + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) return; + } + } + + super.write(ctx, packet, promise); + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { + if (packet.getClass().isAssignableFrom(packetPlayInUseEntityClass)) { + Object packetPlayInEntity = packetPlayInUseEntityClass.cast(packet); + + int entityId = (int) getDeclaredField(packetPlayInEntity, "a"); + + Enum actionEnum; + Enum hand; + Object pos; + if (ReflectionUtil.supports(17)) { + Object action = getDeclaredField(packetPlayInEntity, "b"); + actionEnum = (Enum) callDeclaredMethod(action, "a"); //action type + hand = hasField(action, "a") ? (Enum) getDeclaredField(action, "a") : null; + pos = hasField(action, "b") ? getDeclaredField(action, "b") : null; + } else { + actionEnum = (Enum) getDeclaredField(packetPlayInEntity, ReflectionUtil.supports(13) ? "b" : "a"); //1.13 = b, 1.12 = a + hand = (Enum) callDeclaredMethod(packetPlayInEntity, ReflectionUtil.supports(13) ? "c" : "b"); //1.13 = c, 1.12 = b + pos = callDeclaredMethod(packetPlayInEntity, ReflectionUtil.supports(13) ? "d" : "c"); //1.13 = d, 1.12 = c + } + + if (Bukkit.getScheduler().callSyncMethod(MapReflectionAPI.getInstance(), () -> { + boolean async = !MapReflectionAPI.getInstance().getServer().isPrimaryThread(); + MapInteractEvent event = new MapInteractEvent(player, entityId, actionEnum.ordinal(), pos != null ? vec3DToVector(pos) : null, hand != null ? hand.ordinal() : 0, async); + if (event.getFrame() != null && event.getMapWrapper() != null) { + Bukkit.getPluginManager().callEvent(event); + return event.isCancelled(); + } + return false; + }).get(1, TimeUnit.SECONDS)) return; + } else if (packet.getClass().isAssignableFrom(packetPlayInSetCreativeSlotClass)) { + Object packetPlayInSetCreativeSlot = packetPlayInSetCreativeSlotClass.cast(packet); + + int slot = (int) ReflectionUtil.callDeclaredMethod(packetPlayInSetCreativeSlot, ReflectionUtil.supports(13) ? "b" : "a"); //1.13 = b, 1.12 = a + Object nmsStack = ReflectionUtil.callDeclaredMethod(packetPlayInSetCreativeSlot, ReflectionUtil.supports(18) ? "c" : "getItemStack"); //1.18 = c, 1.17 = getItemStack + ItemStack craftStack = (ItemStack) ReflectionUtil.callDeclaredMethod(craftStackClass, "asBukkitCopy", nmsStack); + + boolean async = !MapReflectionAPI.getInstance().getServer().isPrimaryThread(); + CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(player, slot, craftStack, async); + if (event.getMapWrapper() != null) { + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) return; + } + } + + super.channelRead(ctx, packet); + } + }; + + Channel channel = getChannel(player); + channel.pipeline().addBefore("packet_handler", player.getName(), channelDuplexHandler); } - private void handleOUTMapPacket(PacketEvent event) { - int id = event.getPacket().getIntegers().read(0); //Read first int (a); that's the MAP id - - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - event.getPacket().getIntegers().write(0, newId); //set the MAP id to the reverse - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent cancelEvent = new MapCancelEvent(event.getPlayer(), id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(event.getPlayer(), id)) cancelEvent.setCancelled(true); - if (cancelEvent.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(cancelEvent); - - if (cancelEvent.isCancelled()) event.setCancelled(true); - } + private void removePlayer(Player player) { + Channel channel = getChannel(player); + channel.eventLoop().submit(() -> channel.pipeline().remove(player.getName())); } - private void handleINUseEntityPacket(PacketEvent event) { - int entityId = event.getPacket().getIntegers().read(0); //entityId - WrappedEnumEntityUseAction action = event.getPacket().getEnumEntityUseActions().read(0); - EnumWrappers.EntityUseAction actionEnum = null; - EnumWrappers.Hand hand = null; - Vector pos = null; - try { - actionEnum = action.getAction(); - hand = action.getHand(); - pos = action.getPosition(); - } catch (IllegalArgumentException ignored) { - } - - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent interactEvent = new MapInteractEvent(event.getPlayer(), entityId, actionEnum != null ? actionEnum.ordinal() : 0, pos, hand != null ? hand.ordinal() : 0, async); - if (interactEvent.getFrame() != null && interactEvent.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(interactEvent); - if (interactEvent.isCancelled()) event.setCancelled(true); - } + private Channel getChannel(Player player) { + Object playerHandle = getHandle(player); + Object connection = getDeclaredField(playerHandle, "b"); + Object connection2 = getDeclaredField(connection, ReflectionUtil.supports(19) ? "b" : "a"); //1.19 = b, 1.18 = a + return (Channel) getDeclaredField(connection2, ReflectionUtil.supports(18) ? "m" : "k"); //1.18 = m, 1.17 = k } - private void handleINSetCreativeSlotPacket(PacketEvent event) { - int slot = event.getPacket().getIntegers().read(0); - ItemStack item = event.getPacket().getItemModifier().read(0); + private Vector vec3DToVector(Object vec3d) { + if (!(vec3d.getClass().isAssignableFrom(vec3DClass))) return new Vector(0, 0, 0); - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent updateEvent = new CreateInventoryMapUpdateEvent(event.getPlayer(), slot, item, async); - if (updateEvent.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(updateEvent); - if (updateEvent.isCancelled()) event.setCancelled(true); - } + Object vec3dNMS = vec3DClass.cast(vec3d); + double x = (double) ReflectionUtil.getDeclaredField(vec3dNMS, ReflectionUtil.supports(19) ? "c" : ReflectionUtil.supports(17) ? "b" : "x"); //1.19 = c, 1.18 = b, 1.16 = x + double y = (double) ReflectionUtil.getDeclaredField(vec3dNMS, ReflectionUtil.supports(19) ? "d" : ReflectionUtil.supports(17) ? "c" : "y"); //1.19 = d, 1.18 = c, 1.16 = y + double z = (double) ReflectionUtil.getDeclaredField(vec3dNMS, ReflectionUtil.supports(19) ? "e" : ReflectionUtil.supports(17) ? "d" : "z"); //1.19 = e, 1.18 = d, 1.16 = z + + return new Vector(x, y, z); } } diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtil.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtil.java index ab94819..19ee0d9 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtil.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtil.java @@ -318,6 +318,15 @@ public class ReflectionUtil { } } + public static boolean hasField(Object packet, String field) { + try { + packet.getClass().getDeclaredField(field); + return true; + } catch (NoSuchFieldException ex) { + return false; + } + } + @Nullable public static Object getField(Object object, String field) { try { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 358fc74..41d8a18 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,7 +5,6 @@ api-version: 1.13 authors: [ inventivetalent, SBDeveloper ] description: This API helps developer with viewing images on maps or in inventories. website: https://sbdevelopment.tech -softdepend: [ ProtocolLib ] commands: mapmanager: description: The main command of MapManager. From df98877ebde91570420c245d2589be8486bfb1fa Mon Sep 17 00:00:00 2001 From: SBDeveloper Date: Tue, 27 Sep 2022 21:07:21 +0200 Subject: [PATCH 2/2] Fixed some typos --- .../mapreflectionapi/MapReflectionAPI.java | 2 +- .../listeners/PacketListener.java | 14 ++++----- .../mapreflectionapi/utils/UpdateManager.java | 30 ++++++++++--------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java index df43435..053b7f7 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java @@ -121,7 +121,7 @@ public class MapReflectionAPI extends JavaPlugin { if (Configuration.getInstance().isUpdaterCheck()) { try { - UpdateManager updateManager = new UpdateManager(this, UpdateManager.CheckType.SPIGOT); + UpdateManager updateManager = new UpdateManager(this, 103011); updateManager.handleResponse((versionResponse, version) -> { switch (versionResponse) { diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java index 7887358..c26be7c 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java @@ -43,9 +43,9 @@ import static tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil.*; public class PacketListener implements Listener { private static final Class packetPlayOutMapClass = getNMSClass("network.protocol.game", "PacketPlayOutMap"); private static final Class packetPlayInUseEntityClass = getNMSClass("network.protocol.game", "PacketPlayInUseEntity"); - private static final Class packetPlayInSetCreativeSlotClass = getNMSClass("network.protocol.game", "packetPlayInSetCreativeSlot"); + private static final Class packetPlayInSetCreativeSlotClass = getNMSClass("network.protocol.game", "PacketPlayInSetCreativeSlot"); private static final Class vec3DClass = getNMSClass("world.phys", "Vec3D"); - private static final Class craftStackClass = getCraftClass("CraftItemStack"); + private static final Class craftStackClass = getCraftClass("inventory.CraftItemStack"); @EventHandler public void onJoin(PlayerJoinEvent e) { @@ -98,7 +98,7 @@ public class PacketListener implements Listener { hand = hasField(action, "a") ? (Enum) getDeclaredField(action, "a") : null; pos = hasField(action, "b") ? getDeclaredField(action, "b") : null; } else { - actionEnum = (Enum) getDeclaredField(packetPlayInEntity, ReflectionUtil.supports(13) ? "b" : "a"); //1.13 = b, 1.12 = a + actionEnum = (Enum) callDeclaredMethod(packetPlayInEntity, ReflectionUtil.supports(13) ? "b" : "a"); //1.13 = b, 1.12 = a hand = (Enum) callDeclaredMethod(packetPlayInEntity, ReflectionUtil.supports(13) ? "c" : "b"); //1.13 = c, 1.12 = b pos = callDeclaredMethod(packetPlayInEntity, ReflectionUtil.supports(13) ? "d" : "c"); //1.13 = d, 1.12 = c } @@ -117,7 +117,7 @@ public class PacketListener implements Listener { int slot = (int) ReflectionUtil.callDeclaredMethod(packetPlayInSetCreativeSlot, ReflectionUtil.supports(13) ? "b" : "a"); //1.13 = b, 1.12 = a Object nmsStack = ReflectionUtil.callDeclaredMethod(packetPlayInSetCreativeSlot, ReflectionUtil.supports(18) ? "c" : "getItemStack"); //1.18 = c, 1.17 = getItemStack - ItemStack craftStack = (ItemStack) ReflectionUtil.callDeclaredMethod(craftStackClass, "asBukkitCopy", nmsStack); + ItemStack craftStack = (ItemStack) ReflectionUtil.callMethod(craftStackClass, "asBukkitCopy", nmsStack); boolean async = !MapReflectionAPI.getInstance().getServer().isPrimaryThread(); CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(player, slot, craftStack, async); @@ -142,9 +142,9 @@ public class PacketListener implements Listener { private Channel getChannel(Player player) { Object playerHandle = getHandle(player); - Object connection = getDeclaredField(playerHandle, "b"); - Object connection2 = getDeclaredField(connection, ReflectionUtil.supports(19) ? "b" : "a"); //1.19 = b, 1.18 = a - return (Channel) getDeclaredField(connection2, ReflectionUtil.supports(18) ? "m" : "k"); //1.18 = m, 1.17 = k + Object playerConnection = getDeclaredField(playerHandle, ReflectionUtil.supports(17) ? "b" : "playerConnection"); //1.17 = b, 1.16 = playerConnection + Object networkManager = getDeclaredField(playerConnection, ReflectionUtil.supports(19) ? "b" : ReflectionUtil.supports(17) ? "a" : "networkManager"); //1.19 = b, 1.18 = a, 1.16 = networkManager + return (Channel) getDeclaredField(networkManager, ReflectionUtil.supports(18) ? "m" : ReflectionUtil.supports(17) ? "k" : "channel"); //1.18 = m, 1.17 = k, 1.16 = channel } private Vector vec3DToVector(Object vec3d) { diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/UpdateManager.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/UpdateManager.java index 9445095..7acc5f3 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/UpdateManager.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/UpdateManager.java @@ -35,7 +35,7 @@ import java.util.function.BiConsumer; * Update checker class * * @author Stijn [SBDeveloper] - * @version 2.2 [17-04-2022] - Added Polymart support + * @version 2.3 [27-09-2022] - Added Polymart support ; fixed Spigot support * @since 05-03-2020 */ public class UpdateManager { @@ -68,22 +68,24 @@ public class UpdateManager { * * @param plugin The plugin instance */ - public UpdateManager(Plugin plugin, CheckType type) { - if ("%%__RESOURCE__%%".equals("%%__" + "RES" + "OU" + "RCE" + "__%%")) - throw new IllegalStateException("Resource ID not set!"); - + public UpdateManager(Plugin plugin) { this.plugin = plugin; this.currentVersion = new Version(plugin.getDescription().getVersion()); - this.type = type; + this.type = CheckType.POLYMART_PAID; this.resourceID = Integer.parseInt("%%__RESOURCE__%%"); - if (type == CheckType.POLYMART_PAID) { - this.injector_version = Integer.parseInt("%%__INJECT_VER__%%"); - this.user_id = Integer.parseInt("%%__USER__%%"); - this.nonce = Integer.parseInt("%%__NONCE__%%"); - this.download_agent = Integer.parseInt("%%__AGENT__%%"); - this.download_time = Integer.parseInt("%%__TIMESTAMP__%%"); - this.download_token = "%%__VERIFY_TOKEN__%%"; - } + this.injector_version = Integer.parseInt("%%__INJECT_VER__%%"); + this.user_id = Integer.parseInt("%%__USER__%%"); + this.nonce = Integer.parseInt("%%__NONCE__%%"); + this.download_agent = Integer.parseInt("%%__AGENT__%%"); + this.download_time = Integer.parseInt("%%__TIMESTAMP__%%"); + this.download_token = "%%__VERIFY_TOKEN__%%"; + } + + public UpdateManager(Plugin plugin, int resourceID) { + this.plugin = plugin; + this.currentVersion = new Version(plugin.getDescription().getVersion()); + this.type = CheckType.SPIGOT; + this.resourceID = resourceID; } /**