Fix 1_16_R2 bukkit config reload error

- Refactored VersionParam to include patch version specification
- Added ConstructorParam to cache constructors & get the default constructor.
This commit is contained in:
Frank van der Heijden 2020-09-29 13:38:16 +02:00
parent f268b098a3
commit e2a9fb1dc3
No known key found for this signature in database
GPG key ID: 26DA56488D314D11
9 changed files with 146 additions and 25 deletions

View file

@ -23,6 +23,7 @@ public class BukkitReflection extends ReflectionUtils {
@Override @Override
public boolean isCompatible(VersionParam versionParam) { public boolean isCompatible(VersionParam versionParam) {
return versionParam.min <= MINOR && MINOR <= versionParam.max; return versionParam.min.minor <= MINOR && versionParam.min.patch <= PATCH
&& MINOR <= versionParam.max.minor && PATCH <= versionParam.max.patch;
} }
} }

View file

@ -9,9 +9,9 @@ import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getDeclaredMethod; import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getDeclaredMethod;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke; import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set; import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set;
import static net.frankheijden.serverutils.common.reflection.VersionParam.exact;
import static net.frankheijden.serverutils.common.reflection.VersionParam.max; import static net.frankheijden.serverutils.common.reflection.VersionParam.max;
import static net.frankheijden.serverutils.common.reflection.VersionParam.min; import static net.frankheijden.serverutils.common.reflection.VersionParam.min;
import static net.frankheijden.serverutils.common.reflection.VersionParam.versionOf;
import java.io.File; import java.io.File;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -53,7 +53,7 @@ public class RCraftServer {
fieldOf("console"), fieldOf("console"),
fieldOf("commandsConfiguration"), fieldOf("commandsConfiguration"),
fieldOf("overrideAllCommandBlockCommands"), fieldOf("overrideAllCommandBlockCommands"),
fieldOf("unrestrictedAdvancements", versionOf(12)), fieldOf("unrestrictedAdvancements", exact(12)),
fieldOf("ignoreVanillaPermissions", min(13)), fieldOf("ignoreVanillaPermissions", min(13)),
fieldOf("monsterSpawn"), fieldOf("monsterSpawn"),
fieldOf("animalSpawn"), fieldOf("animalSpawn"),

View file

@ -1,6 +1,7 @@
package net.frankheijden.serverutils.bukkit.reflection; package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.bukkit.entities.BukkitReflection.MINOR; import static net.frankheijden.serverutils.bukkit.entities.BukkitReflection.MINOR;
import static net.frankheijden.serverutils.bukkit.entities.BukkitReflection.PATCH;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf; import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf; import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get; import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
@ -9,6 +10,7 @@ import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke; import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set; import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set;
import static net.frankheijden.serverutils.common.reflection.VersionParam.between; import static net.frankheijden.serverutils.common.reflection.VersionParam.between;
import static net.frankheijden.serverutils.common.reflection.VersionParam.exact;
import static net.frankheijden.serverutils.common.reflection.VersionParam.max; import static net.frankheijden.serverutils.common.reflection.VersionParam.max;
import static net.frankheijden.serverutils.common.reflection.VersionParam.min; import static net.frankheijden.serverutils.common.reflection.VersionParam.min;
@ -18,6 +20,7 @@ import java.lang.reflect.Method;
import java.util.Map; import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection; import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import net.frankheijden.serverutils.common.reflection.VersionParam;
public class RDedicatedServer { public class RDedicatedServer {
@ -50,8 +53,10 @@ public class RDedicatedServer {
methodOf("setForceGamemode", boolean.class), methodOf("setForceGamemode", boolean.class),
methodOf("n", between(13, 15), boolean.class), methodOf("n", between(13, 15), boolean.class),
methodOf("aZ", max(15)), methodOf("aZ", max(15)),
methodOf("aZ", min(new VersionParam.Version(16, 2))),
methodOf("i", min(16), boolean.class), methodOf("i", min(16), boolean.class),
methodOf("aY", min(16))); methodOf("aY", exact(new VersionParam.Version(16, 1))),
methodOf("getCustomRegistry", min(new VersionParam.Version(16, 2))));
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
@ -70,7 +75,14 @@ public class RDedicatedServer {
Object options = get(fields, console, "options"); Object options = get(fields, console, "options");
if (MINOR >= 13) { if (MINOR >= 13) {
Object propertyManager = RDedicatedServerSettings.newInstance(options); Object propertyManager;
if (MINOR >= 16 && PATCH >= 2) {
propertyManager = RDedicatedServerSettings.newInstance(invoke(methods, console, "getCustomRegistry"),
options);
} else {
propertyManager = RDedicatedServerSettings.newInstance(options);
}
set(fields, console, "propertyManager", propertyManager); set(fields, console, "propertyManager", propertyManager);
Object config = invoke(RDedicatedServerSettings.getMethods(), propertyManager, "getProperties"); Object config = invoke(RDedicatedServerSettings.getMethods(), propertyManager, "getProperties");
invoke(methods, console, "setPVP", getConfigValue(config, "pvp")); invoke(methods, console, "setPVP", getConfigValue(config, "pvp"));
@ -78,16 +90,20 @@ public class RDedicatedServer {
invoke(methods, console, "setMotd", getConfigValue(config, "motd")); invoke(methods, console, "setMotd", getConfigValue(config, "motd"));
invoke(methods, console, "setForceGamemode", getConfigValue(config, "forceGamemode")); invoke(methods, console, "setForceGamemode", getConfigValue(config, "forceGamemode"));
Object resourcePackHash;
if (MINOR <= 15 || (MINOR == 16 && PATCH == 1)) {
resourcePackHash = invoke(methods, console, "aZ");
} else {
resourcePackHash = invoke(methods, console, "aY");
}
invoke(methods, console, "setResourcePack", getConfigValue(config, "resourcePack"), resourcePackHash);
if (MINOR <= 15) { if (MINOR <= 15) {
invoke(methods, console, "setSpawnAnimals", getConfigValue(config, "spawnAnimals")); invoke(methods, console, "setSpawnAnimals", getConfigValue(config, "spawnAnimals"));
invoke(methods, console, "setSpawnNPCs", getConfigValue(config, "spawnNpcs")); invoke(methods, console, "setSpawnNPCs", getConfigValue(config, "spawnNpcs"));
invoke(methods, console, "setResourcePack", getConfigValue(config, "resourcePack"),
invoke(methods, console, "aZ"));
invoke(methods, console, "n", getConfigValue(config, "enforceWhitelist")); invoke(methods, console, "n", getConfigValue(config, "enforceWhitelist"));
set(fields, console, "o", getConfigValue(config, "gamemode")); set(fields, console, "o", getConfigValue(config, "gamemode"));
} else { } else {
invoke(methods, console, "setResourcePack", getConfigValue(config, "resourcePack"),
invoke(methods, console, "aY"));
invoke(methods, console, "i", getConfigValue(config, "enforceWhitelist")); invoke(methods, console, "i", getConfigValue(config, "enforceWhitelist"));
} }
} else { } else {

View file

@ -1,9 +1,13 @@
package net.frankheijden.serverutils.bukkit.reflection; package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.ConstructorParam.constructorOf;
import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf; import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllConstructors;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods; import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
import java.util.Map; import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection; import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
@ -12,6 +16,7 @@ public class RDedicatedServerSettings {
private static Class<?> serverSettingsClass; private static Class<?> serverSettingsClass;
private static Map<String, Method> methods; private static Map<String, Method> methods;
private static List<Constructor<?>> constructors;
static { static {
try { try {
@ -19,13 +24,32 @@ public class RDedicatedServerSettings {
BukkitReflection.NMS)); BukkitReflection.NMS));
methods = getAllMethods(serverSettingsClass, methods = getAllMethods(serverSettingsClass,
methodOf("getProperties")); methodOf("getProperties"));
constructors = getAllConstructors(serverSettingsClass,
constructorOf(Class.forName("joptsimple.OptionSet")),
constructorOf(Class.forName(String.format("net.minecraft.server.%s.IRegistryCustom",
BukkitReflection.NMS)), Class.forName("joptsimple.OptionSet")));
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
} }
/**
* Retrieves the default constructor.
* @return The default constructor of DedicatedServerSettings.
* @throws NoSuchMethodException If no constructor was found.
*/
public static Constructor<?> getConstructor() throws NoSuchMethodException {
if (constructors.size() == 0) throw new NoSuchMethodException("No constructor found for "
+ serverSettingsClass.getName());
return constructors.get(0);
}
public static Object newInstance(Object options) throws ReflectiveOperationException { public static Object newInstance(Object options) throws ReflectiveOperationException {
return serverSettingsClass.getDeclaredConstructor(Class.forName("joptsimple.OptionSet")).newInstance(options); return getConstructor().newInstance(options);
}
public static Object newInstance(Object registry, Object options) throws ReflectiveOperationException {
return getConstructor().newInstance(registry, options);
} }
public static Map<String, Method> getMethods() { public static Map<String, Method> getMethods() {

View file

@ -0,0 +1,14 @@
package net.frankheijden.serverutils.common.reflection;
public class ConstructorParam {
public final Class<?>[] params;
private ConstructorParam(Class<?>[] params) {
this.params = params;
}
public static ConstructorParam constructorOf(Class<?>... params) {
return new ConstructorParam(params);
}
}

View file

@ -3,8 +3,9 @@ package net.frankheijden.serverutils.common.reflection;
import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VERSIONS; import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VERSIONS;
public class FieldParam { public class FieldParam {
public String field;
public VersionParam versionParam; public final String field;
public final VersionParam versionParam;
private FieldParam(String field, VersionParam versionParam) { private FieldParam(String field, VersionParam versionParam) {
this.field = field; this.field = field;

View file

@ -4,9 +4,9 @@ import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VE
public class MethodParam { public class MethodParam {
public String method; public final String method;
public VersionParam versionParam; public final VersionParam versionParam;
public Class<?>[] params; public final Class<?>[] params;
private MethodParam(String method, VersionParam versionParam, Class<?>... params) { private MethodParam(String method, VersionParam versionParam, Class<?>... params) {
this.method = method; this.method = method;

View file

@ -1,9 +1,12 @@
package net.frankheijden.serverutils.common.reflection; package net.frankheijden.serverutils.common.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public abstract class ReflectionUtils { public abstract class ReflectionUtils {
@ -122,6 +125,24 @@ public abstract class ReflectionUtils {
return map; return map;
} }
/**
* Fetches all constructors by their parameter input.
* @param clazz The class to find constructors on.
* @param constructorParams The constructor parameters.
* @return The list of constructors.
*/
public static List<Constructor<?>> getAllConstructors(Class<?> clazz, ConstructorParam... constructorParams) {
List<Constructor<?>> constructors = new ArrayList<>();
for (ConstructorParam constructorParam : constructorParams) {
try {
constructors.add(clazz.getDeclaredConstructor(constructorParam.params));
} catch (NoSuchMethodException ignored) {
//
}
}
return constructors;
}
/** /**
* Invokes a method on an instance. * Invokes a method on an instance.
* Will return null if method not present in map. * Will return null if method not present in map.

View file

@ -2,29 +2,73 @@ package net.frankheijden.serverutils.common.reflection;
public class VersionParam { public class VersionParam {
public static VersionParam ALL_VERSIONS = new VersionParam(Integer.MIN_VALUE, Integer.MAX_VALUE); public static final Version MIN_VERSION = new Version(Integer.MIN_VALUE, Integer.MIN_VALUE);
public static final Version MAX_VERSION = new Version(Integer.MAX_VALUE, Integer.MAX_VALUE);
public static final VersionParam ALL_VERSIONS = new VersionParam(MIN_VERSION, MAX_VERSION);
public int min; public final Version min;
public int max; public final Version max;
private VersionParam(int min, int max) { private VersionParam(int min, int max) {
this(min, Integer.MIN_VALUE, max, Integer.MAX_VALUE);
}
private VersionParam(int min, int minPatch, int max, int maxPatch) {
this(new Version(min, minPatch), new Version(max, maxPatch));
}
private VersionParam(Version min, Version max) {
this.min = min; this.min = min;
this.max = max; this.max = max;
} }
public static VersionParam versionOf(int ver) { public static VersionParam exact(int minor) {
return new VersionParam(minor, minor);
}
public static VersionParam exact(Version ver) {
return new VersionParam(ver, ver); return new VersionParam(ver, ver);
} }
public static VersionParam between(int min, int max) { public static VersionParam between(int minMinor, int maxMinor) {
return new VersionParam(minMinor, maxMinor);
}
public static VersionParam between(Version min, Version max) {
return new VersionParam(min, max); return new VersionParam(min, max);
} }
public static VersionParam min(int min) { public static VersionParam min(int minMinor) {
return between(min, Integer.MAX_VALUE); return between(minMinor, Integer.MAX_VALUE);
} }
public static VersionParam max(int max) { public static VersionParam min(Version min) {
return between(Integer.MIN_VALUE, max); return between(min, MAX_VERSION);
}
public static VersionParam max(int maxMinor) {
return between(Integer.MIN_VALUE, maxMinor);
}
public static VersionParam max(Version max) {
return between(MIN_VERSION, max);
}
public static class Version {
public final int minor;
public final int patch;
public Version(int minor, int patch) {
this.minor = minor;
this.patch = patch;
}
public int getMinor() {
return minor;
}
public int getPatch() {
return patch;
}
} }
} }