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