diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 2ddda99..0000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,21 +0,0 @@ -stages: - - build - -variables: - name: "EpicEnchants" - path: "/builds/$CI_PROJECT_PATH" - version: "1.0.10" - -build: - stage: build - image: maven:3.5.3-jdk-8 - script: - - find $path/ -type f -name "*.xml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g - - find $path/ -type f -name "*.yml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g - - mvn clean package - - find $path/ -depth -path '*original*' -delete - - mv $path/target/*.jar $path/ - artifacts: - name: $name-$version - paths: - - "$path/*.jar" diff --git a/pom.xml b/pom.xml index 9c97b54..c7560a8 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ com.songoda EpicEnchants 4.0.0 - maven-version-number + 1.1 clean install EpicEnchants-${project.version} @@ -16,6 +16,28 @@ 1.8 + + com.google.code.maven-replacer-plugin + replacer + 1.5.3 + + + prepare-package + + replace + + + + + ${project.build.directory}/classes/plugin.yml + + + maven-version-number + ${project.version} + + + + org.apache.maven.plugins maven-shade-plugin @@ -32,7 +54,7 @@ false - com.songoda:songodaupdater + com.songoda:SongodaCore fr.mymicky:FastInv @@ -58,10 +80,6 @@ private http://repo.songoda.com/artifactory/private/ - - reserve-repo - https://dl.bintray.com/theneweconomy/java/ - jitpack.io https://jitpack.io @@ -72,7 +90,7 @@ org.spigotmc spigot - 1.14.4 + 1.15 fr.mrmicky @@ -82,24 +100,9 @@ com.songoda - songodaupdater - 1 - - - net.tnemc - Reserve - 0.1.3.0 - provided - - - org.black_ixx - playerpoints - 2.1.4 - - - net.milkbowl - vault - 1.7.1 + SongodaCore + LATEST + compile com.songoda diff --git a/src/main/java/com/songoda/epicenchants/EpicEnchants.java b/src/main/java/com/songoda/epicenchants/EpicEnchants.java index f4430f5..ad8b82e 100644 --- a/src/main/java/com/songoda/epicenchants/EpicEnchants.java +++ b/src/main/java/com/songoda/epicenchants/EpicEnchants.java @@ -1,10 +1,11 @@ package com.songoda.epicenchants; +import com.songoda.core.SongodaCore; +import com.songoda.core.SongodaPlugin; +import com.songoda.core.compatibility.CompatibleMaterial; +import com.songoda.core.configuration.Config; +import com.songoda.core.hooks.EconomyManager; import com.songoda.epicenchants.command.CommandManager; -import com.songoda.epicenchants.economy.Economy; -import com.songoda.epicenchants.economy.PlayerPointsEconomy; -import com.songoda.epicenchants.economy.ReserveEconomy; -import com.songoda.epicenchants.economy.VaultEconomy; import com.songoda.epicenchants.listeners.ArmorListener; import com.songoda.epicenchants.listeners.EntityListener; import com.songoda.epicenchants.listeners.PlayerListener; @@ -16,27 +17,21 @@ import com.songoda.epicenchants.managers.*; import com.songoda.epicenchants.objects.Enchant; import com.songoda.epicenchants.utils.EnchantUtils; import com.songoda.epicenchants.utils.Metrics; -import com.songoda.epicenchants.utils.ServerVersion; import com.songoda.epicenchants.utils.SpecialItems; -import com.songoda.epicenchants.utils.locale.Locale; import com.songoda.epicenchants.utils.objects.FastInv; import com.songoda.epicenchants.utils.settings.Setting; import com.songoda.epicenchants.utils.settings.SettingsManager; import com.songoda.epicenchants.utils.single.ItemGroup; -import com.songoda.epicenchants.utils.updateModules.LocaleModule; -import com.songoda.update.Plugin; -import com.songoda.update.SongodaUpdate; -import org.apache.commons.lang.ArrayUtils; import org.bukkit.Bukkit; import org.bukkit.plugin.PluginManager; -import org.bukkit.plugin.java.JavaPlugin; +import java.util.List; import java.util.stream.Collectors; import static com.songoda.epicenchants.utils.single.GeneralUtils.color; import static org.bukkit.Bukkit.getConsoleSender; -public class EpicEnchants extends JavaPlugin { +public class EpicEnchants extends SongodaPlugin { private static EpicEnchants INSTANCE; @@ -48,12 +43,7 @@ public class EpicEnchants extends JavaPlugin { private SettingsManager settingsManager; private CommandManager commandManager; - private Locale locale; - - private ServerVersion serverVersion = ServerVersion.fromPackageName(Bukkit.getServer().getClass().getPackage().getName()); - private SpecialItems specialItems; - private Economy economy; private EnchantUtils enchantUtils; private ItemGroup itemGroup; @@ -62,25 +52,21 @@ public class EpicEnchants extends JavaPlugin { } @Override - public void onEnable() { + public void onPluginLoad() { INSTANCE = this; + } - getConsoleSender().sendMessage(color("&a=============================")); - getConsoleSender().sendMessage(color("&7" + getDescription().getName() + " " + getDescription().getVersion() + " by &5Songoda <3&7!")); - getConsoleSender().sendMessage(color("&7Action: &aEnabling&7...")); + @Override + public void onPluginEnable() { + // Run Songoda Updater + SongodaCore.registerPlugin(this, 67, CompatibleMaterial.DIAMOND_SWORD); // Setup Setting Manager this.settingsManager = new SettingsManager(this); this.settingsManager.setupConfig(); // Setup Language - new Locale(this, "en_US"); - this.locale = Locale.getLocale(getConfig().getString("System.Language Mode")); - - // Running Songoda Updater - Plugin plugin = new Plugin(this, 67); - plugin.addModule(new LocaleModule()); - SongodaUpdate.load(plugin); + this.setLocale(getConfig().getString("System.Language Mode"), false); preload(); @@ -109,13 +95,19 @@ public class EpicEnchants extends JavaPlugin { pluginManager.registerEvents(new BlackScrollListener(this), this); pluginManager.registerEvents(new DustListener(this), this); + String economyPlugin = null; + // Setup Economy if (Setting.VAULT_ECONOMY.getBoolean() && pluginManager.isPluginEnabled("Vault")) - this.economy = new VaultEconomy(); + economyPlugin = "Vault"; else if (Setting.RESERVE_ECONOMY.getBoolean() && pluginManager.isPluginEnabled("Reserve")) - this.economy = new ReserveEconomy(); + economyPlugin = "Reserve"; else if (Setting.PLAYER_POINTS_ECONOMY.getBoolean() && pluginManager.isPluginEnabled("PlayerPoints")) - this.economy = new PlayerPointsEconomy(); + economyPlugin = "PlayerPoints"; + + EconomyManager.load(); + if (economyPlugin != null) + EconomyManager.getManager().setPreferredHook(economyPlugin); // Start Metrics new Metrics(this); @@ -123,8 +115,6 @@ public class EpicEnchants extends JavaPlugin { if (!enchantManager.getValues().isEmpty()) { getLogger().info("Successfully loaded enchants: " + enchantManager.getValues().stream().map(Enchant::getIdentifier).collect(Collectors.joining(", "))); } - - getConsoleSender().sendMessage(color("&a=============================")); } private void preload() { @@ -134,13 +124,23 @@ public class EpicEnchants extends JavaPlugin { } @Override - public void onDisable() { + public void onPluginDisable() { getConsoleSender().sendMessage(color("&a=============================")); getConsoleSender().sendMessage(color("&7" + getDescription().getName() + " " + getDescription().getVersion() + " by &5Songoda <3&7!")); getConsoleSender().sendMessage(color("&7Action: &cDisabling&7...")); getConsoleSender().sendMessage(color("&a=============================")); } + @Override + public void onConfigReload() { + + } + + @Override + public List getExtraConfig() { + return null; + } + public void reload() { reloadConfig(); @@ -156,26 +156,10 @@ public class EpicEnchants extends JavaPlugin { infoManager.clear(); infoManager.loadMenus(); - this.locale = Locale.getLocale(getConfig().getString("System.Language Mode")); + this.setLocale(getConfig().getString("System.Language Mode"), true); this.locale.reloadMessages(); } - public ServerVersion getServerVersion() { - return serverVersion; - } - - public boolean isServerVersion(ServerVersion version) { - return serverVersion == version; - } - - public boolean isServerVersion(ServerVersion... versions) { - return ArrayUtils.contains(versions, serverVersion); - } - - public boolean isServerVersionAtLeast(ServerVersion version) { - return serverVersion.ordinal() >= version.ordinal(); - } - public EnchantManager getEnchantManager() { return this.enchantManager; } @@ -200,10 +184,6 @@ public class EpicEnchants extends JavaPlugin { return this.specialItems; } - public Economy getEconomy() { - return this.economy; - } - public EnchantUtils getEnchantUtils() { return this.enchantUtils; } @@ -212,10 +192,6 @@ public class EpicEnchants extends JavaPlugin { return this.itemGroup; } - public Locale getLocale() { - return locale; - } - public CommandManager getCommandManager() { return commandManager; } diff --git a/src/main/java/com/songoda/epicenchants/economy/Economy.java b/src/main/java/com/songoda/epicenchants/economy/Economy.java deleted file mode 100644 index 313e4a4..0000000 --- a/src/main/java/com/songoda/epicenchants/economy/Economy.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.songoda.epicenchants.economy; - -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -public interface Economy { - - boolean hasBalance(OfflinePlayer player, double cost); - - double getBalance(Player player); - - boolean withdrawBalance(OfflinePlayer player, double cost); - - boolean deposit(OfflinePlayer player, double amount); -} diff --git a/src/main/java/com/songoda/epicenchants/economy/PlayerPointsEconomy.java b/src/main/java/com/songoda/epicenchants/economy/PlayerPointsEconomy.java deleted file mode 100644 index 836c664..0000000 --- a/src/main/java/com/songoda/epicenchants/economy/PlayerPointsEconomy.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.songoda.epicenchants.economy; - -import org.black_ixx.playerpoints.PlayerPoints; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -public class PlayerPointsEconomy implements Economy { - - private final PlayerPoints playerPoints; - - public PlayerPointsEconomy() { - this.playerPoints = (PlayerPoints) Bukkit.getServer().getPluginManager().getPlugin("PlayerPoints"); - } - - private int convertAmount(double amount) { - return (int) Math.ceil(amount); - } - - @Override - public boolean hasBalance(OfflinePlayer player, double cost) { - int amount = convertAmount(cost); - return playerPoints.getAPI().look(player.getUniqueId()) >= amount; - - } - - @Override - public double getBalance(Player player) { - return playerPoints.getAPI().look(player.getUniqueId()); - } - - @Override - public boolean withdrawBalance(OfflinePlayer player, double cost) { - int amount = convertAmount(cost); - return playerPoints.getAPI().take(player.getUniqueId(), amount); - - } - - @Override - public boolean deposit(OfflinePlayer player, double amount) { - int amt = convertAmount(amount); - return playerPoints.getAPI().give(player.getUniqueId(), amt); - } -} diff --git a/src/main/java/com/songoda/epicenchants/economy/ReserveEconomy.java b/src/main/java/com/songoda/epicenchants/economy/ReserveEconomy.java deleted file mode 100644 index 96bd4e7..0000000 --- a/src/main/java/com/songoda/epicenchants/economy/ReserveEconomy.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.songoda.epicenchants.economy; - -import net.tnemc.core.Reserve; -import net.tnemc.core.economy.EconomyAPI; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -import java.math.BigDecimal; - -public class ReserveEconomy implements Economy { - - EconomyAPI economyAPI; - - public ReserveEconomy() { - if (Reserve.instance().economyProvided()) - economyAPI = Reserve.instance().economy(); - } - - @Override - public boolean hasBalance(OfflinePlayer player, double cost) { - return economyAPI.hasHoldings(player.getUniqueId(), new BigDecimal(cost)); - } - - @Override - public double getBalance(Player player) { - return economyAPI.getHoldings(player.getUniqueId()).doubleValue(); - } - - @Override - public boolean withdrawBalance(OfflinePlayer player, double cost) { - return economyAPI.removeHoldings(player.getUniqueId(), new BigDecimal(cost)); - } - - @Override - public boolean deposit(OfflinePlayer player, double amount) { - return economyAPI.addHoldings(player.getUniqueId(), new BigDecimal(amount)); - } -} diff --git a/src/main/java/com/songoda/epicenchants/economy/VaultEconomy.java b/src/main/java/com/songoda/epicenchants/economy/VaultEconomy.java deleted file mode 100644 index d44396f..0000000 --- a/src/main/java/com/songoda/epicenchants/economy/VaultEconomy.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.songoda.epicenchants.economy; - -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; - -public class VaultEconomy implements Economy { - private final net.milkbowl.vault.economy.Economy vault; - - public VaultEconomy() { - this.vault = Bukkit.getServicesManager(). - getRegistration(net.milkbowl.vault.economy.Economy.class).getProvider(); - } - - @Override - public boolean hasBalance(OfflinePlayer player, double cost) { - return vault.has(player, cost); - } - - @Override - public double getBalance(Player player) { - return vault.getBalance(player); - } - - @Override - public boolean withdrawBalance(OfflinePlayer player, double cost) { - return vault.withdrawPlayer(player, cost).transactionSuccess(); - } - - @Override - public boolean deposit(OfflinePlayer player, double amount) { - return vault.depositPlayer(player, amount).transactionSuccess(); - } -} diff --git a/src/main/java/com/songoda/epicenchants/effect/effects/DropHead.java b/src/main/java/com/songoda/epicenchants/effect/effects/DropHead.java index 0b2863c..9f6808e 100644 --- a/src/main/java/com/songoda/epicenchants/effect/effects/DropHead.java +++ b/src/main/java/com/songoda/epicenchants/effect/effects/DropHead.java @@ -1,5 +1,6 @@ package com.songoda.epicenchants.effect.effects; +import com.songoda.core.compatibility.CompatibleMaterial; import com.songoda.epicenchants.effect.EffectExecutor; import com.songoda.epicenchants.enums.EventType; import org.bukkit.Material; @@ -24,7 +25,7 @@ public class DropHead extends EffectExecutor { } private Optional getHead(Entity entity) { - short data = 3; + ItemStack out = CompatibleMaterial.PLAYER_HEAD.getItem(); String skin = ""; switch (entity.getType()) { @@ -50,10 +51,10 @@ public class DropHead extends EffectExecutor { skin = "MHF_Spider"; break; case ZOMBIE: - data = 2; + out = CompatibleMaterial.ZOMBIE_HEAD.getItem(); break; case SKELETON: - data = 0; + out = CompatibleMaterial.SKELETON_SKULL.getItem(); break; case VILLAGER: skin = "MHF_Villager"; @@ -65,7 +66,7 @@ public class DropHead extends EffectExecutor { skin = "MHF_Blaze"; break; case CREEPER: - data = 4; + out = CompatibleMaterial.CREEPER_HEAD.getItem(); case ENDERMAN: skin = "MHF_Enderman"; break; @@ -80,7 +81,6 @@ public class DropHead extends EffectExecutor { return Optional.empty(); } - ItemStack out = new ItemStack(Material.LEGACY_SKULL_ITEM, 1, data); SkullMeta skullMeta = (SkullMeta) out.getItemMeta(); skullMeta.setOwner(entity instanceof Player ? entity.getName() : skin); diff --git a/src/main/java/com/songoda/epicenchants/effect/effects/SpawnMob.java b/src/main/java/com/songoda/epicenchants/effect/effects/SpawnMob.java index 89a4dd7..3ffd20e 100644 --- a/src/main/java/com/songoda/epicenchants/effect/effects/SpawnMob.java +++ b/src/main/java/com/songoda/epicenchants/effect/effects/SpawnMob.java @@ -3,10 +3,7 @@ package com.songoda.epicenchants.effect.effects; import com.songoda.epicenchants.effect.EffectExecutor; import com.songoda.epicenchants.enums.EventType; import com.songoda.epicenchants.objects.LeveledModifier; -import com.songoda.epicenchants.utils.itemnbtapi.NBTEntity; -import com.songoda.epicenchants.utils.itemnbtapi.NBTList; -import com.songoda.epicenchants.utils.itemnbtapi.NBTListCompound; -import com.songoda.epicenchants.utils.itemnbtapi.NBTType; +import com.songoda.epicenchants.utils.itemnbtapi.*; import com.songoda.epicenchants.utils.objects.ItemBuilder; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; @@ -92,17 +89,17 @@ public class SpawnMob extends EffectExecutor { nbtEntity.setBoolean(user.getUniqueId().toString(), true); - NBTList list = nbtEntity.getList("Attributes", NBTType.NBTTagCompound); + NBTCompoundList list = nbtEntity.getCompoundList("Attributes"); for (int j = 0; j < list.size(); j++) { - NBTListCompound lc = list.getCompound(j); + NBTListCompound lc = list.get(j); if (lc.getString("Name").equals("generic.attackDamage")) { - lc.setDouble("Base", attackDamage.get(level, (int) lc.getDouble("Base"), user, opponent)); + lc.setDouble("Base", attackDamage.get(level, (int) Math.round(lc.getDouble("Base")), user, opponent)); continue; } if (lc.getString("Name").equals("generic.maxHealth")) { - lc.setDouble("Base", health.get(level, (int) lc.getDouble("Base"), user, opponent)); + lc.setDouble("Base", health.get(level, (int) Math.round(lc.getDouble("Base")), user, opponent)); } } } diff --git a/src/main/java/com/songoda/epicenchants/managers/FileManager.java b/src/main/java/com/songoda/epicenchants/managers/FileManager.java index 6dc4f6b..414d972 100644 --- a/src/main/java/com/songoda/epicenchants/managers/FileManager.java +++ b/src/main/java/com/songoda/epicenchants/managers/FileManager.java @@ -1,7 +1,7 @@ package com.songoda.epicenchants.managers; +import com.songoda.core.compatibility.ServerVersion; import com.songoda.epicenchants.EpicEnchants; -import com.songoda.epicenchants.utils.ServerVersion; import com.songoda.epicenchants.utils.objects.FileLocation; import com.songoda.epicenchants.utils.settings.Setting; import org.bukkit.Bukkit; @@ -81,8 +81,8 @@ public class FileManager extends Manager { public FileManager(EpicEnchants instance) { super(instance); - directory = instance.isServerVersionAtLeast(ServerVersion.V1_13) ? "master" : "legacy"; - Bukkit.getConsoleSender().sendMessage("Using the " + directory + " configurations because version is " + instance.getServerVersion().name()); + directory = ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? "master" : "legacy"; + Bukkit.getConsoleSender().sendMessage("Using the " + directory + " configurations because version is " + ServerVersion.getServerVersion().name()); } public void loadFiles() { diff --git a/src/main/java/com/songoda/epicenchants/menus/AlchemistMenu.java b/src/main/java/com/songoda/epicenchants/menus/AlchemistMenu.java index 8fa6b49..71e7f51 100644 --- a/src/main/java/com/songoda/epicenchants/menus/AlchemistMenu.java +++ b/src/main/java/com/songoda/epicenchants/menus/AlchemistMenu.java @@ -1,5 +1,6 @@ package com.songoda.epicenchants.menus; +import com.songoda.core.hooks.EconomyManager; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.objects.Enchant; import com.songoda.epicenchants.objects.Group; @@ -263,12 +264,12 @@ public class AlchemistMenu extends FastInv { of("eco_cost", ecoCost), of("exp_cost", expCost) ).build(), event -> { - if (!instance.getEconomy().hasBalance(event.getPlayer(), ecoCost) || getExp(event.getPlayer()) < expCost) { + if (!EconomyManager.hasBalance(event.getPlayer(), ecoCost) || getExp(event.getPlayer()) < expCost) { instance.getLocale().getMessage("alchemist.cannotafford").sendPrefixedMessage(event.getPlayer()); return; } - instance.getEconomy().withdrawBalance(event.getPlayer(), ecoCost); + EconomyManager.withdrawBalance(event.getPlayer(), ecoCost); changeExp(event.getPlayer(), -expCost); instance.getLocale().getMessage("alchemist.success") .processPlaceholder("eco_cost", ecoCost) diff --git a/src/main/java/com/songoda/epicenchants/menus/EnchanterMenu.java b/src/main/java/com/songoda/epicenchants/menus/EnchanterMenu.java index a07d215..e1761c7 100644 --- a/src/main/java/com/songoda/epicenchants/menus/EnchanterMenu.java +++ b/src/main/java/com/songoda/epicenchants/menus/EnchanterMenu.java @@ -1,5 +1,6 @@ package com.songoda.epicenchants.menus; +import com.songoda.core.hooks.EconomyManager; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.objects.Group; import com.songoda.epicenchants.utils.objects.FastInv; @@ -36,8 +37,8 @@ public class EnchanterMenu extends FastInv { int ecoCost = section.getInt("eco-cost"); int xpLeft = Math.max(expCost - player.getLevel(), 0); double ecoLeft = 0.0d; - if (instance.getEconomy() != null) - ecoLeft = ecoCost - instance.getEconomy().getBalance(player) < 0 ? 0 : ecoCost - instance.getEconomy().getBalance(player); + if (EconomyManager.isEnabled()) + ecoLeft = ecoCost - EconomyManager.getBalance(player) < 0 ? 0 : ecoCost - EconomyManager.getBalance(player); Group group = instance.getGroupManager().getValue(section.getString("group").toUpperCase()) .orElseThrow(() -> new IllegalArgumentException("Invalid group set in enchanter: " + section.getString("group"))); ItemStack itemStack = new ItemBuilder(section, @@ -52,13 +53,13 @@ public class EnchanterMenu extends FastInv { return; } - if (instance.getEconomy() != null && !instance.getEconomy().hasBalance((player), ecoCost) || getExp(player) < expCost) { + if (EconomyManager.isEnabled() && !EconomyManager.hasBalance((player), ecoCost) || getExp(player) < expCost) { instance.getLocale().getMessage("enchanter.cannotafford").sendPrefixedMessage(player); return; } - if (instance.getEconomy() != null) { - instance.getEconomy().withdrawBalance(player, ecoCost); + if (EconomyManager.isEnabled()) { + EconomyManager.withdrawBalance(player, ecoCost); instance.getLocale().getMessage("enchanter.success") .processPlaceholder("group_name", group.getName()) .processPlaceholder("group_color", group.getColor()) diff --git a/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java b/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java index b93a97b..26f4386 100644 --- a/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java +++ b/src/main/java/com/songoda/epicenchants/utils/EnchantUtils.java @@ -1,5 +1,6 @@ package com.songoda.epicenchants.utils; +import com.songoda.core.utils.TextUtils; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.enums.EnchantResult; import com.songoda.epicenchants.enums.EventType; @@ -132,9 +133,12 @@ public class EnchantUtils { return itemStack; } + String format = enchant.getFormat().replace("{level}", "").trim(); + String text = format.isEmpty() ? enchant.getColoredIdentifier(false) : format; + nbtItem.getCompound("enchants").removeKey(enchant.getIdentifier()); ItemBuilder output = new ItemBuilder(nbtItem.getItem()); - output.removeLore(enchant.getFormat().replace("{level}", "").trim()); + output.removeLore(TextUtils.formatText(text)); return output.build(); } } diff --git a/src/main/java/com/songoda/epicenchants/utils/Methods.java b/src/main/java/com/songoda/epicenchants/utils/Methods.java index b9ed78e..0328948 100644 --- a/src/main/java/com/songoda/epicenchants/utils/Methods.java +++ b/src/main/java/com/songoda/epicenchants/utils/Methods.java @@ -1,5 +1,6 @@ package com.songoda.epicenchants.utils; +import com.songoda.core.compatibility.ServerVersion; import com.songoda.epicenchants.EpicEnchants; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -25,10 +26,10 @@ public class Methods { int randomNum = 1 + (int) (Math.random() * 6); ItemStack glass; if (rainbow) { - glass = new ItemStack(EpicEnchants.getInstance().isServerVersionAtLeast(ServerVersion.V1_13) ? + glass = new ItemStack(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.LEGACY_STAINED_GLASS_PANE : Material.valueOf("STAINED_GLASS_PANE"), 1, (short) randomNum); } else { - glass = new ItemStack(EpicEnchants.getInstance().isServerVersionAtLeast(ServerVersion.V1_13) ? + glass = new ItemStack(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.LEGACY_STAINED_GLASS_PANE : Material.valueOf("STAINED_GLASS_PANE"), 1, (short) type); } ItemMeta glassmeta = glass.getItemMeta(); diff --git a/src/main/java/com/songoda/epicenchants/utils/ServerVersion.java b/src/main/java/com/songoda/epicenchants/utils/ServerVersion.java deleted file mode 100644 index c442d9b..0000000 --- a/src/main/java/com/songoda/epicenchants/utils/ServerVersion.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.songoda.epicenchants.utils; - -public enum ServerVersion { - - UNKNOWN("unknown_server_version"), - V1_7("org.bukkit.craftbukkit.v1_7"), - V1_8("org.bukkit.craftbukkit.v1_8"), - V1_9("org.bukkit.craftbukkit.v1_9"), - V1_10("org.bukkit.craftbukkit.v1_10"), - V1_11("org.bukkit.craftbukkit.v1_11"), - V1_12("org.bukkit.craftbukkit.v1_12"), - V1_13("org.bukkit.craftbukkit.v1_13"), - V1_14("org.bukkit.craftbukkit.v1_14"); - - - private final String packagePrefix; - - private ServerVersion(String packagePrefix) { - this.packagePrefix = packagePrefix; - } - - public static ServerVersion fromPackageName(String packageName) { - for (ServerVersion version : values()) - if (packageName.startsWith(version.packagePrefix)) return version; - return ServerVersion.UNKNOWN; - } -} \ No newline at end of file diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ClassWrapper.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ClassWrapper.java deleted file mode 100644 index 4c2d76c..0000000 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ClassWrapper.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.songoda.epicenchants.utils.itemnbtapi; - -import org.bukkit.Bukkit; - -public enum ClassWrapper { - CRAFT_ITEMSTACK("org.bukkit.craftbukkit.", ".inventory.CraftItemStack"), - CRAFT_ENTITY("org.bukkit.craftbukkit.", ".entity.CraftEntity"), - CRAFT_WORLD("org.bukkit.craftbukkit.", ".CraftWorld"), - NMS_NBTBASE("net.minecraft.server.", ".NBTBase"), - NMS_NBTTAGSTRING("net.minecraft.server.", ".NBTTagString"), - NMS_ITEMSTACK("net.minecraft.server.", ".ItemStack"), - NMS_NBTTAGCOMPOUND("net.minecraft.server.", ".NBTTagCompound"), - NMS_NBTTAGLIST("net.minecraft.server.", ".NBTTagList"), - NMS_NBTCOMPRESSEDSTREAMTOOLS("net.minecraft.server.", ".NBTCompressedStreamTools"), - NMS_MOJANGSONPARSER("net.minecraft.server.", ".MojangsonParser"), - NMS_TILEENTITY("net.minecraft.server.", ".TileEntity"), - NMS_BLOCKPOSITION("net.minecraft.server.", ".BlockPosition"), - NMS_WORLD("net.minecraft.server.", ".WorldServer"), - NMS_ENTITY("net.minecraft.server.", ".Entity"),; - - - private Class clazz; - - ClassWrapper(String pre, String suffix) { - try { - String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; - clazz = Class.forName(pre + version + suffix); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public Class getClazz() { - return clazz; - } - -} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompound.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompound.java index 70eefdf..f0e3214 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompound.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompound.java @@ -1,10 +1,17 @@ package com.songoda.epicenchants.utils.itemnbtapi; import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; +import java.io.Serializable; import java.util.Set; - +/** + * Base class representing NMS Compounds. For a standalone implementation check + * {@link NBTContainer} + * + * @author tr7zw + */ public class NBTCompound { private String compundName; @@ -15,11 +22,22 @@ public class NBTCompound { this.parent = owner; } + protected void saveCompound() { + if (parent != null) + parent.saveCompound(); + } + + /** + * @return The Compound name + */ public String getName() { return compundName; } - protected Object getCompound() { + /** + * @return The NMS Compound behind this Object + */ + public Object getCompound() { return parent.getCompound(); } @@ -27,18 +45,41 @@ public class NBTCompound { parent.setCompound(compound); } + /** + * @return The parent Compound + */ public NBTCompound getParent() { return parent; } + /** + * Merges all data from comp into this compound. This is done in one action, so + * it also works with Tiles/Entities + * + * @param comp + */ public void mergeCompound(NBTCompound comp) { - NBTReflectionUtil.addOtherNBTCompound(this, comp); + NBTReflectionUtil.mergeOtherNBTCompound(this, comp); + saveCompound(); } + /** + * Setter + * + * @param key + * @param value + */ public void setString(String key, String value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_STRING, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public String getString(String key) { return (String) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_STRING, key); } @@ -47,153 +88,361 @@ public class NBTCompound { return NBTReflectionUtil.getContent(this, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setInteger(String key, Integer value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INT, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public Integer getInteger(String key) { return (Integer) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_INT, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setDouble(String key, Double value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_DOUBLE, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public Double getDouble(String key) { return (Double) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_DOUBLE, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setByte(String key, Byte value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTE, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public Byte getByte(String key) { return (Byte) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BYTE, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setShort(String key, Short value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_SHORT, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public Short getShort(String key) { return (Short) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_SHORT, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setLong(String key, Long value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_LONG, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public Long getLong(String key) { return (Long) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_LONG, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setFloat(String key, Float value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_FLOAT, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public Float getFloat(String key) { return (Float) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_FLOAT, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setByteArray(String key, byte[] value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BYTEARRAY, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public byte[] getByteArray(String key) { return (byte[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BYTEARRAY, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setIntArray(String key, int[] value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_INTARRAY, key, value); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public int[] getIntArray(String key) { return (int[]) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_INTARRAY, key); } + /** + * Setter + * + * @param key + * @param value + */ public void setBoolean(String key, Boolean value) { NBTReflectionUtil.setData(this, ReflectionMethod.COMPOUND_SET_BOOLEAN, key, value); + saveCompound(); } protected void set(String key, Object val) { NBTReflectionUtil.set(this, key, val); + saveCompound(); } + /** + * Getter + * + * @param key + * @return The stored value or NMS fallback + */ public Boolean getBoolean(String key) { return (Boolean) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_BOOLEAN, key); } + /** + * Uses Gson to store an {@link Serializable} Object + * + * @param key + * @param value + */ public void setObject(String key, Object value) { NBTReflectionUtil.setObject(this, key, value); + saveCompound(); } + /** + * Uses Gson to retrieve a stored Object + * + * @param key + * @param type Class of the Object + * @return The created Object or null if empty + */ public T getObject(String key, Class type) { return NBTReflectionUtil.getObject(this, key, type); } + /** + * @param key + * @return True if the key is set + */ public Boolean hasKey(String key) { Boolean b = (Boolean) NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_HAS_KEY, key); - if (b == null) return false; + if (b == null) + return false; return b; } + /** + * @param key Deletes the given Key + */ public void removeKey(String key) { NBTReflectionUtil.remove(this, key); + saveCompound(); } + /** + * @return Set of all stored Keys + */ public Set getKeys() { return NBTReflectionUtil.getKeys(this); } + /** + * Creates a subCompound + * + * @param name Key to use + * @return The subCompound Object + */ public NBTCompound addCompound(String name) { - if (getType(name) == NBTType.NBTTagCompound) return getCompound(name); + if (getType(name) == NBTType.NBTTagCompound) + return getCompound(name); NBTReflectionUtil.addNBTTagCompound(this, name); - return getCompound(name); + NBTCompound comp = getCompound(name); + if (comp == null) + throw new NbtApiException("Error while adding Compound, got null!"); + saveCompound(); + return comp; } + /** + * @param name + * @return The Compound instance or null + */ public NBTCompound getCompound(String name) { + if (getType(name) != NBTType.NBTTagCompound) + return null; NBTCompound next = new NBTCompound(this, name); - if (NBTReflectionUtil.valideCompound(next)) return next; + if (NBTReflectionUtil.valideCompound(next)) + return next; return null; } - public NBTList getList(String name, NBTType type) { - return NBTReflectionUtil.getList(this, name, type); + /** + * @param name + * @return The retrieved String List + */ + public NBTList getStringList(String name) { + NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagString, String.class); + saveCompound(); + return list; } + /** + * @param name + * @return The retrieved Integer List + */ + public NBTList getIntegerList(String name) { + NBTList list = NBTReflectionUtil.getList(this, name, NBTType.NBTTagInt, Integer.class); + saveCompound(); + return list; + } + + /** + * @param name + * @return The retrieved Compound List + */ + public NBTCompoundList getCompoundList(String name) { + NBTCompoundList list = (NBTCompoundList) NBTReflectionUtil.getList(this, name, NBTType.NBTTagCompound, NBTListCompound.class); + saveCompound(); + return list; + } + + /** + * @param name + * @return The type of the given stored key or null + */ public NBTType getType(String name) { - if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) return null; + if (MinecraftVersion.getVersion() == MinecraftVersion.MC1_7_R4) + return null; Object o = NBTReflectionUtil.getData(this, ReflectionMethod.COMPOUND_GET_TYPE, name); - if (o == null) return null; + if (o == null) + return null; return NBTType.valueOf((byte) o); } @Override public String toString() { - StringBuilder result = new StringBuilder(); - for (String key : getKeys()) { - result.append(toString(key)); - } - return result.toString(); + /*StringBuilder result = new StringBuilder(); + for (String key : getKeys()) { + result.append(toString(key)); + } + return result.toString();*/ + return asNBTString(); } + /** + * @param key + * @return A string representation of the given key + * @deprecated Just use toString() + */ + @Deprecated public String toString(String key) { - StringBuilder result = new StringBuilder(); - NBTCompound compound = this; - while (compound.getParent() != null) { - result.append(" "); - compound = compound.getParent(); - } - if (this.getType(key) == NBTType.NBTTagCompound) { - return this.getCompound(key).toString(); - } else { - return result + "-" + key + ": " + getContent(key) + System.lineSeparator(); - } + /*StringBuilder result = new StringBuilder(); + NBTCompound compound = this; + while (compound.getParent() != null) { + result.append(" "); + compound = compound.getParent(); + } + if (this.getType(key) == NBTType.NBTTagCompound) { + return this.getCompound(key).toString(); + } else { + return result + "-" + key + ": " + getContent(key) + System.lineSeparator(); + }*/ + return asNBTString(); } + /** + * @return A json valid nbt string for this Compound + * @deprecated Just use toString() + */ + @Deprecated public String asNBTString() { Object comp = NBTReflectionUtil.gettoCompount(getCompound(), this); - if (comp == null) return "{}"; + if (comp == null) + return "{}"; return comp.toString(); } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompoundList.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompoundList.java new file mode 100644 index 0000000..f90fe74 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTCompoundList.java @@ -0,0 +1,108 @@ +package com.songoda.epicenchants.utils.itemnbtapi; + +import org.apache.commons.lang.NotImplementedException; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * {@link NBTListCompound} implementation for NBTLists + * + * @author tr7zw + * + */ +public class NBTCompoundList extends NBTList { + + protected NBTCompoundList(NBTCompound owner, String name, NBTType type, Object list) { + super(owner, name, type, list); + } + + /** + * Adds a new Compound to the end of the List and returns it. + * + * @return The added {@link NBTListCompound} + */ + public NBTListCompound addCompound() { + return (NBTListCompound) addCompound(null); + } + + /** + * Adds a copy of the Compound to the end of the List and returns it. + * When null is given, a new Compound will be created + * + * @param comp + * @return + */ + public NBTCompound addCompound(NBTCompound comp) { + try { + Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance(); + if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) { + ReflectionMethod.LIST_ADD.run(listObject, size(), compound); + } else { + ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound); + } + getParent().saveCompound(); + NBTListCompound listcomp = new NBTListCompound(this, compound); + if(comp != null){ + listcomp.mergeCompound(comp); + } + return listcomp; + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } + + /** + * Adds a new Compound to the end of the List. + * + * + * @deprecated Please use addCompound! + * @param empty + * @return True, if compound was added + */ + @Override + @Deprecated + public boolean add(NBTListCompound empty) { + return addCompound(empty) != null; + } + + @Override + public void add(int index, NBTListCompound element) { + if (element != null) { + throw new NotImplementedException("You need to pass null! ListCompounds from other lists won't work."); + } + try { + Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance(); + if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) { + ReflectionMethod.LIST_ADD.run(listObject, index, compound); + } else { + ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound); + } + super.getParent().saveCompound(); + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } + + @Override + public NBTListCompound get(int index) { + try { + Object compound = ReflectionMethod.LIST_GET_COMPOUND.run(listObject, index); + return new NBTListCompound(this, compound); + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } + + @Override + public NBTListCompound set(int index, NBTListCompound element) { + throw new NotImplementedException("This method doesn't work in the ListCompound context."); + } + + @Override + protected Object asTag(NBTListCompound object) { + return null; + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTContainer.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTContainer.java index 0fc72c4..f5b489a 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTContainer.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTContainer.java @@ -1,35 +1,60 @@ package com.songoda.epicenchants.utils.itemnbtapi; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ObjectCreator; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * A Standalone {@link NBTCompound} implementation. All data is just kept inside + * this Object. + * + * @author tr7zw + * + */ public class NBTContainer extends NBTCompound { - private Object nbt; + private Object nbt; - public NBTContainer() { - super(null, null); - nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } + /** + * Creates an empty, standalone NBTCompound + */ + public NBTContainer() { + super(null, null); + nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } - protected NBTContainer(Object nbt) { - super(null, null); - this.nbt = nbt; - } + /** + * Takes in any NMS Compound to wrap it + * + * @param nbt + */ + public NBTContainer(Object nbt) { + super(null, null); + this.nbt = nbt; + } - public NBTContainer(String nbtString) throws IllegalArgumentException { - super(null, null); - try { - nbt = ReflectionMethod.PARSE_NBT.run(null, nbtString); - } catch (Exception ex) { - ex.printStackTrace(); - throw new IllegalArgumentException("Malformed Json: " + ex.getMessage()); - } - } + /** + * Parses in a NBT String to a standalone {@link NBTCompound}. Can throw a + * {@link NbtApiException} in case something goes wrong. + * + * @param nbtString + */ + public NBTContainer(String nbtString) { + super(null, null); + try { + nbt = ReflectionMethod.PARSE_NBT.run(null, nbtString); + } catch (Exception ex) { + throw new NbtApiException("Unable to parse Malformed Json!", ex); + } + } - protected Object getCompound() { - return nbt; - } + @Override + public Object getCompound() { + return nbt; + } - protected void setCompound(Object tag) { - nbt = tag; - } + @Override + public void setCompound(Object tag) { + nbt = tag; + } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTEntity.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTEntity.java index 9bb58a7..83885d0 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTEntity.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTEntity.java @@ -2,21 +2,34 @@ package com.songoda.epicenchants.utils.itemnbtapi; import org.bukkit.entity.Entity; +/** + * NBT class to access vanilla tags from Entities. Entities don't support custom + * tags. Use the NBTInjector for custom tags. Changes will be instantly applied + * to the Entity, use the merge method to do many things at once. + * + * @author tr7zw + * + */ public class NBTEntity extends NBTCompound { - private final Entity ent; + private final Entity ent; - public NBTEntity(Entity entity) { - super(null, null); - ent = entity; - } + /** + * @param entity Any valid Bukkit Entity + */ + public NBTEntity(Entity entity) { + super(null, null); + ent = entity; + } - protected Object getCompound() { - return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent)); - } + @Override + public Object getCompound() { + return NBTReflectionUtil.getEntityNBTTagCompound(NBTReflectionUtil.getNMSEntity(ent)); + } - protected void setCompound(Object compound) { - NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent)); - } + @Override + protected void setCompound(Object compound) { + NBTReflectionUtil.setEntityNBTTag(compound, NBTReflectionUtil.getNMSEntity(ent)); + } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFile.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFile.java index 4341c8b..69852ad 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFile.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTFile.java @@ -5,42 +5,68 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ObjectCreator; + +/** + * {@link NBTCompound} implementation backed by a {@link File} + * + * @author tr7zw + * + */ public class NBTFile extends NBTCompound { - private final File file; - private Object nbt; + private final File file; + private Object nbt; - public NBTFile(File file) throws IOException { - super(null, null); - this.file = file; - if (file.exists()) { - FileInputStream inputsteam = new FileInputStream(file); - nbt = NBTReflectionUtil.readNBTFile(inputsteam); - } else { - nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - save(); - } - } + /** + * Creates a NBTFile that uses @param file to store it's data. If this file + * exists, the data will be loaded. + * + * @param file + * @throws IOException + */ + public NBTFile(File file) throws IOException { + super(null, null); + this.file = file; + if (file.exists()) { + FileInputStream inputsteam = new FileInputStream(file); + nbt = NBTReflectionUtil.readNBTFile(inputsteam); + } else { + nbt = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + save(); + } + } - public void save() throws IOException { - if (!file.exists()) { - file.getParentFile().mkdirs(); - file.createNewFile(); - } - FileOutputStream outStream = new FileOutputStream(file); - NBTReflectionUtil.saveNBTFile(nbt, outStream); - } + /** + * Saves the data to the file + * + * @throws IOException + */ + public void save() throws IOException { + if (!file.exists()) { + file.getParentFile().mkdirs(); + if (!file.createNewFile()) + throw new IOException("Unable to create file at " + file.getAbsolutePath()); + } + FileOutputStream outStream = new FileOutputStream(file); + NBTReflectionUtil.saveNBTFile(nbt, outStream); + } - public File getFile() { - return file; - } + /** + * @return The File used to store the data + */ + public File getFile() { + return file; + } - protected Object getCompound() { - return nbt; - } + @Override + public Object getCompound() { + return nbt; + } - protected void setCompound(Object compound) { - nbt = compound; - } + @Override + protected void setCompound(Object compound) { + nbt = compound; + } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTIntegerList.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTIntegerList.java new file mode 100644 index 0000000..7764d79 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTIntegerList.java @@ -0,0 +1,45 @@ +package com.songoda.epicenchants.utils.itemnbtapi; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * Integer implementation for NBTLists + * + * @author tr7zw + * + */ +public class NBTIntegerList extends NBTList { + + protected NBTIntegerList(NBTCompound owner, String name, NBTType type, Object list) { + super(owner, name, type, list); + } + + @Override + protected Object asTag(Integer object) { + try { + Constructor con = ClassWrapper.NMS_NBTTAGINT.getClazz().getDeclaredConstructor(int.class); + con.setAccessible(true); + return con.newInstance(object); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e); + } + } + + @Override + public Integer get(int index) { + try { + Object obj = ReflectionMethod.LIST_GET.run(listObject, index); + return Integer.valueOf(obj.toString()); + } catch (NumberFormatException nf) { + return 0; + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTItem.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTItem.java index da1ae7b..3167390 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTItem.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTItem.java @@ -2,51 +2,85 @@ package com.songoda.epicenchants.utils.itemnbtapi; import org.bukkit.inventory.ItemStack; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * NBT class to access vanilla/custom tags on ItemStacks. This class doesn't + * autosave to the Itemstack, use getItem to get the changed ItemStack + * + * @author tr7zw + * + */ public class NBTItem extends NBTCompound { - private ItemStack bukkitItem; + private ItemStack bukkitItem; - public NBTItem(ItemStack item) { - super(null, null); - if (item == null) { - throw new NullPointerException("ItemStack can't be null!"); - } - bukkitItem = item.clone(); - } + /** + * Constructor for NBTItems. The ItemStack will be cloned! + * + * @param item + */ + public NBTItem(ItemStack item) { + super(null, null); + if (item == null) { + throw new NullPointerException("ItemStack can't be null!"); + } + bukkitItem = item.clone(); + } - public static NBTContainer convertItemtoNBT(ItemStack item) { - return NBTReflectionUtil.convertNMSItemtoNBTCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, item)); - } + @Override + public Object getCompound() { + return NBTReflectionUtil.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem)); + } - public static ItemStack convertNBTtoItem(NBTCompound comp) { - return (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp)); - } + @Override + protected void setCompound(Object compound) { + Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem); + ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, compound); + bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack); + } - protected Object getCompound() { - return NBTReflectionUtil.getItemRootNBTTagCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem)); - } + /** + * @return The modified ItemStack + */ + public ItemStack getItem() { + return bukkitItem; + } - protected void setCompound(Object compound) { - Object stack = ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, bukkitItem); - ReflectionMethod.ITEMSTACK_SET_TAG.run(stack, compound); - bukkitItem = (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, stack); - } + protected void setItem(ItemStack item) { + bukkitItem = item; + } - public ItemStack getItem() { - return bukkitItem; - } + /** + * This may return true even when the NBT is empty. + * + * @return Does the ItemStack have a NBTCompound. + */ + public boolean hasNBTData() { + return getCompound() != null; + } - protected void setItem(ItemStack item) { - bukkitItem = item; - } + /** + * Helper method that converts {@link ItemStack} to {@link NBTContainer} with + * all it's data like Material, Damage, Amount and Tags. + * + * @param item + * @return Standalone {@link NBTContainer} with the Item's data + */ + public static NBTContainer convertItemtoNBT(ItemStack item) { + return NBTReflectionUtil.convertNMSItemtoNBTCompound(ReflectionMethod.ITEMSTACK_NMSCOPY.run(null, item)); + } - /** - * This may return true even when the NBT is empty. - * - * @return Does the ItemStack have a NBTCompound. - */ - public boolean hasNBTData() { - return getCompound() != null; - } + /** + * Helper method to do the inverse to "convertItemtoNBT". Creates an + * {@link ItemStack} using the {@link NBTCompound} + * + * @param comp + * @return ItemStack using the {@link NBTCompound}'s data + */ + public static ItemStack convertNBTtoItem(NBTCompound comp) { + return (ItemStack) ReflectionMethod.ITEMSTACK_BUKKITMIRROR.run(null, + NBTReflectionUtil.convertNBTCompoundtoNMSItem(comp)); + } } 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 f0df6d3..0eeafd9 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTList.java @@ -1,127 +1,335 @@ package com.songoda.epicenchants.utils.itemnbtapi; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; + import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; -public class NBTList { +/** + * Abstract List implementation for ListCompounds + * + * @author tr7zw + * + * @param + */ +public abstract class NBTList implements List { - private String listName; - private NBTCompound parent; - private NBTType type; - private Object listObject; + private String listName; + private NBTCompound parent; + private NBTType type; + protected Object listObject; - protected NBTList(NBTCompound owner, String name, NBTType type, Object list) { - parent = owner; - listName = name; - this.type = type; - this.listObject = list; - if (!(type == NBTType.NBTTagString || type == NBTType.NBTTagCompound)) { - System.err.println("List types != String/Compound are currently not implemented!"); - } - } + protected NBTList(NBTCompound owner, String name, NBTType type, Object list) { + parent = owner; + listName = name; + this.type = type; + this.listObject = list; + } + + /** + * @return Name of this list-compound + */ + public String getName(){ + return listName; + } + + /** + * @return The Compound's parent Object + */ + public NBTCompound getParent() { + return parent; + } - protected void save() { - parent.set(listName, listObject); - } + protected void save() { + parent.set(listName, listObject); + } - public NBTListCompound addCompound() { - if (type != NBTType.NBTTagCompound) { - new Throwable("Using Compound method on a non Compound list!").printStackTrace(); - return null; - } - try { - Object compound = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance(); - if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) { - ReflectionMethod.LIST_ADD.run(listObject, 0, compound); - } else { - ReflectionMethod.LEGACY_LIST_ADD.run(listObject, compound); - } - return new NBTListCompound(this, compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + protected abstract Object asTag(T object); - public NBTListCompound getCompound(int id) { - if (type != NBTType.NBTTagCompound) { - new Throwable("Using Compound method on a non Compound list!").printStackTrace(); - return null; - } - try { - Object compound = ReflectionMethod.LIST_GET.run(listObject, id); - return new NBTListCompound(this, compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + @Override + public boolean add(T element) { + try { + if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) { + ReflectionMethod.LIST_ADD.run(listObject, size(), asTag(element)); + } else { + ReflectionMethod.LEGACY_LIST_ADD.run(listObject, asTag(element)); + } + save(); + return true; + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } - public String getString(int i) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return null; - } - try { - return (String) ReflectionMethod.LIST_GET_STRING.run(listObject, i); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + @Override + public void add(int index, T element) { + try { + if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) { + ReflectionMethod.LIST_ADD.run(listObject, index, asTag(element)); + } else { + ReflectionMethod.LEGACY_LIST_ADD.run(listObject, asTag(element)); + } + save(); + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } - public void addString(String s) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return; - } - try { - if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_14_R1.getVersionId()) { - ReflectionMethod.LIST_ADD.run(listObject, 0, - ClassWrapper.NMS_NBTTAGSTRING.getClazz().getConstructor(String.class).newInstance(s)); - } else { - ReflectionMethod.LEGACY_LIST_ADD.run(listObject, - ClassWrapper.NMS_NBTTAGSTRING.getClazz().getConstructor(String.class).newInstance(s)); - } - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + @Override + public T set(int index, T element) { + try { + T prev = get(index); + ReflectionMethod.LIST_SET.run(listObject, index, asTag(element)); + save(); + return prev; + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } - public void setString(int i, String s) { - if (type != NBTType.NBTTagString) { - new Throwable("Using String method on a non String list!").printStackTrace(); - return; - } - try { - ReflectionMethod.LIST_SET.run(listObject, i, - ClassWrapper.NMS_NBTTAGSTRING.getClazz().getConstructor(String.class).newInstance(s)); - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public T remove(int i) { + try { + T old = get(i); + ReflectionMethod.LIST_REMOVE_KEY.run(listObject, i); + save(); + return old; + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } - public void remove(int i) { - try { - ReflectionMethod.LIST_REMOVE_KEY.run(listObject, i); - save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + public int size() { + try { + return (int) ReflectionMethod.LIST_SIZE.run(listObject); + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } - public int size() { - try { - return (int) ReflectionMethod.LIST_SIZE.run(listObject); - } catch (Exception ex) { - ex.printStackTrace(); - } - return -1; - } + /** + * @return The type that this list contains + */ + public NBTType getType() { + return type; + } - public NBTType getType() { - return type; - } + @Override + public boolean isEmpty() { + return size() == 0; + } -} \ No newline at end of file + @Override + public void clear() { + while (!isEmpty()) { + remove(0); + } + } + + @Override + public boolean contains(Object o) { + for (int i = 0; i < size(); i++) { + if (o.equals(get(i))) + return true; + } + return false; + } + + @Override + public int indexOf(Object o) { + for (int i = 0; i < size(); i++) { + if (o.equals(get(i))) + return i; + } + return -1; + } + + @Override + public boolean addAll(Collection c) { + int size = size(); + for (T ele : c) { + add(ele); + } + return size != size(); + } + + @Override + public boolean addAll(int index, Collection c) { + int size = size(); + for (T ele : c) { + add(index++, ele); + } + return size != size(); + } + + @Override + public boolean containsAll(Collection c) { + for (Object ele : c) { + if (!contains(ele)) + return false; + } + return true; + } + + @Override + public int lastIndexOf(Object o) { + int index = -1; + for (int i = 0; i < size(); i++) { + if (o.equals(get(i))) + index = i; + } + return index; + } + + @Override + public boolean removeAll(Collection c) { + int size = size(); + for (Object obj : c) { + remove(obj); + } + return size != size(); + } + + @Override + public boolean retainAll(Collection c) { + int size = size(); + for (Object obj : c) { + for (int i = 0; i < size(); i++) { + if (!obj.equals(get(i))) { + remove(i--); + } + } + } + return size != size(); + } + + @Override + public boolean remove(Object o) { + int size = size(); + int id = -1; + while ((id = indexOf(o)) != -1) { + remove(id); + } + return size != size(); + } + + @Override + public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + @Override + public boolean hasNext() { + return size() > index + 1; + } + + @Override + public T next() { + if (!hasNext()) + throw new NoSuchElementException(); + return get(++index); + } + }; + } + + @Override + public ListIterator listIterator() { + return listIterator(0); + } + + @Override + public ListIterator listIterator(int startIndex) { + final NBTList list = this; + return new ListIterator() { + + int index = startIndex; + + @Override + public void add(T e) { + list.add(index, e); + } + + @Override + public boolean hasNext() { + return size() > index + 1; + } + + @Override + public boolean hasPrevious() { + return index > 0; + } + + @Override + public T next() { + if (!hasNext()) + throw new NoSuchElementException(); + return get(++index); + } + + @Override + public int nextIndex() { + return index + 1; + } + + @Override + public T previous() { + return get(--index); + } + + @Override + public int previousIndex() { + return index - 1; + } + + @Override + public void remove() { + list.remove(index); + } + + @Override + public void set(T e) { + list.set(index, e); + } + }; + } + + @Override + public Object[] toArray() { + Object[] ar = new Object[size()]; + for (int i = 0; i < size(); i++) + ar[i] = get(i); + return ar; + } + + @SuppressWarnings("unchecked") + @Override + public E[] toArray(E[] a) { + E[] ar = Arrays.copyOf(a, size()); + Arrays.fill(ar, null); + Class arrayclass = a.getClass().getComponentType(); + for (int i = 0; i < size(); i++) { + T obj = get(i); + if (arrayclass.isInstance(obj)) { + ar[i] = (E) get(i); + } else { + throw new ArrayStoreException("The array does not match the objects stored in the List."); + } + } + return ar; + } + + @Override + public List subList(int fromIndex, int toIndex) { + ArrayList list = new ArrayList<>(); + for (int i = fromIndex; i < toIndex; i++) + list.add(get(i)); + return list; + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTListCompound.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTListCompound.java index 234543e..1cabef8 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTListCompound.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTListCompound.java @@ -1,102 +1,42 @@ package com.songoda.epicenchants.utils.itemnbtapi; -import java.util.HashSet; -import java.util.Set; +/** + * Cut down version of the {@link NBTCompound} for inside + * {@link NBTCompoundList} This Compound implementation is missing the ability + * for further subCompounds and Lists. This class probably will change in the + * future + * + * @author tr7zw + * + */ +public class NBTListCompound extends NBTCompound { -public class NBTListCompound { + private NBTList owner; + private Object compound; - private NBTList owner; - private Object compound; + protected NBTListCompound(NBTList parent, Object obj) { + super(null, null); + owner = parent; + compound = obj; + } + + public NBTList getListParent() { + return owner; + } - protected NBTListCompound(NBTList parent, Object obj) { - owner = parent; - compound = obj; - } + @Override + public Object getCompound() { + return compound; + } - public void setString(String key, String value) { - if (value == null) { - remove(key); - return; - } - try { - compound.getClass().getMethod("setString", String.class, String.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + @Override + protected void setCompound(Object compound) { + this.compound = compound; + } - public void setInteger(String key, int value) { - try { - compound.getClass().getMethod("setInt", String.class, int.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public int getInteger(String value) { - try { - return (int) compound.getClass().getMethod("getInt", String.class).invoke(compound, value); - } catch (Exception ex) { - ex.printStackTrace(); - } - return 0; - } - - public void setDouble(String key, double value) { - try { - compound.getClass().getMethod("setDouble", String.class, double.class).invoke(compound, key, value); - owner.save(); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public double getDouble(String key) { - try { - return (double) compound.getClass().getMethod("getDouble", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return 0; - } - - - public String getString(String key) { - try { - return (String) compound.getClass().getMethod("getString", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return ""; - } - - public boolean hasKey(String key) { - try { - return (boolean) compound.getClass().getMethod("hasKey", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - return false; - } - - @SuppressWarnings("unchecked") - public Set getKeys() { - try { - return (Set) ReflectionMethod.LISTCOMPOUND_GET_KEYS.run(compound); - } catch (Exception ex) { - ex.printStackTrace(); - } - return new HashSet<>(); - } - - public void remove(String key) { - try { - compound.getClass().getMethod("remove", String.class).invoke(compound, key); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + @Override + protected void saveCompound() { + owner.save(); + } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTReflectionUtil.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTReflectionUtil.java index 8e694be..17dcefb 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTReflectionUtil.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTReflectionUtil.java @@ -1,347 +1,498 @@ package com.songoda.epicenchants.utils.itemnbtapi; -import com.songoda.epicenchants.utils.itemnbtapi.utils.GsonWrapper; -import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; -import org.bukkit.block.BlockState; -import org.bukkit.entity.Entity; - import java.io.FileInputStream; import java.io.FileOutputStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; +import java.io.Serializable; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.Set; -import java.util.Stack; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.GsonWrapper; +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ObjectCreator; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * Utility class for translating NBTApi calls to reflections into NMS code All + * methods are allowed to throw {@link NbtApiException} + * + * @author tr7zw + * + */ public class NBTReflectionUtil { - public static Object getNMSEntity(Entity entity) { - try { - return ReflectionMethod.CRAFT_ENTITY_GET_HANDLE.run(ClassWrapper.CRAFT_ENTITY.getClazz().cast(entity)); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Hidden constructor + */ + private NBTReflectionUtil() { - public static Object readNBTFile(FileInputStream stream) { - try { - return ReflectionMethod.NBTFILE_READ.run(null, stream); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + } - public static Object saveNBTFile(Object nbt, FileOutputStream stream) { - try { - return ReflectionMethod.NBTFILE_WRITE.run(null, nbt, stream); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Gets the NMS Entity for a given Bukkit Entity + * + * @param entity Bukkit Entity + * @return NMS Entity + */ + public static Object getNMSEntity(Entity entity) { + try { + return ReflectionMethod.CRAFT_ENTITY_GET_HANDLE.run(ClassWrapper.CRAFT_ENTITY.getClazz().cast(entity)); + } catch (Exception e) { + throw new NbtApiException("Exception while getting the NMS Entity from a Bukkit Entity!", e); + } + } - @SuppressWarnings({"unchecked"}) - public static Object getItemRootNBTTagCompound(Object nmsitem) { - @SuppressWarnings("rawtypes") - Class clazz = nmsitem.getClass(); - Method method; - try { - method = clazz.getMethod("getTag"); - Object answer = method.invoke(nmsitem); - return answer; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Reads in a FileInputStream as NMS Compound + * + * @param stream InputStream of any NBT file + * @return NMS Compound + */ + public static Object readNBTFile(FileInputStream stream) { + try { + return ReflectionMethod.NBTFILE_READ.run(null, stream); + } catch (Exception e) { + throw new NbtApiException("Exception while reading a NBT File!", e); + } + } - @SuppressWarnings({"unchecked"}) - public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) { - @SuppressWarnings("rawtypes") - Class clazz = ClassWrapper.NMS_ITEMSTACK.getClazz(); - try { - if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_12_R1.getVersionId()) { - Constructor constructor = clazz.getConstructor(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()); - constructor.setAccessible(true); - return constructor.newInstance(nbtcompound.getCompound()); - } else { - Method method = clazz.getMethod("createStack", ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()); - method.setAccessible(true); - return method.invoke(null, nbtcompound.getCompound()); - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Writes a NMS Compound to a FileOutputStream + * + * @param nbt NMS Compound + * @param stream Stream to write to + * @return ??? + */ + public static Object saveNBTFile(Object nbt, FileOutputStream stream) { + try { + return ReflectionMethod.NBTFILE_WRITE.run(null, nbt, stream); + } catch (Exception e) { + throw new NbtApiException("Exception while saving a NBT File!", e); + } + } - @SuppressWarnings({"unchecked"}) - public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) { - @SuppressWarnings("rawtypes") - Class clazz = nmsitem.getClass(); - Method method; - try { - method = clazz.getMethod("save", ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()); - Object answer = method.invoke(nmsitem, ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance()); - return new NBTContainer(answer); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Simulates getOrCreateTag. If an Item doesn't yet have a Tag, it will return a + * new empty tag. + * + * @param nmsitem + * @return NMS Compound + */ + public static Object getItemRootNBTTagCompound(Object nmsitem) { + try { + Object answer = ReflectionMethod.NMSITEM_GETTAG.run(nmsitem); + return answer != null ? answer : ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } catch (Exception e) { + throw new NbtApiException("Exception while getting an Itemstack's NBTCompound!", e); + } + } - public static Object getEntityNBTTagCompound(Object NMSEntity) { - try { - Object nbt = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance(); - Object answer = ReflectionMethod.NMS_ENTITY_GET_NBT.run(NMSEntity, nbt); - if (answer == null) - answer = nbt; - return answer; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Converts {@link NBTCompound} to NMS ItemStacks + * + * @param nbtcompound Any valid {@link NBTCompound} + * @return NMS ItemStack + */ + public static Object convertNBTCompoundtoNMSItem(NBTCompound nbtcompound) { + try { + if (MinecraftVersion.getVersion().getVersionId() >= MinecraftVersion.MC1_11_R1.getVersionId()) { + return ObjectCreator.NMS_COMPOUNDFROMITEM.getInstance(nbtcompound.getCompound()); + } else { + return ReflectionMethod.NMSITEM_CREATESTACK.run(null, nbtcompound.getCompound()); + } + } catch (Exception e) { + throw new NbtApiException("Exception while converting NBTCompound to NMS ItemStack!", e); + } + } - public static Object setEntityNBTTag(Object NBTTag, Object NMSEntity) { - try { - ReflectionMethod.NMS_ENTITY_SET_NBT.run(NMSEntity, NBTTag); - return NMSEntity; - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + /** + * Converts NMS ItemStacks to {@link NBTContainer} + * + * @param nmsitem NMS ItemStack + * @return {@link NBTContainer} with all the data + */ + public static NBTContainer convertNMSItemtoNBTCompound(Object nmsitem) { + try { + Object answer = ReflectionMethod.NMSITEM_SAVE.run(nmsitem, ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance()); + return new NBTContainer(answer); + } catch (Exception e) { + throw new NbtApiException("Exception while converting NMS ItemStack to NBTCompound!", e); + } + } - public static Object getTileEntityNBTTagCompound(BlockState tile) { - try { - Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ()); - Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld()); - Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld); - Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos); - Object tag = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance(); - Object answer = ReflectionMethod.TILEENTITY_GET_NBT.run(o, tag); - if (answer == null) - answer = tag; - return answer; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Gets the Vanilla NBT Compound from a given NMS Entity + * + * @param nmsEntity + * @return NMS NBT Compound + */ + public static Object getEntityNBTTagCompound(Object nmsEntity) { + try { + Object nbt = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance(); + Object answer = ReflectionMethod.NMS_ENTITY_GET_NBT.run(nmsEntity, nbt); + if (answer == null) + answer = nbt; + return answer; + } catch (Exception e) { + throw new NbtApiException("Exception while getting NBTCompound from NMS Entity!", e); + } + } - public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) { - try { - Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ()); - Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld()); - Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld); - Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos); - ReflectionMethod.TILEENTITY_SET_NBT.run(o, comp); - } catch (Exception e) { - e.printStackTrace(); - } - } + /** + * Loads all Vanilla tags from a NMS Compound into a NMS Entity + * + * @param nbtTag + * @param nmsEntity + * @return The NMS Entity + */ + public static Object setEntityNBTTag(Object nbtTag, Object nmsEntity) { + try { + ReflectionMethod.NMS_ENTITY_SET_NBT.run(nmsEntity, nbtTag); + return nmsEntity; + } catch (Exception ex) { + throw new NbtApiException("Exception while setting the NBTCompound of an Entity", ex); + } + } + /** + * Gets the NMS Compound from a given TileEntity + * + * @param tile + * @return NMS Compound with the Vanilla data + */ + public static Object getTileEntityNBTTagCompound(BlockState tile) { + try { + Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ()); + Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld()); + Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld); + Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos); + Object tag = ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance(); + Object answer = ReflectionMethod.TILEENTITY_GET_NBT.run(o, tag); + if (answer == null) + answer = tag; + return answer; + } catch (Exception e) { + throw new NbtApiException("Exception while getting NBTCompound from TileEntity!", e); + } + } - @SuppressWarnings("unchecked") - public static Object getSubNBTTagCompound(Object compound, String name) { - @SuppressWarnings("rawtypes") - Class c = compound.getClass(); - Method method; - try { - method = c.getMethod("getCompound", String.class); - Object answer = method.invoke(compound, name); - return answer; - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } + /** + * Sets Vanilla tags from a NMS Compound to a TileEntity + * + * @param tile + * @param comp + */ + public static void setTileEntityNBTTagCompound(BlockState tile, Object comp) { + try { + Object pos = ObjectCreator.NMS_BLOCKPOSITION.getInstance(tile.getX(), tile.getY(), tile.getZ()); + Object cworld = ClassWrapper.CRAFT_WORLD.getClazz().cast(tile.getWorld()); + Object nmsworld = ReflectionMethod.CRAFT_WORLD_GET_HANDLE.run(cworld); + Object o = ReflectionMethod.NMS_WORLD_GET_TILEENTITY.run(nmsworld, pos); + ReflectionMethod.TILEENTITY_SET_NBT.run(o, comp); + } catch (Exception e) { + throw new NbtApiException("Exception while setting NBTData for a TileEntity!", e); + } + } - public static void addNBTTagCompound(NBTCompound comp, String name) { - if (name == null) { - remove(comp, name); - return; - } - Object nbttag = comp.getCompound(); - if (nbttag == null) { - nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(nbttag, comp); - Method method; - try { - method = workingtag.getClass().getMethod("set", String.class, ClassWrapper.NMS_NBTBASE.getClazz()); - method.invoke(workingtag, name, ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance()); - comp.setCompound(nbttag); - return; - } catch (Exception ex) { - ex.printStackTrace(); - } - return; - } + /** + * Gets the subCompound with a given name from a NMS Compound + * + * @param compound + * @param name + * @return NMS Compound or null + */ + public static Object getSubNBTTagCompound(Object compound, String name) { + try { + if ((boolean) ReflectionMethod.COMPOUND_HAS_KEY.run(compound, name)) { + return ReflectionMethod.COMPOUND_GET_COMPOUND.run(compound, name); + } else { + throw new NbtApiException("Tried getting invalide compound '" + name + "' from '" + compound + "'!"); + } + } catch (Exception e) { + throw new NbtApiException("Exception while getting NBT subcompounds!", e); + } + } - public static Boolean valideCompound(NBTCompound comp) { - Object root = comp.getCompound(); - if (root == null) { - root = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - return (gettoCompount(root, comp)) != null; - } + /** + * Creates a subCompound with a given name in the given NMS Compound + * + * @param comp + * @param name + */ + public static void addNBTTagCompound(NBTCompound comp, String name) { + if (name == null) { + remove(comp, name); + return; + } + Object nbttag = comp.getCompound(); + if (nbttag == null) { + nbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) + return; + Object workingtag = gettoCompount(nbttag, comp); + try { + ReflectionMethod.COMPOUND_SET.run(workingtag, name, + ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz().newInstance()); + comp.setCompound(nbttag); + } catch (Exception e) { + throw new NbtApiException("Exception while adding a Compound!", e); + } + } - static Object gettoCompount(Object nbttag, NBTCompound comp) { - Stack structure = new Stack<>(); - while (comp.getParent() != null) { - structure.add(comp.getName()); - comp = comp.getParent(); - } - while (!structure.isEmpty()) { - nbttag = getSubNBTTagCompound(nbttag, structure.pop()); - if (nbttag == null) { - return null; - } - } - return nbttag; - } + /** + * Checks if the Compound is correctly linked to it's roots + * + * @param comp + * @return true if this is a valide Compound, else false + */ + public static Boolean valideCompound(NBTCompound comp) { + Object root = comp.getCompound(); + if (root == null) { + root = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + return (gettoCompount(root, comp)) != null; + } - public static void addOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - try { - ReflectionMethod.COMPOUND_ADD.run(workingtag, nbtcompound.getCompound()); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + protected static Object gettoCompount(Object nbttag, NBTCompound comp) { + Deque structure = new ArrayDeque<>(); + while (comp.getParent() != null) { + structure.add(comp.getName()); + comp = comp.getParent(); + } + while (!structure.isEmpty()) { + String target = structure.pollLast(); + nbttag = getSubNBTTagCompound(nbttag, target); + if (nbttag == null) { + throw new NbtApiException("Unable to find tag '" + target + "' in " + nbttag); + } + } + return nbttag; + } - public static String getContent(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - Method method; - try { - method = workingtag.getClass().getMethod("get", String.class); - return method.invoke(workingtag, key).toString(); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + /** + * Merges the second {@link NBTCompound} into the first one + * + * @param comp Target for the merge + * @param nbtcompound Data to merge + */ + public static void mergeOtherNBTCompound(NBTCompound comp, NBTCompound nbtcompound) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) + throw new NbtApiException("The Compound wasn't able to be linked back to the root!"); + Object workingtag = gettoCompount(rootnbttag, comp); + try { + ReflectionMethod.COMPOUND_MERGE.run(workingtag, nbtcompound.getCompound()); + comp.setCompound(rootnbttag); + } catch (Exception e) { + throw new NbtApiException("Exception while merging two NBTCompounds!", e); + } + } - public static void set(NBTCompound comp, String key, Object val) { - if (val == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - if (!valideCompound(comp)) { - new Throwable("InvalideCompound").printStackTrace(); - return; - } - Object workingtag = gettoCompount(rootnbttag, comp); - Method method; - try { - method = workingtag.getClass().getMethod("set", String.class, ClassWrapper.NMS_NBTBASE.getClazz()); - method.invoke(workingtag, key, val); - comp.setCompound(rootnbttag); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + /** + * Returns the content for a given key inside a Compound + * + * @param comp + * @param key + * @return Content saved under this key + */ + public static String getContent(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) + throw new NbtApiException("The Compound wasn't able to be linked back to the root!"); + Object workingtag = gettoCompount(rootnbttag, comp); + try { + return ReflectionMethod.COMPOUND_GET.run(workingtag, key).toString(); + } catch (Exception e) { + throw new NbtApiException("Exception while getting the Content for key '" + key + "'!", e); + } + } - public static NBTList getList(NBTCompound comp, String key, NBTType type) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - Method method; - try { - method = workingtag.getClass().getMethod("getList", String.class, int.class); - return new NBTList(comp, key, type, method.invoke(workingtag, key, type.getId())); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } + /** + * Sets a key in a {@link NBTCompound} to a given value + * + * @param comp + * @param key + * @param val + */ + public static void set(NBTCompound comp, String key, Object val) { + if (val == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) { + throw new NbtApiException("The Compound wasn't able to be linked back to the root!"); + } + Object workingtag = gettoCompount(rootnbttag, comp); + try { + ReflectionMethod.COMPOUND_SET.run(workingtag, key, val); + comp.setCompound(rootnbttag); + } catch (Exception e) { + throw new NbtApiException("Exception while setting key '" + key + "' to '" + val + "'!", e); + } + } - public static void setObject(NBTCompound comp, String key, Object value) { - if (!MinecraftVersion.hasGsonSupport()) return; - try { - String json = GsonWrapper.getString(value); - setData(comp, ReflectionMethod.COMPOUND_SET_STRING, key, json); - } catch (Exception ex) { - ex.printStackTrace(); - } - } + /** + * Returns the List saved with a given key. + * + * @param comp + * @param key + * @param type + * @param clazz + * @return The list at that key. Null if it's an invalide type + */ + @SuppressWarnings("unchecked") + public static NBTList getList(NBTCompound comp, String key, NBTType type, Class clazz) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) + return null; + Object workingtag = gettoCompount(rootnbttag, comp); + try { + Object nbt = ReflectionMethod.COMPOUND_GET_LIST.run(workingtag, key, type.getId()); + if (clazz == String.class) { + return (NBTList) new NBTStringList(comp, key, type, nbt); + } else if (clazz == NBTListCompound.class) { + return (NBTList) new NBTCompoundList(comp, key, type, nbt); + } else if (clazz == Integer.class) { + return (NBTList) new NBTIntegerList(comp, key, type, nbt); + } else { + return null; + } + } catch (Exception ex) { + throw new NbtApiException("Exception while getting a list with the type '" + type + "'!", ex); + } + } - public static T getObject(NBTCompound comp, String key, Class type) { - if (!MinecraftVersion.hasGsonSupport()) return null; - String json = (String) getData(comp, ReflectionMethod.COMPOUND_GET_STRING, key); - if (json == null) { - return null; - } - return GsonWrapper.deserializeJson(json, type); - } + /** + * Uses Gson to set a {@link Serializable} value in a Compound + * + * @param comp + * @param key + * @param value + */ + public static void setObject(NBTCompound comp, String key, Object value) { + if (!MinecraftVersion.hasGsonSupport()) + return; + try { + String json = GsonWrapper.getString(value); + setData(comp, ReflectionMethod.COMPOUND_SET_STRING, key, json); + } catch (Exception e) { + throw new NbtApiException("Exception while setting the Object '" + value + "'!", e); + } + } - public static void remove(NBTCompound comp, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - ReflectionMethod.COMPOUND_REMOVE_KEY.run(workingtag, key); - comp.setCompound(rootnbttag); - } + /** + * Uses Gson to load back a {@link Serializable} object from the Compound + * + * @param comp + * @param key + * @param type + * @return The loaded Object or null, if not found + */ + public static T getObject(NBTCompound comp, String key, Class type) { + if (!MinecraftVersion.hasGsonSupport()) + return null; + String json = (String) getData(comp, ReflectionMethod.COMPOUND_GET_STRING, key); + if (json == null) { + return null; + } + return GsonWrapper.deserializeJson(json, type); + } - @SuppressWarnings("unchecked") - public static Set getKeys(NBTCompound comp) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - return (Set) ReflectionMethod.COMPOUND_GET_KEYS.run(workingtag); - } + /** + * Deletes the given key + * + * @param comp + * @param key + */ + public static void remove(NBTCompound comp, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) + return; + Object workingtag = gettoCompount(rootnbttag, comp); + ReflectionMethod.COMPOUND_REMOVE_KEY.run(workingtag, key); + comp.setCompound(rootnbttag); + } - public static void setData(NBTCompound comp, ReflectionMethod type, String key, Object data) { - if (data == null) { - remove(comp, key); - return; - } - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); - } - if (!valideCompound(comp)) return; - Object workingtag = gettoCompount(rootnbttag, comp); - type.run(workingtag, key, data); - comp.setCompound(rootnbttag); - } + /** + * Gets the Keyset inside this Compound + * + * @param comp + * @return Set of all keys + */ + @SuppressWarnings("unchecked") + public static Set getKeys(NBTCompound comp) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) + throw new NbtApiException("The Compound wasn't able to be linked back to the root!"); + Object workingtag = gettoCompount(rootnbttag, comp); + return (Set) ReflectionMethod.COMPOUND_GET_KEYS.run(workingtag); + } - public static Object getData(NBTCompound comp, ReflectionMethod type, String key) { - Object rootnbttag = comp.getCompound(); - if (rootnbttag == null) { - return null; - } - if (!valideCompound(comp)) return null; - Object workingtag = gettoCompount(rootnbttag, comp); - return type.run(workingtag, key); - } + /** + * Sets data inside the Compound + * + * @param comp + * @param type + * @param key + * @param data + */ + public static void setData(NBTCompound comp, ReflectionMethod type, String key, Object data) { + if (data == null) { + remove(comp, key); + return; + } + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + rootnbttag = ObjectCreator.NMS_NBTTAGCOMPOUND.getInstance(); + } + if (!valideCompound(comp)) + throw new NbtApiException("The Compound wasn't able to be linked back to the root!"); + Object workingtag = gettoCompount(rootnbttag, comp); + type.run(workingtag, key, data); + comp.setCompound(rootnbttag); + } + + /** + * Gets data from the Compound + * + * @param comp + * @param type + * @param key + * @return The value or default fallback from NMS + */ + public static Object getData(NBTCompound comp, ReflectionMethod type, String key) { + Object rootnbttag = comp.getCompound(); + if (rootnbttag == null) { + return null; + } + if (!valideCompound(comp)) + throw new NbtApiException("The Compound wasn't able to be linked back to the root!"); + Object workingtag = gettoCompount(rootnbttag, comp); + return type.run(workingtag, key); + } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTStringList.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTStringList.java new file mode 100644 index 0000000..079480c --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTStringList.java @@ -0,0 +1,42 @@ +package com.songoda.epicenchants.utils.itemnbtapi; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ClassWrapper; +import com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings.ReflectionMethod; + +/** + * String implementation for NBTLists + * + * @author tr7zw + * + */ +public class NBTStringList extends NBTList { + + protected NBTStringList(NBTCompound owner, String name, NBTType type, Object list) { + super(owner, name, type, list); + } + + @Override + public String get(int index) { + try { + return (String) ReflectionMethod.LIST_GET_STRING.run(listObject, index); + } catch (Exception ex) { + throw new NbtApiException(ex); + } + } + + @Override + protected Object asTag(String object) { + try { + Constructor con = ClassWrapper.NMS_NBTTAGSTRING.getClazz().getDeclaredConstructor(String.class); + con.setAccessible(true); + return con.newInstance(object); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + throw new NbtApiException("Error while wrapping the Object " + object + " to it's NMS object!", e); + } + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTTileEntity.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTTileEntity.java index 3f09d05..f71f970 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTTileEntity.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTTileEntity.java @@ -2,21 +2,35 @@ package com.songoda.epicenchants.utils.itemnbtapi; import org.bukkit.block.BlockState; +/** + * NBT class to access vanilla tags from TileEntities. TileEntities don't + * support custom tags. Use the NBTInjector for custom tags. Changes will be + * instantly applied to the Tile, use the merge method to do many things at + * once. + * + * @author tr7zw + * + */ public class NBTTileEntity extends NBTCompound { - private final BlockState tile; + private final BlockState tile; - public NBTTileEntity(BlockState tile) { - super(null, null); - this.tile = tile; - } + /** + * @param tile BlockState from any TileEntity + */ + public NBTTileEntity(BlockState tile) { + super(null, null); + this.tile = tile; + } - protected Object getCompound() { - return NBTReflectionUtil.getTileEntityNBTTagCompound(tile); - } + @Override + public Object getCompound() { + return NBTReflectionUtil.getTileEntityNBTTagCompound(tile); + } - protected void setCompound(Object compound) { - NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound); - } + @Override + protected void setCompound(Object compound) { + NBTReflectionUtil.setTileEntityNBTTagCompound(tile, compound); + } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTType.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTType.java index f54d603..cdd3c79 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTType.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NBTType.java @@ -1,34 +1,48 @@ package com.songoda.epicenchants.utils.itemnbtapi; +/** + * Enum of all NBT Types Minecraft contains + * + * @author tr7zw + * + */ +@SuppressWarnings("javadoc") public enum NBTType { - NBTTagEnd(0), + NBTTagEnd(0), NBTTagByte(1), - NBTTagShort(2), - NBTTagInt(3), - NBTTagLong(4), - NBTTagFloat(5), - NBTTagDouble(6), - NBTTagByteArray(7), - NBTTagIntArray(11), - NBTTagString(8), - NBTTagList(9), - NBTTagCompound(10); + NBTTagShort(2), + NBTTagInt(3), + NBTTagLong(4), + NBTTagFloat(5), + NBTTagDouble(6), + NBTTagByteArray(7), + NBTTagIntArray(11), + NBTTagString(8), + NBTTagList(9), + NBTTagCompound(10); - private final int id; + NBTType(int i) { + id = i; + } - NBTType(int i) { - id = i; - } + private final int id; - public static NBTType valueOf(int id) { - for (NBTType t : values()) - if (t.getId() == id) - return t; - return NBTType.NBTTagEnd; - } + /** + * @return Id used by Minecraft internally + */ + public int getId() { + return id; + } - public int getId() { - return id; - } + /** + * @param id Internal Minecraft id + * @return Enum representing the id, NBTTagEnd for invalide ids + */ + public static NBTType valueOf(int id) { + for (NBTType t : values()) + if (t.getId() == id) + return t; + return NBTType.NBTTagEnd; + } } diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NbtApiException.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NbtApiException.java new file mode 100644 index 0000000..b623837 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/NbtApiException.java @@ -0,0 +1,56 @@ +package com.songoda.epicenchants.utils.itemnbtapi; + +/** + * A generic {@link RuntimeException} that can be thrown by most methods in the + * NBTAPI. + * + * @author tr7zw + * + */ +public class NbtApiException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -993309714559452334L; + + /** + * + */ + public NbtApiException() { + super(); + } + + /** + * @param message + * @param cause + * @param enableSuppression + * @param writableStackTrace + */ + public NbtApiException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + /** + * @param message + * @param cause + */ + public NbtApiException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param message + */ + public NbtApiException(String message) { + super(message); + } + + /** + * @param cause + */ + public NbtApiException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ObjectCreator.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ObjectCreator.java deleted file mode 100644 index d303394..0000000 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ObjectCreator.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.songoda.epicenchants.utils.itemnbtapi; - -import java.lang.reflect.Constructor; - -public enum ObjectCreator { - NMS_NBTTAGCOMPOUND(ClassWrapper.NMS_NBTTAGCOMPOUND.getClazz()), - NMS_BLOCKPOSITION(ClassWrapper.NMS_BLOCKPOSITION.getClazz(), int.class, int.class, int.class); - - private Constructor construct; - - ObjectCreator(Class clazz, Class... args) { - try { - construct = clazz.getConstructor(args); - } catch (Exception ex) { - ex.printStackTrace(); - } - } - - public Object getInstance(Object... args) { - try { - return construct.newInstance(args); - } catch (Exception ex) { - ex.printStackTrace(); - } - return null; - } - -} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ApiMetricsLite.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ApiMetricsLite.java new file mode 100644 index 0000000..37c7abe --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ApiMetricsLite.java @@ -0,0 +1,377 @@ +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 + 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(); + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/GsonWrapper.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/GsonWrapper.java index 3fb7696..c39deb1 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/GsonWrapper.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/GsonWrapper.java @@ -2,26 +2,53 @@ package com.songoda.epicenchants.utils.itemnbtapi.utils; import com.google.gson.Gson; +import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException; + +/** + * Helper class for 1.7 servers without Gson + * + * @author tr7zw + * + */ public class GsonWrapper { - private static final Gson gson = new Gson(); + /** + * Private constructor + */ + private GsonWrapper() { - public static String getString(Object obj) { - return gson.toJson(obj); - } + } - public static T deserializeJson(String json, Class type) { - try { - if (json == null) { - return null; - } + private static final Gson gson = new Gson(); - T obj = gson.fromJson(json, type); - return type.cast(obj); - } catch (Exception ex) { - ex.printStackTrace(); - return null; - } - } + /** + * Turns Objects into Json Strings + * + * @param obj + * @return Json, representing the Object + */ + public static String getString(Object obj) { + return gson.toJson(obj); + } + + /** + * Creates an Object of the given type using the Json String + * + * @param json + * @param type + * @return Object that got created, or null if the json is null + */ + public static T deserializeJson(String json, Class type) { + try { + if (json == null) { + return null; + } + + T obj = gson.fromJson(json, type); + return type.cast(obj); + } catch (Exception ex) { + throw new NbtApiException("Error while converting json to " + type.getName(), ex); + } + } } 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 75b4f1b..46fbcb9 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 @@ -1,63 +1,141 @@ package com.songoda.epicenchants.utils.itemnbtapi.utils; +import java.util.logging.Level; +import java.util.logging.Logger; + import org.bukkit.Bukkit; +/** + * This class acts as the "Brain" of the NBTApi. It contains the main logger for + * other classes,registers bStats and checks rather Maven shading was done + * correctly. + * + * @author tr7zw + * + */ +@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); + 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); - private static MinecraftVersion version; - private static Boolean hasGsonSupport; + private static MinecraftVersion version; + private static Boolean hasGsonSupport; + private static boolean bStatsDisabled = false; + private static boolean disablePackageWarning = false; + /** + * Logger used by the api + */ + public static final Logger logger = Logger.getLogger("NBTAPI"); - private final int versionId; + private final int versionId; - MinecraftVersion(int versionId) { - this.versionId = versionId; - } + MinecraftVersion(int versionId) { + this.versionId = versionId; + } - public int getVersionId() { - return versionId; - } + /** + * @return A simple comparable Integer, representing the version. + */ + public int getVersionId() { + return versionId; + } - public static MinecraftVersion getVersion() { - if (version != null) { - return version; - } - final String ver = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; - System.out.println("[NBTAPI] Found Spigot: " + ver + "! Trying to find NMS support"); - try { - version = MinecraftVersion.valueOf(ver.replace("v", "MC")); - } catch (IllegalArgumentException ex) { - version = MinecraftVersion.Unknown; - } - if (version != Unknown) { - System.out.println("[NBTAPI] NMS support '" + version.name() + "' loaded!"); - } else { - System.out.println("[NBTAPI] Wasn't able to find NMS Support! Some functions may not work!"); - } - return version; - } + /** + * Getter for this servers MinecraftVersion. Also init's bStats and checks the + * shading. + * + * @return The enum for the MinecraftVersion this server is running + */ + public static MinecraftVersion getVersion() { + if (version != null) { + return version; + } + final String ver = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + logger.info("[NBTAPI] Found Spigot: " + ver + "! Trying to find NMS support"); + try { + version = MinecraftVersion.valueOf(ver.replace("v", "MC")); + } catch (IllegalArgumentException ex) { + version = MinecraftVersion.UNKNOWN; + } + if (version != UNKNOWN) { + logger.info("[NBTAPI] NMS support '" + version.name() + "' loaded!"); + } else { + logger.warning("[NBTAPI] Wasn't able to find NMS Support! Some functions may not work!"); + } + init(); + return version; + } - public static boolean hasGsonSupport() { - if (hasGsonSupport != null) { - return hasGsonSupport; - } - try { - System.out.println("Found Gson: " + Class.forName("com.google.gson.Gson")); - hasGsonSupport = true; - } catch (Exception ex) { - hasGsonSupport = false; - } - return hasGsonSupport; - } + private static void init() { + try { + if (!bStatsDisabled) + new ApiMetricsLite(); + } catch (Exception ex) { + logger.log(Level.WARNING, "[NBTAPI] Error enabeling Metrics!", ex); + } + // 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', + 'a', 'n', 'g', 'e', 'm', 'e', '.', 'n', 'b', 't', 'a', 'p', 'i', '.', 'u', 't', 'i', 'l', 's' }); + if (!disablePackageWarning && MinecraftVersion.class.getPackage().getName().equals(defaultPackage)) { + logger.warning( + "#########################################- NBTAPI -#########################################"); + logger.warning( + "The NBT-API package has not been moved! This *will* cause problems with other plugins containing"); + logger.warning( + "a different version of the api! Please read the guide on the plugin page on how to get the"); + logger.warning( + "Maven Shade plugin to relocate the api to your personal location! If you are not the developer,"); + logger.warning("please check your plugins and contact their developer, so he can fix this issue."); + logger.warning( + "#########################################- NBTAPI -#########################################"); + } + } -} \ No newline at end of file + /** + * @return True, if Gson is usable + */ + public static boolean hasGsonSupport() { + if (hasGsonSupport != null) { + return hasGsonSupport; + } + try { + logger.info("[NBTAPI] Found Gson: " + Class.forName("com.google.gson.Gson")); + hasGsonSupport = true; + } catch (Exception ex) { + logger.info("[NBTAPI] Gson not found! This will not allow the usage of some methods!"); + hasGsonSupport = false; + } + return hasGsonSupport; + } + + /** + * Calling this function before the NBT-Api is used will disable bStats stats + * collection. Please consider not to do that, since it won't affect your plugin + * and helps the NBT-Api developer to see api's demand. + */ + public static void disableBStats() { + bStatsDisabled = true; + } + + /** + * Forcefully disables the log message for plugins not shading the API to + * another location. This may be helpful for networks or development + * environments, but please don't use it for plugins that are uploaded to + * Spigotmc. + */ + public static void disablePackageWarning() { + disablePackageWarning = true; + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ReflectionUtil.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ReflectionUtil.java new file mode 100644 index 0000000..7c4d537 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/ReflectionUtil.java @@ -0,0 +1,53 @@ +package com.songoda.epicenchants.utils.itemnbtapi.utils; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException; + +public final class ReflectionUtil { + + private static Field field_modifiers; + + static { + try { + field_modifiers = Field.class.getDeclaredField("modifiers"); + field_modifiers.setAccessible(true); + } catch (NoSuchFieldException ex) { + try { + // This hacky workaround is for newer jdk versions 11+? + Method fieldGetter = Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class); + fieldGetter.setAccessible(true); + Field[] fields = (Field[]) fieldGetter.invoke(Field.class, false); + for (Field f : fields) + if (f.getName().equals("modifiers")) { + field_modifiers = f; + field_modifiers.setAccessible(true); + break; + } + } catch (Exception e) { + throw new NbtApiException(e); + } + } + if (field_modifiers == null) { + throw new NbtApiException("Unable to init the modifiers Field."); + } + } + + public static Field makeNonFinal(Field field) throws IllegalArgumentException, IllegalAccessException { + int mods = field.getModifiers(); + if (Modifier.isFinal(mods)) { + field_modifiers.set(field, mods & ~Modifier.FINAL); + } + return field; + } + + public static void setFinal(Object obj, Field field, Object newValue) + throws IllegalArgumentException, IllegalAccessException { + field.setAccessible(true); + field = makeNonFinal(field); + field.set(obj, newValue); + } + +} \ No newline at end of file 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 new file mode 100644 index 0000000..3aa04c3 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ClassWrapper.java @@ -0,0 +1,77 @@ +package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings; + +import java.util.logging.Level; +import org.bukkit.Bukkit; + +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; +import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.logger; + +/** + * Wraps NMS and CRAFT classes + * + * @author tr7zw + * + */ +@SuppressWarnings("javadoc") +public enum ClassWrapper { +CRAFT_ITEMSTACK(PackageWrapper.CRAFTBUKKIT, "inventory.CraftItemStack"), +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_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_WORLDSERVER(PackageWrapper.NMS, "WorldServer"), +NMS_MINECRAFTSERVER(PackageWrapper.NMS, "MinecraftServer"), +NMS_WORLD(PackageWrapper.NMS, "World"), +NMS_ENTITY(PackageWrapper.NMS, "Entity"), +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"); + + private Class clazz; + private boolean enabled = false; + + ClassWrapper(PackageWrapper packageId, String suffix){ + this(packageId, suffix, null, null); + } + + ClassWrapper(PackageWrapper packageId, String suffix, MinecraftVersion from, MinecraftVersion to){ + if(from != null && MinecraftVersion.getVersion().getVersionId() < from.getVersionId()) { + return; + } + if(to != null && MinecraftVersion.getVersion().getVersionId() > to.getVersionId()) { + return; + } + enabled = true; + try{ + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + clazz = Class.forName(packageId.getUri() + "." + version + "." + suffix); + }catch(Exception ex){ + logger.log(Level.WARNING, "[NBTAPI] Error while trying to resolve the class '" + suffix + "'!", ex); + } + } + + /** + * @return The wrapped class + */ + public Class getClazz(){ + return clazz; + } + + /** + * @return Is this class available in this Version + */ + public boolean isEnabled() { + return enabled; + } + +} 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 new file mode 100644 index 0000000..8c68fc0 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ObjectCreator.java @@ -0,0 +1,55 @@ +package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings; + +import java.lang.reflect.Constructor; +import java.util.logging.Level; + +import com.songoda.epicenchants.utils.itemnbtapi.NbtApiException; +import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; + +import static com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion.logger; + +/** + * This Enum wraps Constructors for NMS classes + * + * @author tr7zw + * + */ +@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()), + ; + + private Constructor construct; + private Class targetClass; + + 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 new file mode 100644 index 0000000..12d78c8 --- /dev/null +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/PackageWrapper.java @@ -0,0 +1,28 @@ +package com.songoda.epicenchants.utils.itemnbtapi.utils.nmsmappings; + +/** + * Package enum + * + * @author tr7zw + * + */ +@SuppressWarnings("javadoc") +public enum PackageWrapper { + NMS("net.minecraft.server"), + CRAFTBUKKIT("org.bukkit.craftbukkit"), + ; + + private final String uri; + + PackageWrapper(String uri) { + this.uri = uri; + } + + /** + * @return The Uri for that package + */ + public String getUri() { + return uri; + } + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ReflectionMethod.java b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java similarity index 56% rename from src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ReflectionMethod.java rename to src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java index 3f6d844..29ff274 100644 --- a/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/ReflectionMethod.java +++ b/src/main/java/com/songoda/epicenchants/utils/itemnbtapi/utils/nmsmappings/ReflectionMethod.java @@ -1,12 +1,20 @@ -package com.songoda.epicenchants.utils.itemnbtapi; - -import com.songoda.epicenchants.utils.itemnbtapi.utils.MinecraftVersion; -import org.bukkit.inventory.ItemStack; +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")), @@ -19,8 +27,11 @@ public enum ReflectionMethod { 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_ADD(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_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")), @@ -31,10 +42,15 @@ public enum ReflectionMethod { 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")), //FIXME: No Spigot mapping! + 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")), @@ -44,85 +60,123 @@ public enum ReflectionMethod { 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(ClassWrapper.NMS_NBTTAGLIST.getClazz(), new Class[]{int.class}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "get")), - + 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_WORLD.getClazz(), new Class[]{ClassWrapper.NMS_BLOCKPOSITION.getClazz()}, MinecraftVersion.MC1_7_R4, new Since(MinecraftVersion.MC1_7_R4, "getTileEntity")), - + 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; - - ReflectionMethod(Class targetClass, Class[] args, MinecraftVersion addedSince, MinecraftVersion removedAfter, Since... methodnames) { + 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; + 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()) + for(Since s : methodnames){ + if(s.version.getVersionId() <= server.getVersionId() && target.version.getVersionId() < s.version.getVersionId()) target = s; } targetVersion = target; - try { + try{ method = targetClass.getMethod(targetVersion.name, args); method.setAccessible(true); loaded = true; - } catch (NullPointerException | NoSuchMethodException | SecurityException ex) { - ex.printStackTrace(); + 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); + + ReflectionMethod(Class targetClass, Class[] args, MinecraftVersion addedSince, Since... methodnames){ + this(targetClass, args, addedSince, null, methodnames); } - - public Object run(Object target, Object... args) { - try { + + /** + * 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) { - ex.printStackTrace(); + }catch(Exception ex){ + throw new NbtApiException("Error while calling the method '" + methodName + "', loaded: " + loaded + ", Enum: " + this, ex); } - return null; } - + + /** + * @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; } - public static class Since { + protected static class Since{ public final MinecraftVersion version; public final String name; - public Since(MinecraftVersion version, String name) { this.version = version; this.name = name; } } -} \ No newline at end of file + +} diff --git a/src/main/java/com/songoda/epicenchants/utils/locale/Locale.java b/src/main/java/com/songoda/epicenchants/utils/locale/Locale.java deleted file mode 100644 index 18b50f4..0000000 --- a/src/main/java/com/songoda/epicenchants/utils/locale/Locale.java +++ /dev/null @@ -1,302 +0,0 @@ -package com.songoda.epicenchants.utils.locale; - -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -/** - * Assists in the utilization of localization files. - * Created to be used by the Songoda Team. - * - * @author Brianna O'Keefe - Songoda - */ -public class Locale { - - private static final List LOCALES = new ArrayList<>(); - private static final Pattern NODE_PATTERN = Pattern.compile("(\\w+(?:\\.{1}\\w+)*)\\s*=\\s*\"(.*)\""); - private static final String FILE_EXTENSION = ".lang"; - private static JavaPlugin plugin; - private static File localeFolder; - - private final Map nodes = new HashMap<>(); - - private static String defaultLocale; - - private File file; - private String name; - - /** - * Instantiate the Locale class for future use - * - * @param name the name of the instantiated language - */ - private Locale(String name) { - if (plugin == null) - return; - - this.name = name; - - String fileName = name + FILE_EXTENSION; - this.file = new File(localeFolder, fileName); - - if (!this.reloadMessages()) return; - - plugin.getLogger().info("Loaded locale \"" + fileName + "\""); - } - - /** - * Initialize the class to load all existing language files and update them. - * This must be called before any other methods in this class as otherwise - * the methods will fail to invoke - * - * @param plugin the plugin instance - * @param defaultLocale the default language - */ - public Locale(JavaPlugin plugin, String defaultLocale) { - - Locale.plugin = plugin; - Locale.localeFolder = new File(plugin.getDataFolder(), "locales/"); - - if (!localeFolder.exists()) localeFolder.mkdirs(); - - //Save the default locale file. - Locale.defaultLocale = defaultLocale; - saveLocale(defaultLocale); - - for (File file : localeFolder.listFiles()) { - String fileName = file.getName(); - if (!fileName.endsWith(FILE_EXTENSION)) continue; - - String name = fileName.substring(0, fileName.lastIndexOf('.')); - - if (name.split("_").length != 2) continue; - if (localeLoaded(name)) continue; - - LOCALES.add(new Locale(name)); - } - } - - /** - * Save a locale file from the InputStream, to the locale folder - * - * @param fileName the name of the file to save - * @return true if the operation was successful, false otherwise - */ - public static boolean saveLocale(String fileName) { - return saveLocale(plugin.getResource(defaultLocale + FILE_EXTENSION), fileName); - } - - - /** - * Save a locale file from the InputStream, to the locale folder - * - * @param in file to save - * @param fileName the name of the file to save - * @return true if the operation was successful, false otherwise - */ - public static boolean saveLocale(InputStream in, String fileName) { - if (!localeFolder.exists()) localeFolder.mkdirs(); - - if (!fileName.endsWith(FILE_EXTENSION)) - fileName = (fileName.lastIndexOf(".") == -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.'))) + FILE_EXTENSION; - - File destinationFile = new File(localeFolder, fileName); - if (destinationFile.exists()) - return compareFiles(in, destinationFile); - - try (OutputStream outputStream = new FileOutputStream(destinationFile)) { - copy(in, outputStream); - - fileName = fileName.substring(0, fileName.lastIndexOf('.')); - - if (fileName.split("_").length != 2) return false; - - LOCALES.add(new Locale(fileName)); - if (defaultLocale == null) defaultLocale = fileName; - return true; - } catch (IOException e) { - return false; - } - } - - // Write new changes to existing files, if any at all - private static boolean compareFiles(InputStream in, File existingFile) { - InputStream defaultFile = - in == null ? plugin.getResource((defaultLocale != null ? defaultLocale : "en_US") + FILE_EXTENSION) : in; - - boolean changed = false; - - List defaultLines, existingLines; - try (BufferedReader defaultReader = new BufferedReader(new InputStreamReader(defaultFile)); - BufferedReader existingReader = new BufferedReader(new FileReader(existingFile)); - BufferedWriter writer = new BufferedWriter(new FileWriter(existingFile, true))) { - defaultLines = defaultReader.lines().collect(Collectors.toList()); - existingLines = existingReader.lines().map(s -> s.split("\\s*=")[0]).collect(Collectors.toList()); - - for (String defaultValue : defaultLines) { - if (defaultValue.isEmpty() || defaultValue.startsWith("#")) continue; - - String key = defaultValue.split("\\s*=")[0]; - - if (!existingLines.contains(key)) { - if (!changed) { - writer.newLine(); - writer.newLine(); - // Leave a note alerting the user of the newly added messages. - writer.write("# New messages for " + plugin.getName() + " v" + plugin.getDescription().getVersion() + "."); - - // If changes were found outside of the default file leave a note explaining that. - if (in == null) { - writer.newLine(); - writer.write("# These translations were found untranslated, join"); - writer.newLine(); - writer.write("# our translation Discord https://discord.gg/f7fpZEf"); - writer.newLine(); - writer.write("# to request an official update!"); - } - } - - writer.newLine(); - writer.write(defaultValue); - - changed = true; - } - } - if (in != null && !changed) compareFiles(null, existingFile); - } catch (IOException e) { - return false; - } - - return changed; - } - - - /** - * Check whether a locale exists and is registered or not - * - * @param name the whole language tag (i.e. "en_US") - * @return true if it exists - */ - public static boolean localeLoaded(String name) { - for (Locale locale : LOCALES) - if (locale.getName().equals(name)) return true; - return false; - } - - - /** - * Get a locale by its entire proper name (i.e. "en_US") - * - * @param name the full name of the locale - * @return locale of the specified name - */ - public static Locale getLocale(String name) { - for (Locale locale : LOCALES) - if (locale.getName().equalsIgnoreCase(name)) return locale; - return null; - } - - /** - * Clear the previous message cache and load new messages directly from file - * - * @return reload messages from file - */ - public boolean reloadMessages() { - if (!this.file.exists()) { - plugin.getLogger().warning("Could not find file for locale \"" + this.name + "\""); - return false; - } - - this.nodes.clear(); // Clear previous data (if any) - - try (BufferedReader reader = new BufferedReader(new FileReader(file))) { - String line; - for (int lineNumber = 0; (line = reader.readLine()) != null; lineNumber++) { - if (line.trim().isEmpty() || line.startsWith("#") /* Comment */) continue; - - Matcher matcher = NODE_PATTERN.matcher(line); - if (!matcher.find()) { - System.err.println("Invalid locale syntax at (line=" + lineNumber + ")"); - continue; - } - - nodes.put(matcher.group(1), matcher.group(2)); - } - } catch (IOException e) { - e.printStackTrace(); - return false; - } - return true; - } - - /** - * Supply the Message object with the plugins prefix. - * - * @param message message to be applied - * @return applied message - */ - private Message supplyPrefix(Message message) { - return message.setPrefix(this.nodes.getOrDefault("general.nametag.prefix", "[Plugin]")); - } - - /** - * Create a new unsaved Message - * - * @param message the message to create - * @return the created message - */ - public Message newMessage(String message) { - return supplyPrefix(new Message(message)); - } - - /** - * Get a message set for a specific node. - * - * @param node the node to get - * @return the message for the specified node - */ - public Message getMessage(String node) { - return this.getMessageOrDefault(node, node); - } - - /** - * Get a message set for a specific node - * - * @param node the node to get - * @param defaultValue the default value given that a value for the node was not found - * @return the message for the specified node. Default if none found - */ - public Message getMessageOrDefault(String node, String defaultValue) { - return supplyPrefix(new Message(this.nodes.getOrDefault(node, defaultValue))); - } - - /** - * Return the locale name (i.e. "en_US") - * - * @return the locale name - */ - public String getName() { - return name; - } - - private static void copy(InputStream input, OutputStream output) { - int n; - byte[] buffer = new byte[1024 * 4]; - - try { - while ((n = input.read(buffer)) != -1) { - output.write(buffer, 0, n); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - -} diff --git a/src/main/java/com/songoda/epicenchants/utils/locale/Message.java b/src/main/java/com/songoda/epicenchants/utils/locale/Message.java deleted file mode 100644 index 860a125..0000000 --- a/src/main/java/com/songoda/epicenchants/utils/locale/Message.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.songoda.epicenchants.utils.locale; - -import org.bukkit.ChatColor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -/** - * The Message object. This holds the message to be sent - * as well as the plugins prefix so that they can both be - * easily manipulated then deployed - */ -public class Message { - - private String prefix = null; - private String message; - - /** - * create a new message - * - * @param message the message text - */ - public Message(String message) { - this.message = message; - } - - /** - * Format and send the held message to a player - * - * @param player player to send the message to - */ - public void sendMessage(Player player) { - player.sendMessage(this.getMessage()); - } - - /** - * Format and send the held message with the - * appended plugin prefix to a player - * - * @param player player to send the message to - */ - public void sendPrefixedMessage(Player player) { - player.sendMessage(this.getPrefixedMessage()); - } - - /** - * Format and send the held message to a player - * - * @param sender command sender to send the message to - */ - public void sendMessage(CommandSender sender) { - sender.sendMessage(this.getMessage()); - } - - /** - * Format and send the held message to a player as a title message - * - * @param sender command sender to send the message to - */ - public void sendTitle(CommandSender sender) { - if(sender instanceof Player) { - ((Player) sender).sendTitle("", this.getMessage(), 10, 20, 10); - } else { - sender.sendMessage(this.getMessage()); - } - } - - /** - * Format and send the held message with the - * appended plugin prefix to a command sender - * - * @param sender command sender to send the message to - */ - public void sendPrefixedMessage(CommandSender sender) { - sender.sendMessage(this.getPrefixedMessage()); - } - - /** - * Format the held message and append the plugins - * prefix - * - * @return the prefixed message - */ - public String getPrefixedMessage() { - return ChatColor.translateAlternateColorCodes('&',(prefix == null ? "" : this.prefix) - + " " + this.message); - } - - /** - * Get and format the held message - * - * @return the message - */ - public String getMessage() { - return ChatColor.translateAlternateColorCodes('&', this.message); - } - - /** - * Get the held message - * - * @return the message - */ - public String getUnformattedMessage() { - return this.message; - } - - /** - * Replace the provided placeholder with the - * provided object - * - * @param placeholder the placeholder to replace - * @param replacement the replacement object - * @return the modified Message - */ - public Message processPlaceholder(String placeholder, Object replacement) { - this.message = message.replace("{" + placeholder + "}", replacement.toString()); - return this; - } - - Message setPrefix(String prefix) { - this.prefix = prefix; - return this; - } - - @Override - public String toString() { - return this.message; - } -} \ No newline at end of file diff --git a/src/main/java/com/songoda/epicenchants/utils/objects/ItemBuilder.java b/src/main/java/com/songoda/epicenchants/utils/objects/ItemBuilder.java index d2d368e..230e1d8 100644 --- a/src/main/java/com/songoda/epicenchants/utils/objects/ItemBuilder.java +++ b/src/main/java/com/songoda/epicenchants/utils/objects/ItemBuilder.java @@ -254,7 +254,7 @@ public class ItemBuilder { } public ItemBuilder unbreakable(boolean unbreakable) { - meta.spigot().setUnbreakable(unbreakable); + meta.setUnbreakable(unbreakable); return this; } @@ -304,6 +304,6 @@ public class ItemBuilder { * Unbreakability: */ public boolean isUnbreakable() { - return meta.spigot().isUnbreakable(); + return meta.isUnbreakable(); } } diff --git a/src/main/java/com/songoda/epicenchants/utils/settings/SettingsManager.java b/src/main/java/com/songoda/epicenchants/utils/settings/SettingsManager.java index 2a734b7..edf7ae7 100644 --- a/src/main/java/com/songoda/epicenchants/utils/settings/SettingsManager.java +++ b/src/main/java/com/songoda/epicenchants/utils/settings/SettingsManager.java @@ -1,8 +1,8 @@ package com.songoda.epicenchants.utils.settings; +import com.songoda.core.compatibility.ServerVersion; import com.songoda.epicenchants.EpicEnchants; import com.songoda.epicenchants.utils.Methods; -import com.songoda.epicenchants.utils.ServerVersion; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -119,7 +119,7 @@ public class SettingsManager implements Listener { int slot = 10; for (String key : plugin.getConfig().getDefaultSection().getKeys(false)) { - ItemStack item = new ItemStack(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.LEGACY_WOOL : Material.valueOf("WOOL"), 1, (byte) (slot - 9)); + ItemStack item = new ItemStack(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.LEGACY_WOOL : Material.valueOf("WOOL"), 1, (byte) (slot - 9)); ItemMeta meta = item.getItemMeta(); meta.setLore(Collections.singletonList(Methods.formatText("&6Click To Edit This Category."))); meta.setDisplayName(Methods.formatText("&f&l" + key)); @@ -150,13 +150,13 @@ public class SettingsManager implements Listener { item.setType(Material.PAPER); lore.add(Methods.formatText("&7" + config.getString(fKey))); } else if (config.isInt(fKey)) { - item.setType(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH")); + item.setType(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH")); lore.add(Methods.formatText("&7" + config.getInt(fKey))); } else if (config.isLong(fKey)) { - item.setType(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH")); + item.setType(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH")); lore.add(Methods.formatText("&7" + config.getLong(fKey))); } else if (config.isDouble(fKey)) { - item.setType(plugin.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH")); + item.setType(ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13) ? Material.CLOCK : Material.valueOf("WATCH")); lore.add(Methods.formatText("&7" + config.getDouble(fKey))); } 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 9efc23e..846ec73 100644 --- a/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java +++ b/src/main/java/com/songoda/epicenchants/utils/single/ItemGroup.java @@ -2,8 +2,8 @@ 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.epicenchants.utils.ServerVersion; import org.apache.commons.lang.StringUtils; import org.bukkit.Material; @@ -19,7 +19,7 @@ public class ItemGroup { public ItemGroup(EpicEnchants instance) { groupMap = HashMultimap.create(); - if (instance.isServerVersionAtLeast(ServerVersion.V1_13)) setupMaster(); + if (com.songoda.core.compatibility.ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) setupMaster(); else setupLegacy(); } diff --git a/src/main/java/com/songoda/epicenchants/utils/updateModules/LocaleModule.java b/src/main/java/com/songoda/epicenchants/utils/updateModules/LocaleModule.java deleted file mode 100644 index 5c2da51..0000000 --- a/src/main/java/com/songoda/epicenchants/utils/updateModules/LocaleModule.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.songoda.epicenchants.utils.updateModules; - -import com.songoda.epicenchants.EpicEnchants; -import com.songoda.update.Module; -import com.songoda.update.Plugin; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; - -public class LocaleModule implements Module { - - @Override - public void run(Plugin plugin) { - JSONObject json = plugin.getJson(); - try { - JSONArray files = (JSONArray) json.get("neededFiles"); - for (Object o : files) { - JSONObject file = (JSONObject) o; - - if (file.get("type").equals("locale")) { - InputStream in = new URL((String) file.get("link")).openStream(); - EpicEnchants.getInstance().getLocale().saveLocale(in, (String) file.get("name")); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/resources/enchants/unique/Inquisitive.yml b/src/main/resources/enchants/unique/Inquisitive.yml index 4a5a83b..efaf026 100644 --- a/src/main/resources/enchants/unique/Inquisitive.yml +++ b/src/main/resources/enchants/unique/Inquisitive.yml @@ -15,7 +15,7 @@ description: - "more EXP when killing mobs." # How the enchant should be formatted on the enchanted item. -applied-format: "&cInquistive {level}" +applied-format: "&cInquisitive {level}" # What items this enchant can be applied too. item-whitelist: