Refactor reflections and use MinecraftReflection

This commit is contained in:
Frank van der Heijden 2020-12-21 00:11:31 +01:00
parent 295eb77452
commit 8a855d6935
No known key found for this signature in database
GPG key ID: 26DA56488D314D11
34 changed files with 305 additions and 1148 deletions

View file

@ -9,7 +9,6 @@ import java.util.Map;
import net.frankheijden.serverutils.bukkit.commands.CommandPlugins;
import net.frankheijden.serverutils.bukkit.commands.CommandServerUtils;
import net.frankheijden.serverutils.bukkit.entities.BukkitPlugin;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import net.frankheijden.serverutils.bukkit.listeners.BukkitListener;
import net.frankheijden.serverutils.bukkit.managers.BukkitPluginManager;
import net.frankheijden.serverutils.bukkit.reflection.RCommandMap;
@ -46,7 +45,6 @@ public class ServerUtils extends JavaPlugin implements CommandExecutor {
ServerUtilsApp.init(this, plugin);
new Metrics(this, ServerUtilsApp.BSTATS_METRICS_ID);
new BukkitReflection();
this.commandManager = new PaperCommandManager(this);
commandManager.registerCommand(new CommandServerUtils(), true);

View file

@ -1,6 +1,5 @@
package net.frankheijden.serverutils.bukkit.commands;
import static net.frankheijden.serverutils.bukkit.entities.BukkitReflection.MINOR;
import static net.frankheijden.serverutils.common.config.Messenger.sendMessage;
import co.aikar.commands.BaseCommand;
@ -13,6 +12,7 @@ import co.aikar.commands.annotation.Default;
import co.aikar.commands.annotation.Dependency;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@ -303,7 +303,7 @@ public class CommandServerUtils extends BaseCommand {
.add("Name", plugin.getName())
.add("Full Name", description.getFullName())
.add("Version", description.getVersion());
if (MINOR >= 13) builder.add("API Version", description.getAPIVersion());
if (MinecraftReflectionVersion.MINOR >= 13) builder.add("API Version", description.getAPIVersion());
builder.add("Website", description.getWebsite())
.add("Authors", ListBuilder.create(description.getAuthors())
.format(listFormat)
@ -329,11 +329,13 @@ public class CommandServerUtils extends BaseCommand {
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString());
if (MINOR >= 15) builder.add("Provides", ListBuilder.create(description.getProvides())
.format(listFormat)
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString());
if (MinecraftReflectionVersion.MINOR >= 15) {
builder.add("Provides", ListBuilder.create(description.getProvides())
.format(listFormat)
.seperator(seperator)
.lastSeperator(lastSeperator)
.toString());
}
builder.sendTo(sender);
Messenger.sendMessage(sender, "serverutils.plugininfo.footer");

View file

@ -1,29 +0,0 @@
package net.frankheijden.serverutils.bukkit.entities;
import net.frankheijden.serverutils.common.reflection.ReflectionUtils;
import net.frankheijden.serverutils.common.reflection.VersionParam;
import org.bukkit.Bukkit;
public class BukkitReflection extends ReflectionUtils {
public static String NMS;
public static int MAJOR;
public static int MINOR;
public static int PATCH;
static {
String bukkitPackage = Bukkit.getServer().getClass().getPackage().getName();
NMS = bukkitPackage.substring(bukkitPackage.lastIndexOf('.') + 1);
String[] split = NMS.split("_");
MAJOR = Integer.parseInt(split[0].substring(1));
MINOR = Integer.parseInt(split[1]);
PATCH = Integer.parseInt(split[2].substring(1, 2));
}
@Override
public boolean isCompatible(VersionParam versionParam) {
return versionParam.min.minor <= MINOR && versionParam.min.patch <= PATCH
&& MINOR <= versionParam.max.minor && PATCH <= versionParam.max.patch;
}
}

View file

@ -2,7 +2,6 @@ package net.frankheijden.serverutils.bukkit.managers;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -150,12 +149,8 @@ public class BukkitPluginManager extends AbstractPluginManager<Plugin> {
ClassLoader loader = RJavaPlugin.getClassLoader(plugin);
RPluginClassLoader.clearClassLoader(loader);
addIfInstance(closeables, (Closeable) () -> {
try {
Map<String, Class<?>> classes = RPluginClassLoader.getClasses(loader);
RJavaPluginLoader.removeClasses(getPluginLoader(getPluginFile(plugin)), classes.keySet());
} catch (IllegalAccessException ex) {
throw new IOException(ex);
}
Map<String, Class<?>> classes = RPluginClassLoader.getClasses(loader);
RJavaPluginLoader.removeClasses(getPluginLoader(getPluginFile(plugin)), classes.keySet());
});
addIfInstance(closeables, loader);
addIfInstance(closeables, RJavaPlugin.clearJavaPlugin(plugin));
@ -192,11 +187,7 @@ public class BukkitPluginManager extends AbstractPluginManager<Plugin> {
if (Bukkit.getPluginManager().isPluginEnabled(plugin.getName())) return Result.ALREADY_ENABLED;
Bukkit.getPluginManager().enablePlugin(plugin);
try {
RCraftServer.syncCommands();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
}
RCraftServer.syncCommands();
return Bukkit.getPluginManager().isPluginEnabled(plugin.getName()) ? Result.SUCCESS : Result.ERROR;
}
@ -270,11 +261,7 @@ public class BukkitPluginManager extends AbstractPluginManager<Plugin> {
return false;
});
try {
RCraftServer.syncCommands();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
}
RCraftServer.syncCommands();
}
/**
@ -372,11 +359,7 @@ public class BukkitPluginManager extends AbstractPluginManager<Plugin> {
@Override
public File getPluginFile(Plugin plugin) {
try {
return RJavaPlugin.getFile(plugin);
} catch (ReflectiveOperationException ex) {
throw new RuntimeException("Error retrieving current plugin file", ex);
}
return RJavaPlugin.getFile(plugin);
}
/**

View file

@ -1,34 +1,25 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getDeclaredField;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import dev.frankheijden.minecraftreflection.exceptions.MinecraftReflectionException;
import java.util.Map;
import org.bukkit.command.Command;
import org.bukkit.command.SimpleCommandMap;
public class RCommandMap {
private static Field knownCommands = null;
private static Method getKnownCommands = null;
private static final MinecraftReflection reflection = MinecraftReflection
.of(SimpleCommandMap.class);
static {
/**
* Gets the known commands from the given command map.
* TODO: figure out which version causes method change.
*/
public static Map<String, Command> getKnownCommands(SimpleCommandMap map) {
try {
try {
knownCommands = getDeclaredField(SimpleCommandMap.class, "knownCommands");
} catch (NoSuchFieldException ignored) {
getKnownCommands = SimpleCommandMap.class.getDeclaredMethod("getKnownCommands");
}
} catch (Exception ex) {
ex.printStackTrace();
return reflection.get(map, "knownCommands");
} catch (MinecraftReflectionException ignored) {
return reflection.invoke(map, "getKnownCommands");
}
}
@SuppressWarnings("unchecked")
public static Map<String, Command> getKnownCommands(SimpleCommandMap map)
throws IllegalAccessException, InvocationTargetException {
return (Map<String, Command>) (knownCommands == null ? getKnownCommands.invoke(map) : knownCommands.get(map));
}
}

View file

@ -1,24 +1,9 @@
package net.frankheijden.serverutils.bukkit.reflection;
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.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getDeclaredField;
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.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.min;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import org.bukkit.Bukkit;
import org.bukkit.Warning;
import org.bukkit.command.Command;
@ -27,159 +12,117 @@ import org.bukkit.configuration.file.YamlConfiguration;
public class RCraftServer {
private static Class<?> craftServerClass;
private static Object craftServer;
private static File configFile;
private static File commandsConfigFile;
private static SimpleCommandMap commandMap;
private static final MinecraftReflection reflection = MinecraftReflection
.of("org.bukkit.craftbukkit.%s.CraftServer");
private static Map<String, Field> fields;
private static Map<String, Method> methods;
static {
try {
craftServerClass = Class.forName(String.format("org.bukkit.craftbukkit.%s.CraftServer",
BukkitReflection.NMS));
craftServer = craftServerClass.cast(Bukkit.getServer());
commandsConfigFile = (File) getDeclaredMethod(craftServerClass,
"getCommandsConfigFile").invoke(craftServer);
configFile = (File) getDeclaredMethod(craftServerClass, "getConfigFile").invoke(craftServer);
commandMap = (SimpleCommandMap) getDeclaredField(craftServerClass, "commandMap").get(Bukkit.getServer());
fields = getAllFields(craftServerClass,
fieldOf("configuration"),
fieldOf("console"),
fieldOf("commandsConfiguration"),
fieldOf("overrideAllCommandBlockCommands"),
fieldOf("unrestrictedAdvancements", exact(12)),
fieldOf("ignoreVanillaPermissions", min(13)),
fieldOf("monsterSpawn"),
fieldOf("animalSpawn"),
fieldOf("waterAnimalSpawn"),
fieldOf("ambientSpawn"),
fieldOf("warningState"),
fieldOf("minimumAPI", min(14)),
fieldOf("printSaveWarning"),
fieldOf("chunkGCPeriod", max(12)),
fieldOf("chunkGCLoadThresh", max(12)),
fieldOf("playerList"));
methods = getAllMethods(craftServerClass,
methodOf("loadIcon"),
methodOf("syncCommands", min(13)),
methodOf("getHandle"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static Object getCraftServer() {
return craftServer;
public static MinecraftReflection getReflection() {
return reflection;
}
public static File getConfigFile() {
return configFile;
return reflection.invoke(Bukkit.getServer(), "getConfigFile");
}
/**
* Retrieves the options file from a key.
* @param option The option key.
* @return The associated file.
* @throws InvocationTargetException If the method call produced an exception.
* @throws IllegalAccessException When prohibited access to the method.
*/
public static File getOptionsFile(String option) throws IllegalAccessException, InvocationTargetException {
Object console = getConsole();
Object options = get(RDedicatedServer.getFields(), console, "options");
return (File) invoke(ROptionSet.getMethods(), options, "valueOf", option);
public static File getOptionsFile(String option) {
Object options = reflection.get(getConsole(), "options");
return reflection.invoke(options, "valueOf", option);
}
public static File getCommandsConfigFile() {
return commandsConfigFile;
return reflection.invoke(Bukkit.getServer(), "getCommandsConfigFile");
}
public static SimpleCommandMap getCommandMap() {
return commandMap;
return reflection.get(Bukkit.getServer(), "commandMap");
}
public static void syncCommands() throws InvocationTargetException, IllegalAccessException {
invoke(methods, craftServer, "syncCommands");
public static void syncCommands() {
if (MinecraftReflectionVersion.MINOR >= 13) reflection.invoke(Bukkit.getServer(), "syncCommands");
}
public static Object getConsole() throws IllegalAccessException {
return get(fields, craftServer, "console");
public static Object getConsole() {
return reflection.get(Bukkit.getServer(), "console");
}
/**
* Reloads the bukkit configuration.
* @throws ReflectiveOperationException Iff exception thrown regarding reflection.
*/
public static void reloadBukkitConfiguration() throws ReflectiveOperationException {
public static void reloadBukkitConfiguration() {
YamlConfiguration bukkit = YamlConfiguration.loadConfiguration(getConfigFile());
set(fields, craftServer, "configuration", bukkit);
reflection.set(Bukkit.getServer(), "configuration", bukkit);
Object console = getConsole();
RDedicatedServer.reload(console);
RDedicatedServer.reload(getConsole());
set(fields, craftServer, "monsterSpawn", bukkit.getInt("spawn-limits.monsters"));
set(fields, craftServer, "animalSpawn", bukkit.getInt("spawn-limits.animals"));
set(fields, craftServer, "waterAnimalSpawn", bukkit.getInt("spawn-limits.water-animals"));
set(fields, craftServer, "ambientSpawn", bukkit.getInt("spawn-limits.ambient"));
set(fields, craftServer, "warningState",
reflection.set(Bukkit.getServer(), "monsterSpawn", bukkit.getInt("spawn-limits.monsters"));
reflection.set(Bukkit.getServer(), "animalSpawn", bukkit.getInt("spawn-limits.animals"));
reflection.set(Bukkit.getServer(), "waterAnimalSpawn", bukkit.getInt("spawn-limits.water-animals"));
reflection.set(Bukkit.getServer(), "ambientSpawn", bukkit.getInt("spawn-limits.ambient"));
reflection.set(Bukkit.getServer(), "warningState",
Warning.WarningState.value(bukkit.getString("settings.deprecated-verbose")));
set(fields, craftServer, "minimumAPI", bukkit.getString("settings.minimum-api"));
set(fields, craftServer, "printSaveWarning", false);
if (MinecraftReflectionVersion.isMin(14))
reflection.set(Bukkit.getServer(), "minimumAPI", bukkit.getString("settings.minimum-api"));
reflection.set(Bukkit.getServer(), "printSaveWarning", false);
reflection.set(Bukkit.getServer(), "monsterSpawn", bukkit.getInt("spawn-limits.monsters"));
reflection.set(Bukkit.getServer(), "monsterSpawn", bukkit.getInt("spawn-limits.monsters"));
reflection.set(Bukkit.getServer(), "monsterSpawn", bukkit.getInt("spawn-limits.monsters"));
if (MinecraftReflectionVersion.isMax(12)) {
reflection.set(Bukkit.getServer(), "chunkGCPeriod", bukkit.getInt("chunk-gc.period-in-ticks"));
reflection.set(Bukkit.getServer(), "chunkGCLoadThresh", bukkit.getInt("chunk-gc.load-threshold"));
}
set(RDedicatedServer.getFields(), console, "autosavePeriod", bukkit.getInt("ticks-per.autosave"));
set(fields, craftServer, "chunkGCPeriod", bukkit.getInt("chunk-gc.period-in-ticks"));
set(fields, craftServer, "chunkGCLoadThresh", bukkit.getInt("chunk-gc.load-threshold"));
RDedicatedServer.getReflection().set(getConsole(), "autosavePeriod", bukkit.getInt("ticks-per.autosave"));
}
public static void loadIcon() throws InvocationTargetException, IllegalAccessException {
invoke(methods, craftServer, "loadIcon");
public static void loadIcon() {
reflection.invoke(Bukkit.getServer(), "loadIcon");
}
/**
* Reloads the commands.yml file.
* @throws InvocationTargetException If the method call produced an exception.
* @throws IllegalAccessException When prohibited access to the method.
*/
public static void reloadCommandsConfiguration() throws IllegalAccessException, InvocationTargetException {
public static void reloadCommandsConfiguration() {
SimpleCommandMap commandMap = getCommandMap();
Map<String, Command> map = RCommandMap.getKnownCommands(commandMap);
Bukkit.getCommandAliases().keySet().forEach(map::remove);
YamlConfiguration commands = YamlConfiguration.loadConfiguration(getCommandsConfigFile());
set(fields, craftServer, "commandsConfiguration", commands);
set(fields, craftServer, "overrideAllCommandBlockCommands",
reflection.set(Bukkit.getServer(), "commandsConfiguration", commands);
reflection.set(Bukkit.getServer(), "overrideAllCommandBlockCommands",
commands.getStringList("command-block-overrides").contains("*"));
set(fields, craftServer, "ignoreVanillaPermissions",
commands.getBoolean("ignore-vanilla-permissions"));
set(fields, craftServer, "unrestrictedAdvancements",
commands.getBoolean("unrestricted-advancements"));
if (MinecraftReflectionVersion.isMin(13)) reflection.set(
Bukkit.getServer(),
"ignoreVanillaPermissions",
commands.getBoolean("ignore-vanilla-permissions")
);
if (MinecraftReflectionVersion.is(12)) reflection.set(
Bukkit.getServer(),
"unrestrictedAdvancements",
commands.getBoolean("unrestricted-advancements")
);
commandMap.registerServerAliases();
}
/**
* Reloads the ip-bans file.
* @throws InvocationTargetException If the method call produced an exception.
* @throws IllegalAccessException When prohibited access to the method.
*/
public static void reloadIpBans() throws IllegalAccessException, InvocationTargetException {
Object playerList = get(fields, craftServer, "playerList");
Object jsonList = invoke(RPlayerList.getMethods(), playerList, "getIPBans");
public static void reloadIpBans() {
Object playerList = reflection.get(Bukkit.getServer(), "playerList");
Object jsonList = RPlayerList.getReflection().invoke(playerList, "getIPBans");
RJsonList.load(jsonList);
}
/**
* Reloads the profile bans file.
* @throws InvocationTargetException If the method call produced an exception.
* @throws IllegalAccessException When prohibited access to the method.
*/
public static void reloadProfileBans() throws IllegalAccessException, InvocationTargetException {
Object playerList = get(fields, craftServer, "playerList");
Object jsonList = invoke(RPlayerList.getMethods(), playerList, "getProfileBans");
public static void reloadProfileBans() {
Object playerList = reflection.get(Bukkit.getServer(), "playerList");
Object jsonList = RPlayerList.getReflection().invoke(playerList, "getProfileBans");
RJsonList.load(jsonList);
}
}

View file

@ -1,62 +1,36 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.bukkit.entities.BukkitReflection.MINOR;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke;
import static net.frankheijden.serverutils.common.reflection.VersionParam.min;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import net.frankheijden.serverutils.common.utils.MapUtils;
import org.bukkit.plugin.Plugin;
public class RCraftingManager {
private static Class<?> craftingManagerClass;
private static Map<String, Field> fields;
static {
try {
craftingManagerClass = Class.forName(String.format("net.minecraft.server.%s.CraftingManager",
BukkitReflection.NMS));
fields = getAllFields(craftingManagerClass,
fieldOf("recipes", min(12)));
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.CraftingManager");
/**
* Removes all associated recipes of a plugin.
* @param plugin The plugin to remove recipes for.
* @throws IllegalAccessException When prohibited access to the method.
* @throws InvocationTargetException If the method call produced an exception.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public static void removeRecipesFor(Plugin plugin) throws IllegalAccessException, InvocationTargetException {
public static void removeRecipesFor(Plugin plugin) {
// Cleaning up recipes before MC 1.12 is not possible,
// as recipes are not associated to plugins.
if (MINOR < 12) return;
Field recipesField = fields.get("recipes");
if (MINOR == 12) {
Object recipes = get(fields, null, "recipes");
RRegistryMaterials.removeKeysFor(recipes, plugin);
} else {
Object server = invoke(RMinecraftServer.getMethods(), null, "getServer");
Object craftingManager = invoke(RMinecraftServer.getMethods(), server, "getCraftingManager");
Map recipes = (Map) recipesField.get(craftingManager);
if (MinecraftReflectionVersion.MINOR == 12) {
RRegistryMaterials.removeKeysFor(reflection.get(null, "recipes"), plugin);
} else if (MinecraftReflectionVersion.MINOR > 12) {
Object server = RMinecraftServer.getReflection().invoke(null, "getServer");
Object craftingManager = RMinecraftServer.getReflection().invoke(server, "getCraftingManager");
Map recipes = reflection.get(craftingManager, "recipes");
Predicate<Object> predicate = RMinecraftKey.matchingPluginPredicate(new AtomicBoolean(false), plugin);
if (MINOR == 13) {
if (MinecraftReflectionVersion.MINOR == 13) {
MapUtils.removeKeys(recipes, predicate);
} else {
Collection<Map> list = (Collection<Map>) recipes.values();

View file

@ -1,122 +1,73 @@
package net.frankheijden.serverutils.bukkit.reflection;
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.MethodParam.methodOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
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.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.min;
import dev.frankheijden.minecraftreflection.ClassObject;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.Map;
import java.util.Properties;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import net.frankheijden.serverutils.common.reflection.VersionParam;
public class RDedicatedServer {
private static Class<?> dedicatedServerClass;
private static Map<String, Field> fields;
private static Map<String, Method> methods;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.DedicatedServer");
static {
try {
dedicatedServerClass = Class.forName(String.format("net.minecraft.server.%s.DedicatedServer",
BukkitReflection.NMS));
fields = getAllFields(dedicatedServerClass,
fieldOf("propertyManager"),
fieldOf("options"),
fieldOf("autosavePeriod"),
fieldOf("o", between(13, 15)));
methods = getAllMethods(dedicatedServerClass,
methodOf("setSpawnAnimals", max(15), boolean.class),
methodOf("getSpawnAnimals"),
methodOf("setPVP", boolean.class),
methodOf("getPVP"),
methodOf("setAllowFlight", boolean.class),
methodOf("getAllowFlight"),
methodOf("setMotd", String.class),
methodOf("getMotd"),
methodOf("setSpawnNPCs", max(15), boolean.class),
methodOf("setAllowFlight", boolean.class),
methodOf("setResourcePack", String.class, String.class),
methodOf("setForceGamemode", boolean.class),
methodOf("n", between(13, 15), boolean.class),
methodOf("aZ", max(15)),
methodOf("aZ", min(new VersionParam.Version(16, 2))),
methodOf("i", min(16), boolean.class),
methodOf("aY", exact(new VersionParam.Version(16, 1))),
methodOf("getCustomRegistry", min(new VersionParam.Version(16, 2))));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
public static Class<?> getClazz() {
return dedicatedServerClass;
}
public static Object getCustomRegistry(Object dedicatedServer) throws ReflectiveOperationException {
return invoke(methods, dedicatedServer, "getCustomRegistry");
}
public static Map<String, Field> getFields() {
return fields;
public static Object getCustomRegistry(Object dedicatedServer) {
return reflection.invoke(dedicatedServer, "getCustomRegistry");
}
/**
* Reloads the specified console (= DedicatedServer) instance's bukkit config.
* @param console The console to reload.
* @throws ReflectiveOperationException Iff exception thrown regarding reflection.
*/
public static void reload(Object console) throws ReflectiveOperationException {
Object options = get(fields, console, "options");
public static void reload(Object console) {
Object options = reflection.get(console, "options");
if (MINOR >= 13) {
if (MinecraftReflectionVersion.MINOR >= 13) {
Object propertyManager;
if (MINOR >= 16 && PATCH >= 2) {
propertyManager = RDedicatedServerSettings.newInstance(invoke(methods, console, "getCustomRegistry"),
if (MinecraftReflectionVersion.MINOR >= 16 && MinecraftReflectionVersion.PATCH >= 2) {
propertyManager = RDedicatedServerSettings.newInstance(reflection.invoke(console, "getCustomRegistry"),
options);
} else {
propertyManager = RDedicatedServerSettings.newInstance(options);
}
set(fields, console, "propertyManager", propertyManager);
Object config = invoke(RDedicatedServerSettings.getMethods(), propertyManager, "getProperties");
invoke(methods, console, "setPVP", getConfigValue(config, "pvp"));
invoke(methods, console, "setAllowFlight", getConfigValue(config, "allowFlight"));
invoke(methods, console, "setMotd", getConfigValue(config, "motd"));
invoke(methods, console, "setForceGamemode", getConfigValue(config, "forceGamemode"));
reflection.set(console, "propertyManager", propertyManager);
Object config = RDedicatedServerSettings.getReflection().invoke(propertyManager, "getProperties");
reflection.invoke(console, "setPVP", ClassObject.of(boolean.class, getConfigValue(config, "pvp")));
reflection.invoke(console, "setAllowFlight",
ClassObject.of(boolean.class, getConfigValue(config, "allowFlight")));
reflection.invoke(console, "setMotd", getConfigValue(config, "motd"));
reflection.invoke(console, "setForceGamemode",
ClassObject.of(boolean.class, getConfigValue(config, "forceGamemode")));
Object resourcePackHash;
if (MINOR <= 15 || (MINOR == 16 && PATCH == 1)) {
resourcePackHash = invoke(methods, console, "aZ");
if (MinecraftReflectionVersion.MINOR <= 15 || MinecraftReflectionVersion.is(16, 1)) {
resourcePackHash = reflection.invoke(console, "aZ");
} else if (MinecraftReflectionVersion.is(16, 3)) {
resourcePackHash = reflection.invoke(console, "ba");
} else {
resourcePackHash = invoke(methods, console, "aY");
resourcePackHash = reflection.invoke(console, "aY");
}
invoke(methods, console, "setResourcePack", getConfigValue(config, "resourcePack"), resourcePackHash);
reflection.invoke(console, "setResourcePack", getConfigValue(config, "resourcePack"), resourcePackHash);
if (MINOR <= 15) {
invoke(methods, console, "setSpawnAnimals", getConfigValue(config, "spawnAnimals"));
invoke(methods, console, "setSpawnNPCs", getConfigValue(config, "spawnNpcs"));
invoke(methods, console, "n", getConfigValue(config, "enforceWhitelist"));
set(fields, console, "o", getConfigValue(config, "gamemode"));
if (MinecraftReflectionVersion.MINOR <= 15) {
reflection.invoke(console, "setSpawnAnimals",
ClassObject.of(boolean.class, getConfigValue(config, "spawnAnimals")));
reflection.invoke(console, "setSpawnNPCs",
ClassObject.of(boolean.class, getConfigValue(config, "spawnNpcs")));
reflection.invoke(console, "n",
ClassObject.of(boolean.class, getConfigValue(config, "enforceWhitelist")));
reflection.set(console, "o", getConfigValue(config, "gamemode"));
} else {
invoke(methods, console, "i", getConfigValue(config, "enforceWhitelist"));
reflection.invoke(console, "i",
ClassObject.of(boolean.class, getConfigValue(config, "enforceWhitelist")));
}
} else {
Object config = RPropertyManager.newInstance(options);
@ -131,28 +82,28 @@ public class RDedicatedServer {
* Reloads server.properties.
* @throws ReflectiveOperationException Iff exception thrown regarding reflection.
*/
public static void reloadServerProperties() throws ReflectiveOperationException {
public static void reloadServerProperties() {
Object console = RCraftServer.getConsole();
Object playerList = get(RMinecraftServer.getFields(), console, "playerList");
Object propertyManager = get(fields, console, "propertyManager");
Object playerList = RMinecraftServer.getReflection().get(console, "playerList");
Object propertyManager = reflection.get(console, "propertyManager");
Path path = RDedicatedServerSettings.getServerPropertiesPath(propertyManager);
Properties properties = new Properties();
try (InputStream in = new FileInputStream(path.toFile())) {
properties.load(in);
} catch (IOException ex) {
throw new ReflectiveOperationException("Unable to load server.properties", ex);
throw new RuntimeException("Unable to load server.properties", ex);
}
int maxPlayers = Integer.parseInt(properties.getProperty("max-players"));
set(RPlayerList.getFields(), playerList, "maxPlayers", maxPlayers);
RPlayerList.getReflection().set(playerList, "maxPlayers", maxPlayers);
int viewDistance = Integer.parseInt(properties.getProperty("view-distance"));
RPlayerList.setViewDistance(playerList, viewDistance);
}
public static Object getConfigValue(Object config, String key) throws IllegalAccessException {
return get(RDedicatedServerProperties.getFields(), config, key);
public static Object getConfigValue(Object config, String key) {
return RDedicatedServerProperties.getReflection().get(config, key);
}
/**
@ -163,14 +114,11 @@ public class RDedicatedServer {
* @param setMethod The setter method for the config value.
* @param configMethod The method which we call the config value upon.
* @param key The config key.
* @throws InvocationTargetException If the method call produced an exception.
* @throws IllegalAccessException When prohibited access to the method.
*/
public static void setConfigValue(Object config, Object console, String getMethod, String setMethod,
String configMethod, String key)
throws InvocationTargetException, IllegalAccessException {
Object defaultValue = invoke(methods, console, getMethod);
Object configValue = invoke(RPropertyManager.getMethods(), config, configMethod, key, defaultValue);
invoke(methods, console, setMethod, configValue);
String configMethod, String key) {
Object defaultValue = reflection.invoke(console, getMethod);
Object configValue = RPropertyManager.getReflection().invoke(config, configMethod, key, defaultValue);
reflection.invoke(console, setMethod, configValue);
}
}

View file

@ -1,37 +1,13 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import java.lang.reflect.Field;
import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
public class RDedicatedServerProperties {
private static Class<?> serverPropertiesClass;
private static Map<String, Field> fields;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.DedicatedServerProperties");
static {
try {
serverPropertiesClass = Class.forName(String.format("net.minecraft.server.%s.DedicatedServerProperties",
BukkitReflection.NMS));
fields = getAllFields(serverPropertiesClass,
fieldOf("spawnAnimals"),
fieldOf("spawnNpcs"),
fieldOf("pvp"),
fieldOf("allowFlight"),
fieldOf("resourcePack"),
fieldOf("motd"),
fieldOf("forceGamemode"),
fieldOf("enforceWhitelist"),
fieldOf("gamemode"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static Map<String, Field> getFields() {
return fields;
public static MinecraftReflection getReflection() {
return reflection;
}
}

View file

@ -1,69 +1,33 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.ConstructorParam.constructorOf;
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.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllConstructors;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import dev.frankheijden.minecraftreflection.ClassObject;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
public class RDedicatedServerSettings {
private static Class<?> serverSettingsClass;
private static Map<String, Method> methods;
private static Map<String, Field> fields;
private static List<Constructor<?>> constructors;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.DedicatedServerSettings");
static {
try {
serverSettingsClass = Class.forName(String.format("net.minecraft.server.%s.DedicatedServerSettings",
BukkitReflection.NMS));
methods = getAllMethods(serverSettingsClass,
methodOf("getProperties"));
fields = getAllFields(serverSettingsClass,
fieldOf("path"));
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) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
public static Object newInstance(Object options) {
return reflection.newInstance(options);
}
/**
* Retrieves the default constructor.
* @return The default constructor of DedicatedServerSettings.
* @throws NoSuchMethodException If no constructor was found.
* Initiates a new instance of DedicatedServerSettings.
*/
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 registry, Object options) {
return reflection.newInstance(
ClassObject.of(RIRegistryCustom.getReflection().getClazz(), registry),
ClassObject.of(options)
);
}
public static Object newInstance(Object options) throws ReflectiveOperationException {
return getConstructor().newInstance(options);
}
public static Object newInstance(Object registry, Object options) throws ReflectiveOperationException {
return getConstructor().newInstance(registry, options);
}
public static Path getServerPropertiesPath(Object instance) throws ReflectiveOperationException {
return (Path) get(fields, instance, "path");
}
public static Map<String, Method> getMethods() {
return methods;
public static Path getServerPropertiesPath(Object instance) {
return reflection.get(instance, "path");
}
}

View file

@ -0,0 +1,13 @@
package net.frankheijden.serverutils.bukkit.reflection;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
public class RIRegistryCustom {
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.IRegistryCustom");
public static MinecraftReflection getReflection() {
return reflection;
}
}

View file

@ -1,59 +1,35 @@
package net.frankheijden.serverutils.bukkit.reflection;
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.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import java.io.Closeable;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import org.bukkit.plugin.java.JavaPlugin;
public class RJavaPlugin {
private static Class<?> javaPluginClass;
private static Map<String, Field> fields;
private static Map<String, Method> methods;
private static final MinecraftReflection reflection = MinecraftReflection.of(JavaPlugin.class);
static {
try {
javaPluginClass = JavaPlugin.class;
fields = getAllFields(javaPluginClass,
fieldOf("loader"),
fieldOf("classLoader"));
methods = getAllMethods(javaPluginClass,
methodOf("getClassLoader"),
methodOf("getClass"),
methodOf("getFile"));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
public static ClassLoader getClassLoader(Object instance) throws InvocationTargetException, IllegalAccessException {
return (ClassLoader) invoke(methods, instance, "getClassLoader");
public static ClassLoader getClassLoader(Object instance) {
return reflection.invoke(instance, "getClassLoader");
}
public static File getFile(Object instance) throws ReflectiveOperationException {
return (File) invoke(methods, instance, "getFile");
public static File getFile(Object instance) {
return reflection.invoke(instance, "getFile");
}
/**
* Clears the JavaPlugin from instances and returns the classloader associated with it.
* @param instance The instance of the JavaPlugin.
* @return The classloader associated with it.
* @throws ReflectiveOperationException When a reflection error occurred.
*/
public static Closeable clearJavaPlugin(Object instance) throws ReflectiveOperationException {
set(fields, instance, "loader", null);
set(fields, instance, "classLoader", null);
Class<?> clazz = (Class<?>) invoke(methods, instance, "getClass");
public static Closeable clearJavaPlugin(Object instance) {
reflection.set(instance, "loader", null);
reflection.set(instance, "classLoader", null);
Class<?> clazz = reflection.invoke(instance, "getClass");
if (clazz != null && clazz.getClassLoader() instanceof Closeable) {
return (Closeable) clazz.getClassLoader();
}

View file

@ -1,38 +1,25 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import java.lang.reflect.Field;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import java.util.Collection;
import java.util.Map;
import org.bukkit.plugin.java.JavaPluginLoader;
public class RJavaPluginLoader {
private static Class<?> javaPluginLoaderClass;
private static Map<String, Field> fields;
private static final MinecraftReflection reflection = MinecraftReflection.of(JavaPluginLoader.class);
static {
try {
javaPluginLoaderClass = JavaPluginLoader.class;
fields = getAllFields(javaPluginLoaderClass,
fieldOf("classes"));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
/**
* Removes the given classes from the JavaPluginLoader instance.
* @param instance The instance.
* @param list The list of classpaths.
* @throws IllegalAccessException When prohibited access to the method.
*/
@SuppressWarnings("unchecked")
public static void removeClasses(Object instance, Collection<? extends String> list) throws IllegalAccessException {
Map<String, Class<?>> classes = (Map<String, Class<?>>) get(fields, instance, "classes");
public static void removeClasses(Object instance, Collection<? extends String> list) {
Map<String, Class<?>> classes = reflection.get(instance, "classes");
if (classes == null) return;
for (String key : list) {

View file

@ -1,30 +1,16 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
public class RJsonList {
private static Class<?> jsonListClass;
private static Map<String, Method> methods;
private static final MinecraftReflection reflection = MinecraftReflection.of("net.minecraft.server.%s.JsonList");
static {
try {
jsonListClass = Class.forName(String.format("net.minecraft.server.%s.JsonList", BukkitReflection.NMS));
methods = getAllMethods(jsonListClass,
methodOf("load"));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
public static void load(Object jsonList) throws InvocationTargetException, IllegalAccessException {
invoke(methods, jsonList, "load");
public static void load(Object jsonList) {
reflection.invoke(jsonList, "load");
}
}

View file

@ -1,48 +1,31 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.bukkit.entities.BukkitReflection.MINOR;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.VersionParam.max;
import static net.frankheijden.serverutils.common.reflection.VersionParam.min;
import java.lang.reflect.Field;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import dev.frankheijden.minecraftreflection.MinecraftReflectionVersion;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import org.bukkit.plugin.Plugin;
public class RMinecraftKey {
private static Class<?> minecraftKeyClass;
private static Map<String, Field> fields;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.MinecraftKey");
static {
try {
minecraftKeyClass = Class.forName(String.format("net.minecraft.server.%s.MinecraftKey",
BukkitReflection.NMS));
fields = getAllFields(minecraftKeyClass,
fieldOf("a", max(13)),
fieldOf("namespace", min(14)));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
/**
* Retrieves the namespace of the specified MinecraftKey instance.
* @param instance The MinecraftKey instance.
* @return The namespace.
* @throws IllegalAccessException When prohibited access to the field.
*/
public static String getNameSpace(Object instance) throws IllegalAccessException {
if (MINOR <= 13) {
return (String) get(fields, instance, "a");
public static String getNameSpace(Object instance) {
if (MinecraftReflectionVersion.MINOR <= 13) {
return reflection.get(instance, "a");
}
return (String) get(fields, instance, "namespace");
return reflection.get(instance, "namespace");
}
public static boolean isFrom(Object instance, Plugin plugin) throws IllegalAccessException {

View file

@ -1,40 +1,13 @@
package net.frankheijden.serverutils.bukkit.reflection;
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.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
public class RMinecraftServer {
private static Class<?> minecraftServerClass;
private static Map<String, Method> methods;
private static Map<String, Field> fields;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.MinecraftServer");
static {
try {
minecraftServerClass = Class.forName(String.format("net.minecraft.server.%s.MinecraftServer",
BukkitReflection.NMS));
methods = getAllMethods(minecraftServerClass,
methodOf("getServer"),
methodOf("getCraftingManager"));
fields = getAllFields(minecraftServerClass,
fieldOf("playerList"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static Map<String, Method> getMethods() {
return methods;
}
public static Map<String, Field> getFields() {
return fields;
public static MinecraftReflection getReflection() {
return reflection;
}
}

View file

@ -1,27 +1,12 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import java.lang.reflect.Method;
import java.util.Map;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
public class ROptionSet {
private static Class<?> optionSetClass;
private static Map<String, Method> methods;
private static final MinecraftReflection reflection = MinecraftReflection.of("joptsimple.OptionSet");
static {
try {
optionSetClass = Class.forName("joptsimple.OptionSet");
methods = getAllMethods(optionSetClass,
methodOf("valueOf", String.class));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static Map<String, Method> getMethods() {
return methods;
public static MinecraftReflection getReflection() {
return reflection;
}
}

View file

@ -1,48 +1,19 @@
package net.frankheijden.serverutils.bukkit.reflection;
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.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.invoke;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import dev.frankheijden.minecraftreflection.ClassObject;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
public class RPlayerList {
private static Class<?> playerListClass;
private static Map<String, Method> methods;
private static Map<String, Field> fields;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.PlayerList");
static {
try {
playerListClass = Class.forName(String.format("net.minecraft.server.%s.PlayerList", BukkitReflection.NMS));
methods = getAllMethods(playerListClass,
methodOf("getIPBans"),
methodOf("getProfileBans"),
methodOf("a", int.class));
fields = getAllFields(playerListClass,
fieldOf("maxPlayers"),
fieldOf("viewDistance"));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
public static Map<String, Method> getMethods() {
return methods;
}
public static Map<String, Field> getFields() {
return fields;
}
public static void setViewDistance(Object instance, int viewDistance) throws ReflectiveOperationException {
set(fields, instance, "viewDistance", viewDistance);
invoke(methods, instance, "a", viewDistance);
public static void setViewDistance(Object instance, int viewDistance) {
reflection.set(instance, "viewDistance", viewDistance);
reflection.invoke(instance, "a", ClassObject.of(int.class, viewDistance));
}
}

View file

@ -1,42 +1,24 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.set;
import java.lang.reflect.Field;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import java.util.Map;
public class RPluginClassLoader {
private static Class<?> pluginClassLoaderClass;
private static Map<String, Field> fields;
private static final MinecraftReflection reflection = MinecraftReflection
.of("org.bukkit.plugin.java.PluginClassLoader");
static {
try {
pluginClassLoaderClass = Class.forName("org.bukkit.plugin.java.PluginClassLoader");
fields = getAllFields(pluginClassLoaderClass,
fieldOf("plugin"),
fieldOf("pluginInit"),
fieldOf("classes"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static boolean isInstance(Object obj) {
return pluginClassLoaderClass.isInstance(obj);
public static MinecraftReflection getReflection() {
return reflection;
}
/**
* Clears and closes the provided classloader.
* @param loader The classloader instance.
* @throws IllegalAccessException When prohibited access to the field.
*/
public static void clearClassLoader(ClassLoader loader) throws IllegalAccessException {
public static void clearClassLoader(ClassLoader loader) {
if (loader == null) return;
if (isInstance(loader)) {
if (reflection.getClazz().isInstance(loader)) {
clearPluginClassLoader(loader);
}
}
@ -44,16 +26,14 @@ public class RPluginClassLoader {
/**
* Clears the plugin fields from the specified PluginClassLoader.
* @param pluginLoader The plugin loader instance.
* @throws IllegalAccessException When prohibited access to the field.
*/
public static void clearPluginClassLoader(Object pluginLoader) throws IllegalAccessException {
public static void clearPluginClassLoader(Object pluginLoader) {
if (pluginLoader == null) return;
set(fields, pluginLoader, "plugin", null);
set(fields, pluginLoader, "pluginInit", null);
reflection.set(pluginLoader, "plugin", null);
reflection.set(pluginLoader, "pluginInit", null);
}
@SuppressWarnings("unchecked")
public static Map<String, Class<?>> getClasses(Object pluginLoader) throws IllegalAccessException {
return (Map<String, Class<?>>) get(fields, pluginLoader, "classes");
public static Map<String, Class<?>> getClasses(Object pluginLoader) {
return reflection.get(pluginLoader, "classes");
}
}

View file

@ -1,34 +1,17 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.MethodParam.methodOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllMethods;
import java.lang.reflect.Method;
import java.util.Map;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
public class RPropertyManager {
private static Class<?> propertyManagerClass;
private static Map<String, Method> methods;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.PropertyManager");
static {
try {
propertyManagerClass = Class.forName(String.format("net.minecraft.server.%s.PropertyManager",
BukkitReflection.NMS));
methods = getAllMethods(propertyManagerClass,
methodOf("getBoolean", String.class, boolean.class),
methodOf("getString", String.class, String.class));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
public static Object newInstance(Object options) throws ReflectiveOperationException {
return propertyManagerClass.getDeclaredConstructor(Class.forName("joptsimple.OptionSet")).newInstance(options);
}
public static Map<String, Method> getMethods() {
return methods;
public static Object newInstance(Object options) {
return ROptionSet.getReflection().newInstance(options);
}
}

View file

@ -1,42 +1,28 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import java.lang.reflect.Field;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import net.frankheijden.serverutils.common.utils.MapUtils;
import org.bukkit.plugin.Plugin;
public class RRegistryMaterials {
private static Class<?> registryMaterialsClass;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.RegistryMaterials");
private static Map<String, Field> fields;
static {
try {
registryMaterialsClass = Class.forName(String.format("net.minecraft.server.%s.RegistryMaterials",
BukkitReflection.NMS));
fields = getAllFields(registryMaterialsClass,
fieldOf("b"));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
/**
* Removes all registered keys from an instance associated to the specified plugin.
* @param instance The RegistryMaterials instance.
* @param plugin The plugin to remove keys for.
* @throws IllegalAccessException When prohibited access to the field.
*/
@SuppressWarnings("rawtypes")
public static void removeKeysFor(Object instance, Plugin plugin) throws IllegalAccessException {
Map map = (Map) get(fields, instance, "b");
public static void removeKeysFor(Object instance, Plugin plugin) {
Map map = reflection.get(instance, "b");
if (map == null) throw new RuntimeException("Map object was null!");
AtomicBoolean errorThrown = new AtomicBoolean(false);

View file

@ -1,41 +1,28 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import java.lang.reflect.Field;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import net.frankheijden.serverutils.bukkit.entities.BukkitReflection;
import net.frankheijden.serverutils.common.utils.MapUtils;
import org.bukkit.plugin.Plugin;
public class RRegistrySimple {
private static Class<?> registrySimpleClass;
private static Map<String, Field> fields;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.minecraft.server.%s.RegistrySimple");
static {
try {
registrySimpleClass = Class.forName(String.format("net.minecraft.server.%s.RegistrySimple",
BukkitReflection.NMS));
fields = getAllFields(registrySimpleClass,
fieldOf("c"));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
/**
* Removes all registered MinecraftKey's from an instance associated to the specified plugin.
* @param instance The RegistrySimple instance.
* @param plugin The plugin to remove keys for.
* @throws IllegalAccessException When prohibited access to the field.
*/
@SuppressWarnings("rawtypes")
public static void removeKeyFor(Object instance, Plugin plugin) throws IllegalAccessException {
Map map = (Map) get(fields, instance, "c");
public static void removeKeyFor(Object instance, Plugin plugin) {
Map map = reflection.get(instance, "c");
if (map == null) throw new RuntimeException("Map object was null!");
AtomicBoolean errorThrown = new AtomicBoolean(false);

View file

@ -1,10 +1,6 @@
package net.frankheijden.serverutils.bukkit.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import java.lang.reflect.Field;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -15,29 +11,18 @@ import org.bukkit.plugin.SimplePluginManager;
public class RSimplePluginManager {
private static Class<?> simplePluginManagerClass;
private static Map<String, Field> fields;
private static final MinecraftReflection reflection = MinecraftReflection.of(SimplePluginManager.class);
static {
try {
simplePluginManagerClass = SimplePluginManager.class;
fields = getAllFields(simplePluginManagerClass,
fieldOf("plugins"),
fieldOf("lookupNames"),
fieldOf("fileAssociations"));
} catch (Exception ex) {
ex.printStackTrace();
}
public static MinecraftReflection getReflection() {
return reflection;
}
@SuppressWarnings("unchecked")
public static Map<Pattern, PluginLoader> getFileAssociations(Object manager) throws IllegalAccessException {
return (Map<Pattern, PluginLoader>) get(fields, manager, "fileAssociations");
return reflection.get(manager, "fileAssociations");
}
@SuppressWarnings("unchecked")
public static List<Plugin> getPlugins(Object manager) throws IllegalAccessException {
return (List<Plugin>) get(fields, manager, "plugins");
public static List<Plugin> getPlugins(Object manager) {
return reflection.get(manager, "plugins");
}
/**
@ -45,11 +30,9 @@ public class RSimplePluginManager {
* This ensures the plugin cannot be found anymore in Bukkit#getPlugin(String name).
* @param manager The SimplePluginManager instance to remove the lookup name from.
* @param name The name of the plugin to remove.
* @throws IllegalAccessException When prohibited access to the field.
*/
@SuppressWarnings("unchecked")
public static void removeLookupName(Object manager, String name) throws IllegalAccessException {
Map<String, Plugin> lookupNames = (Map<String, Plugin>) get(fields, manager, "lookupNames");
public static void removeLookupName(Object manager, String name) {
Map<String, Plugin> lookupNames = reflection.get(manager, "lookupNames");
if (lookupNames == null) return;
lookupNames.remove(name.replace(' ', '_'));
lookupNames.remove(name.replace(' ', '_').toLowerCase(Locale.ENGLISH)); // Paper

View file

@ -6,7 +6,6 @@ import co.aikar.commands.CommandCompletions;
import net.frankheijden.serverutils.bungee.commands.CommandPlugins;
import net.frankheijden.serverutils.bungee.commands.CommandServerUtils;
import net.frankheijden.serverutils.bungee.entities.BungeePlugin;
import net.frankheijden.serverutils.bungee.entities.BungeeReflection;
import net.frankheijden.serverutils.bungee.listeners.BungeeListener;
import net.frankheijden.serverutils.bungee.managers.BungeePluginManager;
import net.frankheijden.serverutils.bungee.reflection.RPluginClassLoader;
@ -38,7 +37,6 @@ public class ServerUtils extends Plugin {
ServerUtilsApp.init(this, plugin);
new Metrics(this, ServerUtilsApp.BSTATS_METRICS_ID);
new BungeeReflection();
this.commandManager = new BungeeCommandManager(this);
commandManager.registerCommand(new CommandPlugins());

View file

@ -255,13 +255,7 @@ public class CommandServerUtils extends BaseCommand {
return;
}
Plugin plugin;
try {
plugin = RPluginManager.getPlugin(proxy.getPluginManager(), cmd);
} catch (IllegalAccessException ex) {
ex.printStackTrace();
return;
}
Plugin plugin = RPluginManager.getPlugin(proxy.getPluginManager(), cmd);
if (plugin == null) {
return;
}

View file

@ -1,12 +0,0 @@
package net.frankheijden.serverutils.bungee.entities;
import net.frankheijden.serverutils.common.reflection.ReflectionUtils;
import net.frankheijden.serverutils.common.reflection.VersionParam;
public class BungeeReflection extends ReflectionUtils {
@Override
public boolean isCompatible(VersionParam param) {
return true;
}
}

View file

@ -1,55 +1,33 @@
package net.frankheijden.serverutils.bungee.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Map;
import java.util.Set;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.PluginDescription;
public class RPluginClassLoader {
private static Class<?> loaderClass;
private static Map<String, Field> fields;
private static Constructor<?> constructor;
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.md_5.bungee.api.plugin.PluginClassloader");
static {
try {
loaderClass = Class.forName("net.md_5.bungee.api.plugin.PluginClassloader");
constructor = loaderClass.getDeclaredConstructor(ProxyServer.class, PluginDescription.class, URL[].class);
constructor.setAccessible(true);
fields = getAllFields(loaderClass,
fieldOf("allLoaders"),
fieldOf("plugin"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static Object newInstance(ProxyServer proxy, PluginDescription desc, URL... urls) throws Exception {
return constructor.newInstance(proxy, desc, urls);
public static Object newInstance(ProxyServer proxy, PluginDescription desc, URL... urls) {
return reflection.newInstance(proxy, desc, urls);
}
/**
* Retrieves the PluginClassLoader of a specific plugin.
* @param plugin The plugin to lookup the PluginClassLoader for.
* @return The PluginClassLoader.
* @throws ReflectiveOperationException Iff a reflection error occurred.
*/
@SuppressWarnings("unchecked")
public static Object getPluginClassLoader(Plugin plugin) throws ReflectiveOperationException {
Set<Object> allLoaders = (Set<Object>) get(fields, null, "allLoaders");
public static Object getPluginClassLoader(Plugin plugin) {
Set<Object> allLoaders = reflection.get(null, "allLoaders");
if (allLoaders == null) return null;
Object matchingLoader = null;
for (Object loader : allLoaders) {
if (plugin.equals(get(fields, loader, "plugin"))) {
if (plugin.equals(reflection.get(loader, "plugin"))) {
matchingLoader = loader;
break;
}

View file

@ -1,12 +1,8 @@
package net.frankheijden.serverutils.bungee.reflection;
import static net.frankheijden.serverutils.common.reflection.FieldParam.fieldOf;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.get;
import static net.frankheijden.serverutils.common.reflection.ReflectionUtils.getAllFields;
import com.google.common.collect.Multimap;
import java.lang.reflect.Field;
import java.util.Map;
import dev.frankheijden.minecraftreflection.MinecraftReflection;
import net.frankheijden.serverutils.common.utils.MapUtils;
import net.md_5.bungee.api.plugin.Command;
import net.md_5.bungee.api.plugin.Plugin;
@ -14,61 +10,40 @@ import org.yaml.snakeyaml.Yaml;
public class RPluginManager {
private static Class<?> pluginManagerClass;
private static Map<String, Field> fields;
static {
try {
pluginManagerClass = Class.forName("net.md_5.bungee.api.plugin.PluginManager");
fields = getAllFields(pluginManagerClass,
fieldOf("yaml"),
fieldOf("plugins"),
fieldOf("commandMap"),
fieldOf("toLoad"),
fieldOf("commandsByPlugin"));
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static final MinecraftReflection reflection = MinecraftReflection
.of("net.md_5.bungee.api.plugin.PluginManager");
/**
* Clears the plugin from the PluginManager.
* @param instance The instance of the PluginManager.
* @param plugin The plugin to clear.
* @throws ReflectiveOperationException Iff a reflection error happened.
*/
@SuppressWarnings("rawtypes")
public static void clearPlugin(Object instance, Plugin plugin) throws ReflectiveOperationException {
public static void clearPlugin(Object instance, Plugin plugin) {
String pluginName = plugin.getDescription().getName();
MapUtils.remove((Map) get(fields, instance, "plugins"), pluginName);
MapUtils.remove((Map) get(fields, instance, "toLoad"), pluginName);
MapUtils.remove(reflection.get(instance, "plugins"), pluginName);
MapUtils.remove(reflection.get(instance, "toLoad"), pluginName);
}
@SuppressWarnings("unchecked")
public static Map<String, Plugin> getPlugins(Object instance) throws ReflectiveOperationException {
return (Map<String, Plugin>) get(fields, instance, "plugins");
public static Map<String, Plugin> getPlugins(Object instance) {
return reflection.get(instance, "plugins");
}
public static Yaml getYaml(Object instance) throws IllegalAccessException {
return (Yaml) get(fields, instance, "yaml");
public static Yaml getYaml(Object instance) {
return reflection.get(instance, "yaml");
}
@SuppressWarnings("unchecked")
public static Map<String, Command> getCommands(Object instance) throws IllegalAccessException {
return (Map<String, Command>) get(fields, instance, "commandMap");
return reflection.get(instance, "commandMap");
}
/**
* Retrieves the registered plugin of the command.
* @param instance The PluginManager instance.
* @param cmd The command to check the plugin of.
* @return The plugin of the command
* @throws IllegalAccessException Iff some reflection error occurred.
* @return The plugin of the command.
*/
@SuppressWarnings("unchecked")
public static Plugin getPlugin(Object instance, Command cmd) throws IllegalAccessException {
Object obj = get(fields, instance, "commandsByPlugin");
Multimap<Plugin, Command> plugins = (Multimap<Plugin, Command>) obj;
public static Plugin getPlugin(Object instance, Command cmd) {
Multimap<Plugin, Command> plugins = reflection.get(instance, "commandsByPlugin");
if (plugins == null) return null;
for (Map.Entry<Plugin, Command> entry : plugins.entries()) {

View file

@ -1,14 +0,0 @@
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

@ -1,22 +0,0 @@
package net.frankheijden.serverutils.common.reflection;
import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VERSIONS;
public class FieldParam {
public final String field;
public final VersionParam versionParam;
private FieldParam(String field, VersionParam versionParam) {
this.field = field;
this.versionParam = versionParam;
}
public static FieldParam fieldOf(String field, VersionParam versionParam) {
return new FieldParam(field, versionParam);
}
public static FieldParam fieldOf(String field) {
return fieldOf(field, ALL_VERSIONS);
}
}

View file

@ -1,24 +0,0 @@
package net.frankheijden.serverutils.common.reflection;
import static net.frankheijden.serverutils.common.reflection.VersionParam.ALL_VERSIONS;
public class MethodParam {
public final String method;
public final VersionParam versionParam;
public final Class<?>[] params;
private MethodParam(String method, VersionParam versionParam, Class<?>... params) {
this.method = method;
this.versionParam = versionParam;
this.params = params;
}
public static MethodParam methodOf(String method, VersionParam versionParam, Class<?>... params) {
return new MethodParam(method, versionParam, params);
}
public static MethodParam methodOf(String method, Class<?>... params) {
return methodOf(method, ALL_VERSIONS, params);
}
}

View file

@ -1,193 +0,0 @@
package net.frankheijden.serverutils.common.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class ReflectionUtils {
private static ReflectionUtils instance;
public ReflectionUtils() {
instance = this;
}
public static ReflectionUtils getInstance() {
return instance;
}
public abstract boolean isCompatible(VersionParam param);
/**
* Retrieves a declared field from a class and makes it accessible.
* @param clazz The class of the method.
* @param field The field name.
* @return The specified field.
* @throws NoSuchFieldException iff field doesn't exist.
*/
public static Field getDeclaredField(Class<?> clazz, String field) throws NoSuchFieldException {
Field f = clazz.getDeclaredField(field);
f.setAccessible(true);
return f;
}
/**
* Retrieves a field from a class and makes it accessible.
* @param clazz The class of the method.
* @param field The field name.
* @return The specified field.
* @throws NoSuchFieldException iff field doesn't exist.
*/
public static Field getField(Class<?> clazz, String field) throws NoSuchFieldException {
Field f = clazz.getField(field);
f.setAccessible(true);
return f;
}
/**
* Retrieves a declared method from a class and makes it accessible.
* @param clazz The class of the method.
* @param method The method name.
* @param params The parameters of the method.
* @return The specified method.
* @throws NoSuchMethodException iff method doesn't exist.
*/
public static Method getDeclaredMethod(Class<?> clazz, String method, Class<?>... params)
throws NoSuchMethodException {
Method m = clazz.getDeclaredMethod(method, params);
m.setAccessible(true);
return m;
}
/**
* Retrieves a method from a class and makes it accessible.
* @param clazz The class of the method.
* @param method The method name.
* @param params The parameters of the method.
* @return The specified method.
* @throws NoSuchMethodException iff method doesn't exist.
*/
public static Method getMethod(Class<?> clazz, String method, Class<?>... params)
throws NoSuchMethodException {
Method m = clazz.getMethod(method, params);
m.setAccessible(true);
return m;
}
/**
* Retrieves fields from a class based on the specified FieldParams.
* @param clazz The class of the fields.
* @param fieldParams The fields which will be collected.
* @return A map with key the field name and value the actual field.
*/
public static Map<String, Field> getAllFields(Class<?> clazz, FieldParam... fieldParams) {
Map<String, Field> map = new HashMap<>();
for (FieldParam fieldParam : fieldParams) {
if (!getInstance().isCompatible(fieldParam.versionParam)) continue;
try {
map.put(fieldParam.field, getDeclaredField(clazz, fieldParam.field));
} catch (NoSuchFieldException ignored) {
try {
map.put(fieldParam.field, getField(clazz, fieldParam.field));
} catch (NoSuchFieldException ex) {
ex.printStackTrace();
}
}
}
return map;
}
/**
* Retrieves methods from a class based on the specified MethodParams.
* @param clazz The class of the methods.
* @param methodParams The methods which will be collected.
* @return A map with key the method name and value the actual method.
*/
public static Map<String, Method> getAllMethods(Class<?> clazz, MethodParam... methodParams) {
Map<String, Method> map = new HashMap<>();
for (MethodParam methodParam : methodParams) {
if (!getInstance().isCompatible(methodParam.versionParam)) continue;
try {
map.put(methodParam.method, getDeclaredMethod(clazz, methodParam.method, methodParam.params));
} catch (NoSuchMethodException ignored) {
try {
map.put(methodParam.method, getMethod(clazz, methodParam.method, methodParam.params));
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
}
}
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.
* Will return null if method not present in map.
* @param map The map with methods.
* @param instance The instance of the class.
* @param methodName The name of the method.
* @param params The parameters of the method.
* @return The object returned by the method, or null if not present in map.
* @throws InvocationTargetException If the method call produced an exception.
* @throws IllegalAccessException When prohibited access to the method.
*/
public static Object invoke(Map<String, Method> map, Object instance, String methodName, Object... params)
throws InvocationTargetException, IllegalAccessException {
Method method = map.get(methodName);
if (method == null) return null;
return method.invoke(instance, params);
}
/**
* Retrieves the specified field from an object instance.
* Returns null if the field is not in the map.
* @param map The map with fields.
* @param instance The instance of the class.
* @param fieldName The field name.
* @throws IllegalAccessException When prohibited access to the field.
*/
public static Object get(Map<String, Field> map, Object instance, String fieldName) throws IllegalAccessException {
Field field = map.get(fieldName);
if (field == null) return null;
return field.get(instance);
}
/**
* Sets the specified field to the specified value.
* Will silently fail if the field is not in the map.
* @param map The map with fields.
* @param instance The instance of the class.
* @param fieldName The field name.
* @param value The value to set the field to.
* @throws IllegalAccessException When prohibited access to the field.
*/
public static void set(Map<String, Field> map, Object instance, String fieldName, Object value)
throws IllegalAccessException {
Field field = map.get(fieldName);
if (field == null) return;
field.set(instance, value);
}
}

View file

@ -1,74 +0,0 @@
package net.frankheijden.serverutils.common.reflection;
public class VersionParam {
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 final Version min;
public final Version 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.max = max;
}
public static VersionParam exact(int minor) {
return new VersionParam(minor, minor);
}
public static VersionParam exact(Version ver) {
return new VersionParam(ver, ver);
}
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);
}
public static VersionParam min(int minMinor) {
return between(minMinor, Integer.MAX_VALUE);
}
public static VersionParam min(Version min) {
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;
}
}
}

View file

@ -4,6 +4,7 @@ plugins {
}
group = 'net.frankheijden.serverutils'
String dependencyDir = group + '.dependencies'
version = '2.2.4-DEV'
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
@ -17,11 +18,14 @@ subprojects {
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url 'https://repo.aikar.co/content/groups/aikar/' }
maven { url 'https://papermc.io/repo/repository/maven-public/' }
}
dependencies {
implementation 'com.github.FrankHeijden:MinecraftReflection:1.0.0'
testCompile 'org.assertj:assertj-core:3.18.1'
testCompile 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testCompile 'org.junit.jupiter:junit-jupiter-params:5.7.0'
@ -60,4 +64,8 @@ dependencies {
implementation project(path: ':Bungee', configuration: 'shadow')
}
shadowJar {
relocate 'dev.frankheijden.minecraftreflection', dependencyDir + '.minecraftreflection'
}
build.dependsOn shadowJar