diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 8d3469f..337d139 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,8 +1,6 @@ - - diff --git a/.idea/misc.xml b/.idea/misc.xml index 6410ee3..200af21 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -15,8 +15,22 @@ + - + \ No newline at end of file diff --git a/API/pom.xml b/API/pom.xml deleted file mode 100644 index 172cb4c..0000000 --- a/API/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-API - - - 11 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - - - src/main/resources - true - - - - - - - MG-Dev Jenkins CI Maven Repository - https://ci.mg-dev.eu/plugin/repository/everything - - - - - - com.bergerkiller.bukkit - BKCommonLib - 1.19-v1 - provided - - - \ No newline at end of file diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java b/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java deleted file mode 100644 index e797653..0000000 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.api; - -public abstract class MapWrapper { - protected ArrayImage content; - - public MapWrapper(ArrayImage image) { - this.content = image; - } - - public abstract MapController getController(); - - public ArrayImage getContent() { - return content; - } -} diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java b/API/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java deleted file mode 100644 index 6079a40..0000000 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.listeners; - -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.plugin.java.JavaPlugin; -import org.bukkit.util.Vector; - -public abstract class PacketListener implements Listener { - protected JavaPlugin plugin; - - public static PacketListener construct(JavaPlugin plugin) throws IllegalStateException { - String packageName = Bukkit.getServer().getClass().getPackage().getName(); - String version = packageName.substring(packageName.lastIndexOf('.') + 1); - - plugin.getLogger().info("Initializing the packet handler for Minecraft version " + version + "..."); - - try { - final Class clazz = Class.forName("tech.sbdevelopment.mapreflectionapi.nms.PacketListener_" + version); - if (PacketListener.class.isAssignableFrom(clazz)) { - return (PacketListener) clazz.getDeclaredConstructor().newInstance(); - } else { - throw new IllegalStateException("Plugin corrupted! Detected invalid PacketListener class."); - } - } catch (Exception ex) { - throw new IllegalStateException("This Minecraft version (" + version + ") is not supported! Contact the developer to get support."); - } - } - - public void init(JavaPlugin plugin) { - this.plugin = plugin; - Bukkit.getPluginManager().registerEvents(this, plugin); - } - - @EventHandler - public void onJoin(PlayerJoinEvent e) { - injectPlayer(e.getPlayer()); - } - - @EventHandler - public void onQuit(PlayerQuitEvent e) { - removePlayer(e.getPlayer()); - } - - protected abstract void injectPlayer(Player p); - - public abstract void removePlayer(Player p); - - protected abstract Vector vec3DToVector(Object vec3d); - - protected boolean hasField(Object packet, String field) { - try { - packet.getClass().getDeclaredField(field); - return true; - } catch (NoSuchFieldException ex) { - return false; - } - } -} diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/util/ReflectionUtil.java b/API/src/main/java/tech/sbdevelopment/mapreflectionapi/util/ReflectionUtil.java deleted file mode 100644 index 9c508a7..0000000 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/util/ReflectionUtil.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.util; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -public class ReflectionUtil { - public static Object getField(Object packet, String field) throws NoSuchFieldException, IllegalAccessException { - Field f = packet.getClass().getDeclaredField(field); - f.setAccessible(true); - return f.get(packet); - } - - public static Object getField(Class clazz, String field) throws NoSuchFieldException, IllegalAccessException { - Field f = clazz.getDeclaredField(field); - f.setAccessible(true); - return f.get(null); - } - - public static void setField(Object packet, String field, Object value) throws NoSuchFieldException, IllegalAccessException { - Field f = packet.getClass().getDeclaredField(field); - f.setAccessible(true); - f.set(packet, value); - } - - public static Object getValue(Object packet, String method) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { - Method m = packet.getClass().getDeclaredMethod(method, null); - m.setAccessible(true); - return m.invoke(packet, null); - } -} diff --git a/Dist/pom.xml b/Dist/pom.xml deleted file mode 100644 index 29d8267..0000000 --- a/Dist/pom.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - jar - - MapReflectionAPI-Dist - - - ../target - ${project.parent.name}-${project.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - org.apache.maven.plugins - maven-shade-plugin - 3.3.0 - - - package - - shade - - - false - - - - - tech.sbdevelopment:MapReflectionAPI* - - - - - - - - - - - - tech.sbdevelopment - MapReflectionAPI-API - ${project.parent.version} - - - tech.sbdevelopment - MapReflectionAPI-NMS-v1_19_R1 - ${project.parent.version} - - - tech.sbdevelopment - MapReflectionAPI-NMS-v1_18_R2 - ${project.parent.version} - - - tech.sbdevelopment - MapReflectionAPI-NMS-v1_16_R3 - ${project.parent.version} - - - tech.sbdevelopment - MapReflectionAPI-NMS-v1_17_R1 - ${project.parent.version} - - - tech.sbdevelopment - MapReflectionAPI-NMS-v1_15_R1 - ${project.parent.version} - - - tech.sbdevelopment - MapReflectionAPI-NMS-v1_14_R1 - ${project.parent.version} - - - tech.sbdevelopment - MapReflectionAPI-NMS-v1_13_R2 - ${project.parent.version} - - - tech.sbdevelopment - MapReflectionAPI-NMS-v1_12_R1 - ${project.parent.version} - - - \ No newline at end of file diff --git a/NMS-v1_12_R1/pom.xml b/NMS-v1_12_R1/pom.xml deleted file mode 100644 index 97d3164..0000000 --- a/NMS-v1_12_R1/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-NMS-v1_12_R1 - - - 1.12.2-R0.1-SNAPSHOT - 11 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - - - - - org.bukkit - craftbukkit - ${NMSVersion} - provided - - - tech.sbdevelopment - MapReflectionAPI-API - 1.0-SNAPSHOT - provided - - - \ No newline at end of file diff --git a/NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_12_R1.java b/NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_12_R1.java deleted file mode 100644 index 1063510..0000000 --- a/NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_12_R1.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import io.netty.channel.*; -import net.minecraft.server.v1_12_R1.*; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftItemStack; -import org.bukkit.entity.Player; -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.listeners.PacketListener; - -import java.util.concurrent.TimeUnit; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class PacketListener_v1_12_R1 extends PacketListener { - @Override - protected void injectPlayer(Player p) { - ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { - @Override - //On send packet - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (packet instanceof PacketPlayOutMap) { - PacketPlayOutMap packetPlayOutMap = (PacketPlayOutMap) packet; - - int id = (int) getField(packetPlayOutMap, "a"); - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - setField(packetPlayOutMap, "a", newId); //mapId - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent event = new MapCancelEvent(p, id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true); - if (event.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) return; - } - } - - super.write(ctx, packet, promise); - } - - @Override - //On receive packet - public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { - if (packet instanceof PacketPlayInUseEntity) { - PacketPlayInUseEntity packetPlayInUseEntity = (PacketPlayInUseEntity) packet; - - int entityId = (int) getField(packetPlayInUseEntity, "a"); //entityId - PacketPlayInUseEntity.EnumEntityUseAction action = packetPlayInUseEntity.a(); //action - EnumHand hand = packetPlayInUseEntity.b(); //hand - Vec3D pos = packetPlayInUseEntity.c(); //pos - - if (Bukkit.getScheduler().callSyncMethod(plugin, () -> { - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent event = new MapInteractEvent(p, entityId, action.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 instanceof PacketPlayInSetCreativeSlot) { - PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) packet; - - int slot = packetPlayInSetCreativeSlot.a(); - ItemStack item = packetPlayInSetCreativeSlot.getItemStack(); - - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async); - if (event.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) return; - } - } - - super.channelRead(ctx, packet); - } - }; - - ChannelPipeline pipeline = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel.pipeline(); - pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler); - } - - @Override - public void removePlayer(Player p) { - Channel channel = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel; - channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName())); - } - - @Override - protected Vector vec3DToVector(Object vec3d) { - if (!(vec3d instanceof Vec3D)) return new Vector(0, 0, 0); - - Vec3D vec3dObj = (Vec3D) vec3d; - return new Vector(vec3dObj.x, vec3dObj.y, vec3dObj.z); - } -} diff --git a/NMS-v1_13_R2/pom.xml b/NMS-v1_13_R2/pom.xml deleted file mode 100644 index 1e53137..0000000 --- a/NMS-v1_13_R2/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-NMS-v1_13_R2 - - - 1.13.2-R0.1-SNAPSHOT - 11 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - - - - - org.bukkit - craftbukkit - ${NMSVersion} - provided - - - tech.sbdevelopment - MapReflectionAPI-API - 1.0-SNAPSHOT - provided - - - \ No newline at end of file diff --git a/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_13_R2.java b/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_13_R2.java deleted file mode 100644 index cc34470..0000000 --- a/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_13_R2.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.server.v1_13_R2.PacketPlayOutMap; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer; -import org.bukkit.entity.Player; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class MapSender_v1_13_R2 { - private static final List sendQueue = new ArrayList<>(); - private static int senderID = -1; - - public static void addToQueue(final int id, final ArrayImage content, final Player player) { - QueuedMap toSend = new QueuedMap(id, content, player); - if (sendQueue.contains(toSend)) return; - sendQueue.add(toSend); - - runSender(); - } - - private static void runSender() { - if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty()) - return; - - senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> { - if (sendQueue.isEmpty()) return; - - for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) { - QueuedMap current = sendQueue.get(0); - if (current == null) return; - - sendMap(current.id, current.image, current.player); - - if (!sendQueue.isEmpty()) sendQueue.remove(0); - } - }, 0, 2); - } - - public static void sendMap(final int id0, final ArrayImage content, final Player player) { - if (player == null || !player.isOnline()) { - List toRemove = new ArrayList<>(); - for (QueuedMap qMap : sendQueue) { - if (qMap == null) continue; - - if (qMap.player == null || !qMap.player.isOnline()) { - toRemove.add(qMap); - } - } - Bukkit.getScheduler().cancelTask(senderID); - sendQueue.removeAll(toRemove); - - return; - } - - final int id = -id0; - Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> { - try { - PacketPlayOutMap packet = new PacketPlayOutMap( - id, //ID - (byte) 0, //Scale - false, //??? - new ArrayList<>(), //Icons - content.array, //Data - content.minX, //X pos - content.minY, //Y pos - content.maxX, //X size (2nd X pos) - content.maxY //Y size (2nd Y pos) - ); - - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - static final class QueuedMap { - private final int id; - private final ArrayImage image; - private final Player player; - - QueuedMap(int id, ArrayImage image, Player player) { - this.id = id; - this.image = image; - this.player = player; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (QueuedMap) obj; - return this.id == that.id && - Objects.equals(this.image, that.image) && - Objects.equals(this.player, that.player); - } - - @Override - public int hashCode() { - return Objects.hash(id, image, player); - } - - @Override - public String toString() { - return "QueuedMap[" + - "id=" + id + ", " + - "image=" + image + ", " + - "player=" + player + ']'; - } - } -} diff --git a/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_13_R2.java b/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_13_R2.java deleted file mode 100644 index 13b0efa..0000000 --- a/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_13_R2.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.server.v1_13_R2.*; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.*; -import org.bukkit.craftbukkit.v1_13_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftItemStack; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; -import tech.sbdevelopment.mapreflectionapi.api.MapController; -import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; - -import java.util.*; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class MapWrapper_v1_13_R2 extends MapWrapper { - protected MapController controller = new MapController() { - private final Map viewers = new HashMap<>(); - - @Override - public void addViewer(Player player) throws MapLimitExceededException { - if (!isViewing(player)) { - viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player)); - } - } - - @Override - public void removeViewer(OfflinePlayer player) { - viewers.remove(player.getUniqueId()); - } - - @Override - public void clearViewers() { - for (UUID uuid : viewers.keySet()) { - viewers.remove(uuid); - } - } - - @Override - public boolean isViewing(OfflinePlayer player) { - if (player == null) return false; - return viewers.containsKey(player.getUniqueId()); - } - - @Override - public int getMapId(OfflinePlayer player) { - if (isViewing(player)) { - return viewers.get(player.getUniqueId()); - } - return -1; - } - - @Override - public void update(ArrayImage content) { - MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content); - if (duplicate != null) { - MapWrapper_v1_13_R2.this.content = duplicate.getContent(); - return; - } - - MapWrapper_v1_13_R2.this.content = content; - - for (UUID id : viewers.keySet()) { - sendContent(Bukkit.getPlayer(id)); - } - } - - @Override - public ArrayImage getContent() { - return MapWrapper_v1_13_R2.this.getContent(); - } - - @Override - public void sendContent(Player player) { - sendContent(player, false); - } - - @Override - public void sendContent(Player player, boolean withoutQueue) { - if (!isViewing(player)) return; - - int id = getMapId(player); - if (withoutQueue) { - MapSender_v1_13_R2.sendMap(id, MapWrapper_v1_13_R2.this.content, player); - } else { - MapSender_v1_13_R2.addToQueue(id, MapWrapper_v1_13_R2.this.content, player); - } - } - - @Override - public void showInInventory(Player player, int slot, boolean force) { - if (!isViewing(player)) return; - - if (player.getGameMode() == GameMode.CREATIVE && !force) return; - - if (slot < 9) { - slot += 36; - } else if (slot > 35 && slot != 45) { - slot = 8 - (slot - 36); - } - - CraftPlayer craftPlayer = (CraftPlayer) player; - int windowId = craftPlayer.getHandle().defaultContainer.windowId; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - net.minecraft.server.v1_13_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - - PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack); - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } - - @Override - public void showInInventory(Player player, int slot) { - showInInventory(player, slot, false); - } - - @Override - public void showInHand(Player player, boolean force) { - if (player.getInventory().getItemInMainHand().getType() != Material.FILLED_MAP && !force) return; - showInInventory(player, player.getInventory().getHeldItemSlot(), force); - } - - @Override - public void showInHand(Player player) { - showInHand(player, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame) { - showInFrame(player, frame, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame, boolean force) { - if (frame.getItem().getType() != Material.FILLED_MAP && !force) return; - showInFrame(player, frame.getEntityId()); - } - - @Override - public void showInFrame(Player player, int entityId) { - showInFrame(player, entityId, null); - } - - @Override - public void showInFrame(Player player, int entityId, String debugInfo) { - if (!isViewing(player)) return; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - if (debugInfo != null) { - ItemMeta itemMeta = stack.getItemMeta(); - itemMeta.setDisplayName(debugInfo); - stack.setItemMeta(itemMeta); - } - - Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> { - ItemFrame frame = getItemFrameById(player.getWorld(), entityId); - if (frame != null) { - frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance()); - frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_13_R2.this)); - } - - sendItemFramePacket(player, entityId, stack, getMapId(player)); - }); - } - - @Override - public void clearFrame(Player player, int entityId) { - - } - - @Override - public void clearFrame(Player player, ItemFrame frame) { - - } - - @Override - public ItemFrame getItemFrameById(World world, int entityId) { - CraftWorld craftWorld = (CraftWorld) world; - - Entity entity = craftWorld.getHandle().getEntity(entityId); - if (entity == null) return null; - - org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); - if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity; - - return null; - } - - private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) { - net.minecraft.server.v1_13_R2.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - nmsStack.getOrCreateTag().setInt("map", mapId); //getOrCreateTag putInt - - PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, new DataWatcher(null), true); - - try { - List> list = new ArrayList<>(); - DataWatcherObject dataWatcherObject = (DataWatcherObject) getField(EntityItemFrame.class, "e"); - DataWatcher.Item dataWatcherItem = new DataWatcher.Item<>(dataWatcherObject, nmsStack); - list.add(dataWatcherItem); - setField(packet, "b", list); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } - }; - - public MapWrapper_v1_13_R2(ArrayImage image) { - super(image); - } - - @Override - public MapController getController() { - return controller; - } -} diff --git a/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_13_R2.java b/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_13_R2.java deleted file mode 100644 index e8b28ce..0000000 --- a/NMS-v1_13_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_13_R2.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import io.netty.channel.*; -import net.minecraft.server.v1_13_R2.*; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_13_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_13_R2.inventory.CraftItemStack; -import org.bukkit.entity.Player; -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.listeners.PacketListener; - -import java.util.concurrent.TimeUnit; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class PacketListener_v1_13_R2 extends PacketListener { - @Override - protected void injectPlayer(Player p) { - ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { - @Override - //On send packet - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (packet instanceof PacketPlayOutMap) { - PacketPlayOutMap packetPlayOutMap = (PacketPlayOutMap) packet; - - int id = (int) getField(packetPlayOutMap, "a"); - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - setField(packetPlayOutMap, "a", newId); //mapId - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent event = new MapCancelEvent(p, id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true); - if (event.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) return; - } - } - - super.write(ctx, packet, promise); - } - - @Override - //On receive packet - public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { - if (packet instanceof PacketPlayInUseEntity) { - PacketPlayInUseEntity packetPlayInUseEntity = (PacketPlayInUseEntity) packet; - - int entityId = (int) getField(packetPlayInUseEntity, "a"); //entityId - PacketPlayInUseEntity.EnumEntityUseAction action = packetPlayInUseEntity.b(); //action - EnumHand hand = packetPlayInUseEntity.c(); //hand - Vec3D pos = packetPlayInUseEntity.d(); //pos - - if (Bukkit.getScheduler().callSyncMethod(plugin, () -> { - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent event = new MapInteractEvent(p, entityId, action.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 instanceof PacketPlayInSetCreativeSlot) { - PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) packet; - - int slot = packetPlayInSetCreativeSlot.b(); - ItemStack item = packetPlayInSetCreativeSlot.getItemStack(); - - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async); - if (event.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) return; - } - } - - super.channelRead(ctx, packet); - } - }; - - ChannelPipeline pipeline = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel.pipeline(); - pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler); - } - - @Override - public void removePlayer(Player p) { - Channel channel = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel; - channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName())); - } - - @Override - protected Vector vec3DToVector(Object vec3d) { - if (!(vec3d instanceof Vec3D)) return new Vector(0, 0, 0); - - Vec3D vec3dObj = (Vec3D) vec3d; - return new Vector(vec3dObj.x, vec3dObj.y, vec3dObj.z); - } -} diff --git a/NMS-v1_14_R1/pom.xml b/NMS-v1_14_R1/pom.xml deleted file mode 100644 index 51f3551..0000000 --- a/NMS-v1_14_R1/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-NMS-v1_14_R1 - - - 1.14.4-R0.1-SNAPSHOT - 11 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - - - - - org.bukkit - craftbukkit - ${NMSVersion} - provided - - - tech.sbdevelopment - MapReflectionAPI-API - 1.0-SNAPSHOT - provided - - - \ No newline at end of file diff --git a/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_14_R1.java b/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_14_R1.java deleted file mode 100644 index afc893e..0000000 --- a/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_14_R1.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.server.v1_14_R1.PacketPlayOutMap; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class MapSender_v1_14_R1 { - private static final List sendQueue = new ArrayList<>(); - private static int senderID = -1; - - public static void addToQueue(final int id, final ArrayImage content, final Player player) { - QueuedMap toSend = new QueuedMap(id, content, player); - if (sendQueue.contains(toSend)) return; - sendQueue.add(toSend); - - runSender(); - } - - private static void runSender() { - if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty()) - return; - - senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> { - if (sendQueue.isEmpty()) return; - - for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) { - QueuedMap current = sendQueue.get(0); - if (current == null) return; - - sendMap(current.id, current.image, current.player); - - if (!sendQueue.isEmpty()) sendQueue.remove(0); - } - }, 0, 2); - } - - public static void sendMap(final int id0, final ArrayImage content, final Player player) { - if (player == null || !player.isOnline()) { - List toRemove = new ArrayList<>(); - for (QueuedMap qMap : sendQueue) { - if (qMap == null) continue; - - if (qMap.player == null || !qMap.player.isOnline()) { - toRemove.add(qMap); - } - } - Bukkit.getScheduler().cancelTask(senderID); - sendQueue.removeAll(toRemove); - - return; - } - - final int id = -id0; - Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> { - try { - PacketPlayOutMap packet = new PacketPlayOutMap( - id, //ID - (byte) 0, //Scale - false, //Tracking position - false, //Locked - new ArrayList<>(), //Icons - content.array, //Data - content.minX, //X pos - content.minY, //Y pos - content.maxX, //X size (2nd X pos) - content.maxY //Y size (2nd Y pos) - ); - - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - static final class QueuedMap { - private final int id; - private final ArrayImage image; - private final Player player; - - QueuedMap(int id, ArrayImage image, Player player) { - this.id = id; - this.image = image; - this.player = player; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (QueuedMap) obj; - return this.id == that.id && - Objects.equals(this.image, that.image) && - Objects.equals(this.player, that.player); - } - - @Override - public int hashCode() { - return Objects.hash(id, image, player); - } - - @Override - public String toString() { - return "QueuedMap[" + - "id=" + id + ", " + - "image=" + image + ", " + - "player=" + player + ']'; - } - } -} diff --git a/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_14_R1.java b/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_14_R1.java deleted file mode 100644 index 4e526c9..0000000 --- a/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_14_R1.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.server.v1_14_R1.*; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.*; -import org.bukkit.craftbukkit.v1_14_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; -import tech.sbdevelopment.mapreflectionapi.api.MapController; -import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; - -import java.util.*; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class MapWrapper_v1_14_R1 extends MapWrapper { - protected MapController controller = new MapController() { - private final Map viewers = new HashMap<>(); - - @Override - public void addViewer(Player player) throws MapLimitExceededException { - if (!isViewing(player)) { - viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player)); - } - } - - @Override - public void removeViewer(OfflinePlayer player) { - viewers.remove(player.getUniqueId()); - } - - @Override - public void clearViewers() { - for (UUID uuid : viewers.keySet()) { - viewers.remove(uuid); - } - } - - @Override - public boolean isViewing(OfflinePlayer player) { - if (player == null) return false; - return viewers.containsKey(player.getUniqueId()); - } - - @Override - public int getMapId(OfflinePlayer player) { - if (isViewing(player)) { - return viewers.get(player.getUniqueId()); - } - return -1; - } - - @Override - public void update(ArrayImage content) { - MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content); - if (duplicate != null) { - MapWrapper_v1_14_R1.this.content = duplicate.getContent(); - return; - } - - MapWrapper_v1_14_R1.this.content = content; - - for (UUID id : viewers.keySet()) { - sendContent(Bukkit.getPlayer(id)); - } - } - - @Override - public ArrayImage getContent() { - return MapWrapper_v1_14_R1.this.getContent(); - } - - @Override - public void sendContent(Player player) { - sendContent(player, false); - } - - @Override - public void sendContent(Player player, boolean withoutQueue) { - if (!isViewing(player)) return; - - int id = getMapId(player); - if (withoutQueue) { - MapSender_v1_14_R1.sendMap(id, MapWrapper_v1_14_R1.this.content, player); - } else { - MapSender_v1_14_R1.addToQueue(id, MapWrapper_v1_14_R1.this.content, player); - } - } - - @Override - public void showInInventory(Player player, int slot, boolean force) { - if (!isViewing(player)) return; - - if (player.getGameMode() == GameMode.CREATIVE && !force) return; - - if (slot < 9) { - slot += 36; - } else if (slot > 35 && slot != 45) { - slot = 8 - (slot - 36); - } - - CraftPlayer craftPlayer = (CraftPlayer) player; - int windowId = craftPlayer.getHandle().defaultContainer.windowId; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - net.minecraft.server.v1_14_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - - PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack); - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } - - @Override - public void showInInventory(Player player, int slot) { - showInInventory(player, slot, false); - } - - @Override - public void showInHand(Player player, boolean force) { - if (player.getInventory().getItemInMainHand().getType() != Material.FILLED_MAP && !force) return; - showInInventory(player, player.getInventory().getHeldItemSlot(), force); - } - - @Override - public void showInHand(Player player) { - showInHand(player, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame) { - showInFrame(player, frame, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame, boolean force) { - if (frame.getItem().getType() != Material.FILLED_MAP && !force) return; - showInFrame(player, frame.getEntityId()); - } - - @Override - public void showInFrame(Player player, int entityId) { - showInFrame(player, entityId, null); - } - - @Override - public void showInFrame(Player player, int entityId, String debugInfo) { - if (!isViewing(player)) return; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - if (debugInfo != null) { - ItemMeta itemMeta = stack.getItemMeta(); - itemMeta.setDisplayName(debugInfo); - stack.setItemMeta(itemMeta); - } - - Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> { - ItemFrame frame = getItemFrameById(player.getWorld(), entityId); - if (frame != null) { - frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance()); - frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_14_R1.this)); - } - - sendItemFramePacket(player, entityId, stack, getMapId(player)); - }); - } - - @Override - public void clearFrame(Player player, int entityId) { - - } - - @Override - public void clearFrame(Player player, ItemFrame frame) { - - } - - @Override - public ItemFrame getItemFrameById(World world, int entityId) { - CraftWorld craftWorld = (CraftWorld) world; - - Entity entity = craftWorld.getHandle().getEntity(entityId); - if (entity == null) return null; - - org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); - if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity; - - return null; - } - - private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) { - net.minecraft.server.v1_14_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - nmsStack.getOrCreateTag().setInt("map", mapId); //getOrCreateTag putInt - - PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, new DataWatcher(null), true); - - try { - List> list = new ArrayList<>(); - DataWatcherObject dataWatcherObject = (DataWatcherObject) getField(EntityItemFrame.class, "ITEM"); - DataWatcher.Item dataWatcherItem = new DataWatcher.Item<>(dataWatcherObject, nmsStack); - list.add(dataWatcherItem); - setField(packet, "b", list); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } - }; - - public MapWrapper_v1_14_R1(ArrayImage image) { - super(image); - } - - @Override - public MapController getController() { - return controller; - } -} diff --git a/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_14_R1.java b/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_14_R1.java deleted file mode 100644 index 1083801..0000000 --- a/NMS-v1_14_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_14_R1.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import io.netty.channel.*; -import net.minecraft.server.v1_14_R1.*; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_14_R1.inventory.CraftItemStack; -import org.bukkit.entity.Player; -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.listeners.PacketListener; - -import java.util.concurrent.TimeUnit; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class PacketListener_v1_14_R1 extends PacketListener { - @Override - protected void injectPlayer(Player p) { - ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { - @Override - //On send packet - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (packet instanceof PacketPlayOutMap) { - PacketPlayOutMap packetPlayOutMap = (PacketPlayOutMap) packet; - - int id = (int) getField(packetPlayOutMap, "a"); - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - setField(packetPlayOutMap, "a", newId); //mapId - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent event = new MapCancelEvent(p, id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true); - if (event.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) return; - } - } - - super.write(ctx, packet, promise); - } - - @Override - //On receive packet - public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { - if (packet instanceof PacketPlayInUseEntity) { - PacketPlayInUseEntity packetPlayInUseEntity = (PacketPlayInUseEntity) packet; - - int entityId = (int) getField(packetPlayInUseEntity, "a"); //entityId - PacketPlayInUseEntity.EnumEntityUseAction action = packetPlayInUseEntity.b(); //action - EnumHand hand = packetPlayInUseEntity.c(); //hand - Vec3D pos = packetPlayInUseEntity.d(); //pos - - if (Bukkit.getScheduler().callSyncMethod(plugin, () -> { - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent event = new MapInteractEvent(p, entityId, action.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 instanceof PacketPlayInSetCreativeSlot) { - PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) packet; - - int slot = packetPlayInSetCreativeSlot.b(); - ItemStack item = packetPlayInSetCreativeSlot.getItemStack(); - - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async); - if (event.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) return; - } - } - - super.channelRead(ctx, packet); - } - }; - - ChannelPipeline pipeline = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel.pipeline(); - pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler); - } - - @Override - public void removePlayer(Player p) { - Channel channel = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel; - channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName())); - } - - @Override - protected Vector vec3DToVector(Object vec3d) { - if (!(vec3d instanceof Vec3D)) return new Vector(0, 0, 0); - - Vec3D vec3dObj = (Vec3D) vec3d; - return new Vector(vec3dObj.x, vec3dObj.y, vec3dObj.z); - } -} diff --git a/NMS-v1_15_R1/pom.xml b/NMS-v1_15_R1/pom.xml deleted file mode 100644 index cce4f6d..0000000 --- a/NMS-v1_15_R1/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-NMS-v1_15_R1 - - - 1.15.2-R0.1-SNAPSHOT - 11 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - - - - - org.bukkit - craftbukkit - ${NMSVersion} - provided - - - tech.sbdevelopment - MapReflectionAPI-API - 1.0-SNAPSHOT - provided - - - \ No newline at end of file diff --git a/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_15_R1.java b/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_15_R1.java deleted file mode 100644 index e16c48e..0000000 --- a/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_15_R1.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.server.v1_15_R1.PacketPlayOutMap; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class MapSender_v1_15_R1 { - private static final List sendQueue = new ArrayList<>(); - private static int senderID = -1; - - public static void addToQueue(final int id, final ArrayImage content, final Player player) { - QueuedMap toSend = new QueuedMap(id, content, player); - if (sendQueue.contains(toSend)) return; - sendQueue.add(toSend); - - runSender(); - } - - private static void runSender() { - if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty()) - return; - - senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> { - if (sendQueue.isEmpty()) return; - - for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) { - QueuedMap current = sendQueue.get(0); - if (current == null) return; - - sendMap(current.id, current.image, current.player); - - if (!sendQueue.isEmpty()) sendQueue.remove(0); - } - }, 0, 2); - } - - public static void sendMap(final int id0, final ArrayImage content, final Player player) { - if (player == null || !player.isOnline()) { - List toRemove = new ArrayList<>(); - for (QueuedMap qMap : sendQueue) { - if (qMap == null) continue; - - if (qMap.player == null || !qMap.player.isOnline()) { - toRemove.add(qMap); - } - } - Bukkit.getScheduler().cancelTask(senderID); - sendQueue.removeAll(toRemove); - - return; - } - - final int id = -id0; - Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> { - try { - PacketPlayOutMap packet = new PacketPlayOutMap( - id, //ID - (byte) 0, //Scale - false, //Tracking position - false, //Locked - new ArrayList<>(), //Icons - content.array, //Data - content.minX, //X pos - content.minY, //Y pos - content.maxX, //X size (2nd X pos) - content.maxY //Y size (2nd Y pos) - ); - - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - static final class QueuedMap { - private final int id; - private final ArrayImage image; - private final Player player; - - QueuedMap(int id, ArrayImage image, Player player) { - this.id = id; - this.image = image; - this.player = player; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (QueuedMap) obj; - return this.id == that.id && - Objects.equals(this.image, that.image) && - Objects.equals(this.player, that.player); - } - - @Override - public int hashCode() { - return Objects.hash(id, image, player); - } - - @Override - public String toString() { - return "QueuedMap[" + - "id=" + id + ", " + - "image=" + image + ", " + - "player=" + player + ']'; - } - } -} diff --git a/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_15_R1.java b/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_15_R1.java deleted file mode 100644 index 51db039..0000000 --- a/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_15_R1.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.server.v1_15_R1.*; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.*; -import org.bukkit.craftbukkit.v1_15_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; -import tech.sbdevelopment.mapreflectionapi.api.MapController; -import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; - -import java.util.*; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class MapWrapper_v1_15_R1 extends MapWrapper { - - protected MapController controller = new MapController() { - private final Map viewers = new HashMap<>(); - - @Override - public void addViewer(Player player) throws MapLimitExceededException { - if (!isViewing(player)) { - viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player)); - } - } - - @Override - public void removeViewer(OfflinePlayer player) { - viewers.remove(player.getUniqueId()); - } - - @Override - public void clearViewers() { - for (UUID uuid : viewers.keySet()) { - viewers.remove(uuid); - } - } - - @Override - public boolean isViewing(OfflinePlayer player) { - if (player == null) return false; - return viewers.containsKey(player.getUniqueId()); - } - - @Override - public int getMapId(OfflinePlayer player) { - if (isViewing(player)) { - return viewers.get(player.getUniqueId()); - } - return -1; - } - - @Override - public void update(ArrayImage content) { - MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content); - if (duplicate != null) { - MapWrapper_v1_15_R1.this.content = duplicate.getContent(); - return; - } - - MapWrapper_v1_15_R1.this.content = content; - - for (UUID id : viewers.keySet()) { - sendContent(Bukkit.getPlayer(id)); - } - } - - @Override - public ArrayImage getContent() { - return MapWrapper_v1_15_R1.this.getContent(); - } - - @Override - public void sendContent(Player player) { - sendContent(player, false); - } - - @Override - public void sendContent(Player player, boolean withoutQueue) { - if (!isViewing(player)) return; - - int id = getMapId(player); - if (withoutQueue) { - MapSender_v1_15_R1.sendMap(id, MapWrapper_v1_15_R1.this.content, player); - } else { - MapSender_v1_15_R1.addToQueue(id, MapWrapper_v1_15_R1.this.content, player); - } - } - - @Override - public void showInInventory(Player player, int slot, boolean force) { - if (!isViewing(player)) return; - - if (player.getGameMode() == GameMode.CREATIVE && !force) return; - - if (slot < 9) { - slot += 36; - } else if (slot > 35 && slot != 45) { - slot = 8 - (slot - 36); - } - - CraftPlayer craftPlayer = (CraftPlayer) player; - int windowId = craftPlayer.getHandle().defaultContainer.windowId; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - net.minecraft.server.v1_15_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - - PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack); - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } - - @Override - public void showInInventory(Player player, int slot) { - showInInventory(player, slot, false); - } - - @Override - public void showInHand(Player player, boolean force) { - if (player.getInventory().getItemInMainHand().getType() != Material.FILLED_MAP && !force) return; - showInInventory(player, player.getInventory().getHeldItemSlot(), force); - } - - @Override - public void showInHand(Player player) { - showInHand(player, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame) { - showInFrame(player, frame, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame, boolean force) { - if (frame.getItem().getType() != Material.FILLED_MAP && !force) return; - showInFrame(player, frame.getEntityId()); - } - - @Override - public void showInFrame(Player player, int entityId) { - showInFrame(player, entityId, null); - } - - @Override - public void showInFrame(Player player, int entityId, String debugInfo) { - if (!isViewing(player)) return; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - if (debugInfo != null) { - ItemMeta itemMeta = stack.getItemMeta(); - itemMeta.setDisplayName(debugInfo); - stack.setItemMeta(itemMeta); - } - - Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> { - ItemFrame frame = getItemFrameById(player.getWorld(), entityId); - if (frame != null) { - frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance()); - frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_15_R1.this)); - } - - sendItemFramePacket(player, entityId, stack, getMapId(player)); - }); - } - - @Override - public void clearFrame(Player player, int entityId) { - - } - - @Override - public void clearFrame(Player player, ItemFrame frame) { - - } - - @Override - public ItemFrame getItemFrameById(World world, int entityId) { - CraftWorld craftWorld = (CraftWorld) world; - - Entity entity = craftWorld.getHandle().getEntity(entityId); - if (entity == null) return null; - - org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); - if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity; - - return null; - } - - private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) { - net.minecraft.server.v1_15_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - nmsStack.getOrCreateTag().setInt("map", mapId); //getOrCreateTag putInt - - PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, new DataWatcher(null), true); - - try { - List> list = new ArrayList<>(); - DataWatcherObject dataWatcherObject = (DataWatcherObject) getField(EntityItemFrame.class, "ITEM"); - DataWatcher.Item dataWatcherItem = new DataWatcher.Item<>(dataWatcherObject, nmsStack); - list.add(dataWatcherItem); - setField(packet, "b", list); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } - }; - - public MapWrapper_v1_15_R1(ArrayImage image) { - super(image); - } - - @Override - public MapController getController() { - return controller; - } -} diff --git a/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_15_R1.java b/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_15_R1.java deleted file mode 100644 index ba807c1..0000000 --- a/NMS-v1_15_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_15_R1.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import io.netty.channel.*; -import net.minecraft.server.v1_15_R1.*; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack; -import org.bukkit.entity.Player; -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.listeners.PacketListener; - -import java.util.concurrent.TimeUnit; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class PacketListener_v1_15_R1 extends PacketListener { - @Override - protected void injectPlayer(Player p) { - ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { - @Override - //On send packet - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (packet instanceof PacketPlayOutMap) { - PacketPlayOutMap packetPlayOutMap = (PacketPlayOutMap) packet; - - int id = (int) getField(packetPlayOutMap, "a"); - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - setField(packetPlayOutMap, "a", newId); //mapId - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent event = new MapCancelEvent(p, id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true); - if (event.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) return; - } - } - - super.write(ctx, packet, promise); - } - - @Override - //On receive packet - public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { - if (packet instanceof PacketPlayInUseEntity) { - PacketPlayInUseEntity packetPlayInUseEntity = (PacketPlayInUseEntity) packet; - - int entityId = (int) getField(packetPlayInUseEntity, "a"); //entityId - PacketPlayInUseEntity.EnumEntityUseAction action = packetPlayInUseEntity.b(); //action - EnumHand hand = packetPlayInUseEntity.c(); //hand - Vec3D pos = packetPlayInUseEntity.d(); //pos - - if (Bukkit.getScheduler().callSyncMethod(plugin, () -> { - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent event = new MapInteractEvent(p, entityId, action.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 instanceof PacketPlayInSetCreativeSlot) { - PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) packet; - - int slot = packetPlayInSetCreativeSlot.b(); - ItemStack item = packetPlayInSetCreativeSlot.getItemStack(); - - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async); - if (event.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) return; - } - } - - super.channelRead(ctx, packet); - } - }; - - ChannelPipeline pipeline = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel.pipeline(); - pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler); - } - - @Override - public void removePlayer(Player p) { - Channel channel = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel; - channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName())); - } - - @Override - protected Vector vec3DToVector(Object vec3d) { - if (!(vec3d instanceof Vec3D)) return new Vector(0, 0, 0); - - Vec3D vec3dObj = (Vec3D) vec3d; - return new Vector(vec3dObj.x, vec3dObj.y, vec3dObj.z); - } -} diff --git a/NMS-v1_16_R3/pom.xml b/NMS-v1_16_R3/pom.xml deleted file mode 100644 index 17b221c..0000000 --- a/NMS-v1_16_R3/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-NMS-v1_16_R3 - - - 1.16.4-R0.1-SNAPSHOT - 11 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - - - - - org.bukkit - craftbukkit - ${NMSVersion} - provided - - - tech.sbdevelopment - MapReflectionAPI-API - 1.0-SNAPSHOT - provided - - - \ No newline at end of file diff --git a/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_16_R3.java b/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_16_R3.java deleted file mode 100644 index 661205c..0000000 --- a/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_16_R3.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.server.v1_16_R3.PacketPlayOutMap; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; -import org.bukkit.entity.Player; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class MapSender_v1_16_R3 { - private static final List sendQueue = new ArrayList<>(); - private static int senderID = -1; - - public static void addToQueue(final int id, final ArrayImage content, final Player player) { - QueuedMap toSend = new QueuedMap(id, content, player); - if (sendQueue.contains(toSend)) return; - sendQueue.add(toSend); - - runSender(); - } - - private static void runSender() { - if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty()) - return; - - senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> { - if (sendQueue.isEmpty()) return; - - for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) { - QueuedMap current = sendQueue.get(0); - if (current == null) return; - - sendMap(current.id, current.image, current.player); - - if (!sendQueue.isEmpty()) sendQueue.remove(0); - } - }, 0, 2); - } - - public static void sendMap(final int id0, final ArrayImage content, final Player player) { - if (player == null || !player.isOnline()) { - List toRemove = new ArrayList<>(); - for (QueuedMap qMap : sendQueue) { - if (qMap == null) continue; - - if (qMap.player == null || !qMap.player.isOnline()) { - toRemove.add(qMap); - } - } - Bukkit.getScheduler().cancelTask(senderID); - sendQueue.removeAll(toRemove); - - return; - } - - final int id = -id0; - Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> { - try { - PacketPlayOutMap packet = new PacketPlayOutMap( - id, //ID - (byte) 0, //Scale - false, //Tracking position - false, //Locked - new ArrayList<>(), //Icons - content.array, //Data - content.minX, //X pos - content.minY, //Y pos - content.maxX, //X size (2nd X pos) - content.maxY //Y size (2nd Y pos) - ); - - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - static final class QueuedMap { - private final int id; - private final ArrayImage image; - private final Player player; - - QueuedMap(int id, ArrayImage image, Player player) { - this.id = id; - this.image = image; - this.player = player; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - if (obj == null || obj.getClass() != this.getClass()) return false; - var that = (QueuedMap) obj; - return this.id == that.id && - Objects.equals(this.image, that.image) && - Objects.equals(this.player, that.player); - } - - @Override - public int hashCode() { - return Objects.hash(id, image, player); - } - - @Override - public String toString() { - return "QueuedMap[" + - "id=" + id + ", " + - "image=" + image + ", " + - "player=" + player + ']'; - } - } -} diff --git a/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_16_R3.java b/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_16_R3.java deleted file mode 100644 index 061f41b..0000000 --- a/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_16_R3.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.server.v1_16_R3.*; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.*; -import org.bukkit.craftbukkit.v1_16_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; -import tech.sbdevelopment.mapreflectionapi.api.MapController; -import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; - -import java.util.*; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class MapWrapper_v1_16_R3 extends MapWrapper { - protected MapController controller = new MapController() { - private final Map viewers = new HashMap<>(); - - @Override - public void addViewer(Player player) throws MapLimitExceededException { - if (!isViewing(player)) { - viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player)); - } - } - - @Override - public void removeViewer(OfflinePlayer player) { - viewers.remove(player.getUniqueId()); - } - - @Override - public void clearViewers() { - for (UUID uuid : viewers.keySet()) { - viewers.remove(uuid); - } - } - - @Override - public boolean isViewing(OfflinePlayer player) { - if (player == null) return false; - return viewers.containsKey(player.getUniqueId()); - } - - @Override - public int getMapId(OfflinePlayer player) { - if (isViewing(player)) { - return viewers.get(player.getUniqueId()); - } - return -1; - } - - @Override - public void update(ArrayImage content) { - MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content); - if (duplicate != null) { - MapWrapper_v1_16_R3.this.content = duplicate.getContent(); - return; - } - - MapWrapper_v1_16_R3.this.content = content; - - for (UUID id : viewers.keySet()) { - sendContent(Bukkit.getPlayer(id)); - } - } - - @Override - public ArrayImage getContent() { - return MapWrapper_v1_16_R3.this.getContent(); - } - - @Override - public void sendContent(Player player) { - sendContent(player, false); - } - - @Override - public void sendContent(Player player, boolean withoutQueue) { - if (!isViewing(player)) return; - - int id = getMapId(player); - if (withoutQueue) { - MapSender_v1_16_R3.sendMap(id, MapWrapper_v1_16_R3.this.content, player); - } else { - MapSender_v1_16_R3.addToQueue(id, MapWrapper_v1_16_R3.this.content, player); - } - } - - @Override - public void showInInventory(Player player, int slot, boolean force) { - if (!isViewing(player)) return; - - if (player.getGameMode() == GameMode.CREATIVE && !force) return; - - if (slot < 9) { - slot += 36; - } else if (slot > 35 && slot != 45) { - slot = 8 - (slot - 36); - } - - CraftPlayer craftPlayer = (CraftPlayer) player; - int windowId = craftPlayer.getHandle().defaultContainer.windowId; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - - PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack); - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } - - @Override - public void showInInventory(Player player, int slot) { - showInInventory(player, slot, false); - } - - @Override - public void showInHand(Player player, boolean force) { - if (player.getInventory().getItemInMainHand().getType() != Material.FILLED_MAP && !force) return; - showInInventory(player, player.getInventory().getHeldItemSlot(), force); - } - - @Override - public void showInHand(Player player) { - showInHand(player, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame) { - showInFrame(player, frame, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame, boolean force) { - if (frame.getItem().getType() != Material.FILLED_MAP && !force) return; - showInFrame(player, frame.getEntityId()); - } - - @Override - public void showInFrame(Player player, int entityId) { - showInFrame(player, entityId, null); - } - - @Override - public void showInFrame(Player player, int entityId, String debugInfo) { - if (!isViewing(player)) return; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - if (debugInfo != null) { - ItemMeta itemMeta = stack.getItemMeta(); - itemMeta.setDisplayName(debugInfo); - stack.setItemMeta(itemMeta); - } - - Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> { - ItemFrame frame = getItemFrameById(player.getWorld(), entityId); - if (frame != null) { - frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance()); - frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_16_R3.this)); - } - - sendItemFramePacket(player, entityId, stack, getMapId(player)); - }); - } - - @Override - public void clearFrame(Player player, int entityId) { - - } - - @Override - public void clearFrame(Player player, ItemFrame frame) { - - } - - @Override - public ItemFrame getItemFrameById(World world, int entityId) { - CraftWorld craftWorld = (CraftWorld) world; - - Entity entity = craftWorld.getHandle().getEntity(entityId); - if (entity == null) return null; - - org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); - if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity; - - return null; - } - - private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) { - net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - nmsStack.getOrCreateTag().setInt("map", mapId); //getOrCreateTag putInt - - PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, new DataWatcher(null), true); - - try { - List> list = new ArrayList<>(); - DataWatcherObject dataWatcherObject = (DataWatcherObject) getField(EntityItemFrame.class, "ITEM"); - DataWatcher.Item dataWatcherItem = new DataWatcher.Item<>(dataWatcherObject, nmsStack); - list.add(dataWatcherItem); - setField(packet, "b", list); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } - }; - - public MapWrapper_v1_16_R3(ArrayImage image) { - super(image); - } - - @Override - public MapController getController() { - return controller; - } -} diff --git a/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_16_R3.java b/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_16_R3.java deleted file mode 100644 index 3e846ba..0000000 --- a/NMS-v1_16_R3/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_16_R3.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import io.netty.channel.*; -import net.minecraft.server.v1_16_R3.*; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; -import org.bukkit.entity.Player; -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.listeners.PacketListener; - -import java.util.concurrent.TimeUnit; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class PacketListener_v1_16_R3 extends PacketListener { - @Override - protected void injectPlayer(Player p) { - ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { - @Override - //On send packet - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (packet instanceof PacketPlayOutMap) { - PacketPlayOutMap packetPlayOutMap = (PacketPlayOutMap) packet; - - int id = (int) getField(packetPlayOutMap, "a"); - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - setField(packetPlayOutMap, "a", newId); //mapId - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent event = new MapCancelEvent(p, id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true); - if (event.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) return; - } - } - - super.write(ctx, packet, promise); - } - - @Override - //On receive packet - public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { - if (packet instanceof PacketPlayInUseEntity) { - PacketPlayInUseEntity packetPlayInUseEntity = (PacketPlayInUseEntity) packet; - - int entityId = (int) getField(packetPlayInUseEntity, "a"); //entityId - PacketPlayInUseEntity.EnumEntityUseAction action = packetPlayInUseEntity.b(); //action - EnumHand hand = packetPlayInUseEntity.c(); //hand - Vec3D pos = packetPlayInUseEntity.d(); //pos - - if (Bukkit.getScheduler().callSyncMethod(plugin, () -> { - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent event = new MapInteractEvent(p, entityId, action.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 instanceof PacketPlayInSetCreativeSlot) { - PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) packet; - - int slot = packetPlayInSetCreativeSlot.b(); - ItemStack item = packetPlayInSetCreativeSlot.getItemStack(); - - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async); - if (event.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) return; - } - } - - super.channelRead(ctx, packet); - } - }; - - ChannelPipeline pipeline = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel.pipeline(); - pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler); - } - - @Override - public void removePlayer(Player p) { - Channel channel = ((CraftPlayer) p).getHandle().playerConnection.networkManager.channel; - channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName())); - } - - @Override - protected Vector vec3DToVector(Object vec3d) { - if (!(vec3d instanceof Vec3D)) return new Vector(0, 0, 0); - - Vec3D vec3dObj = (Vec3D) vec3d; - return new Vector(vec3dObj.x, vec3dObj.y, vec3dObj.z); - } -} diff --git a/NMS-v1_17_R1/pom.xml b/NMS-v1_17_R1/pom.xml deleted file mode 100644 index b36444c..0000000 --- a/NMS-v1_17_R1/pom.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-NMS-v1_17_R1 - - - 1.17.1-R0.1-SNAPSHOT - 16 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - - - - - org.bukkit - craftbukkit - ${NMSVersion} - provided - - - tech.sbdevelopment - MapReflectionAPI-API - 1.0-SNAPSHOT - provided - - - \ No newline at end of file diff --git a/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_17_R1.java b/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_17_R1.java deleted file mode 100644 index c639def..0000000 --- a/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_17_R1.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.network.protocol.game.PacketPlayOutMap; -import net.minecraft.world.level.saveddata.maps.WorldMap; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; - -import java.util.ArrayList; -import java.util.List; - -public class MapSender_v1_17_R1 { - private static final List sendQueue = new ArrayList<>(); - private static int senderID = -1; - - public static void addToQueue(final int id, final ArrayImage content, final Player player) { - QueuedMap toSend = new QueuedMap(id, content, player); - if (sendQueue.contains(toSend)) return; - sendQueue.add(toSend); - - runSender(); - } - - private static void runSender() { - if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty()) - return; - - senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> { - if (sendQueue.isEmpty()) return; - - for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) { - QueuedMap current = sendQueue.get(0); - if (current == null) return; - - sendMap(current.id, current.image, current.player); - - if (!sendQueue.isEmpty()) sendQueue.remove(0); - } - }, 0, 2); - } - - public static void sendMap(final int id0, final ArrayImage content, final Player player) { - if (player == null || !player.isOnline()) { - List toRemove = new ArrayList<>(); - for (QueuedMap qMap : sendQueue) { - if (qMap == null) continue; - - if (qMap.player == null || !qMap.player.isOnline()) { - toRemove.add(qMap); - } - } - Bukkit.getScheduler().cancelTask(senderID); - sendQueue.removeAll(toRemove); - - return; - } - - final int id = -id0; - Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> { - try { - WorldMap.b updateData = new WorldMap.b( - content.minX, //X pos - content.minY, //Y pos - content.maxX, //X size (2nd X pos) - content.maxY, //Y size (2nd Y pos) - content.array //Data - ); - - PacketPlayOutMap packet = new PacketPlayOutMap( - id, //ID - (byte) 0, //Scale - false, //Show icons - new ArrayList<>(), //Icons - updateData - ); - - ((CraftPlayer) player).getHandle().b.sendPacket(packet); //connection send() - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - record QueuedMap(int id, ArrayImage image, Player player) { - } -} \ No newline at end of file diff --git a/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_17_R1.java b/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_17_R1.java deleted file mode 100644 index e31eb45..0000000 --- a/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_17_R1.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata; -import net.minecraft.network.protocol.game.PacketPlayOutSetSlot; -import net.minecraft.network.syncher.DataWatcher; -import net.minecraft.network.syncher.DataWatcherObject; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.decoration.EntityItemFrame; -import org.bukkit.*; -import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; -import tech.sbdevelopment.mapreflectionapi.api.MapController; -import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; - -import java.util.*; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class MapWrapper_v1_17_R1 extends MapWrapper { - protected MapController controller = new MapController() { - private final Map viewers = new HashMap<>(); - - @Override - public void addViewer(Player player) throws MapLimitExceededException { - if (!isViewing(player)) { - viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player)); - } - } - - @Override - public void removeViewer(OfflinePlayer player) { - viewers.remove(player.getUniqueId()); - } - - @Override - public void clearViewers() { - for (UUID uuid : viewers.keySet()) { - viewers.remove(uuid); - } - } - - @Override - public boolean isViewing(OfflinePlayer player) { - if (player == null) return false; - return viewers.containsKey(player.getUniqueId()); - } - - @Override - public int getMapId(OfflinePlayer player) { - if (isViewing(player)) { - return viewers.get(player.getUniqueId()); - } - return -1; - } - - @Override - public void update(ArrayImage content) { - MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content); - if (duplicate != null) { - MapWrapper_v1_17_R1.this.content = duplicate.getContent(); - return; - } - - MapWrapper_v1_17_R1.this.content = content; - - for (UUID id : viewers.keySet()) { - sendContent(Bukkit.getPlayer(id)); - } - } - - @Override - public ArrayImage getContent() { - return MapWrapper_v1_17_R1.this.getContent(); - } - - @Override - public void sendContent(Player player) { - sendContent(player, false); - } - - @Override - public void sendContent(Player player, boolean withoutQueue) { - if (!isViewing(player)) return; - - int id = getMapId(player); - if (withoutQueue) { - MapSender_v1_17_R1.sendMap(id, MapWrapper_v1_17_R1.this.content, player); - } else { - MapSender_v1_17_R1.addToQueue(id, MapWrapper_v1_17_R1.this.content, player); - } - } - - @Override - public void showInInventory(Player player, int slot, boolean force) { - if (!isViewing(player)) return; - - if (player.getGameMode() == GameMode.CREATIVE && !force) return; - - if (slot < 9) { - slot += 36; - } else if (slot > 35 && slot != 45) { - slot = 8 - (slot - 36); - } - - CraftPlayer craftPlayer = (CraftPlayer) player; - int windowId = craftPlayer.getHandle().bU.j; //inventoryMenu containerId - int stateId = craftPlayer.getHandle().bU.getStateId(); //inventoryMenu getStateId() - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - - PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, stateId, slot, nmsStack); - ((CraftPlayer) player).getHandle().b.sendPacket(packet); - } - - @Override - public void showInInventory(Player player, int slot) { - showInInventory(player, slot, false); - } - - @Override - public void showInHand(Player player, boolean force) { - if (player.getInventory().getItemInMainHand().getType() != Material.FILLED_MAP && !force) return; - showInInventory(player, player.getInventory().getHeldItemSlot(), force); - } - - @Override - public void showInHand(Player player) { - showInHand(player, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame) { - showInFrame(player, frame, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame, boolean force) { - if (frame.getItem().getType() != Material.FILLED_MAP && !force) return; - showInFrame(player, frame.getEntityId()); - } - - @Override - public void showInFrame(Player player, int entityId) { - showInFrame(player, entityId, null); - } - - @Override - public void showInFrame(Player player, int entityId, String debugInfo) { - if (!isViewing(player)) return; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - if (debugInfo != null) { - ItemMeta itemMeta = stack.getItemMeta(); - itemMeta.setDisplayName(debugInfo); - stack.setItemMeta(itemMeta); - } - - Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> { - ItemFrame frame = getItemFrameById(player.getWorld(), entityId); - if (frame != null) { - frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance()); - frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_17_R1.this)); - } - - sendItemFramePacket(player, entityId, stack, getMapId(player)); - }); - } - - @Override - public void clearFrame(Player player, int entityId) { - - } - - @Override - public void clearFrame(Player player, ItemFrame frame) { - - } - - @Override - public ItemFrame getItemFrameById(World world, int entityId) { - CraftWorld craftWorld = (CraftWorld) world; - - Entity entity = craftWorld.getHandle().getEntity(entityId); - if (entity == null) return null; - - if (entity instanceof ItemFrame) return (ItemFrame) entity; - - return null; - } - - private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) { - net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - nmsStack.getOrCreateTag().setInt("map", mapId); //getOrCreateTag putInt - - PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, new DataWatcher(null), true); - - try { - List> list = new ArrayList<>(); - DataWatcherObject dataWatcherObject = (DataWatcherObject) getField(EntityItemFrame.class, "ao"); - DataWatcher.Item dataWatcherItem = new DataWatcher.Item<>(dataWatcherObject, nmsStack); - list.add(dataWatcherItem); - setField(packet, "b", list); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - ((CraftPlayer) player).getHandle().b.sendPacket(packet); - } - }; - - public MapWrapper_v1_17_R1(ArrayImage image) { - super(image); - } - - @Override - public MapController getController() { - return controller; - } -} \ No newline at end of file diff --git a/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_17_R1.java b/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_17_R1.java deleted file mode 100644 index 1b26136..0000000 --- a/NMS-v1_17_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_17_R1.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import io.netty.channel.*; -import net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot; -import net.minecraft.network.protocol.game.PacketPlayInUseEntity; -import net.minecraft.network.protocol.game.PacketPlayOutMap; -import net.minecraft.world.EnumHand; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3D; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_17_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack; -import org.bukkit.entity.Player; -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.listeners.PacketListener; - -import java.util.concurrent.TimeUnit; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.*; - -public class PacketListener_v1_17_R1 extends PacketListener { - @Override - protected void injectPlayer(Player p) { - ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { - @Override - //On send packet - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (packet instanceof PacketPlayOutMap packetPlayOutMap) { - int id = (int) getField(packetPlayOutMap, "a"); - - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - setField(packetPlayOutMap, "a", newId); //mapId - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent event = new MapCancelEvent(p, id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true); - if (event.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) return; - } - } - - super.write(ctx, packet, promise); - } - - @Override - //On receive packet - public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { - if (packet instanceof PacketPlayInUseEntity packetPlayInUseEntity) { - int entityId = (int) getField(packetPlayInUseEntity, "a"); //entityId - Object action = getField(packetPlayInUseEntity, "b"); //action - Enum actionEnum = (Enum) getValue(action, "a"); //action type - EnumHand hand = hasField(action, "a") ? (EnumHand) getField(action, "a") : null; //hand - Vec3D pos = hasField(action, "b") ? (Vec3D) getField(action, "b") : null; //pos - - if (Bukkit.getScheduler().callSyncMethod(plugin, () -> { - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent event = new MapInteractEvent(p, 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 instanceof PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot) { - int slot = packetPlayInSetCreativeSlot.b(); - ItemStack item = packetPlayInSetCreativeSlot.getItemStack(); - - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async); - if (event.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) return; - } - } - - super.channelRead(ctx, packet); - } - }; - - ChannelPipeline pipeline = ((CraftPlayer) p).getHandle().b.a.k.pipeline(); //connection connection channel - pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler); - } - - @Override - public void removePlayer(Player p) { - Channel channel = ((CraftPlayer) p).getHandle().b.a.k; //connection connection channel - channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName())); - } - - @Override - protected Vector vec3DToVector(Object vec3d) { - if (!(vec3d instanceof Vec3D vec3dObj)) return new Vector(0, 0, 0); - return new Vector(vec3dObj.b, vec3dObj.c, vec3dObj.d); //x, y, z - } -} \ No newline at end of file diff --git a/NMS-v1_18_R2/pom.xml b/NMS-v1_18_R2/pom.xml deleted file mode 100644 index d3f7388..0000000 --- a/NMS-v1_18_R2/pom.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-NMS-v1_18_R2 - - - 1.18.2-R0.1-SNAPSHOT - 17 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - - - - - org.bukkit - craftbukkit - ${NMSVersion} - provided - - - tech.sbdevelopment - MapReflectionAPI-API - 1.0-SNAPSHOT - provided - - - \ No newline at end of file diff --git a/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_18_R2.java b/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_18_R2.java deleted file mode 100644 index dae512a..0000000 --- a/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_18_R2.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.network.protocol.game.PacketPlayOutMap; -import net.minecraft.world.level.saveddata.maps.WorldMap; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; -import org.bukkit.entity.Player; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; - -import java.util.ArrayList; -import java.util.List; - -public class MapSender_v1_18_R2 { - private static final List sendQueue = new ArrayList<>(); - private static int senderID = -1; - - public static void addToQueue(final int id, final ArrayImage content, final Player player) { - QueuedMap toSend = new QueuedMap(id, content, player); - if (sendQueue.contains(toSend)) return; - sendQueue.add(toSend); - - runSender(); - } - - private static void runSender() { - if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty()) - return; - - senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> { - if (sendQueue.isEmpty()) return; - - for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) { - QueuedMap current = sendQueue.get(0); - if (current == null) return; - - sendMap(current.id, current.image, current.player); - - if (!sendQueue.isEmpty()) sendQueue.remove(0); - } - }, 0, 2); - } - - public static void sendMap(final int id0, final ArrayImage content, final Player player) { - if (player == null || !player.isOnline()) { - List toRemove = new ArrayList<>(); - for (QueuedMap qMap : sendQueue) { - if (qMap == null) continue; - - if (qMap.player == null || !qMap.player.isOnline()) { - toRemove.add(qMap); - } - } - Bukkit.getScheduler().cancelTask(senderID); - sendQueue.removeAll(toRemove); - - return; - } - - final int id = -id0; - Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> { - try { - WorldMap.b updateData = new WorldMap.b( - content.minX, //X pos - content.minY, //Y pos - content.maxX, //X size (2nd X pos) - content.maxY, //Y size (2nd Y pos) - content.array //Data - ); - - PacketPlayOutMap packet = new PacketPlayOutMap( - id, //ID - (byte) 0, //Scale - false, //Show icons - new ArrayList<>(), //Icons - updateData - ); - - ((CraftPlayer) player).getHandle().b.a(packet); //connection send() - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - record QueuedMap(int id, ArrayImage image, Player player) { - } -} \ No newline at end of file diff --git a/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_18_R2.java b/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_18_R2.java deleted file mode 100644 index 671c86e..0000000 --- a/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_18_R2.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata; -import net.minecraft.network.protocol.game.PacketPlayOutSetSlot; -import net.minecraft.network.syncher.DataWatcher; -import net.minecraft.network.syncher.DataWatcherObject; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.decoration.EntityItemFrame; -import org.bukkit.*; -import org.bukkit.craftbukkit.v1_18_R2.CraftWorld; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; -import tech.sbdevelopment.mapreflectionapi.api.MapController; -import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; - -import java.util.*; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class MapWrapper_v1_18_R2 extends MapWrapper { - protected MapController controller = new MapController() { - private final Map viewers = new HashMap<>(); - - @Override - public void addViewer(Player player) throws MapLimitExceededException { - if (!isViewing(player)) { - viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player)); - } - } - - @Override - public void removeViewer(OfflinePlayer player) { - viewers.remove(player.getUniqueId()); - } - - @Override - public void clearViewers() { - for (UUID uuid : viewers.keySet()) { - viewers.remove(uuid); - } - } - - @Override - public boolean isViewing(OfflinePlayer player) { - if (player == null) return false; - return viewers.containsKey(player.getUniqueId()); - } - - @Override - public int getMapId(OfflinePlayer player) { - if (isViewing(player)) { - return viewers.get(player.getUniqueId()); - } - return -1; - } - - @Override - public void update(ArrayImage content) { - MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content); - if (duplicate != null) { - MapWrapper_v1_18_R2.this.content = duplicate.getContent(); - return; - } - - MapWrapper_v1_18_R2.this.content = content; - - for (UUID id : viewers.keySet()) { - sendContent(Bukkit.getPlayer(id)); - } - } - - @Override - public ArrayImage getContent() { - return MapWrapper_v1_18_R2.this.getContent(); - } - - @Override - public void sendContent(Player player) { - sendContent(player, false); - } - - @Override - public void sendContent(Player player, boolean withoutQueue) { - if (!isViewing(player)) return; - - int id = getMapId(player); - if (withoutQueue) { - MapSender_v1_18_R2.sendMap(id, MapWrapper_v1_18_R2.this.content, player); - } else { - MapSender_v1_18_R2.addToQueue(id, MapWrapper_v1_18_R2.this.content, player); - } - } - - @Override - public void showInInventory(Player player, int slot, boolean force) { - if (!isViewing(player)) return; - - if (player.getGameMode() == GameMode.CREATIVE && !force) return; - - if (slot < 9) { - slot += 36; - } else if (slot > 35 && slot != 45) { - slot = 8 - (slot - 36); - } - - CraftPlayer craftPlayer = (CraftPlayer) player; - int windowId = craftPlayer.getHandle().bU.j; //inventoryMenu containerId - int stateId = craftPlayer.getHandle().bU.j(); //inventoryMenu getStateId() - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - - PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, stateId, slot, nmsStack); - ((CraftPlayer) player).getHandle().b.a(packet); - } - - @Override - public void showInInventory(Player player, int slot) { - showInInventory(player, slot, false); - } - - @Override - public void showInHand(Player player, boolean force) { - if (player.getInventory().getItemInMainHand().getType() != Material.FILLED_MAP && !force) return; - showInInventory(player, player.getInventory().getHeldItemSlot(), force); - } - - @Override - public void showInHand(Player player) { - showInHand(player, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame) { - showInFrame(player, frame, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame, boolean force) { - if (frame.getItem().getType() != Material.FILLED_MAP && !force) return; - showInFrame(player, frame.getEntityId()); - } - - @Override - public void showInFrame(Player player, int entityId) { - showInFrame(player, entityId, null); - } - - @Override - public void showInFrame(Player player, int entityId, String debugInfo) { - if (!isViewing(player)) return; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - if (debugInfo != null) { - ItemMeta itemMeta = stack.getItemMeta(); - itemMeta.setDisplayName(debugInfo); - stack.setItemMeta(itemMeta); - } - - Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> { - ItemFrame frame = getItemFrameById(player.getWorld(), entityId); - if (frame != null) { - frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance()); - frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_18_R2.this)); - } - - sendItemFramePacket(player, entityId, stack, getMapId(player)); - }); - } - - @Override - public void clearFrame(Player player, int entityId) { - - } - - @Override - public void clearFrame(Player player, ItemFrame frame) { - - } - - @Override - public ItemFrame getItemFrameById(World world, int entityId) { - CraftWorld craftWorld = (CraftWorld) world; - - Entity entity = craftWorld.getHandle().a(entityId); - if (entity == null) return null; - - if (entity instanceof ItemFrame) return (ItemFrame) entity; - - return null; - } - - private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) { - net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - nmsStack.u().a("map", mapId); //getOrCreateTag putInt - - PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, new DataWatcher(null), true); - - try { - List> list = new ArrayList<>(); - DataWatcherObject dataWatcherObject = (DataWatcherObject) getField(EntityItemFrame.class, "ao"); - DataWatcher.Item dataWatcherItem = new DataWatcher.Item<>(dataWatcherObject, nmsStack); - list.add(dataWatcherItem); - setField(packet, "b", list); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - ((CraftPlayer) player).getHandle().b.a(packet); - } - }; - - public MapWrapper_v1_18_R2(ArrayImage image) { - super(image); - } - - @Override - public MapController getController() { - return controller; - } -} diff --git a/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_18_R2.java b/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_18_R2.java deleted file mode 100644 index ed14a73..0000000 --- a/NMS-v1_18_R2/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_18_R2.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import io.netty.channel.*; -import net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot; -import net.minecraft.network.protocol.game.PacketPlayInUseEntity; -import net.minecraft.network.protocol.game.PacketPlayOutMap; -import net.minecraft.world.EnumHand; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3D; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_18_R2.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack; -import org.bukkit.entity.Player; -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.listeners.PacketListener; - -import java.util.concurrent.TimeUnit; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.*; - -public class PacketListener_v1_18_R2 extends PacketListener { - @Override - protected void injectPlayer(Player p) { - ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { - @Override - //On send packet - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (packet instanceof PacketPlayOutMap packetPlayOutMap) { - int id = (int) getField(packetPlayOutMap, "a"); - - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - setField(packetPlayOutMap, "a", newId); //mapId - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent event = new MapCancelEvent(p, id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true); - if (event.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) return; - } - } - - super.write(ctx, packet, promise); - } - - @Override - //On receive packet - public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { - if (packet instanceof PacketPlayInUseEntity packetPlayInUseEntity) { - int entityId = (int) getField(packetPlayInUseEntity, "a"); //entityId - Object action = getField(packetPlayInUseEntity, "b"); //action - Enum actionEnum = (Enum) getValue(action, "a"); //action type - EnumHand hand = hasField(action, "a") ? (EnumHand) getField(action, "a") : null; //hand - Vec3D pos = hasField(action, "b") ? (Vec3D) getField(action, "b") : null; //pos - - if (Bukkit.getScheduler().callSyncMethod(plugin, () -> { - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent event = new MapInteractEvent(p, 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 instanceof PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot) { - int slot = packetPlayInSetCreativeSlot.b(); - ItemStack item = packetPlayInSetCreativeSlot.c(); - - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async); - if (event.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) return; - } - } - - super.channelRead(ctx, packet); - } - }; - - ChannelPipeline pipeline = ((CraftPlayer) p).getHandle().b.a.m.pipeline(); //connection connection channel - pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler); - } - - @Override - public void removePlayer(Player p) { - Channel channel = ((CraftPlayer) p).getHandle().b.a.m; //connection connection channel - channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName())); - } - - @Override - protected Vector vec3DToVector(Object vec3d) { - if (!(vec3d instanceof Vec3D vec3dObj)) return new Vector(0, 0, 0); - return new Vector(vec3dObj.b, vec3dObj.c, vec3dObj.d); //x, y, z - } -} diff --git a/NMS-v1_19_R1/pom.xml b/NMS-v1_19_R1/pom.xml deleted file mode 100644 index 6fe4d53..0000000 --- a/NMS-v1_19_R1/pom.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - MapReflectionAPI - tech.sbdevelopment - ${revision} - - 4.0.0 - - MapReflectionAPI-NMS-v1_19_R1 - - - 1.19-R0.1-SNAPSHOT - 17 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.9.0-SNAPSHOT - - ${jdk.version} - - - - org.apache.maven.plugins - maven-deploy-plugin - 3.0.0-M2 - - true - - - - - - - - org.bukkit - craftbukkit - ${NMSVersion} - provided - - - tech.sbdevelopment - MapReflectionAPI-API - 1.0-SNAPSHOT - provided - - - \ No newline at end of file diff --git a/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_19_R1.java b/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_19_R1.java deleted file mode 100644 index 3d420c0..0000000 --- a/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_19_R1.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.network.protocol.game.PacketPlayOutMap; -import net.minecraft.world.level.saveddata.maps.WorldMap; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; - -import java.util.ArrayList; -import java.util.List; - -public class MapSender_v1_19_R1 { - private static final List sendQueue = new ArrayList<>(); - private static int senderID = -1; - - public static void addToQueue(final int id, final ArrayImage content, final Player player) { - QueuedMap toSend = new QueuedMap(id, content, player); - if (sendQueue.contains(toSend)) return; - sendQueue.add(toSend); - - runSender(); - } - - private static void runSender() { - if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty()) - return; - - senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> { - if (sendQueue.isEmpty()) return; - - for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) { - QueuedMap current = sendQueue.get(0); - if (current == null) return; - - sendMap(current.id, current.image, current.player); - - if (!sendQueue.isEmpty()) sendQueue.remove(0); - } - }, 0, 2); - } - - public static void sendMap(final int id0, final ArrayImage content, final Player player) { - if (player == null || !player.isOnline()) { - List toRemove = new ArrayList<>(); - for (QueuedMap qMap : sendQueue) { - if (qMap == null) continue; - - if (qMap.player == null || !qMap.player.isOnline()) { - toRemove.add(qMap); - } - } - Bukkit.getScheduler().cancelTask(senderID); - sendQueue.removeAll(toRemove); - - return; - } - - final int id = -id0; - Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> { - try { - WorldMap.b updateData = new WorldMap.b( - content.minX, //X pos - content.minY, //Y pos - content.maxX, //X size (2nd X pos) - content.maxY, //Y size (2nd Y pos) - content.array //Data - ); - - PacketPlayOutMap packet = new PacketPlayOutMap( - id, //ID - (byte) 0, //Scale - false, //Show icons - new ArrayList<>(), //Icons - updateData - ); - - ((CraftPlayer) player).getHandle().b.a(packet); //connection send() - } catch (Exception e) { - e.printStackTrace(); - } - }); - } - - record QueuedMap(int id, ArrayImage image, Player player) { - } -} diff --git a/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_19_R1.java b/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_19_R1.java deleted file mode 100644 index 9267d6f..0000000 --- a/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_19_R1.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata; -import net.minecraft.network.protocol.game.PacketPlayOutSetSlot; -import net.minecraft.network.syncher.DataWatcher; -import net.minecraft.network.syncher.DataWatcherObject; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.decoration.EntityItemFrame; -import org.bukkit.*; -import org.bukkit.craftbukkit.v1_19_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.metadata.FixedMetadataValue; -import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; -import tech.sbdevelopment.mapreflectionapi.api.MapController; -import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; - -import java.util.*; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; - -public class MapWrapper_v1_19_R1 extends MapWrapper { - protected MapController controller = new MapController() { - private final Map viewers = new HashMap<>(); - - @Override - public void addViewer(Player player) throws MapLimitExceededException { - if (!isViewing(player)) { - viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player)); - } - } - - @Override - public void removeViewer(OfflinePlayer player) { - viewers.remove(player.getUniqueId()); - } - - @Override - public void clearViewers() { - for (UUID uuid : viewers.keySet()) { - viewers.remove(uuid); - } - } - - @Override - public boolean isViewing(OfflinePlayer player) { - if (player == null) return false; - return viewers.containsKey(player.getUniqueId()); - } - - @Override - public int getMapId(OfflinePlayer player) { - if (isViewing(player)) { - return viewers.get(player.getUniqueId()); - } - return -1; - } - - @Override - public void update(ArrayImage content) { - MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content); - if (duplicate != null) { - MapWrapper_v1_19_R1.this.content = duplicate.getContent(); - return; - } - - MapWrapper_v1_19_R1.this.content = content; - - for (UUID id : viewers.keySet()) { - sendContent(Bukkit.getPlayer(id)); - } - } - - @Override - public ArrayImage getContent() { - return MapWrapper_v1_19_R1.this.getContent(); - } - - @Override - public void sendContent(Player player) { - sendContent(player, false); - } - - @Override - public void sendContent(Player player, boolean withoutQueue) { - if (!isViewing(player)) return; - - int id = getMapId(player); - if (withoutQueue) { - MapSender_v1_19_R1.sendMap(id, MapWrapper_v1_19_R1.this.content, player); - } else { - MapSender_v1_19_R1.addToQueue(id, MapWrapper_v1_19_R1.this.content, player); - } - } - - @Override - public void showInInventory(Player player, int slot, boolean force) { - if (!isViewing(player)) return; - - if (player.getGameMode() == GameMode.CREATIVE && !force) return; - - if (slot < 9) { - slot += 36; - } else if (slot > 35 && slot != 45) { - slot = 8 - (slot - 36); - } - - CraftPlayer craftPlayer = (CraftPlayer) player; - int windowId = craftPlayer.getHandle().bT.j; //inventoryMenu containerId - int stateId = craftPlayer.getHandle().bT.j(); //inventoryMenu getStateId() - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - - PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, stateId, slot, nmsStack); - ((CraftPlayer) player).getHandle().b.a(packet); - } - - @Override - public void showInInventory(Player player, int slot) { - showInInventory(player, slot, false); - } - - @Override - public void showInHand(Player player, boolean force) { - if (player.getInventory().getItemInMainHand().getType() != Material.FILLED_MAP && !force) return; - showInInventory(player, player.getInventory().getHeldItemSlot(), force); - } - - @Override - public void showInHand(Player player) { - showInHand(player, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame) { - showInFrame(player, frame, false); - } - - @Override - public void showInFrame(Player player, ItemFrame frame, boolean force) { - if (frame.getItem().getType() != Material.FILLED_MAP && !force) return; - showInFrame(player, frame.getEntityId()); - } - - @Override - public void showInFrame(Player player, int entityId) { - showInFrame(player, entityId, null); - } - - @Override - public void showInFrame(Player player, int entityId, String debugInfo) { - if (!isViewing(player)) return; - - ItemStack stack = new ItemStack(Material.FILLED_MAP, 1); - if (debugInfo != null) { - ItemMeta itemMeta = stack.getItemMeta(); - itemMeta.setDisplayName(debugInfo); - stack.setItemMeta(itemMeta); - } - - Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> { - ItemFrame frame = getItemFrameById(player.getWorld(), entityId); - if (frame != null) { - frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance()); - frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_19_R1.this)); - } - - sendItemFramePacket(player, entityId, stack, getMapId(player)); - }); - } - - @Override - public void clearFrame(Player player, int entityId) { - - } - - @Override - public void clearFrame(Player player, ItemFrame frame) { - - } - - @Override - public ItemFrame getItemFrameById(World world, int entityId) { - CraftWorld craftWorld = (CraftWorld) world; - - Entity entity = craftWorld.getHandle().a(entityId); - if (entity == null) return null; - - if (entity instanceof ItemFrame) return (ItemFrame) entity; - - return null; - } - - private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) { - net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - nmsStack.v().a("map", mapId); //getOrCreateTag putInt - - PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, new DataWatcher(null), true); - - try { - List> list = new ArrayList<>(); - DataWatcherObject dataWatcherObject = (DataWatcherObject) getField(EntityItemFrame.class, "ao"); - DataWatcher.Item dataWatcherItem = new DataWatcher.Item<>(dataWatcherObject, nmsStack); - list.add(dataWatcherItem); - setField(packet, "b", list); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - ((CraftPlayer) player).getHandle().b.a(packet); - } - }; - - public MapWrapper_v1_19_R1(ArrayImage image) { - super(image); - } - - @Override - public MapController getController() { - return controller; - } -} diff --git a/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_19_R1.java b/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_19_R1.java deleted file mode 100644 index 3786d4d..0000000 --- a/NMS-v1_19_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/PacketListener_v1_19_R1.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is part of MapReflectionAPI. - * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package tech.sbdevelopment.mapreflectionapi.nms; - -import io.netty.channel.*; -import net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot; -import net.minecraft.network.protocol.game.PacketPlayInUseEntity; -import net.minecraft.network.protocol.game.PacketPlayOutMap; -import net.minecraft.world.EnumHand; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.phys.Vec3D; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack; -import org.bukkit.entity.Player; -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.listeners.PacketListener; - -import java.util.concurrent.TimeUnit; - -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.*; - -public class PacketListener_v1_19_R1 extends PacketListener { - @Override - protected void injectPlayer(Player p) { - ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() { - @Override - //On send packet - public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { - if (packet instanceof PacketPlayOutMap packetPlayOutMap) { - int id = (int) getField(packetPlayOutMap, "a"); - - if (id < 0) { - //It's one of our maps, invert ID and let through! - int newId = -id; - setField(packetPlayOutMap, "a", newId); //mapId - } else { - boolean async = !plugin.getServer().isPrimaryThread(); - MapCancelEvent event = new MapCancelEvent(p, id, async); - if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true); - if (event.getHandlers().getRegisteredListeners().length > 0) - Bukkit.getPluginManager().callEvent(event); - - if (event.isCancelled()) return; - } - } - - super.write(ctx, packet, promise); - } - - @Override - //On receive packet - public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception { - if (packet instanceof PacketPlayInUseEntity packetPlayInUseEntity) { - int entityId = (int) getField(packetPlayInUseEntity, "a"); //entityId - Object action = getField(packetPlayInUseEntity, "b"); //action - Enum actionEnum = (Enum) getValue(action, "a"); //action type - EnumHand hand = hasField(action, "a") ? (EnumHand) getField(action, "a") : null; //hand - Vec3D pos = hasField(action, "b") ? (Vec3D) getField(action, "b") : null; //pos - - if (Bukkit.getScheduler().callSyncMethod(plugin, () -> { - boolean async = !plugin.getServer().isPrimaryThread(); - MapInteractEvent event = new MapInteractEvent(p, 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 instanceof PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot) { - int slot = packetPlayInSetCreativeSlot.b(); - ItemStack item = packetPlayInSetCreativeSlot.c(); - - boolean async = !plugin.getServer().isPrimaryThread(); - CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async); - if (event.getMapWrapper() != null) { - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) return; - } - } - - super.channelRead(ctx, packet); - } - }; - - ChannelPipeline pipeline = ((CraftPlayer) p).getHandle().b.b.m.pipeline(); //connection connection channel - pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler); - } - - @Override - public void removePlayer(Player p) { - Channel channel = ((CraftPlayer) p).getHandle().b.b.m; //connection connection channel - channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName())); - } - - @Override - protected Vector vec3DToVector(Object vec3d) { - if (!(vec3d instanceof Vec3D vec3dObj)) return new Vector(0, 0, 0); - return new Vector(vec3dObj.c, vec3dObj.d, vec3dObj.e); //x, y, z - } -} diff --git a/pom.xml b/pom.xml index a575d69..0ad424c 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,27 @@ + + @@ -6,60 +29,57 @@ tech.sbdevelopment MapReflectionAPI - pom - ${revision} + 1.1 + jar + + MapReflectionAPI + This API helps developer with viewing images on maps. + https://sbdplugins.nl - 1.0-SNAPSHOT UTF-8 - 11 - - API - Dist - NMS-v1_19_R1 - NMS-v1_18_R2 - NMS-v1_17_R1 - NMS-v1_16_R3 - NMS-v1_15_R1 - NMS-v1_14_R1 - NMS-v1_13_R2 - NMS-v1_12_R1 - + + + nexus-releases + https://repo.sbdevelopment.tech/repository/maven-releases/ + + - clean package org.apache.maven.plugins - maven-toolchains-plugin - 3.1.0 - - - - toolchain - - - + maven-compiler-plugin + 3.9.0-SNAPSHOT - - - ${jdk.version} - - + 11 + + + org.projectlombok + lombok + 1.18.24 + + - org.apache.maven.plugins - maven-compiler-plugin - 3.10.1 - - ${jdk.version} - + maven-shade-plugin + 3.3.1-SNAPSHOT + + + package + + shade + + + false + + + - org.apache.maven.plugins maven-deploy-plugin @@ -68,7 +88,32 @@ true + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.13 + + + default-deploy + deploy + + deploy + + + + + nexus-releases + https://repo.sbdevelopment.tech/ + true + + + + + src/main/resources + true + + @@ -76,6 +121,14 @@ spigot-repo https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + MG-Dev Jenkins CI Maven Repository + https://ci.mg-dev.eu/plugin/repository/everything + + + dmulloy2-repo + https://repo.dmulloy2.net/repository/public/ + @@ -83,6 +136,25 @@ org.spigotmc spigot-api 1.19-R0.1-SNAPSHOT + provided + + + com.bergerkiller.bukkit + BKCommonLib + 1.19-v1 + provided + + + com.comphenix.protocol + ProtocolLib + 5.0.0-SNAPSHOT + provided + + + org.projectlombok + lombok + 1.18.24 + provided \ No newline at end of file diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java similarity index 81% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java index e12d932..85fd0bf 100644 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/MapReflectionAPI.java @@ -23,25 +23,36 @@ package tech.sbdevelopment.mapreflectionapi; +import com.comphenix.protocol.ProtocolLibrary; import org.bukkit.Bukkit; import org.bukkit.map.MapView; import org.bukkit.plugin.java.JavaPlugin; import tech.sbdevelopment.mapreflectionapi.api.MapManager; import tech.sbdevelopment.mapreflectionapi.listeners.MapListener; import tech.sbdevelopment.mapreflectionapi.listeners.PacketListener; +import tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil; import java.util.logging.Level; public class MapReflectionAPI extends JavaPlugin { private static MapReflectionAPI instance; private static MapManager mapManager; - private static PacketListener packetListener; + /** + * Get the plugin instance + * + * @return The {@link MapReflectionAPI} instance + */ public static MapReflectionAPI getInstance() { if (instance == null) throw new IllegalStateException("The plugin is not enabled yet!"); return instance; } + /** + * Get the {@link MapManager} + * + * @return The manager + */ public static MapManager getMapManager() { if (mapManager == null) throw new IllegalStateException("The plugin is not enabled yet!"); return mapManager; @@ -55,31 +66,26 @@ public class MapReflectionAPI extends JavaPlugin { getLogger().info("MapReflectionAPI v" + getDescription().getVersion() + ""); getLogger().info("Made by © Copyright SBDevelopment 2022"); + if (!ReflectionUtil.supports(12)) { + getLogger().severe("MapReflectionAPI only supports Minecraft 1.12 - 1.19!"); + Bukkit.getPluginManager().disablePlugin(this); + return; + } + if (!Bukkit.getPluginManager().isPluginEnabled("BKCommonLib")) { getLogger().severe("MapReflectionAPI requires BKCommonLib to function!"); Bukkit.getPluginManager().disablePlugin(this); return; } - try { - packetListener = PacketListener.construct(this); - } catch (IllegalStateException e) { - getLogger().log(Level.SEVERE, e.getMessage(), e); - Bukkit.getPluginManager().disablePlugin(this); - return; - } - packetListener.init(this); - - try { - mapManager = new MapManager(this); - } catch (IllegalStateException e) { - getLogger().log(Level.SEVERE, e.getMessage(), e); + if (!Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) { + getLogger().severe("MapReflectionAPI requires ProtocolLib to function!"); Bukkit.getPluginManager().disablePlugin(this); return; } - getLogger().info("Registering the events..."); - Bukkit.getPluginManager().registerEvents(new MapListener(), this); + getLogger().info("Loading the map manager..."); + mapManager = new MapManager(); getLogger().info("Discovering occupied Map IDs..."); for (int s = 0; s < Short.MAX_VALUE; s++) { @@ -93,15 +99,16 @@ public class MapReflectionAPI extends JavaPlugin { } } + getLogger().info("Registering the listeners..."); + Bukkit.getPluginManager().registerEvents(new MapListener(), this); + ProtocolLibrary.getProtocolManager().addPacketListener(new PacketListener(this)); + getLogger().info("MapReflectionAPI is enabled!"); getLogger().info("----------------"); } @Override public void onDisable() { - getLogger().info("Disabling the packet handler..."); - if (packetListener != null) Bukkit.getOnlinePlayers().forEach(p -> packetListener.removePlayer(p)); - getLogger().info("MapReflectionAPI is disabled!"); instance = null; diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/ArrayImage.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/ArrayImage.java similarity index 70% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/ArrayImage.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/ArrayImage.java index 47d0244..6ae3b61 100644 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/ArrayImage.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/ArrayImage.java @@ -24,14 +24,21 @@ package tech.sbdevelopment.mapreflectionapi.api; import com.bergerkiller.bukkit.common.map.MapColorPalette; +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.ToString; import java.awt.*; import java.awt.image.BufferedImage; -import java.util.Arrays; -import java.util.Objects; +/** + * This class contains an image converted to a Minecraft byte array + */ +@RequiredArgsConstructor +@EqualsAndHashCode +@ToString public class ArrayImage { - public byte[] array; + public final byte[] array; public int minX = 0; public int minY = 0; public int maxX = 128; @@ -40,10 +47,6 @@ public class ArrayImage { private int height; private int imageType = BufferedImage.TYPE_4BYTE_ABGR; - public ArrayImage(byte[] data) { - this.array = data; - } - /** * Convert a {@link BufferedImage} to an ArrayImage * @@ -71,32 +74,18 @@ public class ArrayImage { this.array = result; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ArrayImage)) return false; - ArrayImage that = (ArrayImage) o; - return width == that.width && height == that.height && imageType == that.imageType && Arrays.equals(array, that.array); - } - - @Override - public int hashCode() { - int result = Objects.hash(width, height, imageType); - result = 31 * result + Arrays.hashCode(array); - return result; - } - - @Override - public String toString() { - return "ArrayImage{" + - "array=" + Arrays.toString(array) + - ", minX=" + minX + - ", minY=" + minY + - ", maxX=" + maxX + - ", maxY=" + maxY + - ", width=" + width + - ", height=" + height + - ", imageType=" + imageType + - '}'; + /** + * Get the {@link BufferedImage} of this ArrayImage + * + * @return The converted image + */ + public BufferedImage toBuffered() { + BufferedImage img = new BufferedImage(width, height, this.imageType); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + img.setRGB(x, y, MapColorPalette.getRealColor(array[y * width + x]).getRGB()); + } + } + return img; } } diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java similarity index 96% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java index 0ea623d..90274d8 100644 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java @@ -27,7 +27,7 @@ import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; +import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException; public interface MapController { /** @@ -72,6 +72,11 @@ public interface MapController { */ void update(ArrayImage content); + /** + * Get the content of the controller + * + * @return The {@link ArrayImage} + */ ArrayImage getContent(); /** diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java similarity index 67% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java index f661e5c..fc1fede 100644 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java @@ -23,15 +23,12 @@ package tech.sbdevelopment.mapreflectionapi.api; -import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.Nullable; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; +import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException; import java.awt.image.BufferedImage; -import java.lang.reflect.InvocationTargetException; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -40,32 +37,23 @@ import java.util.concurrent.CopyOnWriteArrayList; public class MapManager { protected final Set OCCUPIED_IDS = new HashSet<>(); private final List MANAGED_MAPS = new CopyOnWriteArrayList<>(); - private final Class wrapperClass; - public MapManager(JavaPlugin plugin) throws IllegalStateException { - String packageName = Bukkit.getServer().getClass().getPackage().getName(); - String version = packageName.substring(packageName.lastIndexOf('.') + 1); - - plugin.getLogger().info("Initializing the map manager for Minecraft version " + version + "..."); - - try { - final Class clazz = Class.forName("tech.sbdevelopment.mapreflectionapi.nms.MapWrapper_" + version); - if (MapWrapper.class.isAssignableFrom(clazz)) { - wrapperClass = clazz; - } else { - throw new IllegalStateException("Plugin corrupted! Detected invalid MapWrapper class."); - } - } catch (Exception ex) { - throw new IllegalStateException("This Spigot version (" + version + ") is not supported! Contact the developer to get support."); - } - } - - @Nullable + /** + * Wrap a {@link BufferedImage} in a {@link MapWrapper} + * + * @param image The image to wrap + * @return The wrapper + */ public MapWrapper wrapImage(BufferedImage image) { return wrapImage(new ArrayImage(image)); } - @Nullable + /** + * Wrap a {@link ArrayImage} in a {@link MapWrapper} + * + * @param image The image to wrap + * @return The wrapper + */ public MapWrapper wrapImage(ArrayImage image) { for (MapWrapper wrapper : MANAGED_MAPS) { if (wrapper.getContent().equals(image)) return wrapper; @@ -73,18 +61,23 @@ public class MapManager { return wrapNewImage(image); } + /** + * Wrap a new image + * + * @param image The image to wrap + * @return The wrapper + */ private MapWrapper wrapNewImage(ArrayImage image) { - try { - MapWrapper wrapper = (MapWrapper) wrapperClass.getDeclaredConstructor(ArrayImage.class).newInstance(image); - MANAGED_MAPS.add(wrapper); - return wrapper; - } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | - InvocationTargetException e) { - e.printStackTrace(); - return null; - } + MapWrapper wrapper = new MapWrapper(image); + MANAGED_MAPS.add(wrapper); + return wrapper; } + /** + * Unwrap an image (will remove the wrapper) + * + * @param wrapper The {@link MapWrapper} to unwrap + */ public void unwrapImage(MapWrapper wrapper) { //TODO Cancel IDs @@ -92,6 +85,12 @@ public class MapManager { MANAGED_MAPS.remove(wrapper); } + /** + * Get the maps a player can see + * + * @param player The {@link Player} to check for + * @return A {@link Set} with the {@link MapWrapper}s + */ public Set getMapsVisibleTo(OfflinePlayer player) { Set visible = new HashSet<>(); for (MapWrapper wrapper : MANAGED_MAPS) { @@ -102,6 +101,14 @@ public class MapManager { return visible; } + /** + * Get the wrapper by a player and map id + * + * @param player The {@link OfflinePlayer} to check for + * @param id The ID of the map + * @return The {@link MapWrapper} for that map or null + */ + @Nullable public MapWrapper getWrapperForId(OfflinePlayer player, int id) { for (MapWrapper wrapper : getMapsVisibleTo(player)) { if (wrapper.getController().getMapId(player) == id) { @@ -111,14 +118,30 @@ public class MapManager { return null; } + /** + * Register an occupied map ID + * + * @param id The map ID to register + */ public void registerOccupiedID(int id) { OCCUPIED_IDS.add(id); } + /** + * Unregister an occupied map ID + * + * @param id The map ID to unregister + */ public void unregisterOccupiedID(int id) { OCCUPIED_IDS.remove(id); } + /** + * Get the occupied IDs for a player + * + * @param player The {@link OfflinePlayer} to check for + * @return A {@link Set} with the found map IDs + */ public Set getOccupiedIdsFor(OfflinePlayer player) { Set ids = new HashSet<>(); for (MapWrapper wrapper : MANAGED_MAPS) { @@ -130,10 +153,24 @@ public class MapManager { return ids; } + /** + * Check if a player uses a map ID + * + * @param player The {@link OfflinePlayer} to check for + * @param id The map ID to check for + * @return true/false + */ public boolean isIdUsedBy(OfflinePlayer player, int id) { return id > 0 && getOccupiedIdsFor(player).contains(id); } + /** + * Get the next ID that can be used for this player + * + * @param player The {@link Player} to check for + * @return The next ID + * @throws MapLimitExceededException If no IDs are available + */ public int getNextFreeIdFor(Player player) throws MapLimitExceededException { Set occupied = getOccupiedIdsFor(player); //Add the 'default' occupied IDs @@ -162,12 +199,26 @@ public class MapManager { throw new MapLimitExceededException("'" + player + "' reached the maximum amount of available Map-IDs"); } + /** + * Clear all the maps of a player + * This makes them no longer viewable for this player + * + * @param player The {@link OfflinePlayer} to clear for + */ public void clearAllMapsFor(OfflinePlayer player) { for (MapWrapper wrapper : getMapsVisibleTo(player)) { wrapper.getController().removeViewer(player); } } + /** + * Check if a MapWrapper exists for this image + * If so, the same MapWrapper can be used + * + * @param image The {@link ArrayImage} to check for + * @return A {@link MapWrapper} if duplicate, or null if not + */ + @Nullable public MapWrapper getDuplicate(ArrayImage image) { for (MapWrapper wrapper : MANAGED_MAPS) { if (image.equals(wrapper.getContent())) { diff --git a/NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_12_R1.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapSender.java similarity index 60% rename from NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_12_R1.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapSender.java index 88f0e6f..30a1252 100644 --- a/NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapSender_v1_12_R1.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapSender.java @@ -21,23 +21,28 @@ * SOFTWARE. */ -package tech.sbdevelopment.mapreflectionapi.nms; +package tech.sbdevelopment.mapreflectionapi.api; -import net.minecraft.server.v1_12_R1.PacketPlayOutMap; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; import org.bukkit.entity.Player; import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; +import tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil; import java.util.ArrayList; import java.util.List; import java.util.Objects; -public class MapSender_v1_12_R1 { +public class MapSender { private static final List sendQueue = new ArrayList<>(); private static int senderID = -1; + /** + * Add a map to the send queue + * + * @param id The ID of the map + * @param content The {@link ArrayImage} to view on the map + * @param player The {@link Player} to view for + */ public static void addToQueue(final int id, final ArrayImage content, final Player player) { QueuedMap toSend = new QueuedMap(id, content, player); if (sendQueue.contains(toSend)) return; @@ -46,6 +51,9 @@ public class MapSender_v1_12_R1 { runSender(); } + /** + * Run the sender task + */ private static void runSender() { if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty()) return; @@ -64,6 +72,16 @@ public class MapSender_v1_12_R1 { }, 0, 2); } + private static final Class packetPlayOutMapClass = ReflectionUtil.getNMSClass("network.protocol.game", "PacketPlayOutMap"); + private static final Class worldMapData = ReflectionUtil.supports(17) ? ReflectionUtil.getNMSClass("world.level.saveddata.maps", "WorldMap$b") : null; + + /** + * Send a map to a player + * + * @param id0 The ID of the map + * @param content The {@link ArrayImage} to view on the map + * @param player The {@link Player} to view for + */ public static void sendMap(final int id0, final ArrayImage content, final Player player) { if (player == null || !player.isOnline()) { List toRemove = new ArrayList<>(); @@ -81,27 +99,52 @@ public class MapSender_v1_12_R1 { } final int id = -id0; - Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> { - try { - PacketPlayOutMap packet = new PacketPlayOutMap( - id, //ID - (byte) 0, //Scale - false, //??? - new ArrayList<>(), //Icons - content.array, //Data - content.minX, //X pos - content.minY, //Y pos - content.maxX, //X size (2nd X pos) - content.maxY //Y size (2nd Y pos) - ); + Object packet; + if (ReflectionUtil.supports(17)) { //1.17+ + Object updateData = ReflectionUtil.callConstructor(worldMapData, + content.minX, //X pos + content.minY, //Y pos + content.maxX, //X size (2nd X pos) + content.maxY, //Y size (2nd Y pos) + content.array //Data + ); - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); - } catch (Exception e) { - e.printStackTrace(); - } - }); + packet = ReflectionUtil.callConstructor(packetPlayOutMapClass, + id, //ID + (byte) 0, //Scale + false, //Show icons + new ArrayList<>(), //Icons + updateData + ); + } else if (ReflectionUtil.supports(14)) { //1.16-1.14 + packet = ReflectionUtil.callConstructor(packetPlayOutMapClass, + id, //ID + (byte) 0, //Scale + false, //Tracking position + false, //Locked + new ArrayList<>(), //Icons + content.array, //Data + content.minX, //X pos + content.minY, //Y pos + content.maxX, //X size (2nd X pos) + content.maxY //Y size (2nd Y pos) + ); + } else { //1.13- + packet = ReflectionUtil.callConstructor(packetPlayOutMapClass, + id, //ID + (byte) 0, //Scale + false, //??? + new ArrayList<>(), //Icons + content.array, //Data + content.minX, //X pos + content.minY, //Y pos + content.maxX, //X size (2nd X pos) + content.maxY //Y size (2nd Y pos) + ); + } + + ReflectionUtil.sendPacket(player, packet); } - static final class QueuedMap { private final int id; private final ArrayImage image; diff --git a/NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_12_R1.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java similarity index 51% rename from NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_12_R1.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java index 6a38063..7e48ea9 100644 --- a/NMS-v1_12_R1/src/main/java/tech/sbdevelopment/mapreflectionapi/nms/MapWrapper_v1_12_R1.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java @@ -21,32 +21,41 @@ * SOFTWARE. */ -package tech.sbdevelopment.mapreflectionapi.nms; +package tech.sbdevelopment.mapreflectionapi.api; -import net.minecraft.server.v1_12_R1.*; -import org.bukkit.Material; -import org.bukkit.World; import org.bukkit.*; -import org.bukkit.craftbukkit.v1_12_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftItemStack; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.metadata.FixedMetadataValue; import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; -import tech.sbdevelopment.mapreflectionapi.api.ArrayImage; -import tech.sbdevelopment.mapreflectionapi.api.MapController; -import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; -import tech.sbdevelopment.mapreflectionapi.exceptions.MapLimitExceededException; +import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException; +import tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil; import java.util.*; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.getField; -import static tech.sbdevelopment.mapreflectionapi.util.ReflectionUtil.setField; +public class MapWrapper { + protected ArrayImage content; + + /** + * Construct a new {@link MapWrapper} + * + * @param image The {@link ArrayImage} to wrap + */ + public MapWrapper(ArrayImage image) { + this.content = image; + } + + private static final Class craftStackClass = ReflectionUtil.getCraftClass("inventory.CraftItemStack"); + private static final Class setSlotPacketClass = ReflectionUtil.getNMSClass("network.protocol.game", "PacketPlayOutSetSlot"); + private static final Class tagCompoundClass = ReflectionUtil.getNMSClass("nbt", "NBTTagCompound"); + private static final Class entityClass = ReflectionUtil.getNMSClass("world.entity", "Entity"); + private static final Class dataWatcherClass = ReflectionUtil.getNMSClass("network.syncher", "DataWatcher"); + private static final Class entityMetadataPacketClass = ReflectionUtil.getNMSClass("network.protocol.game", "PacketPlayOutEntityMetadata"); + private static final Class entityItemFrameClass = ReflectionUtil.getNMSClass("world.entity.decoration", "EntityItemFrame"); + private static final Class dataWatcherItemClass = ReflectionUtil.getNMSClass("network.syncher", "DataWatcher$Item"); -public class MapWrapper_v1_12_R1 extends MapWrapper { protected MapController controller = new MapController() { private final Map viewers = new HashMap<>(); @@ -87,11 +96,11 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { public void update(ArrayImage content) { MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content); if (duplicate != null) { - MapWrapper_v1_12_R1.this.content = duplicate.getContent(); + MapWrapper.this.content = duplicate.getContent(); return; } - MapWrapper_v1_12_R1.this.content = content; + MapWrapper.this.content = content; for (UUID id : viewers.keySet()) { sendContent(Bukkit.getPlayer(id)); @@ -100,7 +109,7 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { @Override public ArrayImage getContent() { - return MapWrapper_v1_12_R1.this.getContent(); + return MapWrapper.this.getContent(); } @Override @@ -114,9 +123,9 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { int id = getMapId(player); if (withoutQueue) { - MapSender_v1_12_R1.sendMap(id, MapWrapper_v1_12_R1.this.content, player); + MapSender.sendMap(id, MapWrapper.this.content, player); } else { - MapSender_v1_12_R1.addToQueue(id, MapWrapper_v1_12_R1.this.content, player); + MapSender.addToQueue(id, MapWrapper.this.content, player); } } @@ -132,14 +141,33 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { slot = 8 - (slot - 36); } - CraftPlayer craftPlayer = (CraftPlayer) player; - int windowId = craftPlayer.getHandle().defaultContainer.windowId; + Object playerHandle = ReflectionUtil.getHandle(player); + Object inventoryMenu = ReflectionUtil.getField(playerHandle, ReflectionUtil.supports(19) ? "bT" : ReflectionUtil.supports(17) ? "bU" : "defaultContainer"); + int windowId = (int) ReflectionUtil.getField(inventoryMenu, ReflectionUtil.supports(17) ? "j" : "windowId"); - ItemStack stack = new ItemStack(Material.MAP, 1); - net.minecraft.server.v1_12_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); + ItemStack stack = new ItemStack(ReflectionUtil.supports(13) ? Material.FILLED_MAP : Material.MAP, 1); - PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, slot, nmsStack); - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + Object nmsStack = ReflectionUtil.callMethod(craftStackClass, "asNMSCopy", stack); + + Object packet; + if (ReflectionUtil.supports(17)) { //1.17+ + int stateId = (int) ReflectionUtil.callMethod(inventoryMenu, ReflectionUtil.supports(18) ? "j" : "getStateId"); + + packet = ReflectionUtil.callConstructor(setSlotPacketClass, + windowId, + stateId, + slot, + nmsStack + ); + } else { //1.16- + packet = ReflectionUtil.callConstructor(setSlotPacketClass, + windowId, + slot, + nmsStack + ); + } + + ReflectionUtil.sendPacket(player, packet); } @Override @@ -149,7 +177,8 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { @Override public void showInHand(Player player, boolean force) { - if (player.getInventory().getItemInMainHand().getType() != Material.MAP && !force) return; + if (player.getInventory().getItemInMainHand().getType() != (ReflectionUtil.supports(13) ? Material.FILLED_MAP : Material.MAP) && !force) + return; showInInventory(player, player.getInventory().getHeldItemSlot(), force); } @@ -165,7 +194,8 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { @Override public void showInFrame(Player player, ItemFrame frame, boolean force) { - if (frame.getItem().getType() != Material.MAP && !force) return; + if (frame.getItem().getType() != (ReflectionUtil.supports(13) ? Material.FILLED_MAP : Material.MAP) && !force) + return; showInFrame(player, frame.getEntityId()); } @@ -178,7 +208,7 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { public void showInFrame(Player player, int entityId, String debugInfo) { if (!isViewing(player)) return; - ItemStack stack = new ItemStack(Material.MAP, 1); + ItemStack stack = new ItemStack(ReflectionUtil.supports(13) ? Material.FILLED_MAP : Material.MAP, 1); if (debugInfo != null) { ItemMeta itemMeta = stack.getItemMeta(); itemMeta.setDisplayName(debugInfo); @@ -189,7 +219,7 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { ItemFrame frame = getItemFrameById(player.getWorld(), entityId); if (frame != null) { frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance()); - frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_12_R1.this)); + frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper.this)); } sendItemFramePacket(player, entityId, stack, getMapId(player)); @@ -208,44 +238,60 @@ public class MapWrapper_v1_12_R1 extends MapWrapper { @Override public ItemFrame getItemFrameById(World world, int entityId) { - CraftWorld craftWorld = (CraftWorld) world; + Object worldHandle = ReflectionUtil.getHandle(world); + Object nmsEntity = ReflectionUtil.callMethod(worldHandle, ReflectionUtil.supports(18) ? "a" : "getEntity"); + if (nmsEntity == null) return null; - Entity entity = craftWorld.getHandle().getEntity(entityId); - if (entity == null) return null; - - org.bukkit.entity.Entity bukkitEntity = entity.getBukkitEntity(); - if (bukkitEntity instanceof ItemFrame) return (ItemFrame) bukkitEntity; + if (!ReflectionUtil.supports(17)) { + nmsEntity = ReflectionUtil.callMethod(nmsEntity, "getBukkitEntity"); + } + if (nmsEntity instanceof ItemFrame) return (ItemFrame) nmsEntity; return null; } private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) { - net.minecraft.server.v1_12_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack); - if (nmsStack.getTag() == null) nmsStack.setTag(new NBTTagCompound()); //No orCreate on 1.12.2! - nmsStack.getTag().setInt("map", mapId); //getTag putInt + Object nmsStack = ReflectionUtil.callMethod(craftStackClass, "asNMSCopy", stack); + Object nbtObject = ReflectionUtil.callMethod(nmsStack, ReflectionUtil.supports(19) ? "v" : ReflectionUtil.supports(18) ? "u" : ReflectionUtil.supports(13) ? "getOrCreateTag" : "getTag"); - PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, new DataWatcher(null), true); - - try { - List> list = new ArrayList<>(); - DataWatcherObject dataWatcherObject = (DataWatcherObject) getField(EntityItemFrame.class, "c"); - DataWatcher.Item dataWatcherItem = new DataWatcher.Item<>(dataWatcherObject, nmsStack); - list.add(dataWatcherItem); - setField(packet, "b", list); - } catch (Exception e) { - e.printStackTrace(); - return; + if (!ReflectionUtil.supports(13) && nbtObject == null) { //1.12 has no getOrCreate, call create if null! + Object tagCompound = ReflectionUtil.callConstructor(tagCompoundClass); + ReflectionUtil.callMethod(nbtObject, "setTag", tagCompound); } - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + ReflectionUtil.callMethod(nbtObject, ReflectionUtil.supports(18) ? "a" : "setInt", "map", mapId); + Object dataWatcher = ReflectionUtil.callConstructorNull(dataWatcherClass, entityClass); + + Object packet = ReflectionUtil.callConstructor(entityMetadataPacketClass, + entityId, + dataWatcher, //dummy watcher! + true + ); + + List list = new ArrayList<>(); + Object dataWatcherObject = ReflectionUtil.getDeclaredField(entityItemFrameClass, ReflectionUtil.supports(17) ? "ao" : ReflectionUtil.supports(14) ? "ITEM" : ReflectionUtil.supports(13) ? "e" : "c"); + Object dataWatcherItem = ReflectionUtil.callFirstConstructor(dataWatcherItemClass, dataWatcherObject, nmsStack); + list.add(dataWatcherItem); + ReflectionUtil.setDeclaredField(packet, "b", list); + + ReflectionUtil.sendPacket(player, packet); } }; - public MapWrapper_v1_12_R1(ArrayImage image) { - super(image); + /** + * Get the content that is wrapped + * + * @return The {@link ArrayImage} + */ + public ArrayImage getContent() { + return content; } - @Override + /** + * Get the controller of this wrapper + * + * @return The {@link MapController} + */ public MapController getController() { return controller; } diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/CreateInventoryMapUpdateEvent.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/CreateInventoryMapUpdateEvent.java similarity index 75% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/CreateInventoryMapUpdateEvent.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/CreateInventoryMapUpdateEvent.java index 8c9fe99..05c956a 100644 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/CreateInventoryMapUpdateEvent.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/CreateInventoryMapUpdateEvent.java @@ -23,29 +23,42 @@ package tech.sbdevelopment.mapreflectionapi.api.events; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; +/** + * This event gets fired when a map in the creative inventory gets updated + */ +@RequiredArgsConstructor +@Getter public class CreateInventoryMapUpdateEvent extends Event implements Cancellable { private static final HandlerList handlerList = new HandlerList(); + @Setter + private boolean cancelled; + private final Player player; private final int slot; private final ItemStack item; private MapWrapper mapWrapper; - private boolean cancelled; - - public CreateInventoryMapUpdateEvent(Player player, int slot, ItemStack item) { - this.player = player; - this.slot = slot; - this.item = item; - } + /** + * Construct a new {@link CreateInventoryMapUpdateEvent} + * + * @param player The player whose inventory is updated + * @param slot The new slot + * @param item The item in the new slot + * @param isAsync Is this event called async? + */ public CreateInventoryMapUpdateEvent(Player player, int slot, ItemStack item, boolean isAsync) { super(isAsync); this.player = player; @@ -53,44 +66,24 @@ public class CreateInventoryMapUpdateEvent extends Event implements Cancellable this.item = item; } - public static HandlerList getHandlerList() { - return handlerList; - } - - public Player getPlayer() { - return player; - } - - public int getSlot() { - return slot; - } - - public ItemStack getItem() { - return item; - } - - public MapWrapper getMapWrapper() { - if (mapWrapper == null) { - if (item == null) return null; - if (item.getType() != Material.MAP) return null; - MapReflectionAPI.getMapManager().getWrapperForId(player, item.getDurability()); - } - - return mapWrapper; - } - @Override public HandlerList getHandlers() { return handlerList; } - @Override - public boolean isCancelled() { - return cancelled; - } + /** + * Get the {@link MapWrapper} of the map of this event + * + * @return The {@link MapWrapper} + */ + @Nullable + public MapWrapper getMapWrapper() { + if (mapWrapper == null) { + if (item == null) return null; + if (item.getType() != Material.MAP) return null; + mapWrapper = MapReflectionAPI.getMapManager().getWrapperForId(player, item.getDurability()); + } - @Override - public void setCancelled(boolean b) { - this.cancelled = b; + return mapWrapper; } } diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapCancelEvent.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapCancelEvent.java similarity index 79% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapCancelEvent.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapCancelEvent.java index 72d40d0..4ab8825 100644 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapCancelEvent.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapCancelEvent.java @@ -23,52 +23,42 @@ package tech.sbdevelopment.mapreflectionapi.api.events; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +/** + * This event gets fired when a map creation is cancelled + */ +@RequiredArgsConstructor +@Getter public class MapCancelEvent extends Event implements Cancellable { private static final HandlerList handlerList = new HandlerList(); - private final Player player; - private final int id; + @Setter private boolean cancelled; - public MapCancelEvent(Player player, int id) { - this.player = player; - this.id = id; - } + private final Player player; + private final int id; + /** + * Construct a new {@link MapCancelEvent} + * + * @param player The player who tried to create the map + * @param id The ID of the map + * @param isAsync Is this event called async? + */ public MapCancelEvent(Player player, int id, boolean isAsync) { super(isAsync); this.player = player; this.id = id; } - public static HandlerList getHandlerList() { - return handlerList; - } - - public Player getPlayer() { - return player; - } - - public int getId() { - return id; - } - @Override public HandlerList getHandlers() { return handlerList; } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean b) { - this.cancelled = b; - } } diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapInteractEvent.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapInteractEvent.java similarity index 76% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapInteractEvent.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapInteractEvent.java index 327c762..aad264b 100644 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapInteractEvent.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/events/MapInteractEvent.java @@ -23,17 +23,29 @@ package tech.sbdevelopment.mapreflectionapi.api.events; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; import org.bukkit.util.Vector; +import org.jetbrains.annotations.Nullable; import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; import tech.sbdevelopment.mapreflectionapi.api.MapWrapper; +/** + * This event gets fired when a player interact with a map + */ +@RequiredArgsConstructor +@Getter public class MapInteractEvent extends Event implements Cancellable { private static final HandlerList handlerList = new HandlerList(); + @Setter + private boolean cancelled; + private final Player player; private final int entityID; private final int action; @@ -41,16 +53,17 @@ public class MapInteractEvent extends Event implements Cancellable { private final int hand; private ItemFrame frame; private MapWrapper mapWrapper; - private boolean cancelled; - - public MapInteractEvent(Player player, int entityID, int action, Vector vector, int hand) { - this.player = player; - this.entityID = entityID; - this.action = action; - this.vector = vector; - this.hand = hand; - } + /** + * Construct a new {@link MapInteractEvent} + * + * @param player The player who interacted + * @param entityID The ID of the entity the map is in + * @param action The interact action + * @param vector The location of the entity + * @param hand The hand the player clicked with + * @param isAsync Is this event called async? + */ public MapInteractEvent(Player player, int entityID, int action, Vector vector, int hand, boolean isAsync) { super(isAsync); this.player = player; @@ -60,30 +73,17 @@ public class MapInteractEvent extends Event implements Cancellable { this.hand = hand; } - public static HandlerList getHandlerList() { + @Override + public HandlerList getHandlers() { return handlerList; } - public Player getPlayer() { - return player; - } - - public int getEntityID() { - return entityID; - } - - public int getAction() { - return action; - } - - public Vector getVector() { - return vector; - } - - public int getHand() { - return hand; - } - + /** + * Get the {@link ItemFrame} the map is in + * + * @return The frame the map is in, or null if it's not a map + */ + @Nullable public ItemFrame getFrame() { if (getMapWrapper() == null) return null; @@ -93,6 +93,12 @@ public class MapInteractEvent extends Event implements Cancellable { return frame; } + /** + * Get the {@link MapWrapper} of the map + * + * @return The wrapper + */ + @Nullable public MapWrapper getMapWrapper() { if (mapWrapper == null) { mapWrapper = MapReflectionAPI.getMapManager().getWrapperForId(player, entityID); @@ -100,19 +106,4 @@ public class MapInteractEvent extends Event implements Cancellable { return mapWrapper; } - - @Override - public boolean isCancelled() { - return cancelled; - } - - @Override - public void setCancelled(boolean b) { - this.cancelled = b; - } - - @Override - public HandlerList getHandlers() { - return handlerList; - } } diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/exceptions/MapLimitExceededException.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/exceptions/MapLimitExceededException.java similarity index 83% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/exceptions/MapLimitExceededException.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/api/exceptions/MapLimitExceededException.java index 8fd4caa..47e3510 100644 --- a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/exceptions/MapLimitExceededException.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/exceptions/MapLimitExceededException.java @@ -21,9 +21,17 @@ * SOFTWARE. */ -package tech.sbdevelopment.mapreflectionapi.exceptions; +package tech.sbdevelopment.mapreflectionapi.api.exceptions; +/** + * This exception gets thrown if no map IDs are available + */ public class MapLimitExceededException extends Exception { + /** + * Construct a new {@link MapLimitExceededException} + * + * @param message The message in this exception + */ public MapLimitExceededException(String message) { super(message); } diff --git a/API/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/MapListener.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/MapListener.java similarity index 100% rename from API/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/MapListener.java rename to src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/MapListener.java diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java new file mode 100644 index 0000000..38621f8 --- /dev/null +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/listeners/PacketListener.java @@ -0,0 +1,100 @@ +/* + * This file is part of MapReflectionAPI. + * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +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 org.bukkit.Bukkit; +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; + +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); + } + + @Override + public void onPacketSending(PacketEvent event) { + if (event.getPacketType() != PacketType.Play.Server.MAP) return; //Make sure it's the right packet! + + 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); + } + } + + @Override + public void onPacketReceiving(PacketEvent event) { + if (event.getPacketType() == PacketType.Play.Client.USE_ENTITY) { + 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); + } + } else if (event.getPacketType() == PacketType.Play.Client.SET_CREATIVE_SLOT) { + int slot = event.getPacket().getIntegers().read(0); + ItemStack item = event.getPacket().getItemModifier().read(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); + } + } + } +} diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtil.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtil.java new file mode 100644 index 0000000..ac91b23 --- /dev/null +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/utils/ReflectionUtil.java @@ -0,0 +1,486 @@ +/* + * This file is part of MapReflectionAPI. + * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package tech.sbdevelopment.mapreflectionapi.utils; + +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +/** + * ReflectionUtil - Reflection handler for NMS and CraftBukkit.
+ * Caches the packet related methods and is asynchronous. + *

+ * This class does not handle null checks as most of the requests are from the + * other utility classes that already handle null checks. + *

+ * Clientbound Packets are considered fake + * updates to the client without changing the actual data. Since all the data is handled + * by the server. + * + * @author Crypto Morin, Stijn Bannink + * @version 2.1 + */ +public class ReflectionUtil { + /** + * We use reflection mainly to avoid writing a new class for version barrier. + * The version barrier is for NMS that uses the Minecraft version as the main package name. + *

+ * E.g. EntityPlayer in 1.15 is in the class {@code net.minecraft.server.v1_15_R1} + * but in 1.14 it's in {@code net.minecraft.server.v1_14_R1} + * In order to maintain cross-version compatibility we cannot import these classes. + *

+ * Performance is not a concern for these specific statically initialized values. + */ + public static final String VERSION; + + static { // This needs to be right below VERSION because of initialization order. + // This package loop is used to avoid implementation-dependant strings like Bukkit.getVersion() or Bukkit.getBukkitVersion() + // which allows easier testing as well. + String found = null; + for (Package pack : Package.getPackages()) { + String name = pack.getName(); + + // .v because there are other packages. + if (name.startsWith("org.bukkit.craftbukkit.v")) { + found = pack.getName().split("\\.")[3]; + + // Just a final guard to make sure it finds this important class. + // As a protection for forge+bukkit implementation that tend to mix versions. + // The real CraftPlayer should exist in the package. + // Note: Doesn't seem to function properly. Will need to separate the version + // handler for NMS and CraftBukkit for softwares like catmc. + try { + Class.forName("org.bukkit.craftbukkit." + found + ".entity.CraftPlayer"); + break; + } catch (ClassNotFoundException e) { + found = null; + } + } + } + if (found == null) + throw new IllegalArgumentException("Failed to parse server version. Could not find any package starting with name: 'org.bukkit.craftbukkit.v'"); + VERSION = found; + } + + /** + * The raw minor version number. + * E.g. {@code v1_17_R1} to {@code 17} + * + * @since 4.0.0 + */ + public static final int VER = Integer.parseInt(VERSION.substring(1).split("_")[1]); + /** + * Mojang remapped their NMS in 1.17 https://www.spigotmc.org/threads/spigot-bungeecord-1-17.510208/#post-4184317 + */ + public static final String + CRAFTBUKKIT = "org.bukkit.craftbukkit." + VERSION + '.', + NMS = v(17, "net.minecraft.").orElse("net.minecraft.server." + VERSION + '.'); + /** + * A nullable public accessible field only available in {@code EntityPlayer}. + * This can be null if the player is offline. + */ + private static final MethodHandle PLAYER_CONNECTION; + /** + * Responsible for getting the NMS handler {@code EntityPlayer} object for the player. + * {@code CraftPlayer} is simply a wrapper for {@code EntityPlayer}. + * Used mainly for handling packet related operations. + *

+ * This is also where the famous player {@code ping} field comes from! + */ + private static final MethodHandle GET_HANDLE; + private static final MethodHandle GET_HANDLE_WORLD; + /** + * Sends a packet to the player's client through a {@code NetworkManager} which + * is where {@code ProtocolLib} controls packets by injecting channels! + */ + private static final MethodHandle SEND_PACKET; + + static { + Class entityPlayer = getNMSClass("server.level", "EntityPlayer"); + Class worldServer = getNMSClass("server.level", "WorldServer"); + Class craftPlayer = getCraftClass("entity.CraftPlayer"); + Class craftWorld = getCraftClass("CraftWorld"); + Class playerConnection = getNMSClass("server.network", "PlayerConnection"); + + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodHandle sendPacket = null, getHandle = null, getHandleWorld = null, connection = null; + + try { + connection = lookup.findGetter(entityPlayer, + v(17, "b").orElse("playerConnection"), playerConnection); + getHandle = lookup.findVirtual(craftPlayer, "getHandle", MethodType.methodType(entityPlayer)); + getHandleWorld = lookup.findVirtual(craftWorld, "getHandle", MethodType.methodType(worldServer)); + sendPacket = lookup.findVirtual(playerConnection, + v(18, "a").orElse("sendPacket"), + MethodType.methodType(void.class, getNMSClass("network.protocol", "Packet"))); + } catch (NoSuchMethodException | NoSuchFieldException | IllegalAccessException ex) { + ex.printStackTrace(); + } + + PLAYER_CONNECTION = connection; + SEND_PACKET = sendPacket; + GET_HANDLE = getHandle; + GET_HANDLE_WORLD = getHandleWorld; + } + + private ReflectionUtil() { + } + + /** + * This method is purely for readability. + * No performance is gained. + * + * @since 5.0.0 + */ + public static VersionHandler v(int version, T handle) { + return new VersionHandler<>(version, handle); + } + + /** + * Checks whether the server version is equal or greater than the given version. + * + * @param version the version to compare the server version with. + * @return true if the version is equal or newer, otherwise false. + * @since 4.0.0 + */ + public static boolean supports(int version) { + return VER >= version; + } + + private static Class wrapperToPrimitive(Class clazz) { + if (clazz == Boolean.class) return boolean.class; + if (clazz == Integer.class) return int.class; + if (clazz == Double.class) return double.class; + if (clazz == Float.class) return float.class; + if (clazz == Long.class) return long.class; + if (clazz == Short.class) return short.class; + if (clazz == Byte.class) return byte.class; + if (clazz == Void.class) return void.class; + if (clazz == Character.class) return char.class; + if (clazz == ArrayList.class) return Collection.class; + return clazz; + } + + private static Class[] toParamTypes(Object... params) { + return Arrays.stream(params) + .map(obj -> obj != null ? wrapperToPrimitive(obj.getClass()) : null) + .toArray(Class[]::new); + } + + @Nullable + public static Class getClass(@NotNull String name) { + try { + return Class.forName(name); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object callConstructorNull(Class clazz, Class paramClass) { + try { + Constructor con = clazz.getConstructor(paramClass); + con.setAccessible(true); + return con.newInstance(clazz.cast(null)); + } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | + InvocationTargetException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object callFirstConstructor(Class clazz, Object... params) { + try { + Constructor con = clazz.getConstructors()[0]; + con.setAccessible(true); + return con.newInstance(params); + } catch (IllegalAccessException | InstantiationException | + InvocationTargetException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object callConstructor(Class clazz, Object... params) { + try { + Constructor con = clazz.getConstructor(toParamTypes(params)); + con.setAccessible(true); + return con.newInstance(params); + } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | + InvocationTargetException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object callDeclaredConstructor(Class clazz, Object... params) { + try { + Constructor con = clazz.getDeclaredConstructor(toParamTypes(params)); + con.setAccessible(true); + return con.newInstance(params); + } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | + InvocationTargetException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object callMethod(Class clazz, String method, Object... params) { + try { + Method m = clazz.getMethod(method, toParamTypes(params)); + m.setAccessible(true); + return m.invoke(null, params); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object callMethod(Object obj, String method, Object... params) { + try { + Method m = obj.getClass().getMethod(method, toParamTypes(params)); + m.setAccessible(true); + return m.invoke(obj, params); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object callDeclaredMethod(Object obj, String method, Object... params) { + try { + Method m = obj.getClass().getDeclaredMethod(method, toParamTypes(params)); + m.setAccessible(true); + return m.invoke(obj, params); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object getField(Object object, String field) { + try { + Field f = object.getClass().getField(field); + f.setAccessible(true); + return f.get(object); + } catch (NoSuchFieldException | IllegalAccessException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object getDeclaredField(Class clazz, String field) { + try { + Field f = clazz.getDeclaredField(field); + f.setAccessible(true); + return f.get(null); + } catch (NoSuchFieldException | IllegalAccessException ex) { + ex.printStackTrace(); + return null; + } + } + + @Nullable + public static Object getDeclaredField(Object object, String field) { + try { + Field f = object.getClass().getDeclaredField(field); + f.setAccessible(true); + return f.get(object); + } catch (NoSuchFieldException | IllegalAccessException ex) { + ex.printStackTrace(); + return null; + } + } + + public static void setDeclaredField(Object object, String field, Object value) { + try { + Field f = object.getClass().getDeclaredField(field); + f.setAccessible(true); + f.set(object, value); + } catch (NoSuchFieldException | IllegalAccessException ex) { + ex.printStackTrace(); + } + } + + /** + * Get a NMS (net.minecraft.server) class which accepts a package for 1.17 compatibility. + * + * @param newPackage the 1.17 package name. + * @param name the name of the class. + * @return the NMS class or null if not found. + * @since 4.0.0 + */ + @javax.annotation.Nullable + public static Class getNMSClass(@Nonnull String newPackage, @Nonnull String name) { + if (supports(17)) name = newPackage + '.' + name; + return getNMSClass(name); + } + + /** + * Get a NMS (net.minecraft.server) class. + * + * @param name the name of the class. + * @return the NMS class or null if not found. + * @since 1.0.0 + */ + @javax.annotation.Nullable + public static Class getNMSClass(@Nonnull String name) { + try { + return Class.forName(NMS + name); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + return null; + } + } + + /** + * Sends a packet to the player asynchronously if they're online. + * Packets are thread-safe. + * + * @param player the player to send the packet to. + * @param packets the packets to send. + * @return the async thread handling the packet. + * @see #sendPacketSync(Player, Object...) + * @since 1.0.0 + */ + @Nonnull + public static CompletableFuture sendPacket(@Nonnull Player player, @Nonnull Object... packets) { + return CompletableFuture.runAsync(() -> sendPacketSync(player, packets)) + .exceptionally(ex -> { + ex.printStackTrace(); + return null; + }); + } + + /** + * Sends a packet to the player synchronously if they're online. + * + * @param player the player to send the packet to. + * @param packets the packets to send. + * @see #sendPacket(Player, Object...) + * @since 2.0.0 + */ + public static void sendPacketSync(@Nonnull Player player, @Nonnull Object... packets) { + try { + Object handle = GET_HANDLE.invoke(player); + Object connection = PLAYER_CONNECTION.invoke(handle); + + // Checking if the connection is not null is enough. There is no need to check if the player is online. + if (connection != null) { + for (Object packet : packets) SEND_PACKET.invoke(connection, packet); + } + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + } + + @javax.annotation.Nullable + public static Object getHandle(@Nonnull Player player) { + Objects.requireNonNull(player, "Cannot get handle of null player"); + try { + return GET_HANDLE.invoke(player); + } catch (Throwable throwable) { + throwable.printStackTrace(); + return null; + } + } + + @javax.annotation.Nullable + public static Object getHandle(@Nonnull World world) { + Objects.requireNonNull(world, "Cannot get handle of null world"); + try { + return GET_HANDLE_WORLD.invoke(world); + } catch (Throwable throwable) { + throwable.printStackTrace(); + return null; + } + } + + /** + * Get a CraftBukkit (org.bukkit.craftbukkit) class. + * + * @param name the name of the class to load. + * @return the CraftBukkit class or null if not found. + * @since 1.0.0 + */ + @javax.annotation.Nullable + public static Class getCraftClass(@Nonnull String name) { + try { + return Class.forName(CRAFTBUKKIT + name); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + return null; + } + } + + public static final class VersionHandler { + private int version; + private T handle; + + private VersionHandler(int version, T handle) { + if (supports(version)) { + this.version = version; + this.handle = handle; + } + } + + public VersionHandler v(int version, T handle) { + if (version == this.version) + throw new IllegalArgumentException("Cannot have duplicate version handles for version: " + version); + if (version > this.version && supports(version)) { + this.version = version; + this.handle = handle; + } + return this; + } + + public T orElse(T handle) { + return this.version == 0 ? handle : this.handle; + } + } +} \ No newline at end of file diff --git a/API/src/main/resources/plugin.yml b/src/main/resources/plugin.yml similarity index 87% rename from API/src/main/resources/plugin.yml rename to src/main/resources/plugin.yml index 030ee7f..025688e 100644 --- a/API/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,4 +5,4 @@ api-version: 1.13 authors: [ inventivetalent, SBDeveloper ] description: This API helps developer with viewing images on maps. website: https://sbdevelopment.tech -softdepend: [ BKCommonLib ] \ No newline at end of file +softdepend: [ BKCommonLib, ProtocolLib ] \ No newline at end of file