+ * Note: This will completely override current item's {@link ItemMeta}.
+ * If you still want to keep the original item's NBT tags, see
+ * {@link #mergeNBT(ItemStack)} and {@link #mergeCustomNBT(ItemStack)}.
+ *
+ * @param item ItemStack that should get the new NBT data
+ */
+ public void applyNBT(ItemStack item) {
+ if (item == null || item.getType() == Material.AIR) {
+ throw new NullPointerException("ItemStack can't be null/Air!");
+ }
+ NBTItem nbti = new NBTItem(new ItemStack(item.getType()));
+ nbti.mergeCompound(this);
+ item.setItemMeta(nbti.getItem().getItemMeta());
+ }
+
+ /**
+ * Merge all NBT tags to the provided ItemStack.
+ *
+ * @param item ItemStack that should get the new NBT data
+ */
+ public void mergeNBT(ItemStack item) {
+ NBTItem nbti = new NBTItem(item);
+ nbti.mergeCompound(this);
+ item.setItemMeta(nbti.getItem().getItemMeta());
+ }
+
+ /**
+ * Merge only custom (non-vanilla) NBT tags to the provided ItemStack.
+ *
+ * @param item ItemStack that should get the new NBT data
+ */
+ public void mergeCustomNBT(ItemStack item) {
+ if (item == null || item.getType() == Material.AIR) {
+ throw new NullPointerException("ItemStack can't be null/Air!");
+ }
+ ItemMeta meta = item.getItemMeta();
+ NBTReflectionUtil.getUnhandledNBTTags(meta).putAll(NBTReflectionUtil.getUnhandledNBTTags(bukkitItem.getItemMeta()));
+ item.setItemMeta(meta);
+ }
+
+ /**
+ * Remove all custom (non-vanilla) NBT tags from the NBTItem.
+ */
+ public void clearCustomNBT() {
+ ItemMeta meta = bukkitItem.getItemMeta();
+ NBTReflectionUtil.getUnhandledNBTTags(meta).clear();
+ bukkitItem.setItemMeta(meta);
+ }
+
/**
* @return The modified ItemStack
*/
@@ -83,4 +155,11 @@ public class NBTItem extends NBTCompound {
NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp));
}
+ @Override
+ protected void saveCompound() {
+ if(directApply) {
+ applyNBT(originalSrcStack);
+ }
+ }
+
}
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java
index 0eeafd9..a7f152f 100644
--- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java
@@ -31,14 +31,14 @@ public abstract class NBTList
- * Check out https://bStats.org/ to learn more about bStats!
- *
- * This class is modified by tr7zw to work when the api is shaded into other peoples plugins.
- */
-public class ApiMetricsLite {
-
- private static final String PLUGINNAME = "ItemNBTAPI"; // DO NOT CHANGE THE NAME! else it won't link the data on bStats
- private static final String PLUGINVERSION = "2.2.0-SNAPSHOT"; // In case you fork the nbt-api for internal use in your network, plugins and so on, you *may* add that to the version here. (2.x.x-Timolia or something like that?)
- // Not sure how good of an idea that is, so maybe just leave it as is ¯\_(ツ)_/¯
-
- // The version of this bStats class
- public static final int B_STATS_VERSION = 1;
-
- // The version of the NBT-Api bStats
- public static final int NBT_BSTATS_VERSION = 1;
-
- // The url to which the data is sent
- private static final String URL = "https://bStats.org/submitData/bukkit";
-
- // Is bStats enabled on this server?
- private boolean enabled;
-
- // Should failed requests be logged?
- private static boolean logFailedRequests;
-
- // Should the sent data be logged?
- private static boolean logSentData;
-
- // Should the response text be logged?
- private static boolean logResponseStatusText;
-
- // The uuid of the server
- private static String serverUUID;
-
- // The plugin
- private Plugin plugin;
-
- /**
- * Class constructor.
- *
- */
- public ApiMetricsLite() {
-
- // The register method just uses any enabled plugin it can find to register. This *shouldn't* cause any problems, since the plugin isn't used any other way.
- // Register our service
- for(Plugin plug : Bukkit.getPluginManager().getPlugins()) {
- plugin = plug;
- if(plugin != null)
- break;
- }
- if(plugin == null) {
- return;// Didn't find any plugin that could work
- }
-
- // Get the config file
- File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
- File configFile = new File(bStatsFolder, "config.yml");
- YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
-
- // Check if the config file exists
- if (!config.isSet("serverUuid")) {
-
- // Add default values
- config.addDefault("enabled", true);
- // Every server gets it's unique random id.
- config.addDefault("serverUuid", UUID.randomUUID().toString());
- // Should failed request be logged?
- config.addDefault("logFailedRequests", false);
- // Should the sent data be logged?
- config.addDefault("logSentData", false);
- // Should the response text be logged?
- config.addDefault("logResponseStatusText", false);
-
- // Inform the server owners about bStats
- config.options().header(
- "bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
- "To honor their work, you should not disable it.\n" +
- "This has nearly no effect on the server performance!\n" +
- "Check out https://bStats.org/ to learn more :)"
- ).copyDefaults(true);
- try {
- config.save(configFile);
- } catch (IOException ignored) { }
- }
-
- // Load the data
- serverUUID = config.getString("serverUuid");
- logFailedRequests = config.getBoolean("logFailedRequests", false);
- enabled = config.getBoolean("enabled", true);
- logSentData = config.getBoolean("logSentData", false);
- logResponseStatusText = config.getBoolean("logResponseStatusText", false);
- if (enabled) {
- boolean found = false;
- // Search for all other bStats Metrics classes to see if we are the first one
- for (Class> service : Bukkit.getServicesManager().getKnownServices()) {
- try {
- service.getField("NBT_BSTATS_VERSION"); // Create only one instance of the nbt-api bstats.
- return;
- } catch (NoSuchFieldException ignored) { }
- try {
- service.getField("B_STATS_VERSION"); // Our identifier :)
- found = true; // We aren't the first
- break;
- } catch (NoSuchFieldException ignored) { }
- }
- // Register our service
- Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal);
- if (!found) {
- logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
- // We are the first!
- startSubmitting();
- }
- }
- }
-
- /**
- * Checks if bStats is enabled.
- *
- * @return Whether bStats is enabled or not.
- */
- public boolean isEnabled() {
- return enabled;
- }
-
- /**
- * Starts the Scheduler which submits our data every 30 minutes.
- */
- private void startSubmitting() {
- final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
- timer.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- if (!plugin.isEnabled()) { // Plugin was disabled
- timer.cancel();
- return;
- }
- // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
- // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
- Bukkit.getScheduler().runTask(plugin, () -> submitData());
- }
- }, 1000l * 60l * 5l, 1000l * 60l * 30l);
- // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
- // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
- // WARNING: Just don't do it!
- }
-
- /**
- * Gets the plugin specific data.
- * This method is called using Reflection.
- *
- * @return The plugin specific data.
- */
- public JsonObject getPluginData() {
- JsonObject data = new JsonObject();
-
- data.addProperty("pluginName", PLUGINNAME); // Append the name of the plugin
- data.addProperty("pluginVersion", PLUGINVERSION); // Append the version of the plugin
- data.add("customCharts", new JsonArray());
-
- return data;
- }
-
- /**
- * Gets the server specific data.
- *
- * @return The server specific data.
- */
- private JsonObject getServerData() {
- // Minecraft specific data
- int playerAmount;
- try {
- // Around MC 1.8 the return type was changed to a collection from an array,
- // This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
- Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
- playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
- ? ((Collection>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
- : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
- } catch (Exception e) {
- playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
- }
- int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
- String bukkitVersion = Bukkit.getVersion();
- String bukkitName = Bukkit.getName();
-
- // OS/Java specific data
- String javaVersion = System.getProperty("java.version");
- String osName = System.getProperty("os.name");
- String osArch = System.getProperty("os.arch");
- String osVersion = System.getProperty("os.version");
- int coreCount = Runtime.getRuntime().availableProcessors();
-
- JsonObject data = new JsonObject();
-
- data.addProperty("serverUUID", serverUUID);
-
- data.addProperty("playerAmount", playerAmount);
- data.addProperty("onlineMode", onlineMode);
- data.addProperty("bukkitVersion", bukkitVersion);
- data.addProperty("bukkitName", bukkitName);
-
- data.addProperty("javaVersion", javaVersion);
- data.addProperty("osName", osName);
- data.addProperty("osArch", osArch);
- data.addProperty("osVersion", osVersion);
- data.addProperty("coreCount", coreCount);
-
- return data;
- }
-
- /**
- * Collects the data and sends it afterwards.
- */
- private void submitData() {
- final JsonObject data = getServerData();
-
- JsonArray pluginData = new JsonArray();
- // Search for all other bStats Metrics classes to get their plugin data
- for (Class> service : Bukkit.getServicesManager().getKnownServices()) {
- try {
- service.getField("B_STATS_VERSION"); // Our identifier :)
-
- for (RegisteredServiceProvider> provider : Bukkit.getServicesManager().getRegistrations(service)) {
- try {
- Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
- if (plugin instanceof JsonObject) {
- pluginData.add((JsonObject) plugin);
- } else { // old bstats version compatibility
- try {
- Class> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
- if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
- Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
- jsonStringGetter.setAccessible(true);
- String jsonString = (String) jsonStringGetter.invoke(plugin);
- JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
- pluginData.add(object);
- }
- } catch (ClassNotFoundException e) {
- // minecraft version 1.14+
- if (logFailedRequests) {
- logger.log(Level.WARNING, "[NBTAPI][BSTATS] Encountered exception while posting request!", e);
- // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
- //this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
- }
- continue; // continue looping since we cannot do any other thing.
- }
- }
- } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
- }
- }
- } catch (NoSuchFieldException ignored) { }
- }
-
- data.add("plugins", pluginData);
-
- // Create a new thread for the connection to the bStats server
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- // Send the data
- sendData(plugin, data);
- } catch (Exception e) {
- // Something went wrong! :(
- if (logFailedRequests) {
- logger.log(Level.WARNING, "[NBTAPI][BSTATS] Could not submit plugin stats of " + plugin.getName(), e);
- // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
- //plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
- }
- }
- }
- }).start();
- }
-
- /**
- * Sends the data to the bStats server.
- *
- * @param plugin Any plugin. It's just used to get a logger instance.
- * @param data The data to send.
- * @throws Exception If the request failed.
- */
- private static void sendData(Plugin plugin, JsonObject data) throws Exception {
- if (data == null) {
- throw new IllegalArgumentException("Data cannot be null!");
- }
- if (Bukkit.isPrimaryThread()) {
- throw new IllegalAccessException("This method must not be called from the main thread!");
- }
- if (logSentData) {
- System.out.println("[NBTAPI][BSTATS] Sending data to bStats: " + data.toString());
- // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
- //plugin.getLogger().info("Sending data to bStats: " + data.toString());
- }
- HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
-
- // Compress the data to save bandwidth
- byte[] compressedData = compress(data.toString());
-
- // Add headers
- connection.setRequestMethod("POST");
- connection.addRequestProperty("Accept", "application/json");
- connection.addRequestProperty("Connection", "close");
- connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
- connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
- connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
- connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
-
- // Send data
- connection.setDoOutput(true);
- DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
- outputStream.write(compressedData);
- outputStream.flush();
- outputStream.close();
-
- InputStream inputStream = connection.getInputStream();
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
-
- StringBuilder builder = new StringBuilder();
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- builder.append(line);
- }
- bufferedReader.close();
- if (logResponseStatusText) {
- logger.info("[NBTAPI][BSTATS] Sent data to bStats and received response: " + builder.toString());
- // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
- //plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
- }
- }
-
- /**
- * Gzips the given String.
- *
- * @param str The string to gzip.
- * @return The gzipped String.
- * @throws IOException If the compression failed.
- */
- private static byte[] compress(final String str) throws IOException {
- if (str == null) {
- return new byte[0];
- }
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
- gzip.write(str.getBytes(StandardCharsets.UTF_8));
- gzip.close();
- return outputStream.toByteArray();
- }
-
-}
+package com.songoda.epicenchants.utils.itemnbtapi.utils;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.bukkit.Bukkit;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.RegisteredServiceProvider;
+import org.bukkit.plugin.ServicePriority;
+
+import javax.net.ssl.HttpsURLConnection;
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.UUID;
+import java.util.logging.Level;
+import java.util.zip.GZIPOutputStream;
+import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.logger;
+
+/**
+ * bStats collects some data for plugin authors.
+ *
+ * Check out https://bStats.org/ to learn more about bStats!
+ *
+ * This class is modified by tr7zw to work when the api is shaded into other peoples plugins.
+ */
+public class ApiMetricsLite {
+
+ private static final String PLUGINNAME = "ItemNBTAPI"; // DO NOT CHANGE THE NAME! else it won't link the data on bStats
+
+ // The version of this bStats class
+ public static final int B_STATS_VERSION = 1;
+
+ // The version of the NBT-Api bStats
+ public static final int NBT_BSTATS_VERSION = 1;
+
+ // The url to which the data is sent
+ private static final String URL = "https://bStats.org/submitData/bukkit";
+
+ // Is bStats enabled on this server?
+ private boolean enabled;
+
+ // Should failed requests be logged?
+ private static boolean logFailedRequests;
+
+ // Should the sent data be logged?
+ private static boolean logSentData;
+
+ // Should the response text be logged?
+ private static boolean logResponseStatusText;
+
+ // The uuid of the server
+ private static String serverUUID;
+
+ // The plugin
+ private Plugin plugin;
+
+ /**
+ * Class constructor.
+ *
+ */
+ public ApiMetricsLite() {
+
+ // The register method just uses any enabled plugin it can find to register. This *shouldn't* cause any problems, since the plugin isn't used any other way.
+ // Register our service
+ for(Plugin plug : Bukkit.getPluginManager().getPlugins()) {
+ plugin = plug;
+ if(plugin != null)
+ break;
+ }
+ if(plugin == null) {
+ return;// Didn't find any plugin that could work
+ }
+
+ // Get the config file
+ File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
+ File configFile = new File(bStatsFolder, "config.yml");
+ YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile);
+
+ // Check if the config file exists
+ if (!config.isSet("serverUuid")) {
+
+ // Add default values
+ config.addDefault("enabled", true);
+ // Every server gets it's unique random id.
+ config.addDefault("serverUuid", UUID.randomUUID().toString());
+ // Should failed request be logged?
+ config.addDefault("logFailedRequests", false);
+ // Should the sent data be logged?
+ config.addDefault("logSentData", false);
+ // Should the response text be logged?
+ config.addDefault("logResponseStatusText", false);
+
+ // Inform the server owners about bStats
+ config.options().header(
+ "bStats collects some data for plugin authors like how many servers are using their plugins.\n" +
+ "To honor their work, you should not disable it.\n" +
+ "This has nearly no effect on the server performance!\n" +
+ "Check out https://bStats.org/ to learn more :)"
+ ).copyDefaults(true);
+ try {
+ config.save(configFile);
+ } catch (IOException ignored) { }
+ }
+
+ // Load the data
+ serverUUID = config.getString("serverUuid");
+ logFailedRequests = config.getBoolean("logFailedRequests", false);
+ enabled = config.getBoolean("enabled", true);
+ logSentData = config.getBoolean("logSentData", false);
+ logResponseStatusText = config.getBoolean("logResponseStatusText", false);
+ if (enabled) {
+ boolean found = false;
+ // Search for all other bStats Metrics classes to see if we are the first one
+ for (Class> service : Bukkit.getServicesManager().getKnownServices()) {
+ try {
+ service.getField("NBT_BSTATS_VERSION"); // Create only one instance of the nbt-api bstats.
+ return;
+ } catch (NoSuchFieldException ignored) { }
+ try {
+ service.getField("B_STATS_VERSION"); // Our identifier :)
+ found = true; // We aren't the first
+ break;
+ } catch (NoSuchFieldException ignored) { }
+ }
+ boolean fFound = found;
+ // Register our service
+ if(Bukkit.isPrimaryThread()){
+ Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal);
+ if (!fFound) {
+ logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
+ // We are the first!
+ startSubmitting();
+ }
+ }else{
+ Bukkit.getScheduler().runTask(plugin, () -> {
+ Bukkit.getServicesManager().register(ApiMetricsLite.class, this, plugin, ServicePriority.Normal);
+ if (!fFound) {
+ logger.info("[NBTAPI] Using the plugin '" + plugin.getName() + "' to create a bStats instance!");
+ // We are the first!
+ startSubmitting();
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Checks if bStats is enabled.
+ *
+ * @return Whether bStats is enabled or not.
+ */
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ /**
+ * Starts the Scheduler which submits our data every 30 minutes.
+ */
+ private void startSubmitting() {
+ final Timer timer = new Timer(true); // We use a timer cause the Bukkit scheduler is affected by server lags
+ timer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ if (!plugin.isEnabled()) { // Plugin was disabled
+ timer.cancel();
+ return;
+ }
+ // Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
+ // Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
+ Bukkit.getScheduler().runTask(plugin, () -> submitData());
+ }
+ }, 1000l * 60l * 5l, 1000l * 60l * 30l);
+ // Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
+ // WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
+ // WARNING: Just don't do it!
+ }
+
+ /**
+ * Gets the plugin specific data.
+ * This method is called using Reflection.
+ *
+ * @return The plugin specific data.
+ */
+ public JsonObject getPluginData() {
+ JsonObject data = new JsonObject();
+
+ data.addProperty("pluginName", PLUGINNAME); // Append the name of the plugin
+ data.addProperty("pluginVersion", MinecraftVersion.VERSION); // Append the version of the plugin
+ data.add("customCharts", new JsonArray());
+
+ return data;
+ }
+
+ /**
+ * Gets the server specific data.
+ *
+ * @return The server specific data.
+ */
+ private JsonObject getServerData() {
+ // Minecraft specific data
+ int playerAmount;
+ try {
+ // Around MC 1.8 the return type was changed to a collection from an array,
+ // This fixes java.lang.NoSuchMethodError: org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection;
+ Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers");
+ playerAmount = onlinePlayersMethod.getReturnType().equals(Collection.class)
+ ? ((Collection>) onlinePlayersMethod.invoke(Bukkit.getServer())).size()
+ : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length;
+ } catch (Exception e) {
+ playerAmount = Bukkit.getOnlinePlayers().size(); // Just use the new method if the Reflection failed
+ }
+ int onlineMode = Bukkit.getOnlineMode() ? 1 : 0;
+ String bukkitVersion = Bukkit.getVersion();
+ String bukkitName = Bukkit.getName();
+
+ // OS/Java specific data
+ String javaVersion = System.getProperty("java.version");
+ String osName = System.getProperty("os.name");
+ String osArch = System.getProperty("os.arch");
+ String osVersion = System.getProperty("os.version");
+ int coreCount = Runtime.getRuntime().availableProcessors();
+
+ JsonObject data = new JsonObject();
+
+ data.addProperty("serverUUID", serverUUID);
+
+ data.addProperty("playerAmount", playerAmount);
+ data.addProperty("onlineMode", onlineMode);
+ data.addProperty("bukkitVersion", bukkitVersion);
+ data.addProperty("bukkitName", bukkitName);
+
+ data.addProperty("javaVersion", javaVersion);
+ data.addProperty("osName", osName);
+ data.addProperty("osArch", osArch);
+ data.addProperty("osVersion", osVersion);
+ data.addProperty("coreCount", coreCount);
+
+ return data;
+ }
+
+ /**
+ * Collects the data and sends it afterwards.
+ */
+ private void submitData() {
+ final JsonObject data = getServerData();
+
+ JsonArray pluginData = new JsonArray();
+ // Search for all other bStats Metrics classes to get their plugin data
+ for (Class> service : Bukkit.getServicesManager().getKnownServices()) {
+ try {
+ service.getField("B_STATS_VERSION"); // Our identifier :)
+
+ for (RegisteredServiceProvider> provider : Bukkit.getServicesManager().getRegistrations(service)) {
+ try {
+ Object plugin = provider.getService().getMethod("getPluginData").invoke(provider.getProvider());
+ if (plugin instanceof JsonObject) {
+ pluginData.add((JsonObject) plugin);
+ } else { // old bstats version compatibility
+ try {
+ Class> jsonObjectJsonSimple = Class.forName("org.json.simple.JSONObject");
+ if (plugin.getClass().isAssignableFrom(jsonObjectJsonSimple)) {
+ Method jsonStringGetter = jsonObjectJsonSimple.getDeclaredMethod("toJSONString");
+ jsonStringGetter.setAccessible(true);
+ String jsonString = (String) jsonStringGetter.invoke(plugin);
+ JsonObject object = new JsonParser().parse(jsonString).getAsJsonObject();
+ pluginData.add(object);
+ }
+ } catch (ClassNotFoundException e) {
+ // minecraft version 1.14+
+ if (logFailedRequests) {
+ logger.log(Level.WARNING, "[NBTAPI][BSTATS] Encountered exception while posting request!", e);
+ // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
+ //this.plugin.getLogger().log(Level.SEVERE, "Encountered unexpected exception ", e);
+ }
+ continue; // continue looping since we cannot do any other thing.
+ }
+ }
+ } catch (NullPointerException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {
+ }
+ }
+ } catch (NoSuchFieldException ignored) { }
+ }
+
+ data.add("plugins", pluginData);
+
+ // Create a new thread for the connection to the bStats server
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // Send the data
+ sendData(plugin, data);
+ } catch (Exception e) {
+ // Something went wrong! :(
+ if (logFailedRequests) {
+ logger.log(Level.WARNING, "[NBTAPI][BSTATS] Could not submit plugin stats of " + plugin.getName(), e);
+ // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
+ //plugin.getLogger().log(Level.WARNING, "Could not submit plugin stats of " + plugin.getName(), e);
+ }
+ }
+ }
+ }).start();
+ }
+
+ /**
+ * Sends the data to the bStats server.
+ *
+ * @param plugin Any plugin. It's just used to get a logger instance.
+ * @param data The data to send.
+ * @throws Exception If the request failed.
+ */
+ private static void sendData(Plugin plugin, JsonObject data) throws Exception {
+ if (data == null) {
+ throw new IllegalArgumentException("Data cannot be null!");
+ }
+ if (Bukkit.isPrimaryThread()) {
+ throw new IllegalAccessException("This method must not be called from the main thread!");
+ }
+ if (logSentData) {
+ System.out.println("[NBTAPI][BSTATS] Sending data to bStats: " + data.toString());
+ // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
+ //plugin.getLogger().info("Sending data to bStats: " + data.toString());
+ }
+ HttpsURLConnection connection = (HttpsURLConnection) new URL(URL).openConnection();
+
+ // Compress the data to save bandwidth
+ byte[] compressedData = compress(data.toString());
+
+ // Add headers
+ connection.setRequestMethod("POST");
+ connection.addRequestProperty("Accept", "application/json");
+ connection.addRequestProperty("Connection", "close");
+ connection.addRequestProperty("Content-Encoding", "gzip"); // We gzip our request
+ connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
+ connection.setRequestProperty("Content-Type", "application/json"); // We send our data in JSON format
+ connection.setRequestProperty("User-Agent", "MC-Server/" + B_STATS_VERSION);
+
+ // Send data
+ connection.setDoOutput(true);
+ DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
+ outputStream.write(compressedData);
+ outputStream.flush();
+ outputStream.close();
+
+ InputStream inputStream = connection.getInputStream();
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+
+ StringBuilder builder = new StringBuilder();
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ builder.append(line);
+ }
+ bufferedReader.close();
+ if (logResponseStatusText) {
+ logger.info("[NBTAPI][BSTATS] Sent data to bStats and received response: " + builder.toString());
+ // Not using the plugins logger since the plugin isn't the plugin containing the NBT-Api most of the time
+ //plugin.getLogger().info("Sent data to bStats and received response: " + builder.toString());
+ }
+ }
+
+ /**
+ * Gzips the given String.
+ *
+ * @param str The string to gzip.
+ * @return The gzipped String.
+ * @throws IOException If the compression failed.
+ */
+ private static byte[] compress(final String str) throws IOException {
+ if (str == null) {
+ return new byte[0];
+ }
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ GZIPOutputStream gzip = new GZIPOutputStream(outputStream);
+ gzip.write(str.getBytes(StandardCharsets.UTF_8));
+ gzip.close();
+ return outputStream.toByteArray();
+ }
+
+}
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/MinecraftVersion.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/MinecraftVersion.java
index 46fbcb9..adccdfc 100644
--- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/MinecraftVersion.java
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/MinecraftVersion.java
@@ -16,27 +16,22 @@ import org.bukkit.Bukkit;
@SuppressWarnings("javadoc")
public enum MinecraftVersion {
UNKNOWN(Integer.MAX_VALUE), // Use the newest known mappings
- MC1_7_R4(174),
- MC1_8_R3(183),
- MC1_9_R1(191),
- MC1_9_R2(192),
- MC1_10_R1(1101),
- MC1_11_R1(1111),
- MC1_12_R1(1121),
- MC1_13_R1(1131),
- MC1_13_R2(1132),
- MC1_14_R1(1141),
- MC1_15_R1(1151);
+ MC1_7_R4(174), MC1_8_R3(183), MC1_9_R1(191), MC1_9_R2(192), MC1_10_R1(1101), MC1_11_R1(1111), MC1_12_R1(1121),
+ MC1_13_R1(1131), MC1_13_R2(1132), MC1_14_R1(1141), MC1_15_R1(1151), MC1_16_R1(1161);
private static MinecraftVersion version;
private static Boolean hasGsonSupport;
private static boolean bStatsDisabled = false;
private static boolean disablePackageWarning = false;
+ private static boolean updateCheckDisabled = false;
/**
* Logger used by the api
*/
public static final Logger logger = Logger.getLogger("NBTAPI");
+ // NBT-API Version
+ protected static final String VERSION = "2.5.0-SNAPSHOT";
+
private final int versionId;
MinecraftVersion(int versionId) {
@@ -49,6 +44,16 @@ public enum MinecraftVersion {
public int getVersionId() {
return versionId;
}
+
+ /**
+ * Returns true if the current versions is at least the given Version
+ *
+ * @param version The minimum version
+ * @return
+ */
+ public static boolean isAtLeastVersion(MinecraftVersion version) {
+ return getVersion().getVersionId() >= version.getVersionId();
+ }
/**
* Getter for this servers MinecraftVersion. Also init's bStats and checks the
@@ -78,11 +83,20 @@ public enum MinecraftVersion {
private static void init() {
try {
- if (!bStatsDisabled)
+ if (hasGsonSupport() && !bStatsDisabled)
new ApiMetricsLite();
} catch (Exception ex) {
- logger.log(Level.WARNING, "[NBTAPI] Error enabeling Metrics!", ex);
+ logger.log(Level.WARNING, "[NBTAPI] Error enabling Metrics!", ex);
}
+
+ if (hasGsonSupport() && !updateCheckDisabled)
+ new Thread(() -> {
+ try {
+ VersionChecker.checkForUpdates();
+ } catch (Exception ex) {
+ logger.log(Level.WARNING, "[NBTAPI] Error while checking for updates!", ex);
+ }
+ }).start();
// Maven's Relocate is clever and changes strings, too. So we have to use this
// little "trick" ... :D (from bStats)
final String defaultPackage = new String(new byte[] { 'd', 'e', '.', 't', 'r', '7', 'z', 'w', '.', 'c', 'h',
@@ -128,6 +142,14 @@ public enum MinecraftVersion {
bStatsDisabled = true;
}
+ /**
+ * Disables the update check. Uses Spiget to get the current version and prints
+ * a warning when outdated.
+ */
+ public static void disableUpdateCheck() {
+ updateCheckDisabled = true;
+ }
+
/**
* Forcefully disables the log message for plugins not shading the API to
* another location. This may be helpful for networks or development
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/VersionChecker.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/VersionChecker.java
new file mode 100644
index 0000000..2c97002
--- /dev/null
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/VersionChecker.java
@@ -0,0 +1,106 @@
+package com.songoda.epicenchants.utils.itemnbtapi.utils;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.logging.Level;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import com.songoda.epicenchants.utils.itemnbtapi.NBTItem;
+
+/**
+ * This class uses the Spiget API to check for updates
+ *
+ */
+public class VersionChecker {
+
+ private static final String USER_AGENT = "nbt-api Version check";
+ private static final String REQUEST_URL = "https://api.spiget.org/v2/resources/7939/versions?size=100";
+
+ protected static void checkForUpdates() throws Exception {
+ URL url = new URL(REQUEST_URL);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.addRequestProperty("User-Agent", USER_AGENT);// Set
+ // User-Agent
+
+ // If you're not sure if the request will be successful,
+ // you need to check the response code and use #getErrorStream if it
+ // returned an error code
+ InputStream inputStream = connection.getInputStream();
+ InputStreamReader reader = new InputStreamReader(inputStream);
+
+ // This could be either a JsonArray or JsonObject
+ JsonElement element = new JsonParser().parse(reader);
+ if (element.isJsonArray()) {
+ // Is JsonArray
+ JsonArray updates = (JsonArray) element;
+ JsonObject latest = (JsonObject) updates.get(updates.size() - 1);
+ int versionDifference = getVersionDifference(latest.get("name").getAsString());
+ if (versionDifference == -1) { // Outdated
+ MinecraftVersion.logger.log(Level.WARNING,
+ "[NBTAPI] The NBT-API at '" + NBTItem.class.getPackage() + "' seems to be outdated!");
+ MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] Current Version: '" + MinecraftVersion.VERSION
+ + "' Newest Version: " + latest.get("name").getAsString() + "'");
+ MinecraftVersion.logger.log(Level.WARNING,
+ "[NBTAPI] Please update the nbt-api or the plugin that contains the api!");
+
+ } else if (versionDifference == 0) {
+ MinecraftVersion.logger.log(Level.INFO, "[NBTAPI] The NBT-API seems to be up-to-date!");
+ } else if (versionDifference == 1) {
+ MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] The NBT-API at '" + NBTItem.class.getPackage()
+ + "' seems to be a future Version, not yet released on Spigot!");
+ MinecraftVersion.logger.log(Level.WARNING, "[NBTAPI] Current Version: '" + MinecraftVersion.VERSION
+ + "' Newest Version: " + latest.get("name").getAsString() + "'");
+ }
+ } else {
+ // wut?!
+ MinecraftVersion.logger.log(Level.WARNING,
+ "[NBTAPI] Error when looking for Updates! Got non Json Array: '" + element.toString() + "'");
+ }
+ }
+
+ // -1 = we are outdated
+ // 0 = up to date
+ // 1 = using a future version
+ // This method is only able to compare the Format 0.0.0(-SNAPSHOT)
+ private static int getVersionDifference(String version) {
+ String current = MinecraftVersion.VERSION;
+ if (current.equals(version))
+ return 0;
+ String pattern = "\\.";
+ if (current.split(pattern).length != 3 || version.split(pattern).length != 3)
+ return -1;
+ int curMaj = Integer.parseInt(current.split(pattern)[0]);
+ int curMin = Integer.parseInt(current.split(pattern)[1]);
+ String curPatch = current.split(pattern)[2];
+ int relMaj = Integer.parseInt(version.split(pattern)[0]);
+ int relMin = Integer.parseInt(version.split(pattern)[1]);
+ String relPatch = version.split(pattern)[2];
+ if (curMaj < relMaj)
+ return -1;
+ if (curMaj > relMaj)
+ return 1;
+ if (curMin < relMin)
+ return -1;
+ if (curMin > relMin)
+ return 1;
+ int curPatchN = Integer.parseInt(curPatch.split("-")[0]);
+ int relPatchN = Integer.parseInt(relPatch.split("-")[0]);
+ if (curPatchN < relPatchN)
+ return -1;
+ if (curPatchN > relPatchN)
+ return 1;
+ if (!relPatch.contains("-") && curPatch.contains("-"))
+ return -1; // Release has no - but we do = We use a Snapshot of the
+ // release
+ if (relPatch.contains("-") && curPatch.contains("-"))
+ return 0; // Release and cur are Snapshots/alpha/beta
+ return 1;
+ }
+
+}
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/AvaliableSince.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/AvaliableSince.java
new file mode 100644
index 0000000..a9a6676
--- /dev/null
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/AvaliableSince.java
@@ -0,0 +1,17 @@
+package com.songoda.epicenchants.utils.itemnbtapi.utils.annotations;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
+
+@Retention(RUNTIME)
+@Target({ METHOD })
+public @interface AvaliableSince {
+
+ MinecraftVersion version();
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/CheckUtil.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/CheckUtil.java
new file mode 100644
index 0000000..aa40d8d
--- /dev/null
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/annotations/CheckUtil.java
@@ -0,0 +1,16 @@
+package com.songoda.epicenchants.utils.itemnbtapi.utils.annotations;
+
+import java.lang.reflect.Method;
+
+import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException;
+import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
+
+public class CheckUtil {
+
+ public static boolean isAvaliable(Method method) {
+ if(MinecraftVersion.getVersion().getVersionId() < method.getAnnotation(AvaliableSince.class).version().getVersionId())
+ throw new NbtApiException("The Method '" + method.getName() + "' is only avaliable for the Versions " + method.getAnnotation(AvaliableSince.class).version() + "+, but still got called!");
+ return true;
+ }
+
+}
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java
index 3aa04c3..0cb10e9 100644
--- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java
@@ -15,18 +15,22 @@ import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.l
@SuppressWarnings("javadoc")
public enum ClassWrapper {
CRAFT_ITEMSTACK(PackageWrapper.CRAFTBUKKIT, "inventory.CraftItemStack"),
+CRAFT_METAITEM(PackageWrapper.CRAFTBUKKIT, "inventory.CraftMetaItem"),
CRAFT_ENTITY(PackageWrapper.CRAFTBUKKIT, "entity.CraftEntity"),
CRAFT_WORLD(PackageWrapper.CRAFTBUKKIT, "CraftWorld"),
NMS_NBTBASE(PackageWrapper.NMS, "NBTBase"),
NMS_NBTTAGSTRING(PackageWrapper.NMS, "NBTTagString"),
NMS_NBTTAGINT(PackageWrapper.NMS, "NBTTagInt"),
+NMS_NBTTAGFLOAT(PackageWrapper.NMS, "NBTTagFloat"),
+NMS_NBTTAGDOUBLE(PackageWrapper.NMS, "NBTTagDouble"),
+NMS_NBTTAGLONG(PackageWrapper.NMS, "NBTTagLong"),
NMS_ITEMSTACK(PackageWrapper.NMS, "ItemStack"),
NMS_NBTTAGCOMPOUND(PackageWrapper.NMS, "NBTTagCompound"),
NMS_NBTTAGLIST(PackageWrapper.NMS, "NBTTagList"),
NMS_NBTCOMPRESSEDSTREAMTOOLS(PackageWrapper.NMS, "NBTCompressedStreamTools"),
NMS_MOJANGSONPARSER(PackageWrapper.NMS, "MojangsonParser"),
NMS_TILEENTITY(PackageWrapper.NMS, "TileEntity"),
-NMS_BLOCKPOSITION(PackageWrapper.NMS, "BlockPosition"),
+NMS_BLOCKPOSITION(PackageWrapper.NMS, "BlockPosition", MinecraftVersion.MC1_8_R3, null),
NMS_WORLDSERVER(PackageWrapper.NMS, "WorldServer"),
NMS_MINECRAFTSERVER(PackageWrapper.NMS, "MinecraftServer"),
NMS_WORLD(PackageWrapper.NMS, "World"),
@@ -35,7 +39,11 @@ NMS_ENTITYTYPES(PackageWrapper.NMS, "EntityTypes"),
NMS_REGISTRYSIMPLE(PackageWrapper.NMS, "RegistrySimple", MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_12_R1),
NMS_REGISTRYMATERIALS(PackageWrapper.NMS, "RegistryMaterials"),
NMS_IREGISTRY(PackageWrapper.NMS, "IRegistry"),
-NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey");
+NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey", MinecraftVersion.MC1_8_R3, null),
+NMS_GAMEPROFILESERIALIZER(PackageWrapper.NMS, "GameProfileSerializer"),
+NMS_IBLOCKDATA(PackageWrapper.NMS, "IBlockData", MinecraftVersion.MC1_8_R3, null),
+GAMEPROFILE("com.mojang.authlib.GameProfile", MinecraftVersion.MC1_8_R3)
+;
private Class> clazz;
private boolean enabled = false;
@@ -60,6 +68,18 @@ NMS_MINECRAFTKEY(PackageWrapper.NMS, "MinecraftKey");
}
}
+ ClassWrapper(String path, MinecraftVersion from){
+ if(from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId()) {
+ return;
+ }
+ enabled = true;
+ try{
+ clazz = Class.forName(path);
+ }catch(Exception ex){
+ logger.log(Level.WARNING, "[NBTAPI] Error while trying to resolve the class '" + path + "'!", ex);
+ }
+ }
+
/**
* @return The wrapped class
*/
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java
index 8c68fc0..307ea34 100644
--- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java
@@ -16,40 +16,41 @@ import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.l
*/
@SuppressWarnings("javadoc")
public enum ObjectCreator {
- NMS_NBTTAGCOMPOUND(null, null, ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),
- NMS_BLOCKPOSITION(null, null, ClassWrapper.NMS_BLOCKPOSITION.getClazz(), int.class, int.class, int.class),
- NMS_COMPOUNDFROMITEM(MinecraftVersion.MC1_11_R1, null, ClassWrapper.NMS_ITEMSTACK.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),
- ;
+ NMS_NBTTAGCOMPOUND(null, null, ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),
+ NMS_BLOCKPOSITION(null, null, ClassWrapper.NMS_BLOCKPOSITION.getClazz(), int.class, int.class, int.class),
+ NMS_COMPOUNDFROMITEM(MinecraftVersion.MC1_11_R1, null, ClassWrapper.NMS_ITEMSTACK.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()),;
- private Constructor> construct;
- private Class> targetClass;
+ private Constructor> construct;
+ private Class> targetClass;
+
+ ObjectCreator(MinecraftVersion from, MinecraftVersion to, Class> clazz, Class>... args) {
+ if (clazz == null)
+ return;
+ if (from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId())
+ return;
+ if (to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId())
+ return;
+ try {
+ this.targetClass = clazz;
+ construct = clazz.getDeclaredConstructor(args);
+ construct.setAccessible(true);
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, "Unable to find the constructor for the class '" + clazz.getName() + "'", ex);
+ }
+ }
+
+ /**
+ * Creates an Object instance with given args
+ *
+ * @param args
+ * @return Object created
+ */
+ public Object getInstance(Object... args) {
+ try {
+ return construct.newInstance(args);
+ } catch (Exception ex) {
+ throw new NbtApiException("Exception while creating a new instance of '" + targetClass + "'", ex);
+ }
+ }
- ObjectCreator(MinecraftVersion from, MinecraftVersion to, Class> clazz, Class>... args){
- if(from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId())
- return;
- if(to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId())
- return;
- try{
- this.targetClass = clazz;
- construct = clazz.getDeclaredConstructor(args);
- construct.setAccessible(true);
- }catch(Exception ex){
- logger.log(Level.SEVERE, "Unable to find the constructor for the class '" + clazz.getName() + "'", ex);
- }
- }
-
- /**
- * Creates an Object instance with given args
- *
- * @param args
- * @return Object created
- */
- public Object getInstance(Object... args){
- try{
- return construct.newInstance(args);
- }catch(Exception ex){
- throw new NbtApiException("Exception while creating a new instance of '" + targetClass + "'", ex);
- }
- }
-
}
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java
index 12d78c8..bc3f301 100644
--- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java
@@ -8,13 +8,13 @@ package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings;
*/
@SuppressWarnings("javadoc")
public enum PackageWrapper {
- NMS("net.minecraft.server"),
- CRAFTBUKKIT("org.bukkit.craftbukkit"),
+ NMS(new String(new byte[] {'n', 'e', 't', '.', 'm', 'i', 'n', 'e', 'c', 'r', 'a', 'f', 't', '.', 's', 'e', 'r', 'v', 'e', 'r'})),
+ CRAFTBUKKIT(new String(new byte[] {'o', 'r', 'g', '.', 'b', 'u', 'k', 'k', 'i', 't', '.', 'c', 'r', 'a', 'f', 't', 'b', 'u', 'k', 'k', 'i', 't'})),
;
private final String uri;
- PackageWrapper(String uri) {
+ private PackageWrapper(String uri) {
this.uri = uri;
}
diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java
index 29ff274..6c767b4 100644
--- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java
+++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java
@@ -1,182 +1,192 @@
-package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.reflect.Method;
-import org.bukkit.inventory.ItemStack;
-
-import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException;
-import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
-
-/**
- * This class caches method reflections, keeps track of method name changes between versions and allows early checking for problems
- *
- * @author tr7zw
- *
- */
-@SuppressWarnings("javadoc")
-public enum ReflectionMethod {
-
- COMPOUND_SET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, float.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setFloat")),
- COMPOUND_SET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setString")),
- COMPOUND_SET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setInt")),
- COMPOUND_SET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte[].class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByteArray")),
- COMPOUND_SET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int[].class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setIntArray")),
- COMPOUND_SET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, long.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setLong")),
- COMPOUND_SET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, short.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setShort")),
- COMPOUND_SET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByte")),
- COMPOUND_SET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, double.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setDouble")),
- COMPOUND_SET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, boolean.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setBoolean")),
- COMPOUND_MERGE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
- COMPOUND_SET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "set")),
- COMPOUND_GET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")),
- COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getList")),
-
- COMPOUND_GET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getFloat")),
- COMPOUND_GET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")),
- COMPOUND_GET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getInt")),
- COMPOUND_GET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByteArray")),
- COMPOUND_GET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getIntArray")),
- COMPOUND_GET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getLong")),
- COMPOUND_GET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getShort")),
- COMPOUND_GET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByte")),
- COMPOUND_GET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getDouble")),
- COMPOUND_GET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getBoolean")),
- COMPOUND_GET_COMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getCompound")),
-
- NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTag")),
- NMSITEM_SAVE(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "save")),
- NMSITEM_CREATESTACK(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_10_R1, new Since(MinecraftVersion.MC1_7_R4, "createStack")),
-
- COMPOUND_REMOVE_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "remove")),
- COMPOUND_HAS_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "hasKey")),
- COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d"), new Since(MinecraftVersion.MC1_15_R1, "e")), //FIXME: No Spigot mapping!
- COMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")),
-
- LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")),
- LIST_REMOVE_KEY(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a"), new Since(MinecraftVersion.MC1_9_R1, "remove")),
- LIST_SIZE(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "size")),
- LIST_SET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a"), new Since(MinecraftVersion.MC1_13_R1, "set")),
- LEGACY_LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_7_R4, "add")),
- LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_14_R1, new Since(MinecraftVersion.MC1_14_R1, "add")),
- LIST_GET_STRING(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")),
- LIST_GET_COMPOUND(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")),
- LIST_GET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "g"), new Since(MinecraftVersion.MC1_9_R1, "h"), new Since(MinecraftVersion.MC1_12_R1, "i"), new Since(MinecraftVersion.MC1_13_R1, "get")),
-
- ITEMSTACK_SET_TAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTag")),
- ITEMSTACK_NMSCOPY(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ItemStack.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asNMSCopy")),
- ITEMSTACK_BUKKITMIRROR(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_ITEMSTACK.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asCraftMirror")),
-
- CRAFT_WORLD_GET_HANDLE(ClassWrapper.CRAFT_WORLD.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
- NMS_WORLD_GET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")),
- NMS_WORLD_SET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz(), ClassWrapper.NMS_TILEENTITY.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTileEntity")),
- NMS_WORLD_REMOVE_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "t"), new Since(MinecraftVersion.MC1_9_R1, "s"), new Since(MinecraftVersion.MC1_13_R1, "n"), new Since(MinecraftVersion.MC1_14_R1, "removeTileEntity")),
-
- TILEENTITY_LOAD_LEGACY191(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTSERVER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_9_R1, MinecraftVersion.MC1_9_R1, new Since(MinecraftVersion.MC1_9_R1, "a")), //FIXME: No Spigot mapping!
- TILEENTITY_LOAD_LEGACY183(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_9_R2, new Since(MinecraftVersion.MC1_8_R3, "c"), new Since(MinecraftVersion.MC1_9_R1, "a"), new Since(MinecraftVersion.MC1_9_R2, "c")), //FIXME: No Spigot mapping!
- TILEENTITY_LOAD_LEGACY1121(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_WORLD.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_10_R1, MinecraftVersion.MC1_12_R1, new Since(MinecraftVersion.MC1_10_R1, "a"), new Since(MinecraftVersion.MC1_12_R1, "create")),
- TILEENTITY_LOAD(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_12_R1, "create")),
-
- TILEENTITY_GET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "save")),
- TILEENTITY_SET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_12_R1, "load")),
-
- CRAFT_ENTITY_GET_HANDLE(ClassWrapper.CRAFT_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
- NMS_ENTITY_SET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "f")), //FIXME: No Spigot mapping!
- NMS_ENTITY_GET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "e"), new Since(MinecraftVersion.MC1_12_R1, "save")),
- NMS_ENTITY_GETSAVEID(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_14_R1,new Since(MinecraftVersion.MC1_14_R1, "getSaveID")),
-
- NBTFILE_READ(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{InputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
- NBTFILE_WRITE(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), OutputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
-
-
- PARSE_NBT(ClassWrapper.NMS_MOJANGSONPARSER.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "parse")),
- REGISTRY_KEYSET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "keySet")),
- REGISTRY_GET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "get")),
- REGISTRY_SET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class, Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "a")), //FIXME: No Spigot mapping!
- REGISTRY_GET_INVERSE (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")), //FIXME: No Spigot mapping!
- REGISTRYMATERIALS_KEYSET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "keySet")),
- REGISTRYMATERIALS_GET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTKEY.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "get")),
-
-
- ;
-
- private MinecraftVersion removedAfter;
- private Since targetVersion;
- private Method method;
- private boolean loaded = false;
- private boolean compatible = false;
- private String methodName = null;
-
- ReflectionMethod(Class> targetClass, Class>[] args, MinecraftVersion addedSince, MinecraftVersion removedAfter, Since... methodnames){
- this.removedAfter = removedAfter;
- MinecraftVersion server = MinecraftVersion.getVersion();
- if(server.compareTo(addedSince) < 0 || (this.removedAfter != null && server.getVersionId() > this.removedAfter.getVersionId()))return;
- compatible = true;
- Since target = methodnames[0];
- for(Since s : methodnames){
- if(s.version.getVersionId() <= server.getVersionId() && target.version.getVersionId() < s.version.getVersionId())
- target = s;
- }
- targetVersion = target;
- try{
- method = targetClass.getMethod(targetVersion.name, args);
- method.setAccessible(true);
- loaded = true;
- methodName = targetVersion.name;
- }catch(NullPointerException | NoSuchMethodException | SecurityException ex){
- System.out.println("[NBTAPI] Unable to find the method '" + targetVersion.name + "' in '" + targetClass.getSimpleName() + "' Enum: " + this); //NOSONAR This gets loaded before the logger is loaded
- }
- }
-
- ReflectionMethod(Class> targetClass, Class>[] args, MinecraftVersion addedSince, Since... methodnames){
- this(targetClass, args, addedSince, null, methodnames);
- }
-
- /**
- * Runs the method on a given target object using the given args.
- *
- * @param target
- * @param args
- * @return Value returned by the method
- */
- public Object run(Object target, Object... args){
- if(method == null)
- throw new NbtApiException("Method not loaded! '" + this + "'");
- try{
- return method.invoke(target, args);
- }catch(Exception ex){
- throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded + ", Enum: " + this, ex);
- }
- }
-
- /**
- * @return The MethodName, used in this Minecraft Version
- */
- public String getMethodName() {
- return methodName;
- }
-
- /**
- * @return Has this method been linked
- */
- public boolean isLoaded() {
- return loaded;
- }
-
- /**
- * @return Is this method available in this Minecraft Version
- */
- public boolean isCompatible() {
- return compatible;
- }
-
- protected static class Since{
- public final MinecraftVersion version;
- public final String name;
- public Since(MinecraftVersion version, String name) {
- this.version = version;
- this.name = name;
- }
- }
-
-}
+package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.util.UUID;
+
+import org.bukkit.inventory.ItemStack;
+
+import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException;
+import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion;
+
+/**
+ * This class caches method reflections, keeps track of method name changes between versions and allows early checking for problems
+ *
+ * @author tr7zw
+ *
+ */
+@SuppressWarnings("javadoc")
+public enum ReflectionMethod {
+
+ COMPOUND_SET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, float.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setFloat")),
+ COMPOUND_SET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setString")),
+ COMPOUND_SET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setInt")),
+ COMPOUND_SET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte[].class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByteArray")),
+ COMPOUND_SET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int[].class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setIntArray")),
+ COMPOUND_SET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, long.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setLong")),
+ COMPOUND_SET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, short.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setShort")),
+ COMPOUND_SET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, byte.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setByte")),
+ COMPOUND_SET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, double.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setDouble")),
+ COMPOUND_SET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, boolean.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setBoolean")),
+ COMPOUND_SET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, UUID.class}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a")),
+ COMPOUND_MERGE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a")), //FIXME: No Spigot mapping!
+ COMPOUND_SET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "set")),
+ COMPOUND_GET(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")),
+ COMPOUND_GET_LIST(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class, int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getList")),
+ COMPOUND_OWN_TYPE(ClassWrapper.NMS_NBTBASE.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTypeId")), // Only needed for 1.7.10 getType
+
+ COMPOUND_GET_FLOAT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getFloat")),
+ COMPOUND_GET_STRING(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")),
+ COMPOUND_GET_INT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getInt")),
+ COMPOUND_GET_BYTEARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByteArray")),
+ COMPOUND_GET_INTARRAY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getIntArray")),
+ COMPOUND_GET_LONG(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getLong")),
+ COMPOUND_GET_SHORT(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getShort")),
+ COMPOUND_GET_BYTE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getByte")),
+ COMPOUND_GET_DOUBLE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getDouble")),
+ COMPOUND_GET_BOOLEAN(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getBoolean")),
+ COMPOUND_GET_UUID(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "a")),
+ COMPOUND_GET_COMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getCompound")),
+
+ NMSITEM_GETTAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTag")),
+ NMSITEM_SAVE(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "save")),
+ NMSITEM_CREATESTACK(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[] {ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_10_R1, new Since(MinecraftVersion.MC1_7_R4, "createStack")),
+
+ COMPOUND_REMOVE_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "remove")),
+ COMPOUND_HAS_KEY(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "hasKey")),
+ COMPOUND_GET_TYPE(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "b"), new Since(MinecraftVersion.MC1_9_R1, "d"), new Since(MinecraftVersion.MC1_15_R1, "e"), new Since(MinecraftVersion.MC1_16_R1, "d")), //FIXME: No Spigot mapping!
+ COMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")),
+
+ LISTCOMPOUND_GET_KEYS(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "c"), new Since(MinecraftVersion.MC1_13_R1, "getKeys")),
+ LIST_REMOVE_KEY(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_9_R1, "remove")),
+ LIST_SIZE(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "size")),
+ LIST_SET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "a"), new Since(MinecraftVersion.MC1_13_R1, "set")),
+ LEGACY_LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_7_R4, "add")),
+ LIST_ADD(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class, ClassWrapper.NMS_NBTBASE.getClazz()}, MinecraftVersion.MC1_14_R1, new Since(MinecraftVersion.MC1_14_R1, "add")),
+ LIST_GET_STRING(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getString")),
+ LIST_GET_COMPOUND(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")),
+ LIST_GET(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get"), new Since(MinecraftVersion.MC1_8_R3, "g"), new Since(MinecraftVersion.MC1_9_R1, "h"), new Since(MinecraftVersion.MC1_12_R1, "i"), new Since(MinecraftVersion.MC1_13_R1, "get")),
+
+ ITEMSTACK_SET_TAG(ClassWrapper.NMS_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "setTag")),
+ ITEMSTACK_NMSCOPY(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ItemStack.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asNMSCopy")),
+ ITEMSTACK_BUKKITMIRROR(ClassWrapper.CRAFT_ITEMSTACK.getClazz(), new Class[]{ClassWrapper.NMS_ITEMSTACK.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "asCraftMirror")),
+
+ CRAFT_WORLD_GET_HANDLE(ClassWrapper.CRAFT_WORLD.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
+ NMS_WORLD_GET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "getTileEntity")),
+ NMS_WORLD_SET_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz(), ClassWrapper.NMS_TILEENTITY.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "setTileEntity")),
+ NMS_WORLD_REMOVE_TILEENTITY(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "t"), new Since(MinecraftVersion.MC1_9_R1, "s"), new Since(MinecraftVersion.MC1_13_R1, "n"), new Since(MinecraftVersion.MC1_14_R1, "removeTileEntity")),
+
+ NMS_WORLD_GET_TILEENTITY_1_7_10(ClassWrapper.NMS_WORLDSERVER.getClazz(), new Class[]{int.class, int.class, int.class}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")),
+
+ TILEENTITY_LOAD_LEGACY191(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTSERVER.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_9_R1, MinecraftVersion.MC1_9_R1, new Since(MinecraftVersion.MC1_9_R1, "a")), //FIXME: No Spigot mapping!
+ TILEENTITY_LOAD_LEGACY183(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_8_R3, MinecraftVersion.MC1_9_R2, new Since(MinecraftVersion.MC1_8_R3, "c"), new Since(MinecraftVersion.MC1_9_R1, "a"), new Since(MinecraftVersion.MC1_9_R2, "c")), //FIXME: No Spigot mapping!
+ TILEENTITY_LOAD_LEGACY1121(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_WORLD.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_10_R1, MinecraftVersion.MC1_12_R1, new Since(MinecraftVersion.MC1_10_R1, "a"), new Since(MinecraftVersion.MC1_12_R1, "create")),
+ TILEENTITY_LOAD_LEGACY1151(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_13_R1, MinecraftVersion.MC1_15_R1, new Since(MinecraftVersion.MC1_12_R1, "create")),
+ TILEENTITY_LOAD(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_IBLOCKDATA.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "create")),
+
+ TILEENTITY_GET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "b"), new Since(MinecraftVersion.MC1_9_R1, "save")),
+ TILEENTITY_SET_NBT_LEGACY1151(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, MinecraftVersion.MC1_15_R1, new Since(MinecraftVersion.MC1_7_R4, "a"), new Since(MinecraftVersion.MC1_12_R1, "load")),
+ TILEENTITY_SET_NBT(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{ClassWrapper.NMS_IBLOCKDATA.getClazz(), ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "load")),
+ TILEENTITY_GET_BLOCKDATA(ClassWrapper.NMS_TILEENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_16_R1, new Since(MinecraftVersion.MC1_16_R1, "getBlock")),
+
+ CRAFT_ENTITY_GET_HANDLE(ClassWrapper.CRAFT_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getHandle")),
+ NMS_ENTITY_SET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "f"), new Since(MinecraftVersion.MC1_16_R1, "load")), //FIXME: No Spigot mapping!
+ NMS_ENTITY_GET_NBT(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "e"), new Since(MinecraftVersion.MC1_12_R1, "save")),
+ NMS_ENTITY_GETSAVEID(ClassWrapper.NMS_ENTITY.getClazz(), new Class[]{}, MinecraftVersion.MC1_14_R1,new Since(MinecraftVersion.MC1_14_R1, "getSaveID")),
+
+ NBTFILE_READ(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{InputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
+ NBTFILE_WRITE(ClassWrapper.NMS_NBTCOMPRESSEDSTREAMTOOLS.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), OutputStream.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "a")), //FIXME: No Spigot mapping!
+
+ PARSE_NBT(ClassWrapper.NMS_MOJANGSONPARSER.getClazz(), new Class[]{String.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "parse")),
+ REGISTRY_KEYSET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "keySet")),
+ REGISTRY_GET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "get")),
+ REGISTRY_SET (ClassWrapper.NMS_REGISTRYSIMPLE.getClazz(), new Class[]{Object.class, Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "a")), //FIXME: No Spigot mapping!
+ REGISTRY_GET_INVERSE (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_11_R1, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_11_R1, "b")), //FIXME: No Spigot mapping!
+ REGISTRYMATERIALS_KEYSET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "keySet")),
+ REGISTRYMATERIALS_GET (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{ClassWrapper.NMS_MINECRAFTKEY.getClazz()}, MinecraftVersion.MC1_13_R1, new Since(MinecraftVersion.MC1_13_R1, "get")),
+ REGISTRYMATERIALS_GETKEY (ClassWrapper.NMS_REGISTRYMATERIALS.getClazz(), new Class[]{Object.class}, MinecraftVersion.MC1_13_R2, new Since(MinecraftVersion.MC1_13_R2, "getKey")),
+
+ GAMEPROFILE_DESERIALIZE (ClassWrapper.NMS_GAMEPROFILESERIALIZER.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "deserialize")),
+ GAMEPROFILE_SERIALIZE (ClassWrapper.NMS_GAMEPROFILESERIALIZER.getClazz(), new Class[]{ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz(), ClassWrapper.GAMEPROFILE.getClazz()}, MinecraftVersion.MC1_8_R3, new Since(MinecraftVersion.MC1_8_R3, "serialize"));
+
+ private MinecraftVersion removedAfter;
+ private Since targetVersion;
+ private Method method;
+ private boolean loaded = false;
+ private boolean compatible = false;
+ private String methodName = null;
+
+ ReflectionMethod(Class> targetClass, Class>[] args, MinecraftVersion addedSince, MinecraftVersion removedAfter, Since... methodnames){
+ this.removedAfter = removedAfter;
+ MinecraftVersion server = MinecraftVersion.getVersion();
+ if(server.compareTo(addedSince) < 0 || (this.removedAfter != null && server.getVersionId() > this.removedAfter.getVersionId()))return;
+ compatible = true;
+ Since target = methodnames[0];
+ for(Since s : methodnames){
+ if(s.version.getVersionId() <= server.getVersionId() && target.version.getVersionId() < s.version.getVersionId())
+ target = s;
+ }
+ targetVersion = target;
+ try{
+ method = targetClass.getMethod(targetVersion.name, args);
+ method.setAccessible(true);
+ loaded = true;
+ methodName = targetVersion.name;
+ }catch(NullPointerException | NoSuchMethodException | SecurityException ex){
+ System.out.println("[NBTAPI] Unable to find the method '" + targetVersion.name + "' in '" + targetClass.getSimpleName() + "' Enum: " + this); //NOSONAR This gets loaded before the logger is loaded
+ }
+ }
+
+ ReflectionMethod(Class> targetClass, Class>[] args, MinecraftVersion addedSince, Since... methodnames){
+ this(targetClass, args, addedSince, null, methodnames);
+ }
+
+ /**
+ * Runs the method on a given target object using the given args.
+ *
+ * @param target
+ * @param args
+ * @return Value returned by the method
+ */
+ public Object run(Object target, Object... args){
+ if(method == null)
+ throw new NbtApiException("Method not loaded! '" + this + "'");
+ try{
+ return method.invoke(target, args);
+ }catch(Exception ex){
+ throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded + ", Enum: " + this, ex);
+ }
+ }
+
+ /**
+ * @return The MethodName, used in this Minecraft Version
+ */
+ public String getMethodName() {
+ return methodName;
+ }
+
+ /**
+ * @return Has this method been linked
+ */
+ public boolean isLoaded() {
+ return loaded;
+ }
+
+ /**
+ * @return Is this method available in this Minecraft Version
+ */
+ public boolean isCompatible() {
+ return compatible;
+ }
+
+ protected static class Since{
+ public final MinecraftVersion version;
+ public final String name;
+ public Since(MinecraftVersion version, String name) {
+ this.version = version;
+ this.name = name;
+ }
+ }
+
+}
diff --git a/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java b/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java
index 8d57e56..8c27a2a 100644
--- a/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java
+++ b/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java
@@ -2,87 +2,60 @@ package com.songoda.epicenchants.utils.single;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
-import com.songoda.core.compatibility.ServerVersion;
-import com.songoda.epicenchants.EpicEnchants;
+import com.songoda.core.compatibility.CompatibleMaterial;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Material;
import java.util.*;
import java.util.stream.Collectors;
+import static com.songoda.core.compatibility.CompatibleMaterial.*;
import static com.songoda.epicenchants.utils.single.ItemGroup.Group.*;
-import static org.bukkit.Material.*;
public class ItemGroup {
- private Multimap