From ee7bb548948e6dfac679c98b6d641e28464437dd Mon Sep 17 00:00:00 2001 From: Pierre Maurice Schwang Date: Wed, 21 Jul 2021 19:53:33 +0200 Subject: [PATCH] Fix / Compatibility for 1.17 + 1.17.1 (#29) --- pom.xml | 2 +- .../injector/BoundingBoxFixer.java | 11 +- .../legacysupport/injector/NMSReflection.java | 146 ++++++++++++++---- .../legacysupport/listener/SoundListener.java | 11 +- 4 files changed, 133 insertions(+), 37 deletions(-) diff --git a/pom.xml b/pom.xml index 67adcf6..8237cdf 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.gerrygames viarewind-legacy-support - 1.4.0 + 1.4.1 jar diff --git a/src/main/java/de/gerrygames/viarewind/legacysupport/injector/BoundingBoxFixer.java b/src/main/java/de/gerrygames/viarewind/legacysupport/injector/BoundingBoxFixer.java index 642b6f4..d67deb8 100644 --- a/src/main/java/de/gerrygames/viarewind/legacysupport/injector/BoundingBoxFixer.java +++ b/src/main/java/de/gerrygames/viarewind/legacysupport/injector/BoundingBoxFixer.java @@ -15,7 +15,7 @@ public class BoundingBoxFixer { public static void fixLilyPad() { try { - Class blockWaterLilyClass = NMSReflection.getNMSClass("BlockWaterLily"); + Class blockWaterLilyClass = NMSReflection.getNMSBlock("BlockWaterLily"); Field boundingBoxField = ReflectionAPI.getFieldAccessible(blockWaterLilyClass, "a"); Object boundingBox = boundingBoxField.get(null); @@ -27,7 +27,7 @@ public class BoundingBoxFixer { public static void fixLadder() { try { - Class blockLadderClass = NMSReflection.getNMSClass("BlockLadder"); + Class blockLadderClass = NMSReflection.getNMSBlock("BlockLadder"); Field boundingBoxNorthField, boundingBoxSouthField, boundingBoxWestField, boundingBoxEastField; @@ -42,11 +42,16 @@ public class BoundingBoxFixer { boundingBoxWestField = ReflectionAPI.getFieldAccessible(blockLadderClass, "o"); boundingBoxSouthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "p"); boundingBoxNorthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "q"); - } else { + } else if (serverProtocol <= 754) { boundingBoxEastField = ReflectionAPI.getFieldAccessible(blockLadderClass, "c"); boundingBoxWestField = ReflectionAPI.getFieldAccessible(blockLadderClass, "d"); boundingBoxSouthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "e"); boundingBoxNorthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "f"); + } else { + boundingBoxEastField = ReflectionAPI.getFieldAccessible(blockLadderClass, "d"); + boundingBoxWestField = ReflectionAPI.getFieldAccessible(blockLadderClass, "e"); + boundingBoxSouthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "f"); + boundingBoxNorthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "g"); } setBoundingBox(boundingBoxEastField.get(null), 0.0D, 0.0D, 0.0D, 0.125D, 1.0D, 1.0D); diff --git a/src/main/java/de/gerrygames/viarewind/legacysupport/injector/NMSReflection.java b/src/main/java/de/gerrygames/viarewind/legacysupport/injector/NMSReflection.java index b76bdf6..1fd204b 100644 --- a/src/main/java/de/gerrygames/viarewind/legacysupport/injector/NMSReflection.java +++ b/src/main/java/de/gerrygames/viarewind/legacysupport/injector/NMSReflection.java @@ -1,40 +1,128 @@ package de.gerrygames.viarewind.legacysupport.injector; +import com.viaversion.viaversion.api.Via; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import java.lang.reflect.Field; +import java.util.Arrays; + public class NMSReflection { - private static String version; - public static String getVersion() { - return version == null ? version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] : version; - } + private static int protocolVersion = -1; + private static final int PROTOCOL_1_17 = 755; - public static Class getNMSClass(String name) { - try { - return Class.forName("net.minecraft.server." + getVersion() + "." + name); - } catch (ClassNotFoundException ex) { - ex.printStackTrace(); - } - return null; - } + private static String version; + private static Field playerConnectionField; - public static Class getCraftBukkitClass(String name) { - try { - return Class.forName("org.bukkit.craftbukkit." + getVersion() + "." + name); - } catch (ClassNotFoundException ex) { - ex.printStackTrace(); - } - return null; - } + public static String getVersion() { + return version == null ? version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] : version; + } - public static void sendPacket(Player player, Object packet) { - try { - Object nmsPlayer = player.getClass().getMethod("getHandle").invoke(player); - Object playerConnection = nmsPlayer.getClass().getField("playerConnection").get(nmsPlayer); - playerConnection.getClass().getMethod("sendPacket", getNMSClass("Packet")).invoke(playerConnection, packet); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public static int getProtocolVersion() { + return protocolVersion == -1 ? + protocolVersion = Via.getAPI().getServerVersion().lowestSupportedVersion() : + protocolVersion; + } + + public static Class getBlockPositionClass() { + try { + if (getProtocolVersion() >= PROTOCOL_1_17) { + return Class.forName("net.minecraft.core.BlockPosition"); + } + return getLegacyNMSClass("BlockPosition"); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + } + return null; + } + + public static Class getNMSBlock(String name) { + try { + if (getProtocolVersion() >= PROTOCOL_1_17) { + return Class.forName("net.minecraft.world.level.block." + name); + } + return getLegacyNMSClass(name); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + } + return null; + } + + @SuppressWarnings("rawtypes") + public static Class getSoundCategoryClass() { + try { + if (getProtocolVersion() >= PROTOCOL_1_17) { + return Class.forName("net.minecraft.sounds.SoundCategory"); + } + return getLegacyNMSClass("SoundCategory"); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + } + return null; + } + + public static Class getPacketClass() { + try { + if (getProtocolVersion() >= PROTOCOL_1_17) { + return Class.forName("net.minecraft.network.protocol.Packet"); + } + return getLegacyNMSClass("Packet"); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + } + return null; + } + + public static Class getGamePacketClass(String packetType) { + try { + if (getProtocolVersion() >= PROTOCOL_1_17) { + return Class.forName("net.minecraft.network.protocol.game." + packetType); + } + return getLegacyNMSClass(packetType); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + } + return null; + } + + public static Class getPlayerConnectionClass() { + try { + if (getProtocolVersion() >= PROTOCOL_1_17) { + return Class.forName("net.minecraft.server.network.PlayerConnection"); + } + return getLegacyNMSClass("PlayerConnection"); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + } + return null; + } + + public static Class getLegacyNMSClass(String name) throws ClassNotFoundException { + return Class.forName("net.minecraft.server." + getVersion() + "." + name); + } + + public static Class getCraftBukkitClass(String name) { + try { + return Class.forName("org.bukkit.craftbukkit." + getVersion() + "." + name); + } catch (ClassNotFoundException ex) { + ex.printStackTrace(); + } + return null; + } + + public static void sendPacket(Player player, Object packet) { + try { + Object nmsPlayer = player.getClass().getMethod("getHandle").invoke(player); + if (playerConnectionField == null) { + playerConnectionField = Arrays.stream(nmsPlayer.getClass().getFields()) + .filter(field -> field.getType() == getPlayerConnectionClass()).findFirst() + .orElseThrow(() -> new ReflectiveOperationException("Failed to find PlayerConnection field in EntityPlayer")); + } + Object playerConnection = playerConnectionField.get(nmsPlayer); + playerConnection.getClass().getMethod("sendPacket", getPacketClass()).invoke(playerConnection, packet); + } catch (Exception ex) { + ex.printStackTrace(); + } + } } diff --git a/src/main/java/de/gerrygames/viarewind/legacysupport/listener/SoundListener.java b/src/main/java/de/gerrygames/viarewind/legacysupport/listener/SoundListener.java index a924510..d525c68 100644 --- a/src/main/java/de/gerrygames/viarewind/legacysupport/listener/SoundListener.java +++ b/src/main/java/de/gerrygames/viarewind/legacysupport/listener/SoundListener.java @@ -93,8 +93,11 @@ public class SoundListener implements Listener { try { World world = block.getWorld(); Object nmsWorld = world.getClass().getMethod("getHandle").invoke(world); - Class blockPositionClass = NMSReflection.getNMSClass("BlockPosition"); - Object blockPosition = blockPositionClass.getConstructor(int.class, int.class, int.class).newInstance(block.getX(), block.getY(), block.getZ()); + Class blockPositionClass = NMSReflection.getBlockPositionClass(); + Object blockPosition = null; + if (blockPositionClass != null) { + blockPosition = blockPositionClass.getConstructor(int.class, int.class, int.class).newInstance(block.getX(), block.getY(), block.getZ()); + } Object blockData = nmsWorld.getClass().getSuperclass().getMethod("getType", blockPositionClass).invoke(nmsWorld, blockPosition); Method getBlock = blockData.getClass().getMethod("getBlock"); getBlock.setAccessible(true); @@ -134,7 +137,7 @@ public class SoundListener implements Listener { Object soundEffect = soundEffectMethod.invoke(soundType); float volume = (float) volumeMethod.invoke(soundType); float pitch = (float) pitchMethod.invoke(soundType); - Object soundCategory = Enum.valueOf(NMSReflection.getNMSClass("SoundCategory"), "BLOCKS"); + Object soundCategory = Enum.valueOf(NMSReflection.getSoundCategoryClass(), "BLOCKS"); volume = (volume + 1.0f) / 2.0f; pitch *= 0.8; @@ -147,7 +150,7 @@ public class SoundListener implements Listener { private static void playSound(Player player, Object soundEffect, Object soundCategory, double x, double y, double z, float volume, float pitch) { try { - Object packet = NMSReflection.getNMSClass("PacketPlayOutNamedSoundEffect").getConstructor( + Object packet = NMSReflection.getGamePacketClass("PacketPlayOutNamedSoundEffect").getConstructor( soundEffect.getClass(), soundCategory.getClass(), double.class, double.class, double.class, float.class, float.class