From 7988df426d335f23ae6c549a9056b2d6336b50dc Mon Sep 17 00:00:00 2001 From: SkytAsul Date: Sat, 4 Nov 2023 17:59:12 +0100 Subject: [PATCH] :arrow_up: Added support for 1.20.2 --- pom.xml | 2 +- .../java/fr/skytasul/guardianbeam/Laser.java | 292 +++++++++--------- 2 files changed, 148 insertions(+), 146 deletions(-) diff --git a/pom.xml b/pom.xml index 8ba4143..2a270d1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.github.skytasul guardianbeam - 2.3.3 + 2.3.4 jar GuardianBeam diff --git a/src/main/java/fr/skytasul/guardianbeam/Laser.java b/src/main/java/fr/skytasul/guardianbeam/Laser.java index b4767cb..fa144e1 100644 --- a/src/main/java/fr/skytasul/guardianbeam/Laser.java +++ b/src/main/java/fr/skytasul/guardianbeam/Laser.java @@ -4,13 +4,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; @@ -32,14 +26,14 @@ * A whole class to create Guardian Lasers and Ender Crystal Beams using packets and reflection.
* Inspired by the API * GuardianBeamAPI
- * 1.9 -> 1.20 + * 1.9 -> 1.20.2 * * @see GitHub repository - * @version 2.3.3 + * @version 2.3.4 * @author SkytAsul */ public abstract class Laser { - + protected final int distanceSquared; protected final int duration; protected boolean durationInTicks = false; @@ -48,13 +42,13 @@ public abstract class Laser { protected Plugin plugin; protected BukkitRunnable main; - + protected BukkitTask startMove; protected BukkitTask endMove; - + protected Set show = ConcurrentHashMap.newKeySet(); private Set seen = new HashSet<>(); - + private List executeEnd = new ArrayList<>(1); protected Laser(Location start, Location end, int duration, int distance) { @@ -65,7 +59,7 @@ protected Laser(Location start, Location end, int duration, int distance) { this.duration = duration; distanceSquared = distance < 0 ? -1 : distance * distance; } - + /** * Adds a runnable to execute when the laser reaches its final duration * @param runnable action to execute @@ -84,7 +78,7 @@ public Laser durationInTicks() { durationInTicks = true; return this; } - + /** * Starts this laser. *

@@ -150,7 +144,7 @@ public void stop() { if (main == null) throw new IllegalStateException("Task not started"); main.cancel(); } - + /** * Gets laser status. * @return true if the laser is currently running @@ -159,7 +153,7 @@ public void stop() { public boolean isStarted() { return main != null; } - + /** * Gets laser type. * @return LaserType enum constant of this laser @@ -172,14 +166,14 @@ public boolean isStarted() { * @throws ReflectiveOperationException if a reflection exception occurred during laser moving */ public abstract void moveStart(Location location) throws ReflectiveOperationException; - + /** * Instantly moves the end of the laser to the location provided. * @param location New end location * @throws ReflectiveOperationException if a reflection exception occurred during laser moving */ public abstract void moveEnd(Location location) throws ReflectiveOperationException; - + /** * Gets the start location of the laser. * @return where exactly is the start position of the laser located @@ -187,7 +181,7 @@ public boolean isStarted() { public Location getStart() { return start; } - + /** * Gets the end location of the laser. * @return where exactly is the end position of the laser located @@ -195,7 +189,7 @@ public Location getStart() { public Location getEnd() { return end; } - + /** * Moves the start of the laser smoothly to the new location, within a given time. * @param location New start location to go to @@ -205,7 +199,7 @@ public Location getEnd() { public void moveStart(Location location, int ticks, Runnable callback) { startMove = moveInternal(location, ticks, startMove, this::getStart, this::moveStart, callback); } - + /** * Moves the end of the laser smoothly to the new location, within a given time. * @param location New end location to go to @@ -215,7 +209,7 @@ public void moveStart(Location location, int ticks, Runnable callback) { public void moveEnd(Location location, int ticks, Runnable callback) { endMove = moveInternal(location, ticks, endMove, this::getEnd, this::moveEnd, callback); } - + private BukkitTask moveInternal(Location location, int ticks, BukkitTask oldTask, Supplier locationSupplier, ReflectiveConsumer moveConsumer, Runnable callback) { if (ticks <= 0) throw new IllegalArgumentException("Ticks must be a positive value"); if (plugin == null) throw new IllegalStateException("The laser must have been started a least once"); @@ -225,7 +219,7 @@ private BukkitTask moveInternal(Location location, int ticks, BukkitTask oldTask double yPerTick = (location.getY() - locationSupplier.get().getY()) / ticks; double zPerTick = (location.getZ() - locationSupplier.get().getZ()) / ticks; int elapsed = 0; - + @Override public void run() { try { @@ -235,7 +229,7 @@ public void run() { cancel(); return; } - + if (++elapsed == ticks) { cancel(); if (callback != null) callback.run(); @@ -243,11 +237,11 @@ public void run() { } }.runTaskTimer(plugin, 0L, 1L); } - + protected void moveFakeEntity(Location location, int entityId, Object fakeEntity) throws ReflectiveOperationException { if (fakeEntity != null) Packets.moveFakeEntity(fakeEntity, location); if (main == null) return; - + Object packet; if (fakeEntity == null) { packet = Packets.createPacketMoveEntity(location, entityId); @@ -260,7 +254,7 @@ protected void moveFakeEntity(Location location, int entityId, Object fakeEntity } protected abstract void sendStartPackets(Player p, boolean hasSeen) throws ReflectiveOperationException; - + protected abstract void sendDestroyPackets(Player p) throws ReflectiveOperationException; protected boolean isCloseEnough(Player player) { @@ -269,10 +263,10 @@ protected boolean isCloseEnough(Player player) { return getStart().distanceSquared(location) <= distanceSquared || getEnd().distanceSquared(location) <= distanceSquared; } - + public static class GuardianLaser extends Laser { private static AtomicInteger teamID = new AtomicInteger(ThreadLocalRandom.current().nextInt(0, Integer.MAX_VALUE)); - + private Object createGuardianPacket; private Object createSquidPacket; private Object teamCreatePacket; @@ -280,22 +274,22 @@ public static class GuardianLaser extends Laser { private Object metadataPacketGuardian; private Object metadataPacketSquid; private Object fakeGuardianDataWatcher; - + private final UUID squidUUID = UUID.randomUUID(); private final UUID guardianUUID = UUID.randomUUID(); private final int squidID = Packets.generateEID(); private final int guardianID = Packets.generateEID(); private Object squid; private Object guardian; - + private int targetID; private UUID targetUUID; - + protected LivingEntity endEntity; - + private Location correctStart; private Location correctEnd; - + /** * Creates a new Guardian Laser instance * @param start Location where laser will starts @@ -310,15 +304,15 @@ public static class GuardianLaser extends Laser { */ public GuardianLaser(Location start, Location end, int duration, int distance) throws ReflectiveOperationException { super(start, end, duration, distance); - + initSquid(); - + targetID = squidID; targetUUID = squidUUID; - + initLaser(); } - + /** * Creates a new Guardian Laser instance * @param start Location where laser will starts @@ -333,13 +327,13 @@ public GuardianLaser(Location start, Location end, int duration, int distance) t */ public GuardianLaser(Location start, LivingEntity endEntity, int duration, int distance) throws ReflectiveOperationException { super(start, endEntity.getLocation(), duration, distance); - + targetID = endEntity.getEntityId(); targetUUID = endEntity.getUniqueId(); - + initLaser(); } - + private void initLaser() throws ReflectiveOperationException { fakeGuardianDataWatcher = Packets.createFakeDataWatcher(); Packets.initGuardianWatcher(fakeGuardianDataWatcher, targetID); @@ -347,11 +341,11 @@ private void initLaser() throws ReflectiveOperationException { guardian = Packets.createGuardian(getCorrectStart(), guardianUUID, guardianID); } metadataPacketGuardian = Packets.createPacketMetadata(guardianID, fakeGuardianDataWatcher); - + teamCreatePacket = Packets.createPacketTeamCreate("noclip" + teamID.getAndIncrement(), squidUUID, guardianUUID); destroyPackets = Packets.createPacketsRemoveEntities(squidID, guardianID); } - + private void initSquid() throws ReflectiveOperationException { if (Packets.version >= 17) { squid = Packets.createSquid(getCorrectEnd(), squidUUID, squidID); @@ -359,7 +353,7 @@ private void initSquid() throws ReflectiveOperationException { metadataPacketSquid = Packets.createPacketMetadata(squidID, Packets.fakeSquidWatcher); Packets.setDirtyWatcher(Packets.fakeSquidWatcher); } - + private Object getGuardianSpawnPacket() throws ReflectiveOperationException { if (createGuardianPacket == null) { if (Packets.version < 17) { @@ -370,7 +364,7 @@ private Object getGuardianSpawnPacket() throws ReflectiveOperationException { } return createGuardianPacket; } - + private Object getSquidSpawnPacket() throws ReflectiveOperationException { if (createSquidPacket == null) { if (Packets.version < 17) { @@ -381,18 +375,18 @@ private Object getSquidSpawnPacket() throws ReflectiveOperationException { } return createSquidPacket; } - + @Override public LaserType getLaserType() { return LaserType.GUARDIAN; } - + /** * Makes the laser follow an entity (moving end location). - * + * * This is done client-side by making the fake guardian follow the existing entity. * Hence, there is no consuming of server resources. - * + * * @param entity living entity the laser will follow * @throws ReflectiveOperationException if a reflection operation fails */ @@ -401,28 +395,28 @@ public void attachEndEntity(LivingEntity entity) throws ReflectiveOperationExcep this.endEntity = entity; setTargetEntity(entity.getUniqueId(), entity.getEntityId()); } - + public Entity getEndEntity() { return endEntity; } - + private void setTargetEntity(UUID uuid, int id) throws ReflectiveOperationException { targetUUID = uuid; targetID = id; fakeGuardianDataWatcher = Packets.createFakeDataWatcher(); Packets.initGuardianWatcher(fakeGuardianDataWatcher, targetID); metadataPacketGuardian = Packets.createPacketMetadata(guardianID, fakeGuardianDataWatcher); - + for (Player p : show) { Packets.sendPackets(p, metadataPacketGuardian); } } - + @Override public Location getEnd() { return endEntity == null ? end : endEntity.getLocation(); } - + protected Location getCorrectStart() { if (correctStart == null) { correctStart = start.clone(); @@ -430,28 +424,28 @@ protected Location getCorrectStart() { } return correctStart; } - + protected Location getCorrectEnd() { if (correctEnd == null) { correctEnd = end.clone(); correctEnd.subtract(0, 0.5, 0); - + Vector corrective = correctEnd.toVector().subtract(getCorrectStart().toVector()).normalize(); if (Double.isNaN(corrective.getX())) corrective.setX(0); if (Double.isNaN(corrective.getY())) corrective.setY(0); if (Double.isNaN(corrective.getZ())) corrective.setZ(0); // coordinates can be NaN when start and end are stricly equals correctEnd.subtract(corrective); - + } return correctEnd; } - + @Override protected boolean isCloseEnough(Player player) { return player == endEntity || super.isCloseEnough(player); } - + @Override protected void sendStartPackets(Player p, boolean hasSeen) throws ReflectiveOperationException { if (squid == null) { @@ -465,36 +459,36 @@ protected void sendStartPackets(Player p, boolean hasSeen) throws ReflectiveOper metadataPacketGuardian, metadataPacketSquid); } - + if (!hasSeen) Packets.sendPackets(p, teamCreatePacket); } - + @Override protected void sendDestroyPackets(Player p) throws ReflectiveOperationException { Packets.sendPackets(p, destroyPackets); } - + @Override public void moveStart(Location location) throws ReflectiveOperationException { this.start = location; correctStart = null; - + createGuardianPacket = null; // will force re-generation of spawn packet moveFakeEntity(getCorrectStart(), guardianID, guardian); - + if (squid != null) { correctEnd = null; createSquidPacket = null; moveFakeEntity(getCorrectEnd(), squidID, squid); } } - + @Override public void moveEnd(Location location) throws ReflectiveOperationException { this.end = location; createSquidPacket = null; // will force re-generation of spawn packet correctEnd = null; - + if (squid == null) { initSquid(); for (Player p : show) { @@ -508,7 +502,7 @@ public void moveEnd(Location location) throws ReflectiveOperationException { setTargetEntity(squidUUID, squidID); } } - + /** * Asks viewers' clients to change the color of this laser * @throws ReflectiveOperationException @@ -518,19 +512,19 @@ public void callColorChange() throws ReflectiveOperationException { Packets.sendPackets(p, metadataPacketGuardian); } } - + } public static class CrystalLaser extends Laser { - + private Object createCrystalPacket; private Object metadataPacketCrystal; private Object[] destroyPackets; private Object fakeCrystalDataWatcher; - + private final Object crystal; private final int crystalID = Packets.generateEID(); - + /** * Creates a new Ender Crystal Laser instance * @param start Location where laser will starts. The Crystal laser do not handle decimal number, it will be rounded to blocks. @@ -544,7 +538,7 @@ public static class CrystalLaser extends Laser { */ public CrystalLaser(Location start, Location end, int duration, int distance) throws ReflectiveOperationException { super(start, end, duration, distance); - + fakeCrystalDataWatcher = Packets.createFakeDataWatcher(); Packets.setCrystalWatcher(fakeCrystalDataWatcher, end); if (Packets.version < 17) { @@ -553,10 +547,10 @@ public CrystalLaser(Location start, Location end, int duration, int distance) th crystal = Packets.createCrystal(start, UUID.randomUUID(), crystalID); } metadataPacketCrystal = Packets.createPacketMetadata(crystalID, fakeCrystalDataWatcher); - + destroyPackets = Packets.createPacketsRemoveEntities(crystalID); } - + private Object getCrystalSpawnPacket() throws ReflectiveOperationException { if (createCrystalPacket == null) { if (Packets.version < 17) { @@ -567,30 +561,30 @@ private Object getCrystalSpawnPacket() throws ReflectiveOperationException { } return createCrystalPacket; } - + @Override public LaserType getLaserType() { return LaserType.ENDER_CRYSTAL; } - + @Override protected void sendStartPackets(Player p, boolean hasSeen) throws ReflectiveOperationException { Packets.sendPackets(p, getCrystalSpawnPacket()); Packets.sendPackets(p, metadataPacketCrystal); } - + @Override protected void sendDestroyPackets(Player p) throws ReflectiveOperationException { Packets.sendPackets(p, destroyPackets); } - + @Override public void moveStart(Location location) throws ReflectiveOperationException { this.start = location; createCrystalPacket = null; // will force re-generation of spawn packet moveFakeEntity(start, crystalID, crystal); } - + @Override public void moveEnd(Location location) throws ReflectiveOperationException { this.end = location; @@ -602,9 +596,9 @@ public void moveEnd(Location location) throws ReflectiveOperationException { } } } - + } - + public enum LaserType { /** * Represents a laser from a Guardian entity. @@ -613,14 +607,14 @@ public enum LaserType { * can track entities smoothly using {@link GuardianLaser#attachEndEntity(LivingEntity)} */ GUARDIAN, - + /** * Represents a laser from an Ender Crystal entity. *

* Start and end locations are automatically rounded to integers (block locations). */ ENDER_CRYSTAL; - + /** * Creates a new Laser instance, {@link GuardianLaser} or {@link CrystalLaser} depending on this enum value. * @param start Location where laser will starts @@ -656,45 +650,45 @@ static int generateEID() { private static String npack = "net.minecraft.server." + Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; private static String cpack = Bukkit.getServer().getClass().getPackage().getName() + "."; private static ProtocolMappings mappings; - + private static int crystalID = 51; // pre-1.13 - + private static Object crystalType; private static Object squidType; private static Object guardianType; - + private static Constructor crystalConstructor; private static Constructor squidConstructor; private static Constructor guardianConstructor; - + private static Object watcherObject1; // invisilibity private static Object watcherObject2; // spikes private static Object watcherObject3; // attack id private static Object watcherObject4; // crystal target private static Object watcherObject5; // crystal base plate - + private static Constructor watcherConstructor; private static Method watcherSet; private static Method watcherRegister; private static Method watcherDirty; private static Method watcherPack; - + private static Constructor blockPositionConstructor; - + private static Constructor packetSpawnLiving; private static Constructor packetSpawnNormal; private static Constructor packetRemove; private static Constructor packetTeleport; private static Constructor packetMetadata; private static Class packetTeam; - + private static Method createTeamPacket; private static Constructor createTeam; private static Constructor createScoreboard; private static Method setTeamPush; private static Object pushNever; private static Method getTeamPlayers; - + private static Method getHandle; private static Field playerConnection; private static Method sendPacket; @@ -704,9 +698,9 @@ static int generateEID() { private static Object fakeSquid; private static Object fakeSquidWatcher; - + private static Object nmsWorld; - + public static boolean enabled = false; static { @@ -720,7 +714,7 @@ public void log(LogRecord logRecord) { }; logger.setParent(Bukkit.getServer().getLogger()); logger.setLevel(Level.ALL); - + // e.g. Bukkit.getServer().getClass().getPackage().getName() -> org.bukkit.craftbukkit.v1_17_R1 String[] versions = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3].substring(1).split("_"); version = Integer.parseInt(versions[1]); // 1.X @@ -730,14 +724,14 @@ public void log(LogRecord logRecord) { versionMinor = versions.length <= 2 ? 0 : Integer.parseInt(versions[2]); }else versionMinor = Integer.parseInt(versions[2].substring(1)); // 1.X.Y logger.info("Found server version 1." + version + "." + versionMinor); - + mappings = ProtocolMappings.getMappings(version); if (mappings == null) { mappings = ProtocolMappings.values()[ProtocolMappings.values().length - 1]; logger.warning("Loaded not matching version of the mappings for your server version (1." + version + "." + versionMinor + ")"); } logger.info("Loaded mappings " + mappings.name()); - + Class entityTypesClass = getNMSClass("world.entity", "EntityTypes"); Class entityClass = getNMSClass("world.entity", "Entity"); Class crystalClass = getNMSClass("world.entity.boss.enderdragon", "EntityEnderCrystal"); @@ -748,7 +742,7 @@ public void log(LogRecord logRecord) { watcherObject3 = getField(guardianClass, mappings.getWatcherTargetEntity(), null); watcherObject4 = getField(crystalClass, mappings.getWatcherTargetLocation(), null); watcherObject5 = getField(crystalClass, mappings.getWatcherBasePlate(), null); - + if (version >= 13) { crystalType = entityTypesClass.getDeclaredField(mappings.getCrystalTypeName()).get(null); if (version >= 17) { @@ -756,7 +750,7 @@ public void log(LogRecord logRecord) { guardianType = entityTypesClass.getDeclaredField(mappings.getGuardianTypeName()).get(null); } } - + Class dataWatcherClass = getNMSClass("network.syncher", "DataWatcher"); watcherConstructor = dataWatcherClass.getDeclaredConstructor(entityClass); if (version >= 18) { @@ -781,32 +775,35 @@ public void log(LogRecord logRecord) { blockPositionConstructor = getNMSClass("core", "BlockPosition").getConstructor(int.class, int.class, int.class); - + nmsWorld = Class.forName(cpack + "CraftWorld").getDeclaredMethod("getHandle").invoke(Bukkit.getWorlds().get(0)); - + squidConstructor = squidClass.getDeclaredConstructors()[0]; if (version >= 17) { guardianConstructor = guardianClass.getDeclaredConstructors()[0]; crystalConstructor = crystalClass.getDeclaredConstructor(nmsWorld.getClass().getSuperclass(), double.class, double.class, double.class); } - + Object[] entityConstructorParams = version < 14 ? new Object[] { nmsWorld } : new Object[] { entityTypesClass.getDeclaredField(mappings.getSquidTypeName()).get(null), nmsWorld }; fakeSquid = squidConstructor.newInstance(entityConstructorParams); fakeSquidWatcher = createFakeDataWatcher(); tryWatcherSet(fakeSquidWatcher, watcherObject1, (byte) 32); - + getHandle = Class.forName(cpack + "entity.CraftPlayer").getDeclaredMethod("getHandle"); playerConnection = getNMSClass("server.level", "EntityPlayer") .getDeclaredField(version < 17 ? "playerConnection" : (version < 20 ? "b" : "c")); - sendPacket = getNMSClass("server.network", "PlayerConnection").getMethod(version < 18 ? "sendPacket" : "a", getNMSClass("network.protocol", "Packet")); - + playerConnection.setAccessible(true); + sendPacket = getNMSClass("server.network", "PlayerConnection").getMethod( + version < 18 ? "sendPacket" : (version >= 20 && versionMinor >= 2 ? "b" : "a"), + getNMSClass("network.protocol", "Packet")); + if (version >= 17) { setLocation = entityClass.getDeclaredMethod(version < 18 ? "setLocation" : "a", double.class, double.class, double.class, float.class, float.class); setUUID = entityClass.getDeclaredMethod("a_", UUID.class); setID = entityClass.getDeclaredMethod("e", int.class); - + createTeamPacket = packetTeam.getMethod("a", getNMSClass("world.scores", "ScoreboardTeam"), boolean.class); - + Class scoreboardClass = getNMSClass("world.scores", "Scoreboard"); Class teamClass = getNMSClass("world.scores", "ScoreboardTeam"); Class pushClass = getNMSClass("world.scores", "ScoreboardTeamBase$EnumTeamPush"); @@ -816,7 +813,7 @@ public void log(LogRecord logRecord) { pushNever = pushClass.getDeclaredField("b").get(null); getTeamPlayers = teamClass.getDeclaredMethod(mappings.getTeamGetPlayers()); } - + enabled = true; }catch (Exception e) { e.printStackTrace(); @@ -845,21 +842,21 @@ public static Object createFakeDataWatcher() throws ReflectiveOperationException public static void setDirtyWatcher(Object watcher) throws ReflectiveOperationException { if (version >= 15) watcherDirty.invoke(watcher, watcherObject1); } - + public static Object createSquid(Location location, UUID uuid, int id) throws ReflectiveOperationException { Object entity = squidConstructor.newInstance(squidType, nmsWorld); setEntityIDs(entity, uuid, id); moveFakeEntity(entity, location); return entity; } - + public static Object createGuardian(Location location, UUID uuid, int id) throws ReflectiveOperationException { Object entity = guardianConstructor.newInstance(guardianType, nmsWorld); setEntityIDs(entity, uuid, id); moveFakeEntity(entity, location); return entity; } - + public static Object createCrystal(Location location, UUID uuid, int id) throws ReflectiveOperationException { Object entity = crystalConstructor.newInstance(nmsWorld, location.getX(), location.getY(), location.getZ()); setEntityIDs(entity, uuid, id); @@ -879,7 +876,7 @@ public static Object createPacketEntitySpawnLiving(Location location, int typeID if (version <= 14) setField(packet, "m", fakeSquidWatcher); return packet; } - + public static Object createPacketEntitySpawnNormal(Location location, int typeID, Object type, int id) throws ReflectiveOperationException { Object packet = packetSpawnNormal.newInstance(); setField(packet, "a", id); @@ -892,21 +889,21 @@ public static Object createPacketEntitySpawnNormal(Location location, int typeID setField(packet, "k", version < 13 ? typeID : type); return packet; } - + public static Object createPacketEntitySpawnLiving(Object entity) throws ReflectiveOperationException { return packetSpawnLiving.newInstance(entity); } - + public static Object createPacketEntitySpawnNormal(Object entity) throws ReflectiveOperationException { return packetSpawnNormal.newInstance(entity); } - + public static void initGuardianWatcher(Object watcher, int targetId) throws ReflectiveOperationException { tryWatcherSet(watcher, watcherObject1, (byte) 32); tryWatcherSet(watcher, watcherObject2, Boolean.FALSE); tryWatcherSet(watcher, watcherObject3, targetId); } - + public static void setCrystalWatcher(Object watcher, Location target) throws ReflectiveOperationException { Object blockPosition = blockPositionConstructor.newInstance(target.getBlockX(), target.getBlockY(), target.getBlockZ()); @@ -938,20 +935,20 @@ public static Object createPacketMoveEntity(Location location, int entityId) thr setField(packet, "g", true); return packet; } - + public static void setEntityIDs(Object entity, UUID uuid, int id) throws ReflectiveOperationException { setUUID.invoke(entity, uuid); setID.invoke(entity, id); } - + public static void moveFakeEntity(Object entity, Location location) throws ReflectiveOperationException { setLocation.invoke(entity, location.getX(), location.getY(), location.getZ(), location.getPitch(), location.getYaw()); } - + public static Object createPacketMoveEntity(Object entity) throws ReflectiveOperationException { return packetTeleport.newInstance(entity); } - + public static Object createPacketTeamCreate(String teamName, UUID... entities) throws ReflectiveOperationException { Object packet; if (version < 17) { @@ -1007,11 +1004,11 @@ private static Object getField(Class clazz, String name, Object instance) thr field.setAccessible(true); return field.get(instance); } - + private static Class getNMSClass(String package17, String className) throws ClassNotFoundException { return Class.forName((version < 17 ? npack : "net.minecraft." + package17) + "." + className); } - + private enum ProtocolMappings { V1_9(9, "Z", "bA", "bB", "b", "c", 94, 68), V1_10(10, V1_9), @@ -1025,7 +1022,7 @@ private enum ProtocolMappings { public int getSquidID() { return Packets.versionMinor < 2 ? 74 : 81; } - + @Override public String getWatcherFlags() { return Packets.versionMinor < 2 ? "T" : "S"; @@ -1069,9 +1066,14 @@ else if (versionMinor == 3) return "V"; } }, - V1_20(20, "an", "b", "e", "c", "d", 89, 38, "V", "aT", "B", "a", "g"), + V1_20(20, null, "b", "e", "c", "d", 89, 38, "V", "aT", "B", "a", "g") { + @Override + public String getWatcherFlags() { + return versionMinor < 2 ? "an" : "ao"; + } + }, ; - + private final int major; private final String watcherFlags; private final String watcherSpikes; @@ -1085,17 +1087,17 @@ else if (versionMinor == 3) private final String crystalTypeName; private final String teamSetCollision; private final String teamGetPlayers; - + private ProtocolMappings(int major, ProtocolMappings parent) { this(major, parent.watcherFlags, parent.watcherSpikes, parent.watcherTargetEntity, parent.watcherTargetLocation, parent.watcherBasePlate, parent.squidID, parent.guardianID, parent.guardianTypeName, parent.squidTypeName, parent.crystalTypeName, parent.teamSetCollision, parent.teamGetPlayers); } - + private ProtocolMappings(int major, String watcherFlags, String watcherSpikes, String watcherTargetEntity, String watcherTargetLocation, String watcherBasePlate, int squidID, int guardianID) { this(major, watcherFlags, watcherSpikes, watcherTargetEntity, watcherTargetLocation, watcherBasePlate, squidID, guardianID, null, "SQUID", "END_CRYSTAL", null, null); } - + private ProtocolMappings(int major, String watcherFlags, String watcherSpikes, String watcherTargetEntity, String watcherTargetLocation, String watcherBasePlate, int squidID, int guardianID, @@ -1114,59 +1116,59 @@ private ProtocolMappings(int major, this.teamSetCollision = teamSetCollision; this.teamGetPlayers = teamGetPlayers; } - + public int getMajor() { return major; } - + public String getWatcherFlags() { return watcherFlags; } - + public String getWatcherSpikes() { return watcherSpikes; } - + public String getWatcherTargetEntity() { return watcherTargetEntity; } - + public String getWatcherTargetLocation() { return watcherTargetLocation; } - + public String getWatcherBasePlate() { return watcherBasePlate; } - + public int getSquidID() { return squidID; } - + public int getGuardianID() { return guardianID; } - + public String getGuardianTypeName() { return guardianTypeName; } - + public String getSquidTypeName() { return squidTypeName; } - + public String getCrystalTypeName() { return crystalTypeName; } - + public String getTeamSetCollision() { return teamSetCollision; } - + public String getTeamGetPlayers() { return teamGetPlayers; } - + public static ProtocolMappings getMappings(int major) { for (ProtocolMappings map : values()) { if (major == map.getMajor()) return map; @@ -1175,10 +1177,10 @@ public static ProtocolMappings getMappings(int major) { } } } - + @FunctionalInterface public static interface ReflectiveConsumer { abstract void accept(T t) throws ReflectiveOperationException; } - + }