Update lily pad bb fix to 1.13.x, 1.14.x, add ladder bb fix

This commit is contained in:
Gerrygames 2019-07-23 12:35:25 +02:00
parent 7ae66a27e4
commit ba4d64cb56
7 changed files with 434 additions and 74 deletions

View File

@ -6,7 +6,7 @@
<groupId>de.gerrygames</groupId>
<artifactId>viarewind-legacy-support</artifactId>
<version>1.3.1</version>
<version>1.3.2</version>
<packaging>jar</packaging>
<properties>
@ -42,7 +42,7 @@
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>2.1.1</version>
<version>2.1.3</version>
<scope>provided</scope>
</dependency>

View File

@ -1,6 +1,6 @@
package de.gerrygames.viarewind.legacysupport;
import de.gerrygames.viarewind.legacysupport.injector.LilyPadFixer;
import de.gerrygames.viarewind.legacysupport.injector.BoundingBoxFixer;
import de.gerrygames.viarewind.legacysupport.listener.AreaEffectCloudListener;
import de.gerrygames.viarewind.legacysupport.listener.BounceListener;
import de.gerrygames.viarewind.legacysupport.listener.BrewingListener;
@ -27,23 +27,26 @@ public class BukkitPlugin extends JavaPlugin {
new BukkitRunnable() {
@Override
public void run() {
if (ProtocolRegistry.SERVER_PROTOCOL==-1) return;
if (ProtocolRegistry.SERVER_PROTOCOL == -1) return;
cancel();
if (ProtocolRegistry.SERVER_PROTOCOL>5 && config.getBoolean("enchanting-gui-fix"))
if (ProtocolRegistry.SERVER_PROTOCOL > 5 && config.getBoolean("enchanting-gui-fix"))
Bukkit.getPluginManager().registerEvents(new EnchantingListener(), BukkitPlugin.this);
if (ProtocolRegistry.SERVER_PROTOCOL>78 && config.getBoolean("brewing-stand-gui-fix"))
if (ProtocolRegistry.SERVER_PROTOCOL > 78 && config.getBoolean("brewing-stand-gui-fix"))
Bukkit.getPluginManager().registerEvents(new BrewingListener(), BukkitPlugin.this);
if (ProtocolRegistry.SERVER_PROTOCOL>84 && config.getBoolean("lily-pad-fix"))
LilyPadFixer.fix();
if (ProtocolRegistry.SERVER_PROTOCOL>47 && config.getBoolean("sound-fix"))
if (ProtocolRegistry.SERVER_PROTOCOL > 84 && config.getBoolean("lily-pad-fix"))
BoundingBoxFixer.fixLilyPad();
if (ProtocolRegistry.SERVER_PROTOCOL > 48 && config.getBoolean("ladder-fix"))
BoundingBoxFixer.fixLadder();
if (ProtocolRegistry.SERVER_PROTOCOL > 47 && config.getBoolean("sound-fix"))
Bukkit.getPluginManager().registerEvents(new SoundListener(), BukkitPlugin.this);
if (ProtocolRegistry.SERVER_PROTOCOL>5 && config.getBoolean("slime-fix"))
if (ProtocolRegistry.SERVER_PROTOCOL > 5 && config.getBoolean("slime-fix"))
Bukkit.getPluginManager().registerEvents(new BounceListener(), BukkitPlugin.this);
if (ProtocolRegistry.SERVER_PROTOCOL>76 && config.getBoolean("elytra-fix"))
if (ProtocolRegistry.SERVER_PROTOCOL > 76 && config.getBoolean("elytra-fix"))
Bukkit.getPluginManager().registerEvents(new ElytraListener(), BukkitPlugin.this);
if (ProtocolRegistry.SERVER_PROTOCOL>54 && config.getBoolean("area-effect-cloud-particles"))
if (ProtocolRegistry.SERVER_PROTOCOL > 54 && config.getBoolean("area-effect-cloud-particles"))
Bukkit.getPluginManager().registerEvents(new AreaEffectCloudListener(), BukkitPlugin.this);
if (config.getBoolean("versioninfo.active")) new VersionInformer();
if (config.getBoolean("versioninfo.active"))
new VersionInformer();
}
}.runTaskTimer(this, 1L, 1L);
}

View File

@ -0,0 +1,73 @@
package de.gerrygames.viarewind.legacysupport.injector;
import de.gerrygames.viarewind.legacysupport.reflection.ReflectionAPI;
import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class BoundingBoxFixer {
public static void fixLilyPad() {
try {
Class blockWaterLilyClass = NMSReflection.getNMSClass("BlockWaterLily");
Field boundingBoxField = ReflectionAPI.getFieldAccessible(blockWaterLilyClass, "a");
setBoundingBox(boundingBoxField, 0.0625, 0.0, 0.0625, 0.9375, 0.015625, 0.9375);
} catch (Exception ex) {
System.out.println("Could not fix lily pad bounding box.");
ex.printStackTrace();
}
}
public static void fixLadder() {
try {
Class blockLadderClass = NMSReflection.getNMSClass("BlockLadder");
Field boundingBoxNorthField, boundingBoxSouthField, boundingBoxWestField, boundingBoxEastField;
if (ProtocolRegistry.SERVER_PROTOCOL < 107) {
return;
} else if (ProtocolRegistry.SERVER_PROTOCOL <= 340) {
boundingBoxEastField = ReflectionAPI.getFieldAccessible(blockLadderClass, "b");
boundingBoxWestField = ReflectionAPI.getFieldAccessible(blockLadderClass, "c");
boundingBoxSouthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "d");
boundingBoxNorthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "e");
} else if (ProtocolRegistry.SERVER_PROTOCOL <= 404) {
boundingBoxEastField = ReflectionAPI.getFieldAccessible(blockLadderClass, "c");
boundingBoxWestField = ReflectionAPI.getFieldAccessible(blockLadderClass, "o");
boundingBoxSouthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "p");
boundingBoxNorthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "q");
} else {
boundingBoxEastField = ReflectionAPI.getFieldAccessible(blockLadderClass, "c");
boundingBoxWestField = ReflectionAPI.getFieldAccessible(blockLadderClass, "d");
boundingBoxSouthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "e");
boundingBoxNorthField = ReflectionAPI.getFieldAccessible(blockLadderClass, "f");
}
setBoundingBox(boundingBoxEastField, 0.0D, 0.0D, 0.0D, 0.125D, 1.0D, 1.0D);
setBoundingBox(boundingBoxWestField, 0.875D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D);
setBoundingBox(boundingBoxSouthField, 0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 0.125D);
setBoundingBox(boundingBoxNorthField, 0.0D, 0.0D, 0.875D, 1.0D, 1.0D, 1.0D);
} catch (Exception ex) {
System.out.println("Could not fix ladder bounding box.");
ex.printStackTrace();
}
}
private static void setBoundingBox(Field field, double x1, double y1, double z1, double x2, double y2, double z2) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
if (field.getType().getSimpleName().equals("AxisAlignedBB")) {
Class boundingBoxClass = field.getType();
Constructor boundingBoxConstructor = boundingBoxClass.getConstructor(double.class, double.class, double.class, double.class, double.class, double.class);
Object boundingBox = boundingBoxConstructor.newInstance(x1, y1, z1, x2, y2, z2);
ReflectionAPI.setFinalValue(field, boundingBox);
} else if (field.getType().getSimpleName().equals("VoxelShape")) {
Method createVoxelShape = ReflectionAPI.getMethod(NMSReflection.getNMSClass("VoxelShapes"), "create", double.class, double.class, double.class, double.class, double.class, double.class);
Object boundingBox = ReflectionAPI.invokeMethod(createVoxelShape, x1, y1, z1, x2, y2, z2);
ReflectionAPI.setFinalValue(field, boundingBox);
} else {
throw new IllegalStateException();
}
}
}

View File

@ -1,19 +0,0 @@
package de.gerrygames.viarewind.legacysupport.injector;
import de.gerrygames.viarewind.legacysupport.reflection.ReflectionAPI;
import java.lang.reflect.Constructor;
public class LilyPadFixer {
public static void fix() {
try {
Class blockWaterLilyClass = NMSReflection.getNMSClass("BlockWaterLily");
Class boundingBoxClass = NMSReflection.getNMSClass("AxisAlignedBB");
Constructor boundingBoxConstructor = boundingBoxClass.getConstructor(double.class, double.class, double.class, double.class, double.class, double.class);
Object boundingBox = boundingBoxConstructor.newInstance(0.0625, 0.0, 0.0625, 0.9375, 0.015625, 0.9375);
ReflectionAPI.setFinalValue(blockWaterLilyClass, "a", boundingBox);
} catch (Exception ignored) {
System.out.println("Could not fix Lily Pads bounding box.");
}
}
}

View File

@ -7,7 +7,7 @@ public class NMSReflection {
private static String version;
public static String getVersion() {
return version==null ? version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] : version;
return version == null ? version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3] : version;
}
public static Class getNMSClass(String name) {

View File

@ -1,123 +1,392 @@
package de.gerrygames.viarewind.legacysupport.reflection;
import sun.reflect.ReflectionFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
public class ReflectionAPI {
private static Map<String, Field> fields = new HashMap<>();
private static Map<String, Method> methods = new HashMap<>();
public static Field getField(Class clazz, String fieldname) throws NoSuchFieldException {
String c = clazz.getName() + ":" + fieldname;
Field f = fields.get(c);
if (f == null) {
f = clazz.getDeclaredField(fieldname);
fields.put(c, f);
public static Field getField(Class clazz, String fieldname) {
String key = clazz.getName() + ":" + fieldname;
Field field = null;
if (fields.containsKey(key)) {
field = fields.get(key);
} else {
try {
field = clazz.getDeclaredField(fieldname);
} catch (NoSuchFieldException ignored) {}
fields.put(key, field);
}
return f;
}
public static void setFieldNotFinal(Field field) {
try {
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
if (Modifier.isFinal(field.getModifiers())) {
modifiers.set(field, field.getModifiers() & ~Modifier.FINAL);
}
} catch (Exception ignored) {}
}
public static Field getFieldAccessible(Class clazz, String fieldname) throws NoSuchFieldException {
Field field = getField(clazz, fieldname);
field.setAccessible(true);
return field;
}
public static Object getValue(Class clazz, Object object, String fieldname) throws Exception {
return getFieldAccessible(clazz, fieldname).get(object);
public static boolean hasField(Class clazz, String fieldname) {
return getField(clazz, fieldname) != null;
}
public static Object getValue(Object object, String fieldname) throws Exception {
public static Field getFieldAccessible(Class clazz, String fieldname) {
Field field = getField(clazz, fieldname);
if (field != null) field.setAccessible(true);
return field;
}
public static void setFieldNotFinal(Field field) {
int modifiers = field.getModifiers();
if (!Modifier.isFinal(modifiers)) return;
setValuePrintException(Field.class, field, "modifiers", modifiers & ~Modifier.FINAL);
}
public static <E> Constructor<E> getEmptyConstructor(Class<E> clazz) {
try {
return getConstructor(clazz, Object.class.getDeclaredConstructor());
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
return null;
}
public static <E> Constructor<E> getConstructor(Class<E> clazz, Constructor<? super E> superConstructor) {
return (Constructor<E>) ReflectionFactory.getReflectionFactory().newConstructorForSerialization(clazz, superConstructor);
}
public static <E> E getEmptyObject(Class<E> clazz) {
Constructor<E> constructor = getEmptyConstructor(clazz);
try {
return clazz.cast(constructor.newInstance());
} catch (InstantiationException | IllegalArgumentException | InvocationTargetException | IllegalAccessException ex) {
ex.printStackTrace();
}
return null;
}
public static <O, E extends O> E copyAndExtendObject(O object, Class<E> clazz) {
if (!object.getClass().isAssignableFrom(clazz)) throw new IllegalArgumentException(clazz.getName() + " is not compatible to " + object.getClass().getName());
E copy = getEmptyObject(clazz);
Class<?> current = object.getClass();
do {
for (Field f : current.getDeclaredFields()) {
int modifiers = f.getModifiers();
if (Modifier.isStatic(modifiers)) continue;
if (Modifier.isFinal(modifiers)) setFieldNotFinal(f);
if (!f.isAccessible()) f.setAccessible(true);
try {
f.set(copy, f.get(object));
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
} while (((current = current.getSuperclass()) != Object.class));
return copy;
}
public static <E> E invokeMethod(Object object, Method method, Class<E> returnType, Object... params) {
try {
return (E) method.invoke(object, params);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static <E> E invokeMethod(Method method, Class<E> returnType, Object... params) {
return invokeMethod(null, method, returnType, params);
}
public static <E> E invokeMethod(Object object, Method method, Object... params) {
try {
return (E) method.invoke(object, params);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static <E> E invokeMethod(Method method, Object... params) {
return invokeMethod(null, method, params);
}
public static Method getMethod(Class clazz, String methodname, Class<?>... params) throws NoSuchMethodException {
if (clazz == null) throw new NullPointerException();
NoSuchMethodException exception = null;
while (clazz != null) {
try {
Method method = clazz.getDeclaredMethod(methodname, params);
method.setAccessible(true);
return method;
} catch (NoSuchMethodException ex) {
exception = ex;
}
clazz = clazz.getSuperclass();
}
if (exception != null) {
throw exception;
} else {
throw new IllegalStateException();
}
}
public static Method getMethodPrintException(Class clazz, String methodname, Class<?>... params) {
try {
return getMethod(clazz, methodname, params);
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
return null;
}
public static Method getMethodOrNull(Class clazz, String methodname, Class<?>... params) {
try {
return getMethod(clazz, methodname, params);
} catch (NoSuchMethodException ex) {
return null;
}
}
public static <E> E getValue(Class clazz, Object object, String fieldname) throws NoSuchFieldException, IllegalAccessException {
return (E) getFieldAccessible(clazz, fieldname).get(object);
}
public static <E> E getValue(Object object, String fieldname) throws NoSuchFieldException, IllegalAccessException {
return getValue(object.getClass(), object, fieldname);
}
public static Object getValue(Class clazz, String fieldname) throws Exception {
public static <E> E getValue(Class clazz, String fieldname) throws NoSuchFieldException, IllegalAccessException {
return getValue(clazz, null, fieldname);
}
public static Object getValuePrintException(Object object, String fieldname) {
public static <E> E getValue(Field field) throws IllegalAccessException {
return (E) field.get(null);
}
public static <E> E getValue(Object object, Field field) throws IllegalAccessException {
return (E) field.get(object);
}
public static <E> E getValuePrintException(Class clazz, Object object, String fieldname) {
try {
return getValue(clazz, object, fieldname);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static <E> E getValuePrintException(Object object, String fieldname) {
try {
return getValue(object, fieldname);
} catch (Exception ex) {ex.printStackTrace();}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Object getValuePrintException(Class clazz, String fieldname) {
public static <E> E getValuePrintException(Class clazz, String fieldname) {
try {
return getValue(clazz, fieldname);
} catch (Exception ex) {ex.printStackTrace();}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static Object getValueIgnoreException(Object object, String fieldname) {
public static <E> E getValuePrintException(Field field) {
try {
return (E) field.get(null);
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
return null;
}
public static <E> E getValuePrintException(Object object, Field field) {
try {
return (E) field.get(object);
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
return null;
}
public static <E> E getValueIgnoreException(Class clazz, Object object, String fieldname) {
try {
return getValue(clazz, object, fieldname);
} catch (Exception ignored) {}
return null;
}
public static <E> E getValueIgnoreException(Object object, String fieldname) {
try {
return getValue(object, fieldname);
} catch (Exception ignored) {}
return null;
}
public static Object getValueIgnoreException(Class clazz, String fieldname) {
public static <E> E getValueIgnoreException(Class clazz, String fieldname) {
try {
return getValue(clazz, fieldname);
} catch (Exception ignored) {}
return null;
}
private static void setValue(Class clazz, Object object, String fieldname, Object value, boolean isFinal) throws Exception {
public static <E> E getValueIgnoreException(Field field) {
try {
return (E) field.get(null);
} catch (IllegalAccessException ignored) {}
return null;
}
public static <E> E getValueIgnoreException(Object object, Field field) {
try {
return (E) field.get(object);
} catch (IllegalAccessException ignored) {}
return null;
}
public static void setValue(Class clazz, Object object, String fieldname, Object value, boolean isFinal) throws NoSuchFieldException, IllegalAccessException {
Field field = getFieldAccessible(clazz, fieldname);
if (isFinal) setFieldNotFinal(field);
field.set(object, value);
}
public static void setValue(Object object, String fieldname, Object value) throws Exception {
public static void setValue(Class clazz, Object object, String fieldname, Object value) throws NoSuchFieldException, IllegalAccessException {
setValue(clazz, object, fieldname, value, false);
}
public static void setValue(Object object, String fieldname, Object value) throws NoSuchFieldException, IllegalAccessException {
setValue(object.getClass(), object, fieldname, value, false);
}
public static void setValue(Class clazz, String fieldname, Object value) throws Exception {
public static void setValue(Class clazz, String fieldname, Object value) throws NoSuchFieldException, IllegalAccessException {
setValue(clazz, null, fieldname, value, false);
}
public static void setFinalValue(Object object, String fieldname, Object value) throws Exception {
public static void setValue(Field field, Object value) throws IllegalAccessException {
field.set(null, value);
}
public static void setValue(Object object, Field field, Object value) throws IllegalAccessException {
field.set(object, value);
}
public static void setFinalValue(Class clazz, Object object, String fieldname, Object value) throws NoSuchFieldException, IllegalAccessException {
setValue(clazz, object, fieldname, value, true);
}
public static void setFinalValue(Object object, String fieldname, Object value) throws NoSuchFieldException, IllegalAccessException {
setValue(object.getClass(), object, fieldname, value, true);
}
public static void setFinalValue(Class clazz, String fieldname, Object value) throws Exception {
public static void setFinalValue(Class clazz, String fieldname, Object value) throws NoSuchFieldException, IllegalAccessException {
setValue(clazz, null, fieldname, value, true);
}
public static void setFinalValue(Field field, Object value) throws IllegalAccessException {
setFieldNotFinal(field);
field.set(null, value);
}
public static void setFinalValue(Object object, Field field, Object value) throws IllegalAccessException {
setFieldNotFinal(field);
field.set(object, value);
}
public static void setValuePrintException(Class clazz, Object object, String fieldname, Object value) {
try {
setValue(clazz, object, fieldname, value);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void setValuePrintException(Object object, String fieldname, Object value) {
try {
setValue(object, fieldname, value);
} catch (Exception ex) {ex.printStackTrace();}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void setValuePrintException(Class clazz, String fieldname, Object value) {
try {
setValue(clazz, fieldname, value);
} catch (Exception ex) {ex.printStackTrace();}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void setValuePrintException(Field field, Object value) {
try {
field.set(null, value);
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
public static void setValuePrintException(Object object, Field field, Object value) {
try {
field.set(object, value);
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
public static void setFinalValuePrintException(Class clazz, Object object, String fieldname, Object value) {
try {
setFinalValue(clazz, object, fieldname, value);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void setFinalValuePrintException(Object object, String fieldname, Object value) {
try {
setFinalValue(object, fieldname, value);
} catch (Exception ex) {ex.printStackTrace();}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void setFinalValuePrintException(Class clazz, String fieldname, Object value) {
try {
setFinalValue(clazz, fieldname, value);
} catch (Exception ex) {ex.printStackTrace();}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void setFinalValuePrintException(Field field, Object value) {
setFieldNotFinal(field);
try {
field.set(null, value);
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
public static void setFinalValuePrintException(Object object, Field field, Object value) {
setFieldNotFinal(field);
try {
field.set(object, value);
} catch (IllegalAccessException ex) {
ex.printStackTrace();
}
}
public static void setValueIgnoreException(Class clazz, Object object, String fieldname, Object value) {
try {
setValue(clazz, object, fieldname, value);
} catch (Exception ignored) {}
}
public static void setValueIgnoreException(Object object, String fieldname, Object value) {
@ -132,6 +401,24 @@ public class ReflectionAPI {
} catch (Exception ignored) {}
}
public static void setValueIgnoreException(Field field, Object value) {
try {
field.set(null, value);
} catch (IllegalAccessException ignored) {}
}
public static void setValueIgnoreException(Object object, Field field, Object value) {
try {
field.set(object, value);
} catch (IllegalAccessException ignored) {}
}
public static void setFinalValueIgnoreException(Class clazz, Object object, String fieldname, Object value) {
try {
setFinalValue(clazz, object, fieldname, value);
} catch (Exception ignored) {}
}
public static void setFinalValueIgnoreException(Object object, String fieldname, Object value) {
try {
setFinalValue(object, fieldname, value);
@ -143,4 +430,18 @@ public class ReflectionAPI {
setFinalValue(clazz, fieldname, value);
} catch (Exception ignored) {}
}
public static void setFinalValueIgnoreException(Field field, Object value) {
setFieldNotFinal(field);
try {
field.set(null, value);
} catch (IllegalAccessException ignored) {}
}
public static void setFinalValueIgnoreException(Object object, Field field, Object value) {
setFieldNotFinal(field);
try {
field.set(object, value);
} catch (IllegalAccessException ignored) {}
}
}

View File

@ -4,6 +4,8 @@ brewing-stand-gui-fix: true
enchanting-gui-fix: true
#Fix the lily pad bounding box to prevent clients lower than 1.9 from glitching
lily-pad-fix: true
#Fix the ladder bounding box to prevent clients lower than 1.9 from glitching
ladder-fix: true
#If set to true, this plugin will play sounds for 1.8 and lower that got clientside on 1.9 and higher
sound-fix: true
#If set to true, this plugin will apply velocity to 1.7 if they fall onto slime blocks