From a77926b3b18f960bc8a5aa7986bc4bd53aabefd5 Mon Sep 17 00:00:00 2001 From: Flowsqy <47575244+Flowsqy@users.noreply.github.com> Date: Mon, 27 Dec 2021 15:33:03 +0100 Subject: [PATCH] Move plugin src directory into a sub module --- plugin/pom.xml | 19 + .../java/de/epiceric/shopchest/ShopChest.java | 740 +++++ .../shopchest/command/ShopCommand.java | 354 ++ .../command/ShopCommandExecutor.java | 576 ++++ .../shopchest/command/ShopSubCommand.java | 68 + .../shopchest/command/ShopTabCompleter.java | 126 + .../de/epiceric/shopchest/config/Config.java | 614 ++++ .../shopchest/config/HologramFormat.java | 245 ++ .../config/LanguageConfiguration.java | 132 + .../shopchest/config/Placeholder.java | 43 + .../shopchest/event/ShopBuySellEvent.java | 59 + .../shopchest/event/ShopCreateEvent.java | 36 + .../epiceric/shopchest/event/ShopEvent.java | 43 + .../shopchest/event/ShopExtendEvent.java | 37 + .../shopchest/event/ShopInfoEvent.java | 27 + .../shopchest/event/ShopInitializedEvent.java | 32 + .../shopchest/event/ShopOpenEvent.java | 27 + .../shopchest/event/ShopPreCreateEvent.java | 27 + .../shopchest/event/ShopPreInfoEvent.java | 46 + .../shopchest/event/ShopPreOpenEvent.java | 46 + .../shopchest/event/ShopPreRemoveEvent.java | 46 + .../shopchest/event/ShopReloadEvent.java | 46 + .../shopchest/event/ShopRemoveAllEvent.java | 57 + .../shopchest/event/ShopRemoveEvent.java | 27 + .../shopchest/event/ShopsLoadedEvent.java | 33 + .../exceptions/ChestNotFoundException.java | 9 + .../exceptions/NotEnoughSpaceException.java | 9 + .../exceptions/WorldNotFoundException.java | 9 + .../shopchest/external/BentoBoxShopFlag.java | 25 + .../external/PlotSquaredOldShopFlag.java | 112 + .../external/PlotSquaredShopFlag.java | 154 + .../external/WorldGuardShopFlag.java | 31 + .../external/listeners/ASkyBlockListener.java | 62 + .../external/listeners/BentoBoxListener.java | 57 + .../listeners/GriefPreventionListener.java | 62 + .../listeners/IslandWorldListener.java | 59 + .../listeners/PlotSquaredListener.java | 90 + .../external/listeners/TownyListener.java | 85 + .../external/listeners/USkyBlockListener.java | 61 + .../listeners/WorldGuardListener.java | 97 + .../shopchest/language/BannerPatternName.java | 29 + .../language/BookGenerationName.java | 28 + .../shopchest/language/EnchantmentName.java | 53 + .../shopchest/language/EntityName.java | 28 + .../epiceric/shopchest/language/ItemName.java | 42 + .../shopchest/language/LanguageUtils.java | 2895 +++++++++++++++++ .../shopchest/language/LocalizedMessage.java | 29 + .../epiceric/shopchest/language/Message.java | 99 + .../shopchest/language/MusicDiscName.java | 29 + .../shopchest/language/PotionEffectName.java | 29 + .../shopchest/language/PotionName.java | 44 + .../shopchest/language/Replacement.java | 29 + .../shopchest/listeners/AreaShopListener.java | 69 + .../shopchest/listeners/BentoBoxListener.java | 91 + .../listeners/BlockExplodeListener.java | 31 + .../listeners/ChestProtectListener.java | 248 ++ .../listeners/CreativeModeListener.java | 179 + .../listeners/NotifyPlayerOnJoinListener.java | 63 + .../listeners/ShopInteractListener.java | 1213 +++++++ .../shopchest/listeners/ShopItemListener.java | 157 + .../listeners/ShopUpdateListener.java | 153 + .../listeners/WorldGuardListener.java | 89 + .../shopchest/nms/ArmorStandWrapper.java | 159 + .../shopchest/nms/CustomBookMeta.java | 92 + .../de/epiceric/shopchest/nms/Hologram.java | 253 ++ .../epiceric/shopchest/nms/JsonBuilder.java | 252 ++ .../epiceric/shopchest/nms/SpawnEggMeta.java | 93 + .../java/de/epiceric/shopchest/shop/Shop.java | 480 +++ .../de/epiceric/shopchest/shop/ShopItem.java | 164 + .../epiceric/shopchest/shop/ShopProduct.java | 43 + .../de/epiceric/shopchest/sql/Database.java | 877 +++++ .../java/de/epiceric/shopchest/sql/MySQL.java | 110 + .../de/epiceric/shopchest/sql/SQLite.java | 126 + .../de/epiceric/shopchest/utils/Callback.java | 35 + .../epiceric/shopchest/utils/ClickType.java | 222 ++ .../de/epiceric/shopchest/utils/Counter.java | 55 + .../de/epiceric/shopchest/utils/FastMath.java | 42 + .../epiceric/shopchest/utils/ItemUtils.java | 76 + .../de/epiceric/shopchest/utils/Operator.java | 75 + .../epiceric/shopchest/utils/Permissions.java | 24 + .../epiceric/shopchest/utils/ShopUpdater.java | 107 + .../epiceric/shopchest/utils/ShopUtils.java | 524 +++ .../shopchest/utils/UpdateChecker.java | 88 + .../de/epiceric/shopchest/utils/Utils.java | 649 ++++ plugin/src/main/resources/config.yml | 224 ++ plugin/src/main/resources/hologram-format.yml | 78 + plugin/src/main/resources/item_names.txt | 1230 +++++++ .../src/main/resources/lang/de_DE-legacy.lang | 919 ++++++ plugin/src/main/resources/lang/de_DE.lang | 1518 +++++++++ .../src/main/resources/lang/en_US-legacy.lang | 1163 +++++++ plugin/src/main/resources/lang/en_US.lang | 1754 ++++++++++ plugin/src/main/resources/plugin.yml | 93 + 92 files changed, 21580 insertions(+) create mode 100644 plugin/pom.xml create mode 100644 plugin/src/main/java/de/epiceric/shopchest/ShopChest.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/command/ShopCommand.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/command/ShopCommandExecutor.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/command/ShopSubCommand.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/command/ShopTabCompleter.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/config/Config.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/config/HologramFormat.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/config/LanguageConfiguration.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/config/Placeholder.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopBuySellEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopCreateEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopExtendEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopInfoEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopInitializedEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopOpenEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopPreCreateEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopPreInfoEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopPreOpenEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopPreRemoveEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopReloadEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopRemoveAllEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopRemoveEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/event/ShopsLoadedEvent.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/exceptions/ChestNotFoundException.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/exceptions/NotEnoughSpaceException.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/exceptions/WorldNotFoundException.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/BentoBoxShopFlag.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/PlotSquaredOldShopFlag.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/PlotSquaredShopFlag.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/WorldGuardShopFlag.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/listeners/ASkyBlockListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/listeners/BentoBoxListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/listeners/GriefPreventionListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/listeners/IslandWorldListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/listeners/PlotSquaredListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/listeners/TownyListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/listeners/USkyBlockListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/external/listeners/WorldGuardListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/BannerPatternName.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/BookGenerationName.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/EnchantmentName.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/EntityName.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/ItemName.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/LanguageUtils.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/LocalizedMessage.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/Message.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/MusicDiscName.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/PotionEffectName.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/PotionName.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/language/Replacement.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/AreaShopListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/BentoBoxListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/BlockExplodeListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/CreativeModeListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/NotifyPlayerOnJoinListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/ShopItemListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/listeners/WorldGuardListener.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/nms/ArmorStandWrapper.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/nms/CustomBookMeta.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/nms/Hologram.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/nms/JsonBuilder.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/nms/SpawnEggMeta.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/shop/Shop.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/shop/ShopItem.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/shop/ShopProduct.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/sql/Database.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/sql/MySQL.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/sql/SQLite.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/Callback.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/ClickType.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/Counter.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/FastMath.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/ItemUtils.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/Operator.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/Permissions.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/UpdateChecker.java create mode 100644 plugin/src/main/java/de/epiceric/shopchest/utils/Utils.java create mode 100644 plugin/src/main/resources/config.yml create mode 100644 plugin/src/main/resources/hologram-format.yml create mode 100644 plugin/src/main/resources/item_names.txt create mode 100644 plugin/src/main/resources/lang/de_DE-legacy.lang create mode 100644 plugin/src/main/resources/lang/de_DE.lang create mode 100644 plugin/src/main/resources/lang/en_US-legacy.lang create mode 100644 plugin/src/main/resources/lang/en_US.lang create mode 100644 plugin/src/main/resources/plugin.yml diff --git a/plugin/pom.xml b/plugin/pom.xml new file mode 100644 index 0000000..65f8803 --- /dev/null +++ b/plugin/pom.xml @@ -0,0 +1,19 @@ + + + + ShopChest-parent + de.epiceric + 1.14.0-SNAPSHOT + + 4.0.0 + + plugin + + + 17 + 17 + + + \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/ShopChest.java b/plugin/src/main/java/de/epiceric/shopchest/ShopChest.java new file mode 100644 index 0000000..b3fc0a4 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/ShopChest.java @@ -0,0 +1,740 @@ +package de.epiceric.shopchest; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.stream.Stream; + +import com.palmergames.bukkit.towny.Towny; +import com.wasteofplastic.askyblock.ASkyBlock; + +import org.bstats.bukkit.Metrics; +import org.bstats.charts.AdvancedPie; +import org.bstats.charts.SimplePie; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.codemc.worldguardwrapper.WorldGuardWrapper; + +import de.epiceric.shopchest.command.ShopCommand; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.config.HologramFormat; +import de.epiceric.shopchest.event.ShopInitializedEvent; +import de.epiceric.shopchest.external.BentoBoxShopFlag; +import de.epiceric.shopchest.external.PlotSquaredOldShopFlag; +import de.epiceric.shopchest.external.PlotSquaredShopFlag; +import de.epiceric.shopchest.external.WorldGuardShopFlag; +import de.epiceric.shopchest.external.listeners.ASkyBlockListener; +import de.epiceric.shopchest.external.listeners.GriefPreventionListener; +import de.epiceric.shopchest.external.listeners.IslandWorldListener; +import de.epiceric.shopchest.external.listeners.PlotSquaredListener; +import de.epiceric.shopchest.external.listeners.TownyListener; +import de.epiceric.shopchest.external.listeners.USkyBlockListener; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.listeners.AreaShopListener; +import de.epiceric.shopchest.listeners.BentoBoxListener; +import de.epiceric.shopchest.listeners.BlockExplodeListener; +import de.epiceric.shopchest.listeners.ChestProtectListener; +import de.epiceric.shopchest.listeners.CreativeModeListener; +import de.epiceric.shopchest.listeners.NotifyPlayerOnJoinListener; +import de.epiceric.shopchest.listeners.ShopInteractListener; +import de.epiceric.shopchest.listeners.ShopItemListener; +import de.epiceric.shopchest.listeners.ShopUpdateListener; +import de.epiceric.shopchest.listeners.WorldGuardListener; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.shop.Shop.ShopType; +import de.epiceric.shopchest.sql.Database; +import de.epiceric.shopchest.sql.MySQL; +import de.epiceric.shopchest.sql.SQLite; +import de.epiceric.shopchest.utils.Callback; +import de.epiceric.shopchest.utils.ClickType; +import de.epiceric.shopchest.utils.Permissions; +import de.epiceric.shopchest.utils.ShopUpdater; +import de.epiceric.shopchest.utils.ShopUtils; +import de.epiceric.shopchest.utils.UpdateChecker; +import de.epiceric.shopchest.utils.UpdateChecker.UpdateCheckerResult; +import de.epiceric.shopchest.utils.Utils; +import fr.xephi.authme.AuthMe; +import me.ryanhamshire.GriefPrevention.GriefPrevention; +import me.wiefferink.areashop.AreaShop; +import net.milkbowl.vault.economy.Economy; +import pl.islandworld.IslandWorld; +import us.talabrek.ultimateskyblock.api.uSkyBlockAPI; +import world.bentobox.bentobox.BentoBox; + +public class ShopChest extends JavaPlugin { + + private static ShopChest instance; + + private Config config; + private HologramFormat hologramFormat; + private ShopCommand shopCommand; + private Economy econ = null; + private Database database; + private boolean isUpdateNeeded = false; + private String latestVersion = ""; + private String downloadLink = ""; + private ShopUtils shopUtils; + private FileWriter fw; + private Plugin worldGuard; + private Towny towny; + private AuthMe authMe; + private uSkyBlockAPI uSkyBlock; + private ASkyBlock aSkyBlock; + private IslandWorld islandWorld; + private GriefPrevention griefPrevention; + private AreaShop areaShop; + private BentoBox bentoBox; + private ShopUpdater updater; + private ExecutorService shopCreationThreadPool; + + /** + * @return An instance of ShopChest + */ + public static ShopChest getInstance() { + return instance; + } + + /** + * Sets up the economy of Vault + * @return Whether an economy plugin has been registered + */ + private boolean setupEconomy() { + RegisteredServiceProvider rsp = getServer().getServicesManager().getRegistration(Economy.class); + if (rsp == null) { + return false; + } + econ = rsp.getProvider(); + return econ != null; + } + + @Override + public void onLoad() { + instance = this; + + config = new Config(this); + + if (Config.enableDebugLog) { + File debugLogFile = new File(getDataFolder(), "debug.txt"); + + try { + if (!debugLogFile.exists()) { + debugLogFile.createNewFile(); + } + + new PrintWriter(debugLogFile).close(); + + fw = new FileWriter(debugLogFile, true); + } catch (IOException e) { + getLogger().info("Failed to instantiate FileWriter"); + e.printStackTrace(); + } + } + + debug("Loading ShopChest version " + getDescription().getVersion()); + + worldGuard = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard"); + if (worldGuard != null) { + WorldGuardShopFlag.register(this); + } + } + + @Override + public void onEnable() { + debug("Enabling ShopChest version " + getDescription().getVersion()); + + if (!getServer().getPluginManager().isPluginEnabled("Vault")) { + debug("Could not find plugin \"Vault\""); + getLogger().severe("Could not find plugin \"Vault\""); + getServer().getPluginManager().disablePlugin(this); + return; + } + + if (!setupEconomy()) { + debug("Could not find any Vault economy dependency!"); + getLogger().severe("Could not find any Vault economy dependency!"); + getServer().getPluginManager().disablePlugin(this); + return; + } + + switch (Utils.getServerVersion()) { + case "v1_8_R1": + case "v1_8_R2": + case "v1_8_R3": + case "v1_9_R1": + case "v1_9_R2": + case "v1_10_R1": + case "v1_11_R1": + case "v1_12_R1": + case "v1_13_R1": + case "v1_13_R2": + case "v1_14_R1": + case "v1_15_R1": + case "v1_16_R1": + case "v1_16_R2": + case "v1_16_R3": + break; + default: + debug("Server version not officially supported: " + Utils.getServerVersion() + "!"); + debug("Plugin may still work, but more errors are expected!"); + getLogger().warning("Server version not officially supported: " + Utils.getServerVersion() + "!"); + getLogger().warning("Plugin may still work, but more errors are expected!"); + } + + shopUtils = new ShopUtils(this); + saveResource("item_names.txt", true); + LanguageUtils.load(); + + File hologramFormatFile = new File(getDataFolder(), "hologram-format.yml"); + if (!hologramFormatFile.exists()) { + saveResource("hologram-format.yml", false); + } + + hologramFormat = new HologramFormat(this); + shopCommand = new ShopCommand(this); + shopCreationThreadPool = new ThreadPoolExecutor(0, 8, + 5L, TimeUnit.SECONDS, new LinkedBlockingQueue<>()); + + loadExternalPlugins(); + loadMetrics(); + initDatabase(); + checkForUpdates(); + registerListeners(); + registerExternalListeners(); + initializeShops(); + + getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); + + updater = new ShopUpdater(this); + updater.start(); + } + + @Override + public void onDisable() { + debug("Disabling ShopChest..."); + + if (shopUtils == null) { + // Plugin has not been fully enabled (probably due to errors), + // so only close file writer. + if (fw != null && Config.enableDebugLog) { + try { + fw.close(); + } catch (IOException e) { + getLogger().severe("Failed to close FileWriter"); + e.printStackTrace(); + } + } + return; + } + + if (getShopCommand() != null) { + getShopCommand().unregister(); + } + + ClickType.clear(); + + if (updater != null) { + debug("Stopping updater"); + updater.stop(); + } + + if (shopCreationThreadPool != null) { + shopCreationThreadPool.shutdown(); + } + + shopUtils.removeShops(); + debug("Removed shops"); + + if (database != null && database.isInitialized()) { + if (database instanceof SQLite) { + ((SQLite) database).vacuum(); + } + + database.disconnect(); + } + + if (fw != null && Config.enableDebugLog) { + try { + fw.close(); + } catch (IOException e) { + getLogger().severe("Failed to close FileWriter"); + e.printStackTrace(); + } + } + } + + private void loadExternalPlugins() { + Plugin townyPlugin = Bukkit.getServer().getPluginManager().getPlugin("Towny"); + if (townyPlugin instanceof Towny) { + towny = (Towny) townyPlugin; + } + + Plugin authMePlugin = Bukkit.getServer().getPluginManager().getPlugin("AuthMe"); + if (authMePlugin instanceof AuthMe) { + authMe = (AuthMe) authMePlugin; + } + + Plugin uSkyBlockPlugin = Bukkit.getServer().getPluginManager().getPlugin("uSkyBlock"); + if (uSkyBlockPlugin instanceof uSkyBlockAPI) { + uSkyBlock = (uSkyBlockAPI) uSkyBlockPlugin; + } + + Plugin aSkyBlockPlugin = Bukkit.getServer().getPluginManager().getPlugin("ASkyBlock"); + if (aSkyBlockPlugin instanceof ASkyBlock) { + aSkyBlock = (ASkyBlock) aSkyBlockPlugin; + } + + Plugin islandWorldPlugin = Bukkit.getServer().getPluginManager().getPlugin("IslandWorld"); + if (islandWorldPlugin instanceof IslandWorld) { + islandWorld = (IslandWorld) islandWorldPlugin; + } + + Plugin griefPreventionPlugin = Bukkit.getServer().getPluginManager().getPlugin("GriefPrevention"); + if (griefPreventionPlugin instanceof GriefPrevention) { + griefPrevention = (GriefPrevention) griefPreventionPlugin; + } + + Plugin areaShopPlugin = Bukkit.getServer().getPluginManager().getPlugin("AreaShop"); + if (areaShopPlugin instanceof AreaShop) { + areaShop = (AreaShop) areaShopPlugin; + } + + Plugin bentoBoxPlugin = getServer().getPluginManager().getPlugin("BentoBox"); + if (bentoBoxPlugin instanceof BentoBox) { + bentoBox = (BentoBox) bentoBoxPlugin; + } + + if (hasWorldGuard()) { + WorldGuardWrapper.getInstance().registerEvents(this); + } + + if (hasPlotSquared()) { + try { + Class.forName("com.plotsquared.core.PlotSquared"); + PlotSquaredShopFlag.register(this); + } catch (ClassNotFoundException ex) { + PlotSquaredOldShopFlag.register(this); + } + } + + if (hasBentoBox()) { + BentoBoxShopFlag.register(this); + } + } + + private void loadMetrics() { + debug("Initializing Metrics..."); + + Metrics metrics = new Metrics(this, 1726); + metrics.addCustomChart(new SimplePie("creative_setting", () -> Config.creativeSelectItem ? "Enabled" : "Disabled")); + metrics.addCustomChart(new SimplePie("database_type", () -> Config.databaseType.toString())); + metrics.addCustomChart(new AdvancedPie("shop_type", () -> { + int normal = 0; + int admin = 0; + + for (Shop shop : shopUtils.getShops()) { + if (shop.getShopType() == ShopType.NORMAL) normal++; + else if (shop.getShopType() == ShopType.ADMIN) admin++; + } + + Map result = new HashMap<>(); + + result.put("Admin", admin); + result.put("Normal", normal); + + return result; + })); + } + + private void initDatabase() { + if (Config.databaseType == Database.DatabaseType.SQLite) { + debug("Using database type: SQLite"); + getLogger().info("Using SQLite"); + database = new SQLite(this); + } else { + debug("Using database type: MySQL"); + getLogger().info("Using MySQL"); + database = new MySQL(this); + if (Config.databaseMySqlPingInterval > 0) { + Bukkit.getScheduler().runTaskTimer(this, new Runnable() { + @Override + public void run() { + if (database instanceof MySQL) { + ((MySQL) database).ping(); + } + } + }, Config.databaseMySqlPingInterval * 20L, Config.databaseMySqlPingInterval * 20L); + } + } + } + + private void checkForUpdates() { + if (!Config.enableUpdateChecker) { + return; + } + + new BukkitRunnable() { + @Override + public void run() { + UpdateChecker uc = new UpdateChecker(ShopChest.this); + UpdateCheckerResult result = uc.check(); + + switch (result) { + case TRUE: + latestVersion = uc.getVersion(); + downloadLink = uc.getLink(); + isUpdateNeeded = true; + + getLogger().warning(String.format("Version %s is available! You are running version %s.", + latestVersion, getDescription().getVersion())); + + for (Player p : getServer().getOnlinePlayers()) { + if (p.hasPermission(Permissions.UPDATE_NOTIFICATION)) { + Utils.sendUpdateMessage(ShopChest.this, p); + } + } + break; + + case FALSE: + latestVersion = ""; + downloadLink = ""; + isUpdateNeeded = false; + break; + + case ERROR: + latestVersion = ""; + downloadLink = ""; + isUpdateNeeded = false; + getLogger().severe("An error occurred while checking for updates."); + break; + } + } + }.runTaskAsynchronously(this); + } + + private void registerListeners() { + debug("Registering listeners..."); + getServer().getPluginManager().registerEvents(new ShopUpdateListener(this), this); + getServer().getPluginManager().registerEvents(new ShopItemListener(this), this); + getServer().getPluginManager().registerEvents(new ShopInteractListener(this), this); + getServer().getPluginManager().registerEvents(new NotifyPlayerOnJoinListener(this), this); + getServer().getPluginManager().registerEvents(new ChestProtectListener(this), this); + getServer().getPluginManager().registerEvents(new CreativeModeListener(this), this); + + if (!Utils.getServerVersion().equals("v1_8_R1")) { + getServer().getPluginManager().registerEvents(new BlockExplodeListener(this), this); + } + + if (hasWorldGuard()) { + getServer().getPluginManager().registerEvents(new WorldGuardListener(this), this); + + if (hasAreaShop()) { + getServer().getPluginManager().registerEvents(new AreaShopListener(this), this); + } + } + + if (hasBentoBox()) { + getServer().getPluginManager().registerEvents(new BentoBoxListener(this), this); + } + } + + private void registerExternalListeners() { + if (hasASkyBlock()) + getServer().getPluginManager().registerEvents(new ASkyBlockListener(this), this); + if (hasGriefPrevention()) + getServer().getPluginManager().registerEvents(new GriefPreventionListener(this), this); + if (hasIslandWorld()) + getServer().getPluginManager().registerEvents(new IslandWorldListener(this), this); + if (hasPlotSquared()) + getServer().getPluginManager().registerEvents(new PlotSquaredListener(this), this); + if (hasTowny()) + getServer().getPluginManager().registerEvents(new TownyListener(this), this); + if (hasUSkyBlock()) + getServer().getPluginManager().registerEvents(new USkyBlockListener(this), this); + if (hasWorldGuard()) + getServer().getPluginManager().registerEvents(new de.epiceric.shopchest.external.listeners.WorldGuardListener(this), this); + if (hasBentoBox()) + getServer().getPluginManager().registerEvents(new de.epiceric.shopchest.external.listeners.BentoBoxListener(this), this); + } + + /** + * Initializes the shops + */ + private void initializeShops() { + getShopDatabase().connect(new Callback(this) { + @Override + public void onResult(Integer result) { + Chunk[] loadedChunks = getServer().getWorlds().stream().map(World::getLoadedChunks) + .flatMap(Stream::of).toArray(Chunk[]::new); + + shopUtils.loadShopAmounts(new Callback>(ShopChest.this) { + @Override + public void onResult(Map result) { + getLogger().info("Loaded shop amounts"); + debug("Loaded shop amounts"); + } + + @Override + public void onError(Throwable throwable) { + getLogger().severe("Failed to load shop amounts. Shop limits will not be working correctly!"); + if (throwable != null) getLogger().severe(throwable.getMessage()); + } + }); + + shopUtils.loadShops(loadedChunks, new Callback(ShopChest.this) { + @Override + public void onResult(Integer result) { + getServer().getPluginManager().callEvent(new ShopInitializedEvent(result)); + getLogger().info("Loaded " + result + " shops in already loaded chunks"); + debug("Loaded " + result + " shops in already loaded chunks"); + } + + @Override + public void onError(Throwable throwable) { + getLogger().severe("Failed to load shops in already loaded chunks"); + if (throwable != null) getLogger().severe(throwable.getMessage()); + } + }); + } + + @Override + public void onError(Throwable throwable) { + // Database connection probably failed => disable plugin to prevent more errors + getLogger().severe("No database access. Disabling ShopChest"); + if (throwable != null) getLogger().severe(throwable.getMessage()); + getServer().getPluginManager().disablePlugin(ShopChest.this); + } + }); + } + + /** + * Print a message to the /plugins/ShopChest/debug.txt file + * @param message Message to print + */ + public void debug(String message) { + if (Config.enableDebugLog && fw != null) { + try { + Calendar c = Calendar.getInstance(); + String timestamp = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(c.getTime()); + fw.write(String.format("[%s] %s\r\n", timestamp, message)); + fw.flush(); + } catch (IOException e) { + getLogger().severe("Failed to print debug message."); + e.printStackTrace(); + } + } + } + + /** + * Print a {@link Throwable}'s stacktrace to the /plugins/ShopChest/debug.txt file + * @param throwable {@link Throwable} whose stacktrace will be printed + */ + public void debug(Throwable throwable) { + if (Config.enableDebugLog && fw != null) { + PrintWriter pw = new PrintWriter(fw); + throwable.printStackTrace(pw); + pw.flush(); + } + } + + /** + * @return A thread pool for executing shop creation tasks + */ + public ExecutorService getShopCreationThreadPool() { + return shopCreationThreadPool; + } + + public HologramFormat getHologramFormat() { + return hologramFormat; + } + + public ShopCommand getShopCommand() { + return shopCommand; + } + + /** + * @return The {@link ShopUpdater} that schedules hologram and item updates + */ + public ShopUpdater getUpdater() { + return updater; + } + + /** + * @return Whether the plugin 'AreaShop' is enabled + */ + public boolean hasAreaShop() { + return Config.enableAreaShopIntegration && areaShop != null && areaShop.isEnabled(); + } + + /** + * @return Whether the plugin 'GriefPrevention' is enabled + */ + public boolean hasGriefPrevention() { + return Config.enableGriefPreventionIntegration && griefPrevention != null && griefPrevention.isEnabled(); + } + + /** + * @return An instance of {@link GriefPrevention} or {@code null} if GriefPrevention is not enabled + */ + public GriefPrevention getGriefPrevention() { + return griefPrevention; + } + + /** + * @return Whether the plugin 'IslandWorld' is enabled + */ + public boolean hasIslandWorld() { + return Config.enableIslandWorldIntegration && islandWorld != null && islandWorld.isEnabled(); + } + /** + * @return Whether the plugin 'ASkyBlock' is enabled + */ + public boolean hasASkyBlock() { + return Config.enableASkyblockIntegration && aSkyBlock != null && aSkyBlock.isEnabled(); + } + + /** + * @return Whether the plugin 'uSkyBlock' is enabled + */ + public boolean hasUSkyBlock() { + return Config.enableUSkyblockIntegration && uSkyBlock != null && uSkyBlock.isEnabled(); + } + + /** + * @return An instance of {@link uSkyBlockAPI} or {@code null} if uSkyBlock is not enabled + */ + public uSkyBlockAPI getUSkyBlock() { + return uSkyBlock; + } + + /** + * @return Whether the plugin 'PlotSquared' is enabled + */ + public boolean hasPlotSquared() { + if (!Config.enablePlotsquaredIntegration) { + return false; + } + + if (Utils.getMajorVersion() < 13) { + // Supported PlotSquared versions don't support versions below 1.13 + return false; + } + Plugin p = getServer().getPluginManager().getPlugin("PlotSquared"); + return p != null && p.isEnabled(); + } + + /** + * @return Whether the plugin 'AuthMe' is enabled + */ + public boolean hasAuthMe() { + return Config.enableAuthMeIntegration && authMe != null && authMe.isEnabled(); + } + /** + * @return Whether the plugin 'Towny' is enabled + */ + public boolean hasTowny() { + return Config.enableTownyIntegration && towny != null && towny.isEnabled(); + } + + /** + * @return Whether the plugin 'WorldGuard' is enabled + */ + public boolean hasWorldGuard() { + return Config.enableWorldGuardIntegration && worldGuard != null && worldGuard.isEnabled(); + } + + /** + * @return Whether the plugin 'WorldGuard' is enabled + */ + public boolean hasBentoBox() { + return Config.enableBentoBoxIntegration && bentoBox != null && bentoBox.isEnabled(); + } + + /** + * @return ShopChest's {@link ShopUtils} containing some important methods + */ + public ShopUtils getShopUtils() { + return shopUtils; + } + + /** + * @return Registered Economy of Vault + */ + public Economy getEconomy() { + return econ; + } + + /** + * @return ShopChest's shop database + */ + public Database getShopDatabase() { + return database; + } + + /** + * @return Whether an update is needed (will return false if not checked) + */ + public boolean isUpdateNeeded() { + return isUpdateNeeded; + } + + /** + * Set whether an update is needed + * @param isUpdateNeeded Whether an update should be needed + */ + public void setUpdateNeeded(boolean isUpdateNeeded) { + this.isUpdateNeeded = isUpdateNeeded; + } + + /** + * @return The latest version of ShopChest (will return null if not checked or if no update is available) + */ + public String getLatestVersion() { + return latestVersion; + } + + /** + * Set the latest version + * @param latestVersion Version to set as latest version + */ + public void setLatestVersion(String latestVersion) { + this.latestVersion = latestVersion; + } + + /** + * @return The download link of the latest version (will return null if not checked or if no update is available) + */ + public String getDownloadLink() { + return downloadLink; + } + + /** + * Set the download Link of the latest version (will return null if not checked or if no update is available) + * @param downloadLink Link to set as Download Link + */ + public void setDownloadLink(String downloadLink) { + this.downloadLink = downloadLink; + } + + /** + * @return The {@link Config} of ShopChest + */ + public Config getShopChestConfig() { + return config; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/command/ShopCommand.java b/plugin/src/main/java/de/epiceric/shopchest/command/ShopCommand.java new file mode 100644 index 0000000..0a0b90b --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/command/ShopCommand.java @@ -0,0 +1,354 @@ +package de.epiceric.shopchest.command; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; +import org.bukkit.command.SimpleCommandMap; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; +import org.bukkit.permissions.PermissionAttachmentInfo; +import org.bukkit.plugin.Plugin; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.language.Message; +import de.epiceric.shopchest.language.Replacement; +import de.epiceric.shopchest.utils.ClickType.SelectClickType; +import de.epiceric.shopchest.utils.Permissions; + +public class ShopCommand { + + private static boolean commandCreated = false; + + private final ShopChest plugin; + private final String name; + private final String fallbackPrefix; + private final PluginCommand pluginCommand; + private final ShopCommandExecutor executor; + + private final List subCommands = new ArrayList<>(); + + public ShopCommand(final ShopChest plugin) { + if (commandCreated) { + IllegalStateException e = new IllegalStateException("Command has already been registered"); + plugin.debug(e); + throw e; + } + + this.plugin = plugin; + this.name = Config.mainCommandName.toLowerCase(Locale.ENGLISH).trim(); + this.fallbackPrefix = plugin.getName().toLowerCase(Locale.ENGLISH).trim(); + this.pluginCommand = createPluginCommand(); + this.executor = new ShopCommandExecutor(plugin); + + ShopTabCompleter tabCompleter = new ShopTabCompleter(plugin); + + final Replacement cmdReplacement = new Replacement(Placeholder.COMMAND, name); + + addSubCommand(new ShopSubCommand("create", true, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + boolean receiveCreateMessage = sender.hasPermission(Permissions.CREATE); + if (!receiveCreateMessage) { + for (PermissionAttachmentInfo permInfo : sender.getEffectivePermissions()) { + String perm = permInfo.getPermission(); + if (perm.startsWith(Permissions.CREATE) && sender.hasPermission(perm)) { + receiveCreateMessage = true; + break; + } + } + } + + if (sender.hasPermission(Permissions.CREATE_ADMIN)) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_CREATE_ADMIN, cmdReplacement); + } else if (receiveCreateMessage) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_CREATE, cmdReplacement); + } + + return ""; + } + }); + + addSubCommand(new ShopSubCommand("remove", true, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_REMOVE, cmdReplacement); + } + }); + + addSubCommand(new ShopSubCommand("info", true, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_INFO, cmdReplacement); + } + }); + + addSubCommand(new ShopSubCommand("limits", true, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_LIMITS, cmdReplacement); + } + }); + + addSubCommand(new ShopSubCommand("open", true, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_OPEN, cmdReplacement); + } + }); + + addSubCommand(new ShopSubCommand("removeall", false, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + if (sender.hasPermission(Permissions.REMOVE_OTHER)) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_REMOVEALL, cmdReplacement); + } else { + return ""; + } + } + }); + + addSubCommand(new ShopSubCommand("reload", false, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + if (sender.hasPermission(Permissions.RELOAD)) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_RELOAD, cmdReplacement); + } else { + return ""; + } + } + }); + + addSubCommand(new ShopSubCommand("update", false, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + if (sender.hasPermission(Permissions.UPDATE)) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_UPDATE, cmdReplacement); + } else { + return ""; + } + } + }); + + addSubCommand(new ShopSubCommand("config", false, executor, tabCompleter) { + @Override + public String getHelpMessage(CommandSender sender) { + if (sender.hasPermission(Permissions.CONFIG)) { + return LanguageUtils.getMessage(Message.COMMAND_DESC_CONFIG, cmdReplacement); + } else { + return ""; + } + } + }); + + register(); + commandCreated = true; + } + + public PluginCommand getCommand() { + return pluginCommand; + } + + /** + * Call the second part of the create method after the player + * has selected an item from the creative inventory. + */ + public void createShopAfterSelected(Player player, SelectClickType clickType) { + executor.create2(player, clickType); + } + + private PluginCommand createPluginCommand() { + plugin.debug("Creating plugin command"); + try { + Constructor c = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); + c.setAccessible(true); + + PluginCommand cmd = c.newInstance(name, plugin); + cmd.setDescription("Manage players' shops or this plugin."); + cmd.setUsage("/" + name); + cmd.setExecutor(new ShopBaseCommandExecutor()); + cmd.setTabCompleter(new ShopBaseTabCompleter()); + + return cmd; + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) { + plugin.getLogger().severe("Failed to create command"); + plugin.debug("Failed to create plugin command"); + plugin.debug(e); + } + + return null; + } + + public void addSubCommand(ShopSubCommand subCommand) { + plugin.debug("Adding sub command \"" + subCommand.getName() + "\""); + this.subCommands.add(subCommand); + } + + public List getSubCommands() { + return new ArrayList<>(subCommands); + } + + private void register() { + if (pluginCommand == null) return; + + plugin.debug("Registering command " + name); + + try { + Field fCommandMap = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap"); + fCommandMap.setAccessible(true); + + Object commandMapObject = fCommandMap.get(Bukkit.getPluginManager()); + if (commandMapObject instanceof CommandMap) { + CommandMap commandMap = (CommandMap) commandMapObject; + commandMap.register(fallbackPrefix, pluginCommand); + } + } catch (NoSuchFieldException | IllegalAccessException e) { + plugin.getLogger().severe("Failed to register command"); + plugin.debug("Failed to register plugin command"); + plugin.debug(e); + } + } + + public void unregister() { + if (pluginCommand == null) return; + + plugin.debug("Unregistering command " + name); + + try { + Field fCommandMap = Bukkit.getPluginManager().getClass().getDeclaredField("commandMap"); + fCommandMap.setAccessible(true); + + Object commandMapObject = fCommandMap.get(Bukkit.getPluginManager()); + if (commandMapObject instanceof CommandMap) { + CommandMap commandMap = (CommandMap) commandMapObject; + pluginCommand.unregister(commandMap); + + Field fKnownCommands = SimpleCommandMap.class.getDeclaredField("knownCommands"); + fKnownCommands.setAccessible(true); + + Object knownCommandsObject = fKnownCommands.get(commandMap); + if (knownCommandsObject instanceof Map) { + Map knownCommands = (Map) knownCommandsObject; + knownCommands.remove(fallbackPrefix + ":" + name); + if (pluginCommand.equals(knownCommands.get(name))) { + knownCommands.remove(name); + } + } + } + } catch (NoSuchFieldException | IllegalAccessException e) { + plugin.getLogger().severe("Failed to unregister command"); + plugin.debug("Failed to unregister plugin command"); + plugin.debug(e); + } + } + + /** + * Sends the basic help message + * + * @param sender {@link CommandSender} who will receive the message + */ + private void sendBasicHelpMessage(CommandSender sender) { + plugin.debug("Sending basic help message to " + sender.getName()); + + sender.sendMessage(" "); + String header = LanguageUtils.getMessage(Message.COMMAND_DESC_HEADER, + new Replacement(Placeholder.COMMAND, Config.mainCommandName)); + + if (!header.trim().isEmpty()) sender.sendMessage(header); + + for (ShopSubCommand subCommand : subCommands) { + String msg = subCommand.getHelpMessage(sender); + if (msg == null || msg.isEmpty()) { + continue; + } + + sender.sendMessage(msg); + } + + String footer = LanguageUtils.getMessage(Message.COMMAND_DESC_FOOTER, + new Replacement(Placeholder.COMMAND,Config.mainCommandName)); + + if (!footer.trim().isEmpty()) sender.sendMessage(footer); + sender.sendMessage(" "); + } + + private class ShopBaseCommandExecutor implements CommandExecutor { + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length > 0) { + for (ShopSubCommand subCommand : subCommands) { + if (subCommand.getName().equalsIgnoreCase(args[0])) { + if (!(sender instanceof Player) && subCommand.isPlayerCommand()) { + sender.sendMessage(ChatColor.RED + "Only players can use this command."); + return true; + } + + if (!subCommand.execute(sender, command, label, args)) { + sendBasicHelpMessage(sender); + } + + return true; + } + } + + sendBasicHelpMessage(sender); + } else { + sendBasicHelpMessage(sender); + } + + return true; + } + } + + private class ShopBaseTabCompleter implements TabCompleter { + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + List subCommandNames = new ArrayList<>(); + + List tabCompletions = new ArrayList<>(); + + for (ShopSubCommand subCommand : subCommands) { + subCommandNames.add(subCommand.getName()); + } + + if (args.length == 1) { + if (!args[0].isEmpty()) { + for (String s : subCommandNames) { + if (s.startsWith(args[0])) { + tabCompletions.add(s); + } + } + return tabCompletions; + } else { + return subCommandNames; + } + } else if (args.length > 1) { + for (ShopSubCommand subCmd : subCommands) { + if (subCmd.getName().equalsIgnoreCase(args[0])) { + return subCmd.getTabCompletions(sender, command, label, args); + } + } + } + + return new ArrayList<>(); + } + + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/command/ShopCommandExecutor.java b/plugin/src/main/java/de/epiceric/shopchest/command/ShopCommandExecutor.java new file mode 100644 index 0000000..eb131cc --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/command/ShopCommandExecutor.java @@ -0,0 +1,576 @@ +package de.epiceric.shopchest.command; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.GameMode; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.event.ShopPreCreateEvent; +import de.epiceric.shopchest.event.ShopPreInfoEvent; +import de.epiceric.shopchest.event.ShopPreOpenEvent; +import de.epiceric.shopchest.event.ShopPreRemoveEvent; +import de.epiceric.shopchest.event.ShopReloadEvent; +import de.epiceric.shopchest.event.ShopRemoveAllEvent; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.language.Message; +import de.epiceric.shopchest.language.Replacement; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.shop.Shop.ShopType; +import de.epiceric.shopchest.shop.ShopProduct; +import de.epiceric.shopchest.utils.Callback; +import de.epiceric.shopchest.utils.ClickType; +import de.epiceric.shopchest.utils.ClickType.CreateClickType; +import de.epiceric.shopchest.utils.ClickType.SelectClickType; +import de.epiceric.shopchest.utils.ItemUtils; +import de.epiceric.shopchest.utils.Permissions; +import de.epiceric.shopchest.utils.ShopUtils; +import de.epiceric.shopchest.utils.UpdateChecker; +import de.epiceric.shopchest.utils.Utils; + +class ShopCommandExecutor implements CommandExecutor { + + private ShopChest plugin; + private ShopUtils shopUtils; + + ShopCommandExecutor(ShopChest plugin) { + this.plugin = plugin; + this.shopUtils = plugin.getShopUtils(); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + List subCommands = plugin.getShopCommand().getSubCommands(); + + if (args.length > 0) { + String _subCommand = args[0]; + ShopSubCommand subCommand = null; + + for (ShopSubCommand shopSubCommand : subCommands) { + if (shopSubCommand.getName().equalsIgnoreCase(_subCommand)) { + subCommand = shopSubCommand; + break; + } + } + + if (subCommand == null) { + return false; + } + + if (subCommand.getName().equalsIgnoreCase("reload")) { + if (sender.hasPermission(Permissions.RELOAD)) { + reload(sender); + } else { + sender.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_RELOAD)); + } + } else if (subCommand.getName().equalsIgnoreCase("update")) { + if (sender.hasPermission(Permissions.UPDATE)) { + checkUpdates(sender); + } else { + sender.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_UPDATE)); + } + } else if (subCommand.getName().equalsIgnoreCase("config")) { + if (sender.hasPermission(Permissions.CONFIG)) { + return args.length >= 4 && changeConfig(sender, args); + } else { + sender.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CONFIG)); + } + } else if (subCommand.getName().equalsIgnoreCase("removeall")) { + if (sender.hasPermission(Permissions.REMOVE_OTHER)) { + if (args.length >= 2) { + removeAll(sender, args); + } else { + return false; + } + } else { + sender.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_REMOVE_OTHERS)); + } + } else { + if (sender instanceof Player) { + Player p = (Player) sender; + + if (subCommand.getName().equalsIgnoreCase("create")) { + if (args.length == 4) { + create(args, Shop.ShopType.NORMAL, p); + } else if (args.length == 5) { + if (args[4].equalsIgnoreCase("normal")) { + create(args, Shop.ShopType.NORMAL, p); + } else if (args[4].equalsIgnoreCase("admin")) { + if (p.hasPermission(Permissions.CREATE_ADMIN)) { + create(args, Shop.ShopType.ADMIN, p); + } else { + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_ADMIN)); + } + } else { + return false; + } + } else { + return false; + } + } else if (subCommand.getName().equalsIgnoreCase("remove")) { + remove(p); + } else if (subCommand.getName().equalsIgnoreCase("info")) { + info(p); + } else if (subCommand.getName().equalsIgnoreCase("limits")) { + plugin.debug(p.getName() + " is viewing his shop limits: " + shopUtils.getShopAmount(p) + "/" + shopUtils.getShopLimit(p)); + int limit = shopUtils.getShopLimit(p); + p.sendMessage(LanguageUtils.getMessage(Message.OCCUPIED_SHOP_SLOTS, + new Replacement(Placeholder.LIMIT, (limit < 0 ? "∞" : String.valueOf(limit))), + new Replacement(Placeholder.AMOUNT, String.valueOf(shopUtils.getShopAmount(p))))); + } else if (subCommand.getName().equalsIgnoreCase("open")) { + open(p); + } else { + return false; + } + } + } + + return true; + } + + return false; + } + + /** + * A given player checks for updates + * @param sender The command executor + */ + private void checkUpdates(CommandSender sender) { + plugin.debug(sender.getName() + " is checking for updates"); + + sender.sendMessage(LanguageUtils.getMessage(Message.UPDATE_CHECKING)); + + UpdateChecker uc = new UpdateChecker(ShopChest.getInstance()); + UpdateChecker.UpdateCheckerResult result = uc.check(); + + if (result == UpdateChecker.UpdateCheckerResult.TRUE) { + plugin.setLatestVersion(uc.getVersion()); + plugin.setDownloadLink(uc.getLink()); + plugin.setUpdateNeeded(true); + + if (sender instanceof Player) { + Utils.sendUpdateMessage(plugin, (Player) sender); + } else { + sender.sendMessage(LanguageUtils.getMessage(Message.UPDATE_AVAILABLE, new Replacement(Placeholder.VERSION, uc.getVersion()))); + } + + } else if (result == UpdateChecker.UpdateCheckerResult.FALSE) { + plugin.setLatestVersion(""); + plugin.setDownloadLink(""); + plugin.setUpdateNeeded(false); + sender.sendMessage(LanguageUtils.getMessage(Message.UPDATE_NO_UPDATE)); + } else { + plugin.setLatestVersion(""); + plugin.setDownloadLink(""); + plugin.setUpdateNeeded(false); + sender.sendMessage(LanguageUtils.getMessage(Message.UPDATE_ERROR)); + } + } + + /** + * A given player reloads the shops + * @param sender The command executor + */ + private void reload(final CommandSender sender) { + plugin.debug(sender.getName() + " is reloading the shops"); + + ShopReloadEvent event = new ShopReloadEvent(sender); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()){ + plugin.debug("Reload event cancelled"); + return; + } + + // Reload configurations + plugin.getShopChestConfig().reload(false, true, true); + plugin.getHologramFormat().reload(); + plugin.getUpdater().restart(); + + // Remove all shops + for (Shop shop : shopUtils.getShops()) { + shopUtils.removeShop(shop, false); + } + + Chunk[] loadedChunks = Bukkit.getWorlds().stream().map(World::getLoadedChunks) + .flatMap(Stream::of).toArray(Chunk[]::new); + + // Reconnect to the database and re-load shops in loaded chunks + plugin.getShopDatabase().connect(new Callback(plugin) { + @Override + public void onResult(Integer result) { + shopUtils.loadShops(loadedChunks, new Callback(plugin) { + @Override + public void onResult(Integer result) { + sender.sendMessage(LanguageUtils.getMessage(Message.RELOADED_SHOPS, + new Replacement(Placeholder.AMOUNT, String.valueOf(result)))); + plugin.debug(sender.getName() + " has reloaded " + result + " shops"); + } + + @Override + public void onError(Throwable throwable) { + sender.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, + new Replacement(Placeholder.ERROR, "Failed to load shops from database"))); + plugin.getLogger().severe("Failed to load shops"); + if (throwable != null) plugin.getLogger().severe(throwable.getMessage()); + } + }); + } + + @Override + public void onError(Throwable throwable) { + // Database connection probably failed => disable plugin to prevent more errors + sender.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, + new Replacement(Placeholder.ERROR, "No database access: Disabling ShopChest"))); + plugin.getLogger().severe("No database access: Disabling ShopChest"); + if (throwable != null) plugin.getLogger().severe(throwable.getMessage()); + plugin.getServer().getPluginManager().disablePlugin(plugin); + } + }); + } + + /** + * A given player creates a shop + * @param args Arguments of the entered command + * @param shopType The {@link Shop.ShopType}, the shop will have + * @param p The command executor + */ + private void create(String[] args, Shop.ShopType shopType, final Player p) { + plugin.debug(p.getName() + " wants to create a shop"); + + int amount; + double buyPrice, sellPrice; + + // Check if amount and prices are valid + try { + amount = Integer.parseInt(args[1]); + buyPrice = Double.parseDouble(args[2]); + sellPrice = Double.parseDouble(args[3]); + } catch (NumberFormatException e) { + p.sendMessage(LanguageUtils.getMessage(Message.AMOUNT_PRICE_NOT_NUMBER)); + plugin.debug(p.getName() + " has entered an invalid amount and/or prices"); + return; + } + + if (!Utils.hasPermissionToCreateShop(p, Utils.getPreferredItemInHand(p), buyPrice > 0, sellPrice > 0)) { + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE)); + plugin.debug(p.getName() + " is not permitted to create the shop"); + return; + } + + // Check for limits + int limit = shopUtils.getShopLimit(p); + if (limit != -1) { + if (shopUtils.getShopAmount(p) >= limit) { + if (shopType != Shop.ShopType.ADMIN) { + p.sendMessage(LanguageUtils.getMessage(Message.SHOP_LIMIT_REACHED, new Replacement(Placeholder.LIMIT, String.valueOf(limit)))); + plugin.debug(p.getName() + " has reached the limit"); + return; + } + } + } + + if (amount <= 0) { + p.sendMessage(LanguageUtils.getMessage(Message.AMOUNT_IS_ZERO)); + plugin.debug(p.getName() + " has entered an invalid amount"); + return; + } + + if (!Config.allowDecimalsInPrice && (buyPrice != (int) buyPrice || sellPrice != (int) sellPrice)) { + p.sendMessage(LanguageUtils.getMessage(Message.PRICES_CONTAIN_DECIMALS)); + plugin.debug(p.getName() + " has entered an invalid price"); + return; + } + + boolean buyEnabled = buyPrice > 0; + boolean sellEnabled = sellPrice > 0; + + if (!buyEnabled && !sellEnabled) { + p.sendMessage(LanguageUtils.getMessage(Message.BUY_SELL_DISABLED)); + plugin.debug(p.getName() + " has disabled buying and selling"); + return; + } + + ItemStack inHand = Utils.getPreferredItemInHand(p); + + // Check if item in hand + if (inHand == null) { + plugin.debug(p.getName() + " does not have an item in his hand"); + + if (!Config.creativeSelectItem) { + p.sendMessage(LanguageUtils.getMessage(Message.NO_ITEM_IN_HAND)); + return; + } + + if (!(ClickType.getPlayerClickType(p) instanceof SelectClickType)) { + // Don't set previous game mode to creative if player already has select click type + ClickType.setPlayerClickType(p, new SelectClickType(p.getGameMode(), amount, buyPrice, sellPrice, shopType)); + p.setGameMode(GameMode.CREATIVE); + } + + p.sendMessage(LanguageUtils.getMessage(Message.SELECT_ITEM)); + } else { + SelectClickType ct = new SelectClickType(null, amount, buyPrice, sellPrice, shopType); + ct.setItem(inHand); + create2(p, ct); + } + } + + /** + * SHALL ONLY BE CALLED VIA {@link ShopCommand#createShopAfterSelected()} + */ + protected void create2(Player p, SelectClickType selectClickType) { + ItemStack itemStack = selectClickType.getItem(); + int amount = selectClickType.getAmount(); + double buyPrice = selectClickType.getBuyPrice(); + double sellPrice = selectClickType.getSellPrice(); + boolean buyEnabled = buyPrice > 0; + boolean sellEnabled = sellPrice > 0; + ShopType shopType = selectClickType.getShopType(); + + // Check if item on blacklist + for (String item :Config.blacklist) { + ItemStack is = ItemUtils.getItemStack(item); + + if (is == null) { + plugin.getLogger().warning("Invalid item found in blacklist: " + item); + plugin.debug("Invalid item in blacklist: " + item); + continue; + } + + if (is.getType().equals(itemStack.getType()) && is.getDurability() == itemStack.getDurability()) { + p.sendMessage(LanguageUtils.getMessage(Message.CANNOT_SELL_ITEM)); + plugin.debug(p.getName() + "'s item is on the blacklist"); + return; + } + } + + // Check if prices lower than minimum price + for (String key :Config.minimumPrices) { + ItemStack is = ItemUtils.getItemStack(key); + double minPrice = plugin.getConfig().getDouble("minimum-prices." + key); + + if (is == null) { + plugin.getLogger().warning("Invalid item found in minimum-prices: " + key); + plugin.debug("Invalid item in minimum-prices: " + key); + continue; + } + + if (is.getType().equals(itemStack.getType()) && is.getDurability() == itemStack.getDurability()) { + if (buyEnabled) { + if ((buyPrice < amount * minPrice) && (buyPrice > 0)) { + p.sendMessage(LanguageUtils.getMessage(Message.BUY_PRICE_TOO_LOW, new Replacement(Placeholder.MIN_PRICE, String.valueOf(amount * minPrice)))); + plugin.debug(p.getName() + "'s buy price is lower than the minimum"); + return; + } + } + + if (sellEnabled) { + if ((sellPrice < amount * minPrice) && (sellPrice > 0)) { + p.sendMessage(LanguageUtils.getMessage(Message.SELL_PRICE_TOO_LOW, new Replacement(Placeholder.MIN_PRICE, String.valueOf(amount * minPrice)))); + plugin.debug(p.getName() + "'s sell price is lower than the minimum"); + return; + } + } + } + } + + // Check if prices higher than maximum price + for (String key :Config.maximumPrices) { + ItemStack is = ItemUtils.getItemStack(key); + double maxPrice = plugin.getConfig().getDouble("maximum-prices." + key); + + if (is == null) { + plugin.getLogger().warning("Invalid item found in maximum-prices: " + key); + plugin.debug("Invalid item in maximum-prices: " + key); + continue; + } + + if (is.getType().equals(itemStack.getType()) && is.getDurability() == itemStack.getDurability()) { + if (buyEnabled) { + if ((buyPrice > amount * maxPrice) && (buyPrice > 0)) { + p.sendMessage(LanguageUtils.getMessage(Message.BUY_PRICE_TOO_HIGH, new Replacement(Placeholder.MAX_PRICE, String.valueOf(amount * maxPrice)))); + plugin.debug(p.getName() + "'s buy price is higher than the maximum"); + return; + } + } + + if (sellEnabled) { + if ((sellPrice > amount * maxPrice) && (sellPrice > 0)) { + p.sendMessage(LanguageUtils.getMessage(Message.SELL_PRICE_TOO_HIGH, new Replacement(Placeholder.MAX_PRICE, String.valueOf(amount * maxPrice)))); + plugin.debug(p.getName() + "'s sell price is higher than the maximum"); + return; + } + } + } + } + + + if (sellEnabled && buyEnabled) { + if (Config.buyGreaterOrEqualSell) { + if (buyPrice < sellPrice) { + p.sendMessage(LanguageUtils.getMessage(Message.BUY_PRICE_TOO_LOW, new Replacement(Placeholder.MIN_PRICE, String.valueOf(sellPrice)))); + plugin.debug(p.getName() + "'s buy price is lower than the sell price"); + return; + } + } + } + + if (Enchantment.DURABILITY.canEnchantItem(itemStack)) { + if (itemStack.getDurability() > 0 && !Config.allowBrokenItems) { + p.sendMessage(LanguageUtils.getMessage(Message.CANNOT_SELL_BROKEN_ITEM)); + plugin.debug(p.getName() + "'s item is broken"); + return; + } + } + + double creationPrice = (shopType == Shop.ShopType.NORMAL) ?Config.shopCreationPriceNormal :Config.shopCreationPriceAdmin; + if (creationPrice > 0) { + if (plugin.getEconomy().getBalance(p, p.getWorld().getName()) < creationPrice) { + p.sendMessage(LanguageUtils.getMessage(Message.SHOP_CREATE_NOT_ENOUGH_MONEY, new Replacement(Placeholder.CREATION_PRICE, String.valueOf(creationPrice)))); + plugin.debug(p.getName() + " can not pay the creation price"); + return; + } + } + + ShopProduct product = new ShopProduct(itemStack, amount); + ShopPreCreateEvent event = new ShopPreCreateEvent(p, new Shop(plugin, p, product, null, buyPrice, sellPrice, shopType)); + Bukkit.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + ClickType.setPlayerClickType(p, new CreateClickType(product, buyPrice, sellPrice, shopType)); + plugin.debug(p.getName() + " can now click a chest"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_CHEST_CREATE)); + } else { + plugin.debug("Shop pre create event cancelled"); + } + } + + /** + * A given player removes a shop + * @param p The command executor + */ + private void remove(final Player p) { + plugin.debug(p.getName() + " wants to remove a shop"); + + ShopPreRemoveEvent event = new ShopPreRemoveEvent(p); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + plugin.debug("Shop pre remove event cancelled"); + return; + } + + plugin.debug(p.getName() + " can now click a chest"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_CHEST_REMOVE)); + ClickType.setPlayerClickType(p, new ClickType(ClickType.EnumClickType.REMOVE)); + } + + /** + * A given player retrieves information about a shop + * @param p The command executor + */ + private void info(final Player p) { + plugin.debug(p.getName() + " wants to retrieve information"); + + ShopPreInfoEvent event = new ShopPreInfoEvent(p); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + plugin.debug("Shop pre info event cancelled"); + return; + } + + plugin.debug(p.getName() + " can now click a chest"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_CHEST_INFO)); + ClickType.setPlayerClickType(p, new ClickType(ClickType.EnumClickType.INFO)); + } + + /** + * A given player opens a shop + * @param p The command executor + */ + private void open(final Player p) { + plugin.debug(p.getName() + " wants to open a shop"); + + ShopPreOpenEvent event = new ShopPreOpenEvent(p); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + plugin.debug("Shop pre open event cancelled"); + return; + } + + plugin.debug(p.getName() + " can now click a chest"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_CHEST_OPEN)); + ClickType.setPlayerClickType(p, new ClickType(ClickType.EnumClickType.OPEN)); + } + + private boolean changeConfig(CommandSender sender, String[] args) { + plugin.debug(sender.getName() + " is changing the configuration"); + + String property = args[2]; + String value = args[3]; + + if (args[1].equalsIgnoreCase("set")) { + plugin.getShopChestConfig().set(property, value); + sender.sendMessage(LanguageUtils.getMessage(Message.CHANGED_CONFIG_SET, new Replacement(Placeholder.PROPERTY, property), new Replacement(Placeholder.VALUE, value))); + } else if (args[1].equalsIgnoreCase("add")) { + plugin.getShopChestConfig().add(property, value); + sender.sendMessage(LanguageUtils.getMessage(Message.CHANGED_CONFIG_ADDED, new Replacement(Placeholder.PROPERTY, property), new Replacement(Placeholder.VALUE, value))); + } else if (args[1].equalsIgnoreCase("remove")) { + plugin.getShopChestConfig().remove(property, value); + sender.sendMessage(LanguageUtils.getMessage(Message.CHANGED_CONFIG_REMOVED, new Replacement(Placeholder.PROPERTY, property), new Replacement(Placeholder.VALUE, value))); + } else { + return false; + } + + return true; + } + + private void removeAll(CommandSender sender, String[] args) { + OfflinePlayer vendor = Bukkit.getOfflinePlayer(args[1]); + + plugin.debug(sender.getName() + " is removing all shops of " + vendor.getName()); + + plugin.getShopUtils().getShops(vendor, new Callback>(plugin) { + @Override + public void onResult(Collection result) { + List shops = new ArrayList<>(result); + + ShopRemoveAllEvent event = new ShopRemoveAllEvent(sender, vendor, shops); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()){ + plugin.debug("Remove all event cancelled"); + return; + } + + for (Shop shop : shops) { + shopUtils.removeShop(shop, true); + } + + sender.sendMessage(LanguageUtils.getMessage(Message.ALL_SHOPS_REMOVED, + new Replacement(Placeholder.AMOUNT, String.valueOf(shops.size())), + new Replacement(Placeholder.VENDOR, vendor.getName()))); + } + + @Override + public void onError(Throwable throwable) { + sender.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, + new Replacement(Placeholder.ERROR, "Failed to get player's shops"))); + } + }); + + + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/command/ShopSubCommand.java b/plugin/src/main/java/de/epiceric/shopchest/command/ShopSubCommand.java new file mode 100644 index 0000000..d52f7f6 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/command/ShopSubCommand.java @@ -0,0 +1,68 @@ +package de.epiceric.shopchest.command; + +import java.util.ArrayList; +import java.util.List; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; + +public abstract class ShopSubCommand { + private String name; + private boolean playerCommand; + private CommandExecutor executor; + private TabCompleter tabCompleter; + + public ShopSubCommand(String name, boolean playerCommand, CommandExecutor executor, TabCompleter tabCompleter) { + this.name = name; + this.playerCommand = playerCommand; + this.executor = executor; + this.tabCompleter = tabCompleter; + } + + public String getName() { + return name; + } + + /** + * @return Whether the command can only be used by players, not by the console + */ + public boolean isPlayerCommand() { + return playerCommand; + } + + /** + * Execute the sub command + * @param sender Sender of the command + * @param command Command which was executed + * @param args Arguments of the command ({@code args[0]} is the sub command's name) + * @param label Alias of the command which was used + * @param args Passed command arguments + * @return Whether the sender should be sent the help message + */ + public boolean execute(CommandSender sender, Command command, String label, String[] args) { + return executor.onCommand(sender, command, label, args); + } + + /** + * @param sender Sender of the command + * @param command Command which was executed + * @param label Alias of the command which was used + * @param args Arguments of the command ({@code args[0]} is the sub command's name) + * @return A list of tab completions for the sub command (may be an empty list) + */ + public List getTabCompletions(CommandSender sender, Command command, String label, String[] args) { + if (tabCompleter == null) { + return new ArrayList<>(); + } + + return tabCompleter.onTabComplete(sender, command, label, args); + } + + /** + * @param sender Sender to receive the help message + * @return The help message for the command. + */ + public abstract String getHelpMessage(CommandSender sender); +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/command/ShopTabCompleter.java b/plugin/src/main/java/de/epiceric/shopchest/command/ShopTabCompleter.java new file mode 100644 index 0000000..ec438d1 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/command/ShopTabCompleter.java @@ -0,0 +1,126 @@ +package de.epiceric.shopchest.command; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; + +class ShopTabCompleter implements TabCompleter { + private ShopChest plugin; + + ShopTabCompleter(ShopChest plugin) { + this.plugin = plugin; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + if (command.getName().equalsIgnoreCase(Config.mainCommandName)) { + + List createSubCommands = Arrays.asList("admin"); + List configSubCommands = Arrays.asList("add", "remove", "set"); + List areaShopRemoveEvents = Arrays.asList("DELETE", "RESELL", "SELL", "UNRENT"); + List townyShopPlots = Arrays.asList("ARENA", "COMMERCIAL", "EMBASSY", "FARM", "INN", "JAIL", "RESIDENTIAL", "SPLEEF", "WILDS"); + + Set configValues = plugin.getConfig().getKeys(true); + List playerNames = Bukkit.getOnlinePlayers().stream().map(Player::getName).collect(Collectors.toList()); + + ArrayList returnCompletions = new ArrayList<>(); + + if (args.length == 2) { + if (args[0].equals("config")) { + if (!args[1].equals("")) { + for (String s : configSubCommands) { + if (s.startsWith(args[1])) { + returnCompletions.add(s); + } + } + + return returnCompletions; + } else { + return configSubCommands; + } + } else if (args[0].equals("removeall")) { + if (!args[1].equals("")) { + for (String name : playerNames) { + if (name.startsWith(args[1])) { + returnCompletions.add(name); + } + } + + return returnCompletions; + } else { + return playerNames; + } + } + } else if (args.length == 3) { + if (args[0].equals("config")) { + if (!args[2].equals("")) { + for (String s : configValues) { + if (s.startsWith(args[2])) { + returnCompletions.add(s); + } + } + + return returnCompletions; + } else { + return new ArrayList<>(configValues); + } + } + } else if (args.length == 4) { + if (args[0].equals("config")) { + if (args[2].equals("towny-shop-plots")) { + if (!args[3].equals("")) { + for (String s : townyShopPlots) { + if (s.startsWith(args[3])) { + returnCompletions.add(s); + } + } + + return returnCompletions; + } else { + return townyShopPlots; + } + } else if (args[2].equals("areashop-remove-shops")) { + if (!args[3].equals("")) { + for (String s : areaShopRemoveEvents) { + if (s.startsWith(args[3])) { + returnCompletions.add(s); + } + } + + return returnCompletions; + } else { + return areaShopRemoveEvents; + } + } + } + } else if (args.length == 5) { + if (args[0].equals("create")) { + if (!args[4].equals("")) { + for (String s : createSubCommands) { + if (s.startsWith(args[4])) { + returnCompletions.add(s); + } + } + + return returnCompletions; + } else { + return createSubCommands; + } + } + } + } + + return new ArrayList<>(); + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/config/Config.java b/plugin/src/main/java/de/epiceric/shopchest/config/Config.java new file mode 100644 index 0000000..21e9cb3 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/config/Config.java @@ -0,0 +1,614 @@ +package de.epiceric.shopchest.config; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.inventory.ItemStack; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.sql.Database; +import de.epiceric.shopchest.utils.ItemUtils; +import de.epiceric.shopchest.utils.Utils; + +public class Config { + + /** + * The item with which a player can click a shop to retrieve information + **/ + public static ItemStack shopInfoItem; + + /** + * The default value for the custom WorldGuard flag 'create-shop' + **/ + public static boolean wgAllowCreateShopDefault; + + /** + * The default value for the custom WorldGuard flag 'use-admin-shop' + **/ + public static boolean wgAllowUseAdminShopDefault; + + /** + * The default value for the custom WorldGuard flag 'use-shop' + **/ + public static boolean wgAllowUseShopDefault; + + /** + * The types of town plots residents are allowed to create shops in + **/ + public static List townyShopPlotsResidents; + + /** + * The types of town plots the mayor is allowed to create shops in + **/ + public static List townyShopPlotsMayor; + + /** + * The types of town plots the king is allowed to create shops in + **/ + public static List townyShopPlotsKing; + + /** + * The events of AreaShop when shops in that region should be removed + **/ + public static List areashopRemoveShopEvents; + + /** + * The hostname used in ShopChest's MySQL database + **/ + public static String databaseMySqlHost; + + /** + * The port used for ShopChest's MySQL database + **/ + public static int databaseMySqlPort; + + /** + * The database used for ShopChest's MySQL database + **/ + public static String databaseMySqlDatabase; + + /** + * The username used in ShopChest's MySQL database + **/ + public static String databaseMySqlUsername; + + /** + * The password used in ShopChest's MySQL database + **/ + public static String databaseMySqlPassword; + + /** + * The prefix to be used for database tables + */ + public static String databaseTablePrefix; + + /** + * The database type used for ShopChest + **/ + public static Database.DatabaseType databaseType; + + /** + * The interval in seconds, a ping is sent to the MySQL server + **/ + public static int databaseMySqlPingInterval; + + /** + *

The minimum prices for certain items

+ * This returns a key set, which contains e.g "STONE", "STONE:1", of the minimum-prices section in ShopChest's config. + * To actually retrieve the minimum price for an item, you have to get the double {@code minimum-prices.}. + **/ + public static Set minimumPrices; + + /** + *

The maximum prices for certain items

+ * This returns a key set, which contains e.g "STONE", "STONE:1", of the {@code maximum-prices} section in ShopChest's config. + * To actually retrieve the maximum price for an item, you have to get the double {@code maximum-prices.}. + **/ + public static Set maximumPrices; + + /** + *

List containing items, of which players can't create a shop

+ * If this list contains an item (e.g "STONE", "STONE:1"), it's in the blacklist. + **/ + public static List blacklist; + + /** + * Whether prices may contain decimals + **/ + public static boolean allowDecimalsInPrice; + + /** + * Whether the buy price of a shop must be greater than or equal the sell price + **/ + public static boolean buyGreaterOrEqualSell; + + /** + * Whether buys and sells must be confirmed + **/ + public static boolean confirmShopping; + + /** + * Whether the shop creation price should be refunded at removal. + */ + public static boolean refundShopCreation; + + /** + *

Whether the update checker should run on start and notify players on join.

+ * The command is not affected by this setting and will continue to check for updates. + **/ + public static boolean enableUpdateChecker; + + /** + * Whether the debug log file should be created + **/ + public static boolean enableDebugLog; + + /** + * Whether buys and sells should be logged in the database + **/ + public static boolean enableEconomyLog; + + /** + * Whether WorldGuard integration should be enabled + **/ + public static boolean enableWorldGuardIntegration; + + /** + *

Sets the time limit for cleaning up the economy log in days

+ * + * If this equals to {@code 0}, the economy log will not be cleaned. + **/ + public static int cleanupEconomyLogDays; + + /** + * Whether Towny integration should be enabled + **/ + public static boolean enableTownyIntegration; + + /** + * Whether AuthMe integration should be enabled + **/ + public static boolean enableAuthMeIntegration; + + /** + * Whether PlotSquared integration should be enabled + **/ + public static boolean enablePlotsquaredIntegration; + + /** + * Whether uSkyBlock integration should be enabled + **/ + public static boolean enableUSkyblockIntegration; + + /** + * Whether ASkyBlock integration should be enabled + **/ + public static boolean enableASkyblockIntegration; + + /** + * Whether BentoBox integration should be enabled + **/ + public static boolean enableBentoBoxIntegration; + + /** + * Whether IslandWorld integration should be enabled + **/ + public static boolean enableIslandWorldIntegration; + + /** + * Whether GriefPrevention integration should be enabled + **/ + public static boolean enableGriefPreventionIntegration; + + /** + * Whether AreaShop integration should be enabled + **/ + public static boolean enableAreaShopIntegration; + + /** + * Whether the vendor of the shop should get messages about buys and sells + **/ + public static boolean enableVendorMessages; + + /** + * Whether the vendor of the shop should get messages on all servers about buys and sells + **/ + public static boolean enableVendorBungeeMessages; + + /** + * Whether the extension of a potion or tipped arrow (if available) should be appended to the item name. + **/ + public static boolean appendPotionLevelToItemName; + + /** + * Whether players are allowed to sell/buy broken items + **/ + public static boolean allowBrokenItems; + + /** + * Whether only the shop a player is pointing at should be shown + **/ + public static boolean onlyShowShopsInSight; + + /** + *

Whether shops should automatically be removed from the database if an error occurred while loading

+ * (e.g. when no chest is found at a shop's location) + */ + public static boolean removeShopOnError; + + /** + * Whether the item amount should be calculated to fit the available money or inventory space + **/ + public static boolean autoCalculateItemAmount; + + /** + * Whether players should be able to select an item from the creative inventory + */ + public static boolean creativeSelectItem; + + /** + *

Whether the mouse buttons are inverted

+ * Default:
+ * Right-Click: Buy
+ * Left-Click: Sell + **/ + public static boolean invertMouseButtons; + + /** + * Whether the hologram's location should be fixed at the bottom + **/ + public static boolean hologramFixedBottom; + + /** + * Amount every hologram should be lifted + **/ + public static double hologramLift; + + /** + * The maximum distance between a player and a shop to see the hologram + **/ + public static double maximalDistance; + + /** + * The maximum distance between a player and a shop to see the shop item + **/ + public static double maximalItemDistance; + + /** + * The price a player has to pay in order to create a normal shop + **/ + public static double shopCreationPriceNormal; + + /** + * The price a player has to pay in order to create an admin shop + **/ + public static double shopCreationPriceAdmin; + + /** + * The default shop limit for players whose limit is not set via a permission + **/ + public static int defaultLimit; + + /** + * The main command of ShopChest (default: shop) + **/ + public static String mainCommandName; + + /** + * The language file to use (e.g en_US, de_DE) + **/ + public static String languageFile; + + /** + * The language configuration of the currently selected language file + */ + public static LanguageConfiguration langConfig; + + private ShopChest plugin; + + public Config(ShopChest plugin) { + this.plugin = plugin; + + plugin.saveDefaultConfig(); + + reload(true, true, true); + } + + /** + *

Set a configuration value

+ * Config is automatically reloaded + * + * @param property Property to change + * @param value Value to set + */ + public void set(String property, String value) { + boolean langChange = (property.equalsIgnoreCase("language-file")); + try { + int intValue = Integer.parseInt(value); + plugin.getConfig().set(property, intValue); + + plugin.saveConfig(); + reload(false, langChange, false); + + return; + } catch (NumberFormatException e) { /* Value not an integer */ } + + try { + double doubleValue = Double.parseDouble(value); + plugin.getConfig().set(property, doubleValue); + + plugin.saveConfig(); + reload(false, langChange, false); + + return; + } catch (NumberFormatException e) { /* Value not a double */ } + + if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) { + boolean boolValue = Boolean.parseBoolean(value); + plugin.getConfig().set(property, boolValue); + } else { + plugin.getConfig().set(property, value); + } + + plugin.saveConfig(); + + reload(false, langChange, false); + } + + /** + * Add a value to a list in the config.yml. + * If the list does not exist, a new list with the given value will be created + * + * @param property Location of the list + * @param value Value to add + */ + public void add(String property, String value) { + List list = (plugin.getConfig().getList(property) == null) ? new ArrayList<>() : plugin.getConfig().getList(property); + + try { + int intValue = Integer.parseInt(value); + list.add(intValue); + + plugin.saveConfig(); + reload(false, false, false); + + return; + } catch (NumberFormatException e) { /* Value not an integer */ } + + try { + double doubleValue = Double.parseDouble(value); + list.add(doubleValue); + + plugin.saveConfig(); + reload(false, false, false); + + return; + } catch (NumberFormatException e) { /* Value not a double */ } + + if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) { + boolean boolValue = Boolean.parseBoolean(value); + list.add(boolValue); + } else { + list.add(value); + } + + plugin.saveConfig(); + + reload(false, false, false); + } + + public void remove(String property, String value) { + List list = (plugin.getConfig().getList(property) == null) ? new ArrayList<>() : plugin.getConfig().getList(property); + + try { + int intValue = Integer.parseInt(value); + list.remove(intValue); + + plugin.saveConfig(); + reload(false, false, false); + + return; + } catch (NumberFormatException e) { /* Value not an integer */ } + + try { + double doubleValue = Double.parseDouble(value); + list.remove(doubleValue); + + plugin.saveConfig(); + reload(false, false, false); + + return; + } catch (NumberFormatException e) { /* Value not a double */ } + + if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) { + boolean boolValue = Boolean.parseBoolean(value); + list.remove(boolValue); + } else { + list.remove(value); + } + + plugin.saveConfig(); + + reload(false, false, false); + } + + /** + * Reload the configuration values from config.yml + * @param firstLoad Whether the config values have not been loaded before + * @param langReload Whether the language configuration should be reloaded + * @param showMessages Whether console (error) messages should be shown + */ + public void reload(boolean firstLoad, boolean langReload, boolean showMessages) { + plugin.reloadConfig(); + + shopInfoItem = ItemUtils.getItemStack(plugin.getConfig().getString("shop-info-item")); + wgAllowCreateShopDefault = plugin.getConfig().getBoolean("worldguard-default-flag-values.create-shop"); + wgAllowUseAdminShopDefault = plugin.getConfig().getBoolean("worldguard-default-flag-values.use-admin-shop"); + wgAllowUseShopDefault = plugin.getConfig().getBoolean("worldguard-default-flag-values.use-shop"); + townyShopPlotsResidents = plugin.getConfig().getStringList("towny-shop-plots.residents"); + townyShopPlotsMayor = plugin.getConfig().getStringList("towny-shop-plots.mayor"); + townyShopPlotsKing = plugin.getConfig().getStringList("towny-shop-plots.king"); + areashopRemoveShopEvents = plugin.getConfig().getStringList("areashop-remove-shops"); + databaseMySqlPingInterval = plugin.getConfig().getInt("database.mysql.ping-interval"); + databaseMySqlHost = plugin.getConfig().getString("database.mysql.hostname"); + databaseMySqlPort = plugin.getConfig().getInt("database.mysql.port"); + databaseMySqlDatabase = plugin.getConfig().getString("database.mysql.database"); + databaseMySqlUsername = plugin.getConfig().getString("database.mysql.username"); + databaseMySqlPassword = plugin.getConfig().getString("database.mysql.password"); + databaseTablePrefix = plugin.getConfig().getString("database.table-prefix"); + databaseType = Database.DatabaseType.valueOf(plugin.getConfig().getString("database.type")); + minimumPrices = (plugin.getConfig().getConfigurationSection("minimum-prices") == null) ? new HashSet() : plugin.getConfig().getConfigurationSection("minimum-prices").getKeys(true); + maximumPrices = (plugin.getConfig().getConfigurationSection("maximum-prices") == null) ? new HashSet() : plugin.getConfig().getConfigurationSection("maximum-prices").getKeys(true); + allowDecimalsInPrice = plugin.getConfig().getBoolean("allow-decimals-in-price"); + allowBrokenItems = plugin.getConfig().getBoolean("allow-broken-items"); + autoCalculateItemAmount = (allowDecimalsInPrice && plugin.getConfig().getBoolean("auto-calculate-item-amount")); + creativeSelectItem = plugin.getConfig().getBoolean("creative-select-item"); + blacklist = (plugin.getConfig().getStringList("blacklist") == null) ? new ArrayList() : plugin.getConfig().getStringList("blacklist"); + buyGreaterOrEqualSell = plugin.getConfig().getBoolean("buy-greater-or-equal-sell"); + confirmShopping = plugin.getConfig().getBoolean("confirm-shopping"); + refundShopCreation = plugin.getConfig().getBoolean("refund-shop-creation"); + enableUpdateChecker = plugin.getConfig().getBoolean("enable-update-checker"); + enableDebugLog = plugin.getConfig().getBoolean("enable-debug-log"); + enableEconomyLog = plugin.getConfig().getBoolean("enable-economy-log"); + cleanupEconomyLogDays = plugin.getConfig().getInt("cleanup-economy-log-days"); + enableWorldGuardIntegration = plugin.getConfig().getBoolean("enable-worldguard-integration"); + enableTownyIntegration = plugin.getConfig().getBoolean("enable-towny-integration"); + enableAuthMeIntegration = plugin.getConfig().getBoolean("enable-authme-integration"); + enablePlotsquaredIntegration = plugin.getConfig().getBoolean("enable-plotsquared-integration"); + enableUSkyblockIntegration = plugin.getConfig().getBoolean("enable-uskyblock-integration"); + enableASkyblockIntegration = plugin.getConfig().getBoolean("enable-askyblock-integration"); + enableBentoBoxIntegration = plugin.getConfig().getBoolean("enable-bentobox-integration"); + enableIslandWorldIntegration = plugin.getConfig().getBoolean("enable-islandworld-integration"); + enableGriefPreventionIntegration = plugin.getConfig().getBoolean("enable-griefprevention-integration"); + enableAreaShopIntegration = plugin.getConfig().getBoolean("enable-areashop-integration"); + enableVendorMessages = plugin.getConfig().getBoolean("enable-vendor-messages"); + enableVendorBungeeMessages = plugin.getConfig().getBoolean("enable-vendor-bungee-messages"); + onlyShowShopsInSight = plugin.getConfig().getBoolean("only-show-shops-in-sight"); + appendPotionLevelToItemName = plugin.getConfig().getBoolean("append-potion-level-to-item-name"); + removeShopOnError = plugin.getConfig().getBoolean("remove-shop-on-error"); + invertMouseButtons = plugin.getConfig().getBoolean("invert-mouse-buttons"); + hologramFixedBottom = plugin.getConfig().getBoolean("hologram-fixed-bottom"); + hologramLift = plugin.getConfig().getDouble("hologram-lift"); + maximalDistance = plugin.getConfig().getDouble("maximal-distance"); + maximalItemDistance = plugin.getConfig().getDouble("maximal-item-distance"); + shopCreationPriceNormal = plugin.getConfig().getDouble("shop-creation-price.normal"); + shopCreationPriceAdmin = plugin.getConfig().getDouble("shop-creation-price.admin"); + defaultLimit = plugin.getConfig().getInt("shop-limits.default"); + mainCommandName = plugin.getConfig().getString("main-command-name"); + languageFile = plugin.getConfig().getString("language-file"); + + if (firstLoad || langReload) loadLanguageConfig(showMessages); + if (!firstLoad && langReload) LanguageUtils.load(); + } + + /** + * @return ShopChest's {@link LanguageConfiguration} + */ + public LanguageConfiguration getLanguageConfig() { + return langConfig; + } + + private Reader getTextResource(String file, boolean showMessages) { + try { + return (Reader) plugin.getClass().getDeclaredMethod("getTextResource", String.class).invoke(plugin, file); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + if (showMessages) plugin.getLogger().severe("Failed to get file from jar: " + file); + plugin.debug("Failed to get file from jar: " + file); + plugin.debug(e); + } + + return null; + } + + private void loadLanguageConfig(boolean showMessages) { + langConfig = new LanguageConfiguration(plugin, showMessages); + File langFolder = new File(plugin.getDataFolder(), "lang"); + + String legacy = Utils.getMajorVersion() < 13 ? "-legacy" : ""; + + if (!(new File(langFolder, "en_US" + legacy + ".lang")).exists()) + plugin.saveResource("lang/en_US" + legacy + ".lang", false); + + if (!(new File(langFolder, "de_DE" + legacy + ".lang")).exists()) + plugin.saveResource("lang/de_DE" + legacy + ".lang", false); + + File langConfigFile = new File(langFolder, languageFile + legacy + ".lang"); + File langDefaultFile = new File(langFolder, "en_US" + legacy + ".lang"); + + if (!langConfigFile.exists()) { + if (!langDefaultFile.exists()) { + try { + Reader r = getTextResource("lang/" + langConfigFile.getName(), showMessages); + + if (r == null) { + r = getTextResource("lang/en_US" + legacy + ".lang", showMessages); + if (showMessages) plugin.getLogger().info("Using locale \"en_US" + legacy + "\" (Streamed from jar file)"); + } else { + if (showMessages) + plugin.getLogger().info("Using locale \"" + langConfigFile.getName().substring(0, langConfigFile.getName().length() - 5) + "\" (Streamed from jar file)"); + } + + if (r == null) { + if (showMessages) plugin.getLogger().warning("Using default language values"); + plugin.debug("Using default language values (#1)"); + } + + BufferedReader br = new BufferedReader(r); + + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append("\n"); + line = br.readLine(); + } + + langConfig.loadFromString(sb.toString()); + } catch (IOException | InvalidConfigurationException e) { + if (showMessages) { + plugin.getLogger().warning("Using default language values"); + } + + plugin.debug("Using default language values (#2)"); + plugin.debug(e); + } + } else { + try { + langConfig.load(langDefaultFile); + if (showMessages) plugin.getLogger().info("Using locale \"en_US" + legacy + "\""); + } catch (IOException | InvalidConfigurationException e) { + if (showMessages) { + plugin.getLogger().warning("Using default language values"); + } + + plugin.debug("Using default language values (#3)"); + plugin.debug(e); + } + } + } else { + try { + if (showMessages) + plugin.getLogger().info("Using locale \"" + langConfigFile.getName().substring(0, langConfigFile.getName().length() - 5) + "\""); + langConfig.load(langConfigFile); + } catch (IOException | InvalidConfigurationException e) { + if (showMessages) { + plugin.getLogger().warning("Using default language values"); + } + + plugin.debug("Using default language values (#4)"); + plugin.debug(e); + } + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/config/HologramFormat.java b/plugin/src/main/java/de/epiceric/shopchest/config/HologramFormat.java new file mode 100644 index 0000000..6e50ddf --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/config/HologramFormat.java @@ -0,0 +1,245 @@ +package de.epiceric.shopchest.config; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.utils.Operator; + +public class HologramFormat { + + public enum Requirement { + VENDOR, AMOUNT, ITEM_TYPE, ITEM_NAME, HAS_ENCHANTMENT, BUY_PRICE, + SELL_PRICE, HAS_POTION_EFFECT, IS_MUSIC_DISC, IS_POTION_EXTENDED, IS_BANNER_PATTERN, + IS_WRITTEN_BOOK, ADMIN_SHOP, NORMAL_SHOP, IN_STOCK, MAX_STACK, CHEST_SPACE, DURABILITY + } + + // no "-" sign since no variable can be negative + // e.g.: 100.0 >= 50.0 + private static final Pattern SIMPLE_NUMERIC_CONDITION = Pattern.compile("^(\\d+(?:\\.\\d+)?) ([<>][=]?|[=!]=) (\\d+(?:\\.\\d+)?)$"); + + // e.g.: "STONE" == "DIAMOND_SWORD" + private static final Pattern SIMPLE_STRING_CONDITION = Pattern.compile("^\"([^\"]*)\" ([=!]=) \"([^\"]*)\"$"); + + private ScriptEngineManager manager = new ScriptEngineManager(); + private ScriptEngine engine = manager.getEngineByName("JavaScript"); + + private ShopChest plugin; + private File configFile; + private YamlConfiguration config; + + public HologramFormat(ShopChest plugin) { + this.configFile = new File(plugin.getDataFolder(), "hologram-format.yml"); + this.config = YamlConfiguration.loadConfiguration(configFile); + this.plugin = plugin; + } + + /** + * Get the format for the given line of the hologram + * @param line Line of the hologram + * @param reqMap Values of the requirements that might be needed by the format (contains {@code null} if not comparable) + * @param plaMap Values of the placeholders that might be needed by the format + * @return The format of the first working option, or an empty String if no option is working + * because of not fulfilled requirements + */ + public String getFormat(int line, Map reqMap, Map plaMap) { + ConfigurationSection options = config.getConfigurationSection("lines." + line + ".options"); + + optionLoop: + for (String key : options.getKeys(false)) { + ConfigurationSection option = options.getConfigurationSection(key); + List requirements = option.getStringList("requirements"); + + String format = option.getString("format"); + + for (String sReq : requirements) { + for (Requirement req : reqMap.keySet()) { + if (sReq.contains(req.toString())) { + if (!evalRequirement(sReq, reqMap)) { + continue optionLoop; + } + } + } + } + + return evalPlaceholder(format, plaMap); + } + + return ""; + } + + public void reload() { + config = YamlConfiguration.loadConfiguration(configFile); + } + + /** + * @return Whether the hologram text has to change dynamically without reloading + */ + public boolean isDynamic() { + int count = getLineCount(); + for (int i = 0; i < count; i++) { + ConfigurationSection options = config.getConfigurationSection("lines." + i + ".options"); + + for (String key : options.getKeys(false)) { + ConfigurationSection option = options.getConfigurationSection(key); + + String format = option.getString("format"); + if (format.contains(Placeholder.STOCK.toString()) || format.contains(Placeholder.CHEST_SPACE.toString())) { + return true; + } + + for (String req : option.getStringList("requirements")) { + if (req.contains(Requirement.IN_STOCK.toString()) || req.contains(Requirement.CHEST_SPACE.toString())) { + return true; + } + } + } + } + + return false; + } + + /** + * @return Amount of lines in a hologram + */ + public int getLineCount() { + return config.getConfigurationSection("lines").getKeys(false).size(); + } + + /** + * @return Configuration of the "hologram-format.yml" file + */ + public YamlConfiguration getConfig() { + return config; + } + + /** + * Parse and evaluate a condition + * @param condition Condition to evaluate + * @param values Values of the requirements + * @return Result of the condition + */ + public boolean evalRequirement(String condition, Map values) { + String cond = condition; + + for (HologramFormat.Requirement req : HologramFormat.Requirement.values()) { + if (cond.contains(req.toString()) && values.containsKey(req)) { + Object val = values.get(req); + String sVal = String.valueOf(val); + + if (val instanceof String && !(sVal.startsWith("\"") && sVal.endsWith("\""))) { + sVal = String.format("\"%s\"", sVal); + } + + cond = cond.replace(req.toString(), sVal); + } + } + + if (cond.equals("true")) { + // e.g.: ADMIN_SHOP + return true; + } else if (cond.equals("false")) { + return false; + } else { + char firstChar = cond.charAt(0); + + // numeric cond: first char must be a digit (no variable can be negative) + if (firstChar >= '0' && firstChar <= '9') { + Matcher matcher = SIMPLE_NUMERIC_CONDITION.matcher(cond); + + if (matcher.find()) { + Double a, b; + Operator operator; + try { + a = Double.valueOf(matcher.group(1)); + operator = Operator.from(matcher.group(2)); + b = Double.valueOf(matcher.group(3)); + + return operator.compare(a, b); + } catch (IllegalArgumentException ignored) { + // should not happen, since regex checked that there is valid number and valid operator + } + } + } + + // string cond: first char must be a: " + if (firstChar == '"') { + Matcher matcher = SIMPLE_STRING_CONDITION.matcher(cond); + + if (matcher.find()) { + String a, b; + Operator operator; + try { + a = matcher.group(1); + operator = Operator.from(matcher.group(2)); + b = matcher.group(3); + + return operator.compare(a, b); + } catch (IllegalArgumentException | UnsupportedOperationException ignored) { + // should not happen, since regex checked that there is valid operator + } + } + } + + // complex comparison + try { + return (boolean) engine.eval(cond); + } catch (ScriptException e) { + plugin.debug("Failed to eval condition: " + condition); + plugin.debug(e); + return false; + } + } + } + + /** + * Parse and evaluate a condition + * @param string Message or hologram format whose containing scripts to execute + * @param values Values of the placeholders + * @return Result of the condition + */ + public String evalPlaceholder(String string, Map values) { + try { + Matcher matcher = Pattern.compile("\\{([^}]+)}").matcher(string); + String newString = string; + + while (matcher.find()) { + String withBrackets = matcher.group(); + String script = withBrackets.substring(1, withBrackets.length() - 1); + + for (Placeholder placeholder : values.keySet()) { + if (script.contains(placeholder.toString())) { + Object val = values.get(placeholder); + String sVal = String.valueOf(val); + + if (val instanceof String && !(sVal.startsWith("\"") && sVal.endsWith("\""))) { + sVal = String.format("\"%s\"", sVal); + } + + script = script.replace(placeholder.toString(), sVal); + } + } + + String result = String.valueOf(engine.eval(script)); + newString = newString.replace(withBrackets, result); + } + + return newString; + } catch (ScriptException e) { + plugin.debug("Failed to eval placeholder script in string: " + string); + plugin.debug(e); + } + + return string; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/config/LanguageConfiguration.java b/plugin/src/main/java/de/epiceric/shopchest/config/LanguageConfiguration.java new file mode 100644 index 0000000..7bc3f3c --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/config/LanguageConfiguration.java @@ -0,0 +1,132 @@ +package de.epiceric.shopchest.config; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.HashMap; + +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.FileConfiguration; + +import de.epiceric.shopchest.ShopChest; + +public class LanguageConfiguration extends FileConfiguration { + + private ArrayList lines = new ArrayList<>(); + private HashMap values = new HashMap<>(); + + private ShopChest plugin; + private boolean showMessages; + private File file; + + public LanguageConfiguration(ShopChest plugin, boolean showMessages) { + this.plugin = plugin; + this.showMessages = showMessages; + } + + @Override + public String saveToString() { + StringBuilder sb = new StringBuilder(""); + + for (String line : lines) { + sb.append(line); + sb.append("\n"); + } + + return sb.toString(); + } + + @Override + public String getString(String path, String def) { + for (String key : values.keySet()) { + if (key.equals(path)) { + return values.get(key); + } + } + + values.put(path, def); + + if (file != null) { + // Append missing entry to loaded language file + try (FileWriter writer = new FileWriter(file, true)) { + writer.write(path + "=" + def + "\n"); + if (showMessages) + plugin.getLogger().info("Missing translation for \"" + path + "\" has been added as \"" + def + "\" to the selected language file."); + } catch (IOException e) { + plugin.debug("Failed to add language entry"); + plugin.debug(e); + if (showMessages) + plugin.getLogger().severe("Failed to add missing translation for \"" + path + "\" to the selected langauge file."); + } + } + + return def; + } + + @Override + public void load(File file) throws IOException, InvalidConfigurationException { + this.file = file; + + FileInputStream fis = new FileInputStream(file); + InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(isr); + + StringBuilder sb = new StringBuilder(); + + String line = br.readLine(); + while (line != null) { + sb.append(line); + sb.append("\n"); + line = br.readLine(); + } + + fis.close(); + isr.close(); + br.close(); + + loadFromString(sb.toString()); + } + + @Override + public void loadFromString(String s) throws InvalidConfigurationException { + String[] lines = s.split("\n"); + for (String line : lines) { + if (!line.isEmpty()) { + this.lines.add(line); + + if (!line.startsWith("#")) { + if (line.contains("=")) { + if (line.split("=").length >= 2) { + String key = line.split("=")[0]; + StringBuilder sbValue = new StringBuilder(); + + for (int i = 1; i < line.split("=").length; i++) { + if (i > 1) { + sbValue.append("="); + } + sbValue.append(line.split("=")[i]); + } + + String value = sbValue.toString(); + + values.put(key, value); + } else if (line.split("=").length == 1) { + String key = line.split("=")[0]; + values.put(key, ""); + } + } + } + } + } + } + + @Override + protected String buildHeader() { + return null; + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/config/Placeholder.java b/plugin/src/main/java/de/epiceric/shopchest/config/Placeholder.java new file mode 100644 index 0000000..a2b15ce --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/config/Placeholder.java @@ -0,0 +1,43 @@ +package de.epiceric.shopchest.config; + +public enum Placeholder { + + VENDOR("%VENDOR%"), + AMOUNT("%AMOUNT%"), + ITEM_NAME("%ITEMNAME%"), + CREATION_PRICE("%CREATION-PRICE%"), + ERROR("%ERROR%"), + ENCHANTMENT("%ENCHANTMENT%"), + MIN_PRICE("%MIN-PRICE%"), + MAX_PRICE("%MAX-PRICE%"), + VERSION("%VERSION%"), + BUY_PRICE("%BUY-PRICE%"), + SELL_PRICE("%SELL-PRICE%"), + LIMIT("%LIMIT%"), + PLAYER("%PLAYER%"), + POTION_EFFECT("%POTION-EFFECT%"), + MUSIC_TITLE("%MUSIC-TITLE%"), + BANNER_PATTERN_NAME("%BANNER-PATTERN-NAME%"), + PROPERTY("%PROPERTY%"), + VALUE("%VALUE%"), + EXTENDED("%EXTENDED%"), + REVENUE("%REVENUE%"), + GENERATION("%GENERATION%"), + STOCK("%STOCK%"), + CHEST_SPACE("%CHEST-SPACE%"), + MAX_STACK("%MAX-STACK%"), + COMMAND("%COMMAND%"), + DURABILITY("%DURABILITY%"); + + private String name; + + Placeholder(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopBuySellEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopBuySellEvent.java new file mode 100644 index 0000000..eaa17cb --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopBuySellEvent.java @@ -0,0 +1,59 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +import de.epiceric.shopchest.shop.Shop; + +/** + * Called when a player buys or sells something from or to a shop + */ +public class ShopBuySellEvent extends ShopEvent implements Cancellable { + private Type type; + private int newAmount; + private double newPrice; + private boolean cancelled; + + public ShopBuySellEvent(Player player, Shop shop, Type type, int newAmount, double newPrice) { + super(player, shop); + this.type = type; + this.newAmount = newAmount; + this.newPrice = newPrice; + } + + /** + * @return Whether the player buys or sells something + */ + public Type getType() { + return type; + } + + /** + * @return The amount which might be modified because of automatic item amount calculation + */ + public int getNewAmount() { + return newAmount; + } + + /** + * @return The price which might be modified because of automatic item amount calculation + */ + public double getNewPrice() { + return newPrice; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } + + public enum Type { + BUY, + SELL; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopCreateEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopCreateEvent.java new file mode 100644 index 0000000..d8dbd74 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopCreateEvent.java @@ -0,0 +1,36 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +import de.epiceric.shopchest.shop.Shop; + +/** + * Called when a player creates a shop (clicks on a chest) + */ +public class ShopCreateEvent extends ShopEvent implements Cancellable { + private double creationPrice; + private boolean cancelled; + + public ShopCreateEvent(Player player, Shop shop, double creationPrice) { + super(player, shop); + this.creationPrice = creationPrice; + } + /** + * @return The price the player has to pay in order to create the shop (only if the event is not cancelled) + */ + public double getCreationPrice() { + return creationPrice; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopEvent.java new file mode 100644 index 0000000..9eaa980 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopEvent.java @@ -0,0 +1,43 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import de.epiceric.shopchest.shop.Shop; + +public abstract class ShopEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + private Shop shop; + private Player player; + + public ShopEvent(Player player, Shop shop) { + this.player = player; + this.shop = shop; + } + + /** + * @return Shop which is involved in this event + */ + public Shop getShop() { + return shop; + } + + /** + * @return Player who is involved in this event + */ + public Player getPlayer() { + return player; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopExtendEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopExtendEvent.java new file mode 100644 index 0000000..168059f --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopExtendEvent.java @@ -0,0 +1,37 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +import de.epiceric.shopchest.shop.Shop; + +/** + * Called when a player extends a shop (making a chest a double chest) + */ +public class ShopExtendEvent extends ShopEvent implements Cancellable { + private boolean cancelled; + private Location newChestLocation; + + public ShopExtendEvent(Player player, Shop shop, Location newChest) { + super(player, shop); + this.newChestLocation = newChest; + } + + /** + * @return Location of the placed chest + */ + public Location getNewChestLocation() { + return newChestLocation; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopInfoEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopInfoEvent.java new file mode 100644 index 0000000..7a14887 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopInfoEvent.java @@ -0,0 +1,27 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +import de.epiceric.shopchest.shop.Shop; + +/** + * Called when a player retrieves information about a shop (clicks on a chest) + */ +public class ShopInfoEvent extends ShopEvent implements Cancellable { + private boolean cancelled; + + public ShopInfoEvent(Player player, Shop shop) { + super(player, shop); + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopInitializedEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopInitializedEvent.java new file mode 100644 index 0000000..c18f2c4 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopInitializedEvent.java @@ -0,0 +1,32 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * @deprecated Use {@link ShopsLoadedEvent} instead since shops are loaded + * dynamically based on chunk loading + */ +@Deprecated +public class ShopInitializedEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + private int amount; + + public ShopInitializedEvent(int amount) { + this.amount = amount; + } + + public int getAmount() { + return amount; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopOpenEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopOpenEvent.java new file mode 100644 index 0000000..d9c1541 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopOpenEvent.java @@ -0,0 +1,27 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +import de.epiceric.shopchest.shop.Shop; + +/** + * Called when a player opens a shop (clicks on a chest) + */ +public class ShopOpenEvent extends ShopEvent implements Cancellable { + private boolean cancelled; + + public ShopOpenEvent(Player player, Shop shop) { + super(player, shop); + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreCreateEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreCreateEvent.java new file mode 100644 index 0000000..b93b525 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreCreateEvent.java @@ -0,0 +1,27 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +import de.epiceric.shopchest.shop.Shop; + +/** + * Called when a player wants to create a shop (enters the command) + */ +public class ShopPreCreateEvent extends ShopEvent implements Cancellable { + private boolean cancelled; + + public ShopPreCreateEvent(Player player, Shop shop) { + super(player, shop); + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreInfoEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreInfoEvent.java new file mode 100644 index 0000000..7e8e88d --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreInfoEvent.java @@ -0,0 +1,46 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Called when a player wants to retrieve information about a shop (enters the command) + */ +public class ShopPreInfoEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + + private Player player; + private boolean cancelled; + + public ShopPreInfoEvent(Player player) { + this.player = player; + } + + /** + * @return Player who is involved in this event + */ + public Player getPlayer() { + return player; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreOpenEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreOpenEvent.java new file mode 100644 index 0000000..4df20cb --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreOpenEvent.java @@ -0,0 +1,46 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Called when a player wants to open a shop (enters the command) + */ +public class ShopPreOpenEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + + private Player player; + private boolean cancelled; + + public ShopPreOpenEvent(Player player) { + this.player = player; + } + + /** + * @return Player who is involved in this event + */ + public Player getPlayer() { + return player; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreRemoveEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreRemoveEvent.java new file mode 100644 index 0000000..d97d9dd --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopPreRemoveEvent.java @@ -0,0 +1,46 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Called when a player wants to remove a shop (enters the command) + */ +public class ShopPreRemoveEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + + private Player player; + private boolean cancelled; + + public ShopPreRemoveEvent(Player player) { + this.player = player; + } + + /** + * @return Player who is involved in this event + */ + public Player getPlayer() { + return player; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopReloadEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopReloadEvent.java new file mode 100644 index 0000000..6bb15d7 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopReloadEvent.java @@ -0,0 +1,46 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.command.CommandSender; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Called when a player reloads the shops + */ +public class ShopReloadEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + + private CommandSender sender; + private boolean cancelled; + + public ShopReloadEvent(CommandSender sender) { + this.sender = sender; + } + + /** + * @return Sender, who caused the reload ({@link org.bukkit.entity.Player} or {@link org.bukkit.command.ConsoleCommandSender}) + */ + public CommandSender getSender() { + return sender; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopRemoveAllEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopRemoveAllEvent.java new file mode 100644 index 0000000..5282a8e --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopRemoveAllEvent.java @@ -0,0 +1,57 @@ +package de.epiceric.shopchest.event; + +import java.util.List; + +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import de.epiceric.shopchest.shop.Shop; + +public class ShopRemoveAllEvent extends Event implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + + private CommandSender sender; + private OfflinePlayer vendor; + private List shops; + private boolean cancelled; + + public ShopRemoveAllEvent(CommandSender sender, OfflinePlayer vendor, List shops) { + this.sender = sender; + this.vendor = vendor; + this.shops = shops; + } + + public CommandSender getSender() { + return sender; + } + + public OfflinePlayer getVendor() { + return vendor; + } + + public List getShops() { + return shops; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopRemoveEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopRemoveEvent.java new file mode 100644 index 0000000..2376763 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopRemoveEvent.java @@ -0,0 +1,27 @@ +package de.epiceric.shopchest.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +import de.epiceric.shopchest.shop.Shop; + +/** + * Called when a player removes a shop (clicks on a chest) + */ +public class ShopRemoveEvent extends ShopEvent implements Cancellable { + private boolean cancelled; + + public ShopRemoveEvent(Player player, Shop shop) { + super(player, shop); + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/event/ShopsLoadedEvent.java b/plugin/src/main/java/de/epiceric/shopchest/event/ShopsLoadedEvent.java new file mode 100644 index 0000000..1fec3b6 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/event/ShopsLoadedEvent.java @@ -0,0 +1,33 @@ +package de.epiceric.shopchest.event; + +import java.util.Collection; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import de.epiceric.shopchest.shop.Shop; + +/** + * Called when shops have been loaded and added to the server + */ +public class ShopsLoadedEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + private Collection shops; + + public ShopsLoadedEvent(Collection shops) { + this.shops = shops; + } + + public Collection getShops() { + return shops; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/exceptions/ChestNotFoundException.java b/plugin/src/main/java/de/epiceric/shopchest/exceptions/ChestNotFoundException.java new file mode 100644 index 0000000..0faa62e --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/exceptions/ChestNotFoundException.java @@ -0,0 +1,9 @@ +package de.epiceric.shopchest.exceptions; + +public class ChestNotFoundException extends Exception { + private static final long serialVersionUID = -6446875473671870708L; + + public ChestNotFoundException(String message) { + super(message); + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/exceptions/NotEnoughSpaceException.java b/plugin/src/main/java/de/epiceric/shopchest/exceptions/NotEnoughSpaceException.java new file mode 100644 index 0000000..d6dd5c0 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/exceptions/NotEnoughSpaceException.java @@ -0,0 +1,9 @@ +package de.epiceric.shopchest.exceptions; + +public class NotEnoughSpaceException extends Exception { + private static final long serialVersionUID = 3718475607700458355L; + + public NotEnoughSpaceException(String message) { + super(message); + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/exceptions/WorldNotFoundException.java b/plugin/src/main/java/de/epiceric/shopchest/exceptions/WorldNotFoundException.java new file mode 100644 index 0000000..4af4e62 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/exceptions/WorldNotFoundException.java @@ -0,0 +1,9 @@ +package de.epiceric.shopchest.exceptions; + +public class WorldNotFoundException extends Exception { + private static final long serialVersionUID = -555886332156936972L; + + public WorldNotFoundException(String worldName) { + super("Could not find world with name \"" + worldName + "\""); + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/BentoBoxShopFlag.java b/plugin/src/main/java/de/epiceric/shopchest/external/BentoBoxShopFlag.java new file mode 100644 index 0000000..de47c60 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/BentoBoxShopFlag.java @@ -0,0 +1,25 @@ +package de.epiceric.shopchest.external; + +import org.bukkit.Material; + +import de.epiceric.shopchest.ShopChest; +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.flags.Flag; +import world.bentobox.bentobox.managers.RanksManager; + +public class BentoBoxShopFlag { + public static final Flag SHOP_FLAG = new Flag.Builder("CREATE_SHOPS", Material.CHEST) + .type(Flag.Type.PROTECTION) + .mode(Flag.Mode.BASIC) + .defaultRank(RanksManager.TRUSTED_RANK) + .build(); + + public static void register(ShopChest plugin) { + if (BentoBox.getInstance().getFlagsManager().registerFlag(SHOP_FLAG)) { + plugin.debug("Registered BentoBox shop flag"); + } else { + plugin.getLogger().warning("Failed to register BentoBox shop flag"); + plugin.debug("Failed to register BentoBox shop flag"); + } + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/PlotSquaredOldShopFlag.java b/plugin/src/main/java/de/epiceric/shopchest/external/PlotSquaredOldShopFlag.java new file mode 100644 index 0000000..8eb8a27 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/PlotSquaredOldShopFlag.java @@ -0,0 +1,112 @@ +package de.epiceric.shopchest.external; + +import com.github.intellectualsites.plotsquared.plot.flag.Flag; +import com.github.intellectualsites.plotsquared.plot.flag.Flags; +import com.github.intellectualsites.plotsquared.plot.object.Plot; + +import org.bukkit.entity.Player; + +import de.epiceric.shopchest.ShopChest; + +import java.util.Locale; + +public class PlotSquaredOldShopFlag { + public enum Group { + OWNERS, MEMBERS, TRUSTED, EVERYONE, NONE + } + + public static final GroupFlag CREATE_SHOP = new GroupFlag("create-shop"); + public static final GroupFlag USE_SHOP = new GroupFlag("use-shop"); + public static final GroupFlag USE_ADMIN_SHOP = new GroupFlag("use-admin-shop"); + + private static boolean registered = false; + + public static void register(ShopChest plugin) { + if (registered) return; + + Flags.registerFlag(CREATE_SHOP); + Flags.registerFlag(USE_SHOP); + Flags.registerFlag(USE_ADMIN_SHOP); + registered = true; + + plugin.debug("Registered custom PlotSquared flags"); + } + + /** + * Check if a flag is allowed for a player on a plot from PlotSquared + * @param plot Plot from PlotSquared + * @param flag Flag to check + * @param p Player to check + * @return Whether the flag is allowed for the player + */ + public static boolean isFlagAllowedOnPlot(Plot plot, GroupFlag flag, Player p) { + if (plot != null && flag != null) { + Group group = plot.getFlag(flag, Group.NONE); + ShopChest.getInstance().debug("Flag " + flag.getName() + " is set to " + group); + + switch (group) { + case OWNERS: + return plot.getOwners().contains(p.getUniqueId()); + case TRUSTED: + return plot.getOwners().contains(p.getUniqueId()) || plot.getTrusted().contains(p.getUniqueId()); + case MEMBERS: + return plot.getOwners().contains(p.getUniqueId()) || plot.getTrusted().contains(p.getUniqueId()) || plot.getMembers().contains(p.getUniqueId()); + case EVERYONE: + return true; + case NONE: + return false; + } + } + + ShopChest.getInstance().debug("Flag or plot is null, or value of flag is not a group"); + + return true; + } + + public static class GroupFlag extends Flag { + public GroupFlag(String name) { + super(name); + } + + @Override + public String valueToString(Object value) { + return String.valueOf(value); + } + + @Override + public Group parseValue(String s) { + String val = s.toLowerCase(Locale.ENGLISH); + + switch (val) { + case "owners": + case "owner": + return Group.OWNERS; + case "members": + case "member": + case "helpers": + case "helper": + return Group.MEMBERS; + case "trusted": + return Group.TRUSTED; + case "everyone": + case "all": + return Group.EVERYONE; + case "deny": + case "disallow": + case "false": + case "no": + case "0": + case "none": + case "noone": + return Group.NONE; + } + + return null; + } + + @Override + public String getValueDescription() { + return "Flag value must be a group: 'owner' , 'members', 'trusted', 'everyone' or 'none'"; + } + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/PlotSquaredShopFlag.java b/plugin/src/main/java/de/epiceric/shopchest/external/PlotSquaredShopFlag.java new file mode 100644 index 0000000..8ecaa86 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/PlotSquaredShopFlag.java @@ -0,0 +1,154 @@ +package de.epiceric.shopchest.external; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; + +import com.plotsquared.core.configuration.caption.Caption; +import com.plotsquared.core.configuration.caption.StaticCaption; +import com.plotsquared.core.configuration.caption.TranslatableCaption; +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.flag.FlagParseException; +import com.plotsquared.core.plot.flag.GlobalFlagContainer; +import com.plotsquared.core.plot.flag.PlotFlag; + +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import de.epiceric.shopchest.ShopChest; +import net.kyori.adventure.text.minimessage.Template; + +public class PlotSquaredShopFlag { + public enum Group { + OWNERS, MEMBERS, TRUSTED, EVERYONE, NONE + } + + private static final String[] lowercaseValues = Arrays.asList(Group.values()).stream() + .map(value -> String.valueOf(value).toLowerCase(Locale.ENGLISH)) + .toArray(String[]::new); + + public static final GroupFlag CREATE_SHOP = new CreateShopFlag(Group.MEMBERS); + public static final GroupFlag USE_SHOP = new UseShopFlag(Group.EVERYONE); + + private static boolean registered = false; + + public static void register(ShopChest plugin) { + if (registered) return; + + GlobalFlagContainer.getInstance().addFlag(CREATE_SHOP); + GlobalFlagContainer.getInstance().addFlag(USE_SHOP); + registered = true; + + plugin.debug("Registered custom PlotSquared flags"); + } + + /** + * Check if a flag is allowed for a player on a plot from PlotSquared + * + * @param plot Plot from PlotSquared + * @param flag Flag to check + * @param p Player to check + * @return Whether the flag is allowed for the player + */ + public static boolean isFlagAllowedOnPlot(Plot plot, GroupFlag flag, Player p) { + if (plot != null && flag != null) { + Group group = plot.getFlag(flag); + ShopChest.getInstance().debug("Flag " + flag.getName() + " is set to " + group); + + switch (group) { + case OWNERS: + return plot.getOwners().contains(p.getUniqueId()); + case TRUSTED: + return plot.getOwners().contains(p.getUniqueId()) || plot.getTrusted().contains(p.getUniqueId()); + case MEMBERS: + return plot.getOwners().contains(p.getUniqueId()) || plot.getTrusted().contains(p.getUniqueId()) || plot.getMembers().contains(p.getUniqueId()); + case EVERYONE: + return true; + case NONE: + return false; + } + } + + ShopChest.getInstance().debug("Flag or plot is null, or value of flag is not a group"); + + return true; + } + + public static class CreateShopFlag extends GroupFlag { + public CreateShopFlag(Group value) { + super(value, StaticCaption.of("Set to the group that is allowed to create shops.")); + } + + @Override + protected CreateShopFlag flagOf(@NotNull Group value) { + return new CreateShopFlag(value); + } + } + + public static class UseShopFlag extends GroupFlag { + public UseShopFlag(Group value) { + super(value, StaticCaption.of("Set to the group that is allowed to use shops.")); + } + + @Override + protected UseShopFlag flagOf(@NotNull Group value) { + return new UseShopFlag(value); + } + } + + public abstract static class GroupFlag> extends PlotFlag { + protected GroupFlag(Group value, Caption description) { + super(value, TranslatableCaption.of("flags.flag_category_enum"), description); + } + + @Override + public String toString() { + return String.valueOf(getValue()).toLowerCase(Locale.ENGLISH); + } + + @Override + public String getExample() { + return "members"; + } + + @Override + public F merge(@NotNull Group newValue) { + return flagOf(newValue); + } + + @Override + public F parse(@NotNull String input) throws FlagParseException { + switch (input.toLowerCase(Locale.ENGLISH)) { + case "owners": + case "owner": + return this.flagOf(Group.OWNERS); + case "members": + case "member": + case "helpers": + case "helper": + return this.flagOf(Group.MEMBERS); + case "trusted": + return this.flagOf(Group.TRUSTED); + case "everyone": + case "all": + return this.flagOf(Group.EVERYONE); + case "deny": + case "disallow": + case "false": + case "no": + case "0": + case "none": + case "noone": + return this.flagOf(Group.NONE); + } + + throw new FlagParseException(this, input, TranslatableCaption.of("flags.flag_error_enum"), + Template.of("list", String.join(", ", lowercaseValues))); + } + + @Override + public Collection getTabCompletions() { + return Arrays.asList(lowercaseValues); + } + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/WorldGuardShopFlag.java b/plugin/src/main/java/de/epiceric/shopchest/external/WorldGuardShopFlag.java new file mode 100644 index 0000000..266d819 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/WorldGuardShopFlag.java @@ -0,0 +1,31 @@ +package de.epiceric.shopchest.external; + +import java.util.Optional; + +import org.codemc.worldguardwrapper.WorldGuardWrapper; +import org.codemc.worldguardwrapper.flag.IWrappedFlag; +import org.codemc.worldguardwrapper.flag.WrappedState; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; + +public class WorldGuardShopFlag { + + public static void register(final ShopChest plugin) { + WorldGuardWrapper wrapper = WorldGuardWrapper.getInstance(); + + Optional> createFlag = wrapper.registerFlag("create-shop", + WrappedState.class, Config.wgAllowCreateShopDefault ? WrappedState.ALLOW : WrappedState.DENY); + + Optional> useFlag = wrapper.registerFlag("use-shop", + WrappedState.class, Config.wgAllowUseShopDefault ? WrappedState.ALLOW : WrappedState.DENY); + + Optional> useAdminFlag = wrapper.registerFlag("use-admin-shop", + WrappedState.class, Config.wgAllowUseAdminShopDefault ? WrappedState.ALLOW : WrappedState.DENY); + + plugin.debug("Flag create-shop: " + String.valueOf(createFlag.isPresent())); + plugin.debug("Flag use-shop: " + String.valueOf(useFlag.isPresent())); + plugin.debug("Flag use-admin-shop: " + String.valueOf(useAdminFlag.isPresent())); + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/listeners/ASkyBlockListener.java b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/ASkyBlockListener.java new file mode 100644 index 0000000..701d2d1 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/ASkyBlockListener.java @@ -0,0 +1,62 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import com.wasteofplastic.askyblock.ASkyBlockAPI; +import com.wasteofplastic.askyblock.Island; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; + +public class ASkyBlockListener implements Listener { + private final ShopChest plugin; + + public ASkyBlockListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableASkyblockIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableASkyblockIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + Island island = ASkyBlockAPI.getInstance().getIslandAt(loc); + if (island == null) + return false; + + if (!player.getUniqueId().equals(island.getOwner()) && !island.getMembers().contains(player.getUniqueId())) { + e.setCancelled(true); + plugin.debug("Cancel Reason: ASkyBlock"); + return true; + } + + return false; + } + +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/listeners/BentoBoxListener.java b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/BentoBoxListener.java new file mode 100644 index 0000000..c638d58 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/BentoBoxListener.java @@ -0,0 +1,57 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.external.BentoBoxShopFlag; +import de.epiceric.shopchest.utils.Utils; +import world.bentobox.bentobox.api.flags.FlagListener; + +public class BentoBoxListener extends FlagListener { + private ShopChest plugin; + + public BentoBoxListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableBentoBoxIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableBentoBoxIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + boolean allowed = checkIsland((Event) e, player, loc, BentoBoxShopFlag.SHOP_FLAG); + if (!allowed) { + e.setCancelled(true); + plugin.debug("Cancel Reason: BentoBox"); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/listeners/GriefPreventionListener.java b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/GriefPreventionListener.java new file mode 100644 index 0000000..3246b0f --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/GriefPreventionListener.java @@ -0,0 +1,62 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; +import me.ryanhamshire.GriefPrevention.Claim; +import me.ryanhamshire.GriefPrevention.GriefPrevention; + +public class GriefPreventionListener implements Listener { + private final ShopChest plugin; + private final GriefPrevention griefPrevention; + + public GriefPreventionListener(ShopChest plugin) { + this.plugin = plugin; + this.griefPrevention = plugin.getGriefPrevention(); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableGriefPreventionIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableASkyblockIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + Claim claim = griefPrevention.dataStore.getClaimAt(loc, false, null); + if (claim == null) + return false; + + if (claim.allowContainers(player) != null) { + e.setCancelled(true); + plugin.debug("Cancel Reason: GriefPrevention"); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/listeners/IslandWorldListener.java b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/IslandWorldListener.java new file mode 100644 index 0000000..2745008 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/IslandWorldListener.java @@ -0,0 +1,59 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; +import pl.islandworld.api.IslandWorldApi; + +public class IslandWorldListener implements Listener { + private final ShopChest plugin; + + public IslandWorldListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableIslandWorldIntegration || !IslandWorldApi.isInitialized()) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableIslandWorldIntegration || !IslandWorldApi.isInitialized()) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + if (!loc.getWorld().getName().equals(IslandWorldApi.getIslandWorld().getName())) + return false; + + if (!IslandWorldApi.canBuildOnLocation(player, loc, true)) { + e.setCancelled(true); + plugin.debug("Cancel Reason: IslandWorld"); + return true; + } + + return false; + } + +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/listeners/PlotSquaredListener.java b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/PlotSquaredListener.java new file mode 100644 index 0000000..c102de3 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/PlotSquaredListener.java @@ -0,0 +1,90 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.Plot; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.external.PlotSquaredOldShopFlag; +import de.epiceric.shopchest.external.PlotSquaredShopFlag; +import de.epiceric.shopchest.utils.Utils; + +public class PlotSquaredListener implements Listener { + private final ShopChest plugin; + + public PlotSquaredListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enablePlotsquaredIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (org.bukkit.Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enablePlotsquaredIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + // TODO: Outsource shop use external permission + + // @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + // public void onBuySell(ShopBuySellEvent e) { + // if (!Config.enablePlotsquaredIntegration) + // return; + + // Set chestLocations = Utils.getChestLocations(e.getShop()); + // for (org.bukkit.Location loc : chestLocations) { + // Location plotLocation = new Location(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + // Plot plot = plotLocation.getOwnedPlot(); + // if (!isFlagAllowed(plot, PlotSquaredShopFlag.USE_SHOP, e.getPlayer())) { + // e.setCancelled(true); + // plugin.debug("Cancel Reason: PlotSquared"); + // return; + // } + // } + // } + + private boolean handleForLocation(Player player, org.bukkit.Location loc, Cancellable e) { + boolean isAllowed = false; + + try { + Class.forName("com.plotsquared.core.PlotSquared"); + Location plotLocation = Location.at(loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + Plot plot = plotLocation.getOwnedPlot(); + isAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredShopFlag.CREATE_SHOP, player); + } catch (ClassNotFoundException ex) { + com.github.intellectualsites.plotsquared.plot.object.Location plotLocation = new com.github.intellectualsites.plotsquared.plot.object.Location( + loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); + com.github.intellectualsites.plotsquared.plot.object.Plot plot = plotLocation.getOwnedPlot(); + isAllowed = PlotSquaredOldShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredOldShopFlag.CREATE_SHOP, player); + } + + if (!isAllowed) { + e.setCancelled(true); + plugin.debug("Cancel Reason: PlotSquared"); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/listeners/TownyListener.java b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/TownyListener.java new file mode 100644 index 0000000..db59382 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/TownyListener.java @@ -0,0 +1,85 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Optional; +import java.util.Set; + +import com.palmergames.bukkit.towny.exceptions.NotRegisteredException; +import com.palmergames.bukkit.towny.object.Resident; +import com.palmergames.bukkit.towny.object.Town; +import com.palmergames.bukkit.towny.object.TownBlock; +import com.palmergames.bukkit.towny.object.WorldCoord; +import com.palmergames.bukkit.towny.TownyUniverse; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; + +public class TownyListener implements Listener { + private final ShopChest plugin; + + public TownyListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableTownyIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enablePlotsquaredIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + try { + TownBlock townBlock = TownyUniverse.getInstance().getTownBlock(WorldCoord.parseWorldCoord(loc)); + if (townBlock == null) + return false; + + Town town = townBlock.getTown(); + Optional playerResident = town.getResidents().stream() + .filter(r -> r.getName().equals(player.getName())) + .findFirst(); + + if (!playerResident.isPresent()) { + e.setCancelled(true); + plugin.debug("Cancel Reason: Towny (no resident)"); + return true; + } + + Resident resident = playerResident.get(); + String plotType = townBlock.getType().name(); + boolean cancel = (resident.isMayor() && !Config.townyShopPlotsMayor.contains(plotType)) + || (resident.isKing() && !Config.townyShopPlotsKing.contains(plotType)) + || (!resident.isKing() && !resident.isMayor() && !Config.townyShopPlotsResidents.contains(plotType)); + + if (cancel) { + e.setCancelled(true); + plugin.debug("Cancel Reason: Towny (no permission)"); + return true; + } + } catch (NotRegisteredException ignored) { + } + return false; + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/listeners/USkyBlockListener.java b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/USkyBlockListener.java new file mode 100644 index 0000000..ee86a8e --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/USkyBlockListener.java @@ -0,0 +1,61 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; +import us.talabrek.ultimateskyblock.api.IslandInfo; +import us.talabrek.ultimateskyblock.api.uSkyBlockAPI; + +public class USkyBlockListener implements Listener { + private final ShopChest plugin; + private final uSkyBlockAPI uSkyBlockAPI; + + public USkyBlockListener(ShopChest plugin) { + this.plugin = plugin; + this.uSkyBlockAPI = plugin.getUSkyBlock(); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableUSkyblockIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enablePlotsquaredIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e); + } + + private boolean handleForLocation(Player player, Location loc, Cancellable e) { + IslandInfo islandInfo = uSkyBlockAPI.getIslandInfo(loc); + if (islandInfo == null) + return false; + + if (!player.getName().equals(islandInfo.getLeader()) && !islandInfo.getMembers().contains(player.getName())) { + e.setCancelled(true); + plugin.debug("Cancel Reason: uSkyBlock"); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/external/listeners/WorldGuardListener.java b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/WorldGuardListener.java new file mode 100644 index 0000000..fe7b440 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/external/listeners/WorldGuardListener.java @@ -0,0 +1,97 @@ +package de.epiceric.shopchest.external.listeners; + +import java.util.Optional; +import java.util.Set; + +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.codemc.worldguardwrapper.WorldGuardWrapper; +import org.codemc.worldguardwrapper.flag.IWrappedFlag; +import org.codemc.worldguardwrapper.flag.WrappedState; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.utils.Utils; + +public class WorldGuardListener implements Listener { + + private final ShopChest plugin; + private final WorldGuardWrapper wgWrapper; + + public WorldGuardListener(ShopChest plugin) { + this.plugin = plugin; + this.wgWrapper = WorldGuardWrapper.getInstance(); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onCreateShop(ShopCreateEvent e) { + if (!Config.enableWorldGuardIntegration) + return; + + Set chestLocations = Utils.getChestLocations(e.getShop()); + IWrappedFlag flag = getStateFlag("create-shop"); + for (Location loc : chestLocations) { + if (handleForLocation(e.getPlayer(), loc, e, flag)) + return; + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onExtendShop(ShopExtendEvent e) { + if (!Config.enableWorldGuardIntegration) + return; + + handleForLocation(e.getPlayer(), e.getNewChestLocation(), e, getStateFlag("create-shop")); + } + + // TODO: Outsource shop use external permission + + // @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + // public void onBuySell(ShopBuySellEvent e) { + // if (!Config.enableWorldGuardIntegration) + // return; + + // Set chestLocations = Utils.getChestLocations(e.getShop()); + // String flagName = e.getShop().getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop"; + // IWrappedFlag flag = getStateFlag(flagName); + // for (Location loc : chestLocations) { + // WrappedState state = wgWrapper.queryFlag(e.getPlayer(), loc, flag).orElse(WrappedState.DENY); + // if (state == WrappedState.DENY) { + // e.setCancelled(true); + // return; + // } + // } + // } + + private boolean handleForLocation(Player player, Location loc, Cancellable e, IWrappedFlag flag) { + if (flag == null) { + // Flag may have not been registered successfully, so ignore them. + return false; + } + + WrappedState state = wgWrapper.queryFlag(player, loc, flag).orElse(WrappedState.DENY); + if (state == WrappedState.DENY) { + e.setCancelled(true); + plugin.debug("Cancel Reason: WorldGuard"); + return true; + } + return false; + } + + private IWrappedFlag getStateFlag(String flagName) { + Optional> flagOptional = wgWrapper.getFlag(flagName, WrappedState.class); + if (!flagOptional.isPresent()) { + plugin.getLogger().severe("Failed to get WorldGuard state flag '" + flagName + "'."); + plugin.debug("WorldGuard state flag '" + flagName + "' is not present!"); + return null; + } + return flagOptional.get(); + } + +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/BannerPatternName.java b/plugin/src/main/java/de/epiceric/shopchest/language/BannerPatternName.java new file mode 100644 index 0000000..71ee11d --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/BannerPatternName.java @@ -0,0 +1,29 @@ +package de.epiceric.shopchest.language; + +import org.bukkit.Material; + +public class BannerPatternName { + + private Material bannerPatternMaterial; + private String localizedName; + + public BannerPatternName(Material bannerPatternMaterial, String localizedName) { + this.bannerPatternMaterial = bannerPatternMaterial; + this.localizedName = localizedName; + } + + /** + * @return Localized Name of the Banner Pattern + */ + public String getLocalizedName() { + return localizedName; + } + + /** + * @return Material of the Banner Pattern + */ + public Material getBannerPatternMaterial() { + return bannerPatternMaterial; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/BookGenerationName.java b/plugin/src/main/java/de/epiceric/shopchest/language/BookGenerationName.java new file mode 100644 index 0000000..b0bc651 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/BookGenerationName.java @@ -0,0 +1,28 @@ +package de.epiceric.shopchest.language; + +import de.epiceric.shopchest.nms.CustomBookMeta; + +public class BookGenerationName { + + private String localizedName; + private CustomBookMeta.Generation generation; + + public BookGenerationName(CustomBookMeta.Generation generation, String localizedName) { + this.generation = generation; + this.localizedName = localizedName; + } + + /** + * @return Generation linked to the name + */ + public CustomBookMeta.Generation getGeneration() { + return generation; + } + + /** + * @return Name linked to the book generation + */ + public String getLocalizedName() { + return localizedName; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/EnchantmentName.java b/plugin/src/main/java/de/epiceric/shopchest/language/EnchantmentName.java new file mode 100644 index 0000000..277d951 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/EnchantmentName.java @@ -0,0 +1,53 @@ +package de.epiceric.shopchest.language; + +import org.bukkit.enchantments.Enchantment; + +public class EnchantmentName { + + private Enchantment enchantment; + private String localizedName; + + public EnchantmentName(Enchantment enchantment, String localizedName) { + this.enchantment = enchantment; + this.localizedName = localizedName; + } + + /** + * @return Enchantment linked to the name + */ + public Enchantment getEnchantment() { + return enchantment; + } + + /** + * @return Name linked to the enchantment + */ + public String getLocalizedName() { + return localizedName; + } + + public static class EnchantmentLevelName { + private int level; + private String localizedName; + + public EnchantmentLevelName(int level, String localizedName) { + this.level = level; + this.localizedName = localizedName; + } + + /** + * @return Level linked to the name + */ + public int getLevel() { + return level; + } + + /** + * @return Name linked to the level + */ + public String getLocalizedName() { + return localizedName; + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/EntityName.java b/plugin/src/main/java/de/epiceric/shopchest/language/EntityName.java new file mode 100644 index 0000000..953fb78 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/EntityName.java @@ -0,0 +1,28 @@ +package de.epiceric.shopchest.language; + +import org.bukkit.entity.EntityType; + +public class EntityName { + + private String localizedName; + private EntityType entityType; + + public EntityName(EntityType entityType, String localizedName) { + this.entityType = entityType; + this.localizedName = localizedName; + } + + /** + * @return EntityType linked to the name + */ + public EntityType getEntityType() { + return entityType; + } + + /** + * @return Name linked to the EntityType + */ + public String getLocalizedName() { + return localizedName; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/ItemName.java b/plugin/src/main/java/de/epiceric/shopchest/language/ItemName.java new file mode 100644 index 0000000..5fd6354 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/ItemName.java @@ -0,0 +1,42 @@ +package de.epiceric.shopchest.language; + +import org.bukkit.Material; + +public class ItemName { + + private Material material; + private int subId; + private String localizedName; + + public ItemName(Material material, String localizedName) { + this(material, 0, localizedName); + } + + public ItemName(Material material, int subId, String localizedName) { + this.material = material; + this.subId = subId; + this.localizedName = localizedName; + } + + /** + * @return Material linked to the name + */ + public Material getMaterial() { + return material; + } + + /** + * @return Sub ID linked to the name + */ + public int getSubId() { + return subId; + } + + /** + * @return Name linked to the item + */ + public String getLocalizedName() { + return localizedName; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/LanguageUtils.java b/plugin/src/main/java/de/epiceric/shopchest/language/LanguageUtils.java new file mode 100644 index 0000000..44d7afa --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/LanguageUtils.java @@ -0,0 +1,2895 @@ +package de.epiceric.shopchest.language; + +import java.util.ArrayList; +import java.util.Map; +import java.util.StringJoiner; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.potion.Potion; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.potion.PotionType; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.config.LanguageConfiguration; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.nms.CustomBookMeta; +import de.epiceric.shopchest.nms.SpawnEggMeta; +import de.epiceric.shopchest.utils.Utils; + +public class LanguageUtils { + + private static ShopChest plugin = ShopChest.getInstance(); + private static LanguageConfiguration langConfig; + + private static ArrayList itemNames = new ArrayList<>(); + private static ArrayList enchantmentNames = new ArrayList<>(); + private static ArrayList enchantmentLevelNames = new ArrayList<>(); + private static ArrayList potionEffectNames = new ArrayList<>(); + private static ArrayList entityNames = new ArrayList<>(); + private static ArrayList potionNames = new ArrayList<>(); + private static ArrayList musicDiscNames = new ArrayList<>(); + private static ArrayList bannerPatternNames = new ArrayList<>(); + private static ArrayList generationNames = new ArrayList<>(); + private static ArrayList messages = new ArrayList<>(); + + + private static void loadLegacy() { + // Add Block Names + itemNames.add(new ItemName(Material.valueOf("STONE"), langConfig.getString("tile.stone.stone.name", "Stone"))); + itemNames.add(new ItemName(Material.valueOf("STONE"), 1, langConfig.getString("tile.stone.granite.name", "Granite"))); + itemNames.add(new ItemName(Material.valueOf("STONE"), 2, langConfig.getString("tile.stone.graniteSmooth.name", "Polished Granite"))); + itemNames.add(new ItemName(Material.valueOf("STONE"), 3, langConfig.getString("tile.stone.diorite.name", "Diorite"))); + itemNames.add(new ItemName(Material.valueOf("STONE"), 4, langConfig.getString("tile.stone.dioriteSmooth.name", "Polished Diorite"))); + itemNames.add(new ItemName(Material.valueOf("STONE"), 5, langConfig.getString("tile.stone.andesite.name", "Andesite"))); + itemNames.add(new ItemName(Material.valueOf("STONE"), 6, langConfig.getString("tile.stone.andesiteSmooth.name", "Polished Andesite"))); + itemNames.add(new ItemName(Material.valueOf("GRASS"), langConfig.getString("tile.grass.name", "Grass Block"))); + itemNames.add(new ItemName(Material.valueOf("DIRT"), langConfig.getString("tile.dirt.default.name", "Dirt"))); + itemNames.add(new ItemName(Material.valueOf("DIRT"), 1, langConfig.getString("tile.dirt.coarse.name", "Coarse Dirt"))); + itemNames.add(new ItemName(Material.valueOf("DIRT"), 2, langConfig.getString("tile.dirt.podzol.name", "Podzol"))); + itemNames.add(new ItemName(Material.valueOf("COBBLESTONE"), langConfig.getString("tile.stonebrick.name", "Cobblestone"))); + itemNames.add(new ItemName(Material.valueOf("WOOD"), langConfig.getString("tile.wood.oak.name", "Oak Wood Planks"))); + itemNames.add(new ItemName(Material.valueOf("WOOD"), 1, langConfig.getString("tile.wood.spruce.name", "Spruce Wood Planks"))); + itemNames.add(new ItemName(Material.valueOf("WOOD"), 2, langConfig.getString("tile.wood.birch.name", "Birch Wood Planks"))); + itemNames.add(new ItemName(Material.valueOf("WOOD"), 3, langConfig.getString("tile.wood.jungle.name", "Jungle Wood Planks"))); + itemNames.add(new ItemName(Material.valueOf("WOOD"), 4, langConfig.getString("tile.wood.acacia.name", "Acacia Wood Planks"))); + itemNames.add(new ItemName(Material.valueOf("WOOD"), 5, langConfig.getString("tile.wood.big_oak.name", "Dark Oak Wood Planks"))); + itemNames.add(new ItemName(Material.valueOf("SAPLING"), langConfig.getString("tile.sapling.oak.name", "Oak Sapling"))); + itemNames.add(new ItemName(Material.valueOf("SAPLING"), 1, langConfig.getString("tile.sapling.spruce.name", "Spruce Sapling"))); + itemNames.add(new ItemName(Material.valueOf("SAPLING"), 2, langConfig.getString("tile.sapling.birch.name", "Birch Sapling"))); + itemNames.add(new ItemName(Material.valueOf("SAPLING"), 3, langConfig.getString("tile.sapling.jungle.name", "Jungle Sapling"))); + itemNames.add(new ItemName(Material.valueOf("SAPLING"), 4, langConfig.getString("tile.sapling.acacia.name", "Acacia Sapling"))); + itemNames.add(new ItemName(Material.valueOf("SAPLING"), 5, langConfig.getString("tile.sapling.big_oak.name", "Dark Oak Sapling"))); + itemNames.add(new ItemName(Material.valueOf("BEDROCK"), langConfig.getString("tile.bedrock.name", "Bedrock"))); + itemNames.add(new ItemName(Material.valueOf("WATER"), langConfig.getString("tile.water.name", "Water"))); + itemNames.add(new ItemName(Material.valueOf("LAVA"), langConfig.getString("tile.lava.name", "Lava"))); + itemNames.add(new ItemName(Material.valueOf("SAND"), langConfig.getString("tile.sand.default.name", "Sand"))); + itemNames.add(new ItemName(Material.valueOf("SAND"), 1, langConfig.getString("tile.sand.red.name", "Red Sand"))); + itemNames.add(new ItemName(Material.valueOf("GRAVEL"), langConfig.getString("tile.gravel.name", "Gravel"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_ORE"), langConfig.getString("tile.oreGold.name", "Gold Ore"))); + itemNames.add(new ItemName(Material.valueOf("IRON_ORE"), langConfig.getString("tile.oreIron.name", "Iron Ore"))); + itemNames.add(new ItemName(Material.valueOf("COAL_ORE"), langConfig.getString("tile.oreCoal.name", "Coal Ore"))); + itemNames.add(new ItemName(Material.valueOf("LOG"), langConfig.getString("tile.log.oak.name", "Oak Wood"))); + itemNames.add(new ItemName(Material.valueOf("LOG"), 1, langConfig.getString("tile.log.spruce.name", "Spruce Wood"))); + itemNames.add(new ItemName(Material.valueOf("LOG"), 2, langConfig.getString("tile.log.birch.name", "Birch Wood"))); + itemNames.add(new ItemName(Material.valueOf("LOG"), 3, langConfig.getString("tile.log.jungle.name", "Jungle Wood"))); + itemNames.add(new ItemName(Material.valueOf("LEAVES"), langConfig.getString("tile.leaves.oak.name", "Oak Leaves"))); + itemNames.add(new ItemName(Material.valueOf("LEAVES"), 1, langConfig.getString("tile.leaves.spruce.name", "Spruce Leaves"))); + itemNames.add(new ItemName(Material.valueOf("LEAVES"), 2, langConfig.getString("tile.leaves.birch.name", "Birch Leaves"))); + itemNames.add(new ItemName(Material.valueOf("LEAVES"), 3, langConfig.getString("tile.leaves.jungle.name", "Jungle Leaves"))); + itemNames.add(new ItemName(Material.valueOf("SPONGE"), langConfig.getString("tile.sponge.dry.name", "Sponge"))); + itemNames.add(new ItemName(Material.valueOf("SPONGE"), 1, langConfig.getString("tile.sponge.wet.name", "Wet Sponge"))); + itemNames.add(new ItemName(Material.valueOf("GLASS"), langConfig.getString("tile.glass.name", "Glass"))); + itemNames.add(new ItemName(Material.valueOf("LAPIS_ORE"), langConfig.getString("tile.oreLapis.name", "Lapis Lazuli Ore"))); + itemNames.add(new ItemName(Material.valueOf("LAPIS_BLOCK"), langConfig.getString("tile.blockLapis.name", "Lapis Lazuli Block"))); + itemNames.add(new ItemName(Material.valueOf("DISPENSER"), langConfig.getString("tile.dispenser.name", "Dispenser"))); + itemNames.add(new ItemName(Material.valueOf("SANDSTONE"), langConfig.getString("tile.sandStone.default.name", "Sandstone"))); + itemNames.add(new ItemName(Material.valueOf("SANDSTONE"), 1, langConfig.getString("tile.sandStone.chiseled.name", "Chiseled Sandstone"))); + itemNames.add(new ItemName(Material.valueOf("SANDSTONE"), 2, langConfig.getString("tile.sandStone.smooth.name", "Smooth Sandstone"))); + itemNames.add(new ItemName(Material.valueOf("NOTE_BLOCK"), langConfig.getString("tile.musicBlock.name", "Note Block"))); + itemNames.add(new ItemName(Material.valueOf("POWERED_RAIL"), langConfig.getString("tile.goldenRail.name", "Powered Rail"))); + itemNames.add(new ItemName(Material.valueOf("DETECTOR_RAIL"), langConfig.getString("tile.detectorRail.name", "Detector Rail"))); + itemNames.add(new ItemName(Material.valueOf("PISTON_STICKY_BASE"), langConfig.getString("tile.pistonStickyBase.name", "Sticky Piston"))); + itemNames.add(new ItemName(Material.valueOf("WEB"), langConfig.getString("tile.web.name", "Web"))); + itemNames.add(new ItemName(Material.valueOf("LONG_GRASS"), langConfig.getString("tile.tallgrass.shrub.name", "Shrub"))); + itemNames.add(new ItemName(Material.valueOf("LONG_GRASS"), 1, langConfig.getString("tile.tallgrass.grass.name", "Grass"))); + itemNames.add(new ItemName(Material.valueOf("LONG_GRASS"), 2, langConfig.getString("tile.tallgrass.fern.name", "Fern"))); + itemNames.add(new ItemName(Material.valueOf("DEAD_BUSH"), langConfig.getString("tile.deadbush.name", "Dead Bush"))); + itemNames.add(new ItemName(Material.valueOf("PISTON_BASE"), langConfig.getString("tile.pistonBase.name", "Piston"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), langConfig.getString("tile.cloth.white.name", "White Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 1, langConfig.getString("tile.cloth.orange.name", "Orange Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 2, langConfig.getString("tile.cloth.magenta.name", "Magenta Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 3, langConfig.getString("tile.cloth.lightBlue.name", "Light Blue Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 4, langConfig.getString("tile.cloth.yellow.name", "Yellow Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 5, langConfig.getString("tile.cloth.lime.name", "Lime Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 6, langConfig.getString("tile.cloth.pink.name", "Pink Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 7, langConfig.getString("tile.cloth.gray.name", "Gray Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 8, langConfig.getString("tile.cloth.silver.name", "Light Gray Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 9, langConfig.getString("tile.cloth.cyan.name", "Cyan Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 10, langConfig.getString("tile.cloth.purple.name", "Purple Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 11, langConfig.getString("tile.cloth.blue.name", "Blue Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 12, langConfig.getString("tile.cloth.brown.name", "Brown Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 13, langConfig.getString("tile.cloth.green.name", "Green Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 14, langConfig.getString("tile.cloth.red.name", "Red Wool"))); + itemNames.add(new ItemName(Material.valueOf("WOOL"), 15, langConfig.getString("tile.cloth.black.name", "Black Wool"))); + itemNames.add(new ItemName(Material.valueOf("YELLOW_FLOWER"), langConfig.getString("tile.flower1.dandelion.name", "Dandelion"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), langConfig.getString("tile.flower2.poppy.name", "Poppy"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), 1, langConfig.getString("tile.flower2.blueOrchid.name", "Blue Orchid"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), 2, langConfig.getString("tile.flower2.allium.name", "Allium"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), 3, langConfig.getString("tile.flower2.houstonia.name", "Azure Bluet"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), 4, langConfig.getString("tile.flower2.tulipRed.name", "Red Tulip"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), 5, langConfig.getString("tile.flower2.tulipOrange.name", "Orange Tulip"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), 6, langConfig.getString("tile.flower2.tulipWhite.name", "White Tulip"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), 7, langConfig.getString("tile.flower2.tulipPink.name", "Pink Tulip"))); + itemNames.add(new ItemName(Material.valueOf("RED_ROSE"), 8, langConfig.getString("tile.flower2.oxeyeDaisy.name", "Oxeye Daisy"))); + itemNames.add(new ItemName(Material.valueOf("BROWN_MUSHROOM"), langConfig.getString("tile.mushroom.name", "Mushroom"))); + itemNames.add(new ItemName(Material.valueOf("RED_MUSHROOM"), langConfig.getString("tile.mushroom.name", "Mushroom"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_BLOCK"), langConfig.getString("tile.blockGold.name", "Block of Gold"))); + itemNames.add(new ItemName(Material.valueOf("IRON_BLOCK"), langConfig.getString("tile.blockIron.name", "Block of Iron"))); + itemNames.add(new ItemName(Material.valueOf("STEP"), langConfig.getString("tile.stoneSlab.stone.name", "Stone Slab"))); + itemNames.add(new ItemName(Material.valueOf("STEP"), 1, langConfig.getString("tile.stoneSlab.sand.name", "Sandstone Slab"))); + itemNames.add(new ItemName(Material.valueOf("STEP"), 2, langConfig.getString("tile.stoneSlab.wood.name", "Wooden Slab"))); + itemNames.add(new ItemName(Material.valueOf("STEP"), 3, langConfig.getString("tile.stoneSlab.cobble.name", "Cobblestone Slab"))); + itemNames.add(new ItemName(Material.valueOf("STEP"), 4, langConfig.getString("tile.stoneSlab.brick.name", "Brick Slab"))); + itemNames.add(new ItemName(Material.valueOf("STEP"), 5, langConfig.getString("tile.stoneSlab.smoothStoneBrick.name", "Stone Brick Slab"))); + itemNames.add(new ItemName(Material.valueOf("STEP"), 6, langConfig.getString("tile.stoneSlab.netherBrick.name", "Nether Brick Slab"))); + itemNames.add(new ItemName(Material.valueOf("STEP"), 7, langConfig.getString("tile.stoneSlab.quartz.name", "Quartz Slab"))); + itemNames.add(new ItemName(Material.valueOf("BRICK"), langConfig.getString("tile.brick.name", "Brick"))); + itemNames.add(new ItemName(Material.valueOf("TNT"), langConfig.getString("tile.tnt.name", "TNT"))); + itemNames.add(new ItemName(Material.valueOf("BOOKSHELF"), langConfig.getString("tile.bookshelf.name", "Bookshelf"))); + itemNames.add(new ItemName(Material.valueOf("MOSSY_COBBLESTONE"), langConfig.getString("tile.stoneMoss.name", "Moss Stone"))); + itemNames.add(new ItemName(Material.valueOf("OBSIDIAN"), langConfig.getString("tile.obsidian.name", "Obsidian"))); + itemNames.add(new ItemName(Material.valueOf("TORCH"), langConfig.getString("tile.torch.name", "Torch"))); + itemNames.add(new ItemName(Material.valueOf("FIRE"), langConfig.getString("tile.fire.name", "Fire"))); + itemNames.add(new ItemName(Material.valueOf("MOB_SPAWNER"), langConfig.getString("tile.mobSpawner.name", "Mob Spawner"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_STAIRS"), langConfig.getString("tile.stairsWood.name", "Oak Wood Stairs"))); + itemNames.add(new ItemName(Material.valueOf("CHEST"), langConfig.getString("tile.chest.name", "Chest"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_ORE"), langConfig.getString("tile.oreDiamond.name", "Diamond Ore"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_BLOCK"), langConfig.getString("tile.blockDiamond.name", "Block of Diamond"))); + itemNames.add(new ItemName(Material.valueOf("WORKBENCH"), langConfig.getString("tile.workbench.name", "Crafting Table"))); + itemNames.add(new ItemName(Material.valueOf("SOIL"), langConfig.getString("tile.farmland.name", "Farmland"))); + itemNames.add(new ItemName(Material.valueOf("FURNACE"), langConfig.getString("tile.furnace.name", "Furnace"))); + itemNames.add(new ItemName(Material.valueOf("LADDER"), langConfig.getString("tile.ladder.name", "Ladder"))); + itemNames.add(new ItemName(Material.valueOf("RAILS"), langConfig.getString("tile.rail.name", "Rail"))); + itemNames.add(new ItemName(Material.valueOf("COBBLESTONE_STAIRS"), langConfig.getString("tile.stairsStone.name", "Stone Stairs"))); + itemNames.add(new ItemName(Material.valueOf("LEVER"), langConfig.getString("tile.lever.name", "Lever"))); + itemNames.add(new ItemName(Material.valueOf("STONE_PLATE"), langConfig.getString("tile.pressurePlateStone.name", "Stone Pressure Plate"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_PLATE"), langConfig.getString("tile.pressurePlateWood.name", "Wooden Pressure Plate"))); + itemNames.add(new ItemName(Material.valueOf("REDSTONE_ORE"), langConfig.getString("tile.oreRedstone.name", "Redstone Ore"))); + itemNames.add(new ItemName(Material.valueOf("REDSTONE_TORCH_ON"), langConfig.getString("tile.notGate.name", "Redstone Torch"))); + itemNames.add(new ItemName(Material.valueOf("SNOW"), langConfig.getString("tile.snow.name", "Snow"))); + itemNames.add(new ItemName(Material.valueOf("ICE"), langConfig.getString("tile.ice.name", "Ice"))); + itemNames.add(new ItemName(Material.valueOf("SNOW_BLOCK"), langConfig.getString("tile.snow.name", "Snow"))); + itemNames.add(new ItemName(Material.valueOf("CACTUS"), langConfig.getString("tile.cactus.name", "Cactus"))); + itemNames.add(new ItemName(Material.valueOf("CLAY"), langConfig.getString("tile.clay.name", "Clay"))); + itemNames.add(new ItemName(Material.valueOf("JUKEBOX"), langConfig.getString("tile.jukebox.name", "Jukebox"))); + itemNames.add(new ItemName(Material.valueOf("FENCE"), langConfig.getString("tile.fence.name", "Oak Fence"))); + itemNames.add(new ItemName(Material.valueOf("PUMPKIN"), langConfig.getString("tile.pumpkin.name", "Pumpkin"))); + itemNames.add(new ItemName(Material.valueOf("NETHERRACK"), langConfig.getString("tile.hellrock.name", "Netherrack"))); + itemNames.add(new ItemName(Material.valueOf("SOUL_SAND"), langConfig.getString("tile.hellsand.name", "Soul Sand"))); + itemNames.add(new ItemName(Material.valueOf("GLOWSTONE"), langConfig.getString("tile.lightgem.name", "Glowstone"))); + itemNames.add(new ItemName(Material.valueOf("PORTAL"), langConfig.getString("tile.portal.name", "Portal"))); + itemNames.add(new ItemName(Material.valueOf("JACK_O_LANTERN"), langConfig.getString("tile.litpumpkin.name", "Jack o'Lantern"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), langConfig.getString("tile.stainedGlass.white.name", "White Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 1, langConfig.getString("tile.stainedGlass.orange.name", "Orange Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 2, langConfig.getString("tile.stainedGlass.magenta.name", "Magenta Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 3, langConfig.getString("tile.stainedGlass.lightBlue.name", "Light Blue Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 4, langConfig.getString("tile.stainedGlass.yellow.name", "Yellow Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 5, langConfig.getString("tile.stainedGlass.lime.name", "Lime Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 6, langConfig.getString("tile.stainedGlass.pink.name", "Pink Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 7, langConfig.getString("tile.stainedGlass.gray.name", "Gray Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 8, langConfig.getString("tile.stainedGlass.silver.name", "Light Gray Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 9, langConfig.getString("tile.stainedGlass.cyan.name", "Cyan Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 10, langConfig.getString("tile.stainedGlass.purple.name", "Purple Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 11, langConfig.getString("tile.stainedGlass.blue.name", "Blue Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 12, langConfig.getString("tile.stainedGlass.brown.name", "Brown Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 13, langConfig.getString("tile.stainedGlass.green.name", "Green Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 14, langConfig.getString("tile.stainedGlass.red.name", "Red Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS"), 15, langConfig.getString("tile.stainedGlass.black.name", "Black Stained Glass"))); + itemNames.add(new ItemName(Material.valueOf("TRAP_DOOR"), langConfig.getString("tile.trapdoor.name", "Wooden Trapdoor"))); + itemNames.add(new ItemName(Material.valueOf("MONSTER_EGGS"), langConfig.getString("tile.monsterStoneEgg.stone.name", "Stone Monster Egg"))); + itemNames.add(new ItemName(Material.valueOf("MONSTER_EGGS"), 1, langConfig.getString("tile.monsterStoneEgg.cobble.name", "Cobblestone Monster Egg"))); + itemNames.add(new ItemName(Material.valueOf("MONSTER_EGGS"), 2, langConfig.getString("tile.monsterStoneEgg.brick.name", "Stone Brick Monster Egg"))); + itemNames.add(new ItemName(Material.valueOf("MONSTER_EGGS"), 3, langConfig.getString("tile.monsterStoneEgg.mossybrick.name", "Mossy Stone Brick Monster Egg"))); + itemNames.add(new ItemName(Material.valueOf("MONSTER_EGGS"), 4, langConfig.getString("tile.monsterStoneEgg.crackedbrick.name", "Cracked Stone Brick Monster Egg"))); + itemNames.add(new ItemName(Material.valueOf("MONSTER_EGGS"), 5, langConfig.getString("tile.monsterStoneEgg.chiseledbrick.name", "Chiseled Stone Brick Monster Egg"))); + itemNames.add(new ItemName(Material.valueOf("SMOOTH_BRICK"), langConfig.getString("tile.stonebricksmooth.default.name", "Stone Bricks"))); + itemNames.add(new ItemName(Material.valueOf("SMOOTH_BRICK"), 1, langConfig.getString("tile.stonebricksmooth.mossy.name", "Mossy Stone Bricks"))); + itemNames.add(new ItemName(Material.valueOf("SMOOTH_BRICK"), 2, langConfig.getString("tile.stonebricksmooth.cracked.name", "Cracked Stone Bricks"))); + itemNames.add(new ItemName(Material.valueOf("SMOOTH_BRICK"), 3, langConfig.getString("tile.stonebricksmooth.chiseled.name", "Chiseled Stone Bricks"))); + itemNames.add(new ItemName(Material.valueOf("HUGE_MUSHROOM_1"), langConfig.getString("tile.mushroom.name", "Mushroom"))); + itemNames.add(new ItemName(Material.valueOf("HUGE_MUSHROOM_2"), langConfig.getString("tile.mushroom.name", "Mushroom"))); + itemNames.add(new ItemName(Material.valueOf("IRON_FENCE"), langConfig.getString("tile.fenceIron.name", "Iron Bars"))); + itemNames.add(new ItemName(Material.valueOf("THIN_GLASS"), langConfig.getString("tile.thinGlass.name", "Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("MELON_BLOCK"), langConfig.getString("tile.melon.name", "Melon"))); + itemNames.add(new ItemName(Material.valueOf("VINE"), langConfig.getString("tile.vine.name", "Vines"))); + itemNames.add(new ItemName(Material.valueOf("FENCE_GATE"), langConfig.getString("tile.fenceGate.name", "Oak Fence Gate"))); + itemNames.add(new ItemName(Material.valueOf("BRICK_STAIRS"), langConfig.getString("tile.stairsBrick.name", "Brick Stairs"))); + itemNames.add(new ItemName(Material.valueOf("SMOOTH_STAIRS"), langConfig.getString("tile.stairsStoneBrickSmooth.name", "Stone Brick Stairs"))); + itemNames.add(new ItemName(Material.valueOf("MYCEL"), langConfig.getString("tile.mycel.name", "Mycelium"))); + itemNames.add(new ItemName(Material.valueOf("WATER_LILY"), langConfig.getString("tile.waterlily.name", "Lily Pad"))); + itemNames.add(new ItemName(Material.valueOf("NETHER_BRICK"), langConfig.getString("tile.netherBrick.name", "Nether Brick"))); + itemNames.add(new ItemName(Material.valueOf("NETHER_FENCE"), langConfig.getString("tile.netherFence.name", "Nether Brick Fence"))); + itemNames.add(new ItemName(Material.valueOf("NETHER_BRICK_STAIRS"), langConfig.getString("tile.stairsNetherBrick.name", "Nether Brick Stairs"))); + itemNames.add(new ItemName(Material.valueOf("ENCHANTMENT_TABLE"), langConfig.getString("tile.enchantmentTable.name", "Enchantment Table"))); + itemNames.add(new ItemName(Material.valueOf("ENDER_PORTAL_FRAME"), langConfig.getString("tile.endPortalFrame.name", "End Portal Frame"))); + itemNames.add(new ItemName(Material.valueOf("ENDER_STONE"), langConfig.getString("tile.whiteStone.name", "End Stone"))); + itemNames.add(new ItemName(Material.valueOf("DRAGON_EGG"), langConfig.getString("tile.dragonEgg.name", "Dragon Egg"))); + itemNames.add(new ItemName(Material.valueOf("REDSTONE_LAMP_OFF"), langConfig.getString("tile.redstoneLight.name", "Redstone Lamp"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_STEP"), langConfig.getString("tile.woodSlab.oak.name", "Oak Wood Slab"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_STEP"), 1, langConfig.getString("tile.woodSlab.spruce.name", "Spruce Wood Slab"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_STEP"), 2, langConfig.getString("tile.woodSlab.birch.name", "Birch Wood Slab"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_STEP"), 3, langConfig.getString("tile.woodSlab.jungle.name", "Jungle Wood Slab"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_STEP"), 4, langConfig.getString("tile.woodSlab.acacia.name", "Acacia Wood Slab"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_STEP"), 5, langConfig.getString("tile.woodSlab.big_oak.name", "Dark Oak Wood Slab"))); + itemNames.add(new ItemName(Material.valueOf("SANDSTONE_STAIRS"), langConfig.getString("tile.stairsSandStone.name", "Mycelium"))); + itemNames.add(new ItemName(Material.valueOf("EMERALD_ORE"), langConfig.getString("tile.oreEmerald.name", "Emerald Ore"))); + itemNames.add(new ItemName(Material.valueOf("ENDER_CHEST"), langConfig.getString("tile.enderChest.name", "Ender Chest"))); + itemNames.add(new ItemName(Material.valueOf("TRIPWIRE_HOOK"), langConfig.getString("tile.tripWireSource.name", "Tripwire Hook"))); + itemNames.add(new ItemName(Material.valueOf("EMERALD_BLOCK"), langConfig.getString("tile.blockEmerald.name", "Block of Emerald"))); + itemNames.add(new ItemName(Material.valueOf("SPRUCE_WOOD_STAIRS"), langConfig.getString("tile.stairsWoodSpruce.name", "Spruce Wood Stairs"))); + itemNames.add(new ItemName(Material.valueOf("BIRCH_WOOD_STAIRS"), langConfig.getString("tile.stairsWoodBirch.name", "Birch Wood Stairs"))); + itemNames.add(new ItemName(Material.valueOf("JUNGLE_WOOD_STAIRS"), langConfig.getString("tile.stairsWoodJungle.name", "Jungle Wood Stairs"))); + itemNames.add(new ItemName(Material.valueOf("COMMAND"), langConfig.getString("tile.commandBlock.name", "Command Block"))); + itemNames.add(new ItemName(Material.valueOf("BEACON"), langConfig.getString("tile.beacon.name", "Beacon"))); + itemNames.add(new ItemName(Material.valueOf("COBBLE_WALL"), langConfig.getString("tile.cobbleWall.normal.name", "Cobblestone Wall"))); + itemNames.add(new ItemName(Material.valueOf("COBBLE_WALL"), 1, langConfig.getString("tile.cobbleWall.mossy.name", "Mossy Cobblestone Wall"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_BUTTON"), langConfig.getString("tile.button.name", "Button"))); + itemNames.add(new ItemName(Material.valueOf("NETHER_STALK"), langConfig.getString("tile.netherStalk.name", "Nether Wart"))); + itemNames.add(new ItemName(Material.valueOf("ANVIL"), langConfig.getString("tile.anvil.intact.name", "Anvil"))); + itemNames.add(new ItemName(Material.valueOf("ANVIL"), 1, langConfig.getString("tile.anvil.slightlyDamaged.name", "Slightly Damaged Anvil"))); + itemNames.add(new ItemName(Material.valueOf("ANVIL"), 2, langConfig.getString("tile.anvil.veryDamaged.name", "Very Damaged Anvil"))); + itemNames.add(new ItemName(Material.valueOf("TRAPPED_CHEST"), langConfig.getString("tile.chestTrap.name", "Trapped Chest"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_PLATE"), langConfig.getString("tile.weightedPlate_light.name", "Weighted Pressure Plate (Light)"))); + itemNames.add(new ItemName(Material.valueOf("IRON_PLATE"), langConfig.getString("tile.weightedPlate_heavy.name", "Weighted Pressure Plate (Heavy)"))); + itemNames.add(new ItemName(Material.valueOf("DAYLIGHT_DETECTOR"), langConfig.getString("tile.daylightDetector.name", "Daylight Sensor"))); + itemNames.add(new ItemName(Material.valueOf("REDSTONE_BLOCK"), langConfig.getString("tile.blockRedstone.name", "Block of Redstone"))); + itemNames.add(new ItemName(Material.valueOf("QUARTZ_ORE"), langConfig.getString("tile.netherquartz.name", "Nether Quartz Ore"))); + itemNames.add(new ItemName(Material.valueOf("HOPPER"), langConfig.getString("tile.hopper.name", "Hopper"))); + itemNames.add(new ItemName(Material.valueOf("QUARTZ_BLOCK"), langConfig.getString("tile.quartzBlock.default.name", "Block of Quartz"))); + itemNames.add(new ItemName(Material.valueOf("QUARTZ_BLOCK"), langConfig.getString("tile.quartzBlock.chiseled.name", "Chiseled Quartz Block"))); + itemNames.add(new ItemName(Material.valueOf("QUARTZ_BLOCK"), langConfig.getString("tile.quartzBlock.lines.name", "Pillar Quartz Block"))); + itemNames.add(new ItemName(Material.valueOf("QUARTZ_STAIRS"), langConfig.getString("tile.stairsQuartz.name", "Quartz Stairs"))); + itemNames.add(new ItemName(Material.valueOf("ACTIVATOR_RAIL"), langConfig.getString("tile.activatorRail.name", "Activator Rail"))); + itemNames.add(new ItemName(Material.valueOf("DROPPER"), langConfig.getString("tile.dropper.name", "Dropper"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), langConfig.getString("tile.clayHardenedStained.white.name", "White Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 1, langConfig.getString("tile.clayHardenedStained.orange.name", "Orange Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 2, langConfig.getString("tile.clayHardenedStained.magenta.name", "Magenta Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 3, langConfig.getString("tile.clayHardenedStained.lightBlue.name", "Light Blue Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 4, langConfig.getString("tile.clayHardenedStained.yellow.name", "Yellow Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 5, langConfig.getString("tile.clayHardenedStained.lime.name", "Lime Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 6, langConfig.getString("tile.clayHardenedStained.pink.name", "Pink Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 7, langConfig.getString("tile.clayHardenedStained.gray.name", "Gray Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 8, langConfig.getString("tile.clayHardenedStained.silver.name", "Light Gray Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 9, langConfig.getString("tile.clayHardenedStained.cyan.name", "Cyan Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 10, langConfig.getString("tile.clayHardenedStained.purple.name", "Purple Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 11, langConfig.getString("tile.clayHardenedStained.blue.name", "Blue Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 12, langConfig.getString("tile.clayHardenedStained.brown.name", "Brown Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 13, langConfig.getString("tile.clayHardenedStained.green.name", "Green Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 14, langConfig.getString("tile.clayHardenedStained.red.name", "Red Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_CLAY"), 15, langConfig.getString("tile.clayHardenedStained.black.name", "Black Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), langConfig.getString("tile.thinStainedGlass.white.name", "White Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 1, langConfig.getString("tile.thinStainedGlass.orange.name", "Orange Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 2, langConfig.getString("tile.thinStainedGlass.magenta.name", "Magenta Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 3, langConfig.getString("tile.thinStainedGlass.lightBlue.name", "Light Blue Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 4, langConfig.getString("tile.thinStainedGlass.yellow.name", "Yellow Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 5, langConfig.getString("tile.thinStainedGlass.lime.name", "Lime Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 6, langConfig.getString("tile.thinStainedGlass.pink.name", "Pink Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 7, langConfig.getString("tile.thinStainedGlass.gray.name", "Gray Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 8, langConfig.getString("tile.thinStainedGlass.silver.name", "Light Gray Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 9, langConfig.getString("tile.thinStainedGlass.cyan.name", "Cyan Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 10, langConfig.getString("tile.thinStainedGlass.purple.name", "Purple Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 11, langConfig.getString("tile.thinStainedGlass.blue.name", "Blue Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 12, langConfig.getString("tile.thinStainedGlass.brown.name", "Brown Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 13, langConfig.getString("tile.thinStainedGlass.green.name", "Green Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 14, langConfig.getString("tile.thinStainedGlass.red.name", "Red Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("STAINED_GLASS_PANE"), 15, langConfig.getString("tile.thinStainedGlass.black.name", "Black Stained Glass Pane"))); + itemNames.add(new ItemName(Material.valueOf("LEAVES_2"), langConfig.getString("tile.leaves.acacia.name", "Acacia Leaves"))); + itemNames.add(new ItemName(Material.valueOf("LEAVES_2"), 1, langConfig.getString("tile.leaves.big_oak.name", "Dark Oak Leaves"))); + itemNames.add(new ItemName(Material.valueOf("LOG_2"), langConfig.getString("tile.log.acacia.name", "Acacia Wood"))); + itemNames.add(new ItemName(Material.valueOf("LOG_2"), 1, langConfig.getString("tile.log.big_oak.name", "Dark Oak Wood"))); + itemNames.add(new ItemName(Material.valueOf("ACACIA_STAIRS"), langConfig.getString("tile.stairsWoodAcacia.name", "Acacia Wood Stairs"))); + itemNames.add(new ItemName(Material.valueOf("DARK_OAK_STAIRS"), langConfig.getString("tile.stairsWoodDarkOak.name", "Dark Oak Wood Stairs"))); + itemNames.add(new ItemName(Material.valueOf("SLIME_BLOCK"), langConfig.getString("tile.slime.name", "Slime Block"))); + itemNames.add(new ItemName(Material.valueOf("BARRIER"), langConfig.getString("tile.barrier.name", "Barrier"))); + itemNames.add(new ItemName(Material.valueOf("IRON_TRAPDOOR"), langConfig.getString("tile.ironTrapdoor.name", "Iron Trapdoor"))); + itemNames.add(new ItemName(Material.valueOf("PRISMARINE"), langConfig.getString("tile.prismarine.rough.name", "Prismarine"))); + itemNames.add(new ItemName(Material.valueOf("PRISMARINE"), 1, langConfig.getString("tile.prismarine.bricks.name", "Prismarine Bricks"))); + itemNames.add(new ItemName(Material.valueOf("PRISMARINE"), 2, langConfig.getString("tile.prismarine.dark.name", "Dark Prismarine"))); + itemNames.add(new ItemName(Material.valueOf("SEA_LANTERN"), langConfig.getString("tile.seaLantern.name", "Sea Lantern"))); + itemNames.add(new ItemName(Material.valueOf("HAY_BLOCK"), langConfig.getString("tile.hayBlock.name", "Hay Bale"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), langConfig.getString("tile.woolCarpet.white.name", "White Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 1, langConfig.getString("tile.woolCarpet.orange.name", "Orange Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 2, langConfig.getString("tile.woolCarpet.magenta.name", "Magenta Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 3, langConfig.getString("tile.woolCarpet.lightBlue.name", "Light Blue Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 4, langConfig.getString("tile.woolCarpet.yellow.name", "Yellow Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 5, langConfig.getString("tile.woolCarpet.lime.name", "Lime Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 6, langConfig.getString("tile.woolCarpet.pink.name", "Pink Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 7, langConfig.getString("tile.woolCarpet.gray.name", "Gray Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 8, langConfig.getString("tile.woolCarpet.silver.name", "Light Gray Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 9, langConfig.getString("tile.woolCarpet.cyan.name", "Cyan Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 10, langConfig.getString("tile.woolCarpet.purple.name", "Purple Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 11, langConfig.getString("tile.woolCarpet.blue.name", "Blue Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 12, langConfig.getString("tile.woolCarpet.brown.name", "Brown Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 13, langConfig.getString("tile.woolCarpet.green.name", "Green Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 14, langConfig.getString("tile.woolCarpet.red.name", "Red Carpet"))); + itemNames.add(new ItemName(Material.valueOf("CARPET"), 15, langConfig.getString("tile.woolCarpet.black.name", "Black Carpet"))); + itemNames.add(new ItemName(Material.valueOf("HARD_CLAY"), langConfig.getString("tile.clayHardened.name", "Hardened Clay"))); + itemNames.add(new ItemName(Material.valueOf("COAL_BLOCK"), langConfig.getString("tile.blockCoal.name", "Block of Coal"))); + itemNames.add(new ItemName(Material.valueOf("PACKED_ICE"), langConfig.getString("tile.icePacked.name", "Packed Ice"))); + itemNames.add(new ItemName(Material.valueOf("DOUBLE_PLANT"), langConfig.getString("tile.doublePlant.sunflower.name", "Sunflower"))); + itemNames.add(new ItemName(Material.valueOf("DOUBLE_PLANT"), 1, langConfig.getString("tile.doublePlant.syringa.name", "Lilac"))); + itemNames.add(new ItemName(Material.valueOf("DOUBLE_PLANT"), 2, langConfig.getString("tile.doublePlant.grass.name", "Double Tallgrass"))); + itemNames.add(new ItemName(Material.valueOf("DOUBLE_PLANT"), 3, langConfig.getString("tile.doublePlant.fern.name", "Large Fern"))); + itemNames.add(new ItemName(Material.valueOf("DOUBLE_PLANT"), 4, langConfig.getString("tile.doublePlant.rose.name", "Rose Bush"))); + itemNames.add(new ItemName(Material.valueOf("DOUBLE_PLANT"), 5, langConfig.getString("tile.doublePlant.paeonia.name", "Peony"))); + itemNames.add(new ItemName(Material.valueOf("RED_SANDSTONE"), langConfig.getString("tile.redSandStone.default.name", "Red Sandstone"))); + itemNames.add(new ItemName(Material.valueOf("RED_SANDSTONE"), 1, langConfig.getString("tile.redSandStone.chiseled.name", "Chiseled Red Sandstone"))); + itemNames.add(new ItemName(Material.valueOf("RED_SANDSTONE"), 2, langConfig.getString("tile.redSandStone.smooth.name", "Smooth Red Sandstone"))); + itemNames.add(new ItemName(Material.valueOf("RED_SANDSTONE_STAIRS"), langConfig.getString("tile.stairsRedSandStone.name", "Red Sandstone Stairs"))); + itemNames.add(new ItemName(Material.valueOf("STONE_SLAB2"), langConfig.getString("tile.stoneSlab2.red_sandstone.name", "Red Sandstone Slab"))); + itemNames.add(new ItemName(Material.valueOf("SPRUCE_FENCE_GATE"), langConfig.getString("tile.spruceFenceGate.name", "Spruce Fence Gate"))); + itemNames.add(new ItemName(Material.valueOf("BIRCH_FENCE_GATE"), langConfig.getString("tile.birchFenceGate.name", "Birch Fence Gate"))); + itemNames.add(new ItemName(Material.valueOf("JUNGLE_FENCE_GATE"), langConfig.getString("tile.jungleFenceGate.name", "Jungle Fence Gate"))); + itemNames.add(new ItemName(Material.valueOf("DARK_OAK_FENCE_GATE"), langConfig.getString("tile.darkOakFenceGate.name", "Dark Oak Fence Gate"))); + itemNames.add(new ItemName(Material.valueOf("ACACIA_FENCE_GATE"), langConfig.getString("tile.acaciaFenceGate.name", "Acacia Fence Gate"))); + itemNames.add(new ItemName(Material.valueOf("SPRUCE_FENCE"), langConfig.getString("tile.spruceFence.name", "Spruce Fence"))); + itemNames.add(new ItemName(Material.valueOf("BIRCH_FENCE"), langConfig.getString("tile.birchFence.name", "Birch Fence"))); + itemNames.add(new ItemName(Material.valueOf("JUNGLE_FENCE"), langConfig.getString("tile.jungleFence.name", "Jungle Fence"))); + itemNames.add(new ItemName(Material.valueOf("DARK_OAK_FENCE"), langConfig.getString("tile.darkOakFence.name", "Dark Oak Fence"))); + itemNames.add(new ItemName(Material.valueOf("ACACIA_FENCE"), langConfig.getString("tile.acaciaFence.name", "Acacia Fence"))); + + if (Utils.getMajorVersion() >= 9) { + // Add Block Names of 1.9 + itemNames.add(new ItemName(Material.valueOf("END_ROD"), langConfig.getString("tile.endRod.name", "End Rod"))); + itemNames.add(new ItemName(Material.valueOf("CHORUS_PLANT"), langConfig.getString("tile.chorusPlant.name", "Chorus Plant"))); + itemNames.add(new ItemName(Material.valueOf("CHORUS_FLOWER"), langConfig.getString("tile.chorusFlower.name", "Chorus Flower"))); + itemNames.add(new ItemName(Material.valueOf("PURPUR_BLOCK"), langConfig.getString("tile.purpurBlock.name", "Purpur Block"))); + itemNames.add(new ItemName(Material.valueOf("PURPUR_PILLAR"), langConfig.getString("tile.purpurPillar.name", "Purpur Pillar"))); + itemNames.add(new ItemName(Material.valueOf("PURPUR_STAIRS"), langConfig.getString("tile.stairsPurpur.name", "Purpur Stairs"))); + itemNames.add(new ItemName(Material.valueOf("PURPUR_SLAB"), langConfig.getString("tile.purpurSlab.name", "Purpur Slab"))); + itemNames.add(new ItemName(Material.valueOf("END_BRICKS"), langConfig.getString("tile.endBricks.name", "End Stone Bricks"))); + itemNames.add(new ItemName(Material.valueOf("GRASS_PATH"), langConfig.getString("tile.grassPath.name", "Grass Path"))); + itemNames.add(new ItemName(Material.valueOf("COMMAND_REPEATING"), langConfig.getString("tile.repeatingCommandBlock.name", "Repeating Command Block"))); + itemNames.add(new ItemName(Material.valueOf("COMMAND_CHAIN"), langConfig.getString("tile.chainCommandBlock.name", "Chain Command Block"))); + itemNames.add(new ItemName(Material.valueOf("STRUCTURE_BLOCK"), langConfig.getString("tile.structureBlock.name", "Structure Block"))); + } + + if (Utils.getMajorVersion() >= 10) { + // Add Block Names of 1.10 + itemNames.add(new ItemName(Material.valueOf("MAGMA"), langConfig.getString("tile.magma.name", "Magma Block"))); + itemNames.add(new ItemName(Material.valueOf("NETHER_WART_BLOCK"), langConfig.getString("tile.netherWartBlock.name", "Nether Wart Block"))); + itemNames.add(new ItemName(Material.valueOf("RED_NETHER_BRICK"), langConfig.getString("tile.redNetherBrick.name", "Red Nether Brick"))); + itemNames.add(new ItemName(Material.valueOf("BONE_BLOCK"), langConfig.getString("tile.boneBlock.name", "Bone Block"))); + itemNames.add(new ItemName(Material.valueOf("STRUCTURE_VOID"), langConfig.getString("tile.structureVoid.name", "Structure Void"))); + } + + if (Utils.getMajorVersion() >= 11) { + // Add Block Names of 1.11 + itemNames.add(new ItemName(Material.valueOf("OBSERVER"), langConfig.getString("tile.observer.name", "Observer"))); + itemNames.add(new ItemName(Material.valueOf("WHITE_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxWhite.name", "White Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("ORANGE_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxOrange.name", "Orange Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("MAGENTA_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxMagenta.name", "Magenta Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("LIGHT_BLUE_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxLightBlue.name", "Light Blue Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("YELLOW_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxYellow.name", "Yellow Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("LIME_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxLime.name", "Lime Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("PINK_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxPink.name", "Pink Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("GRAY_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxGray.name", "Gray Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("SILVER_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxSilver.name", "Light Gray Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("CYAN_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxCyan.name", "Cyan Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("PURPLE_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxPurple.name", "Purple Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("BLUE_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxBlue.name", "Blue Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("BROWN_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxBrown.name", "Brown Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("GREEN_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxGreen.name", "Green Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("RED_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxRed.name", "Red Shulker Box"))); + itemNames.add(new ItemName(Material.valueOf("BLACK_SHULKER_BOX"), langConfig.getString("tile.shulkerBoxBlack.name", "Black Shulker Box"))); + } + + if (Utils.getMajorVersion() >= 12) { + // Add Block Names of 1.12 + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), langConfig.getString("tile.concrete.white.name", "White Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 1, langConfig.getString("tile.concrete.orange.name", "Orange Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 2, langConfig.getString("tile.concrete.magenta.name", "Magenta Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 3, langConfig.getString("tile.concrete.lightBlue.name", "Light Blue Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 4, langConfig.getString("tile.concrete.yellow.name", "Yellow Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 5, langConfig.getString("tile.concrete.lime.name", "Lime Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 6, langConfig.getString("tile.concrete.pink.name", "Pink Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 7, langConfig.getString("tile.concrete.gray.name", "Gray Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 8, langConfig.getString("tile.concrete.silver.name", "Light Gray Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 9, langConfig.getString("tile.concrete.cyan.name", "Cyan Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 10, langConfig.getString("tile.concrete.purple.name", "Purple Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 11, langConfig.getString("tile.concrete.blue.name", "Blue Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 12, langConfig.getString("tile.concrete.brown.name", "Brown Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 13, langConfig.getString("tile.concrete.green.name", "Green Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 14, langConfig.getString("tile.concrete.red.name", "Red Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE"), 15, langConfig.getString("tile.concrete.black.name", "Black Concrete"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), langConfig.getString("tile.concretePowder.white.name", "White Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 1, langConfig.getString("tile.concretePowder.orange.name", "Orange Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 2, langConfig.getString("tile.concretePowder.magenta.name", "Magenta Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 3, langConfig.getString("tile.concretePowder.lightBlue.name", "Light Blue Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 4, langConfig.getString("tile.concretePowder.yellow.name", "Yellow Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 5, langConfig.getString("tile.concretePowder.lime.name", "Lime Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 6, langConfig.getString("tile.concretePowder.pink.name", "Pink Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 7, langConfig.getString("tile.concretePowder.gray.name", "Gray Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 8, langConfig.getString("tile.concretePowder.silver.name", "Light Gray Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 9, langConfig.getString("tile.concretePowder.cyan.name", "Cyan Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 10, langConfig.getString("tile.concretePowder.purple.name", "Purple Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 11, langConfig.getString("tile.concretePowder.blue.name", "Blue Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 12, langConfig.getString("tile.concretePowder.brown.name", "Brown Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 13, langConfig.getString("tile.concretePowder.green.name", "Green Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 14, langConfig.getString("tile.concretePowder.red.name", "Red Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("CONCRETE_POWDER"), 15, langConfig.getString("tile.concretePowder.black.name", "Black Concrete Powder"))); + itemNames.add(new ItemName(Material.valueOf("WHITE_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaWhite.name", "White Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("ORANGE_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaOrange.name", "Orange Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("MAGENTA_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaMagenta.name", "Magenta Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("LIGHT_BLUE_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaLightBlue.name", "Light Blue Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("YELLOW_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaYellow.name", "Yellow Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("LIME_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaLime.name", "Lime Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("PINK_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaPink.name", "Pink Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("GRAY_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaGray.name", "Gray Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("SILVER_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaSilver.name", "Light Gray Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("CYAN_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaCyan.name", "Cyan Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("PURPLE_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaPurple.name", "Purple Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("BLUE_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaBlue.name", "Blue Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("BROWN_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaBrown.name", "Brown Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("GREEN_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaGreen.name", "Green Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("RED_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaRed.name", "Red Glazed Terracotta"))); + itemNames.add(new ItemName(Material.valueOf("BLACK_GLAZED_TERRACOTTA"), langConfig.getString("tile.glazedTerracottaBlack.name", "Black Glazed Terracotta"))); + } + + // Add Item Names + itemNames.add(new ItemName(Material.valueOf("IRON_SPADE"), langConfig.getString("item.shovelIron.name", "Iron Shovel"))); + itemNames.add(new ItemName(Material.valueOf("IRON_PICKAXE"), langConfig.getString("item.pickaxeIron.name", "Iron Pickaxe"))); + itemNames.add(new ItemName(Material.valueOf("IRON_AXE"), langConfig.getString("item.hatchetIron.name", "Iron Axe"))); + itemNames.add(new ItemName(Material.valueOf("FLINT_AND_STEEL"), langConfig.getString("item.flintAndSteel.name", "Flint and Steel"))); + itemNames.add(new ItemName(Material.valueOf("APPLE"), langConfig.getString("item.apple.name", "Apple"))); + itemNames.add(new ItemName(Material.valueOf("BOW"), langConfig.getString("item.bow.name", "Bow"))); + itemNames.add(new ItemName(Material.valueOf("ARROW"), langConfig.getString("item.arrow.name", "Arrow"))); + itemNames.add(new ItemName(Material.valueOf("COAL"), langConfig.getString("item.coal.name", "Coal"))); + itemNames.add(new ItemName(Material.valueOf("COAL"), 1, langConfig.getString("item.charcoal.name", "Charcoal"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND"), langConfig.getString("item.diamond.name", "Diamond"))); + itemNames.add(new ItemName(Material.valueOf("IRON_INGOT"), langConfig.getString("item.ingotIron.name", "Iron Ingot"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_INGOT"), langConfig.getString("item.ingotGold.name", "Gold Ingot"))); + itemNames.add(new ItemName(Material.valueOf("IRON_SWORD"), langConfig.getString("item.swordIron.name", "Iron Sword"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_SWORD"), langConfig.getString("item.swordWood.name", "Wooden Sword"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_SPADE"), langConfig.getString("item.shovelWood.name", "Wooden Shovel"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_PICKAXE"), langConfig.getString("item.pickaxeWood.name", "Wooden Pickaxe"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_AXE"), langConfig.getString("item.hatchetWood.name", "Wooden Axe"))); + itemNames.add(new ItemName(Material.valueOf("STONE_SWORD"), langConfig.getString("item.swordStone.name", "Stone Sword"))); + itemNames.add(new ItemName(Material.valueOf("STONE_SPADE"), langConfig.getString("item.shovelStone.name", "Stone Shovel"))); + itemNames.add(new ItemName(Material.valueOf("STONE_PICKAXE"), langConfig.getString("item.pickaxeStone.name", "Stone Pickaxe"))); + itemNames.add(new ItemName(Material.valueOf("STONE_AXE"), langConfig.getString("item.hatchetStone.name", "Stone Axe"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_SWORD"), langConfig.getString("item.swordDiamond.name", "Diamond Sword"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_SPADE"), langConfig.getString("item.shovelDiamond.name", "Diamond Shovel"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_PICKAXE"), langConfig.getString("item.pickaxeDiamond.name", "Diamond Pickaxe"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_AXE"), langConfig.getString("item.hatchetDiamond.name", "Diamond Axe"))); + itemNames.add(new ItemName(Material.valueOf("STICK"), langConfig.getString("item.stick.name", "Stick"))); + itemNames.add(new ItemName(Material.valueOf("BOWL"), langConfig.getString("item.bowl.name", "Bowl"))); + itemNames.add(new ItemName(Material.valueOf("MUSHROOM_SOUP"), langConfig.getString("item.mushroomStew.name", "Mushroom Stew"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_SWORD"), langConfig.getString("item.swordGold.name", "Golden Sword"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_SPADE"), langConfig.getString("item.shovelGold.name", "Golden Shovel"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_PICKAXE"), langConfig.getString("item.pickaxeGold.name", "Golden Pickaxe"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_AXE"), langConfig.getString("item.hatchetGold.name", "Golden Axe"))); + itemNames.add(new ItemName(Material.valueOf("STRING"), langConfig.getString("item.string.name", "String"))); + itemNames.add(new ItemName(Material.valueOf("FEATHER"), langConfig.getString("item.feather.name", "Feather"))); + itemNames.add(new ItemName(Material.valueOf("SULPHUR"), langConfig.getString("item.sulphur.name", "Gunpowder"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_HOE"), langConfig.getString("item.hoeWood.name", "Wooden Hoe"))); + itemNames.add(new ItemName(Material.valueOf("STONE_HOE"), langConfig.getString("item.hoeStone.name", "Stone Hoe"))); + itemNames.add(new ItemName(Material.valueOf("IRON_HOE"), langConfig.getString("item.hoeIron.name", "Iron Hoe"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_HOE"), langConfig.getString("item.hoeDiamond.name", "Diamond Hoe"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_HOE"), langConfig.getString("item.hoeGold.name", "Golden Hoe"))); + itemNames.add(new ItemName(Material.valueOf("SEEDS"), langConfig.getString("item.seeds.name", "Seeds"))); + itemNames.add(new ItemName(Material.valueOf("WHEAT"), langConfig.getString("item.wheat.name", "Wheat"))); + itemNames.add(new ItemName(Material.valueOf("BREAD"), langConfig.getString("item.bread.name", "Bread"))); + itemNames.add(new ItemName(Material.valueOf("LEATHER_HELMET"), langConfig.getString("item.helmetCloth.name", "Leather Cap"))); + itemNames.add(new ItemName(Material.valueOf("LEATHER_CHESTPLATE"), langConfig.getString("item.chestplateCloth.name", "Leather Tunic"))); + itemNames.add(new ItemName(Material.valueOf("LEATHER_LEGGINGS"), langConfig.getString("item.leggingsCloth.name", "Leather Pants"))); + itemNames.add(new ItemName(Material.valueOf("LEATHER_BOOTS"), langConfig.getString("item.bootsCloth.name", "Leather Boots"))); + itemNames.add(new ItemName(Material.valueOf("CHAINMAIL_HELMET"), langConfig.getString("item.helmetChain.name", "Chain Helmet"))); + itemNames.add(new ItemName(Material.valueOf("CHAINMAIL_CHESTPLATE"), langConfig.getString("item.chestplateChain.name", "Chain Chestplate"))); + itemNames.add(new ItemName(Material.valueOf("CHAINMAIL_LEGGINGS"), langConfig.getString("item.leggingsChain.name", "Chain Leggings"))); + itemNames.add(new ItemName(Material.valueOf("CHAINMAIL_BOOTS"), langConfig.getString("item.bootsChain.name", "Chain Boots"))); + itemNames.add(new ItemName(Material.valueOf("IRON_HELMET"), langConfig.getString("item.helmetIron.name", "Iron Helmet"))); + itemNames.add(new ItemName(Material.valueOf("IRON_CHESTPLATE"), langConfig.getString("item.chestplateIron.name", "Iron Chestplate"))); + itemNames.add(new ItemName(Material.valueOf("IRON_LEGGINGS"), langConfig.getString("item.leggingsIron.name", "Iron Leggings"))); + itemNames.add(new ItemName(Material.valueOf("IRON_BOOTS"), langConfig.getString("item.bootsIron.name", "Iron Boots"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_HELMET"), langConfig.getString("item.helmetDiamond.name", "Diamond Helmet"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_CHESTPLATE"), langConfig.getString("item.chestplateDiamond.name", "Diamond Chestplate"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_LEGGINGS"), langConfig.getString("item.leggingsDiamond.name", "Diamond Leggings"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_BOOTS"), langConfig.getString("item.bootsDiamond.name", "Diamond Boots"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_HELMET"), langConfig.getString("item.helmetGold.name", "Golden Helmet"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_CHESTPLATE"), langConfig.getString("item.chestplateGold.name", "Golden Chestplate"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_LEGGINGS"), langConfig.getString("item.leggingsGold.name", "Golden Leggings"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_BOOTS"), langConfig.getString("item.bootsGold.name", "Golden Boots"))); + itemNames.add(new ItemName(Material.valueOf("FLINT"), langConfig.getString("item.flint.name", "Flint"))); + itemNames.add(new ItemName(Material.valueOf("PORK"), langConfig.getString("item.porkchopRaw.name", "Raw Porkchop"))); + itemNames.add(new ItemName(Material.valueOf("GRILLED_PORK"), langConfig.getString("item.porkchopCooked.name", "Cooked Porkchop"))); + itemNames.add(new ItemName(Material.valueOf("PAINTING"), langConfig.getString("item.painting.name", "Painting"))); + itemNames.add(new ItemName(Material.valueOf("GOLDEN_APPLE"), langConfig.getString("item.appleGold.name", "Golden Apple"))); + itemNames.add(new ItemName(Material.valueOf("GOLDEN_APPLE"), 1, langConfig.getString("item.appleGold.name", "Golden Apple"))); + itemNames.add(new ItemName(Material.valueOf("SIGN"), langConfig.getString("item.sign.name", "Sign"))); + itemNames.add(new ItemName(Material.valueOf("WOOD_DOOR"), langConfig.getString("item.doorOak.name", "Oak Door"))); + itemNames.add(new ItemName(Material.valueOf("BUCKET"), langConfig.getString("item.bucket.name", "Bucket"))); + itemNames.add(new ItemName(Material.valueOf("WATER_BUCKET"), langConfig.getString("item.bucketWater.name", "Water Bucket"))); + itemNames.add(new ItemName(Material.valueOf("LAVA_BUCKET"), langConfig.getString("item.bucketLava.name", "Lava Bucket"))); + itemNames.add(new ItemName(Material.valueOf("MINECART"), langConfig.getString("item.minecart.name", "Minecart"))); + itemNames.add(new ItemName(Material.valueOf("SADDLE"), langConfig.getString("item.saddle.name", "Saddle"))); + itemNames.add(new ItemName(Material.valueOf("IRON_DOOR"), langConfig.getString("item.doorIron.name", "Iron Door"))); + itemNames.add(new ItemName(Material.valueOf("REDSTONE"), langConfig.getString("item.redstone.name", "Redstone"))); + itemNames.add(new ItemName(Material.valueOf("SNOW_BALL"), langConfig.getString("item.snowball.name", "Snowball"))); + itemNames.add(new ItemName(Material.valueOf("BOAT"), langConfig.getString("item.boat.oak.name", "Oak Boat"))); + itemNames.add(new ItemName(Material.valueOf("LEATHER"), langConfig.getString("item.leather.name", "Leather"))); + itemNames.add(new ItemName(Material.valueOf("MILK_BUCKET"), langConfig.getString("item.milk.name", "Milk"))); + itemNames.add(new ItemName(Material.valueOf("BRICK"), langConfig.getString("item.brick.name", "Brick"))); + itemNames.add(new ItemName(Material.valueOf("CLAY_BALL"), langConfig.getString("item.clay.name", "Clay"))); + itemNames.add(new ItemName(Material.valueOf("SUGAR_CANE"), langConfig.getString("item.reeds.name", "Sugar Canes"))); + itemNames.add(new ItemName(Material.valueOf("PAPER"), langConfig.getString("item.paper.name", "Paper"))); + itemNames.add(new ItemName(Material.valueOf("BOOK"), langConfig.getString("item.book.name", "Book"))); + itemNames.add(new ItemName(Material.valueOf("SLIME_BALL"), langConfig.getString("item.slimeball.name", "Slimeball"))); + itemNames.add(new ItemName(Material.valueOf("STORAGE_MINECART"), langConfig.getString("item.minecartChest.name", "Minecart with Chest"))); + itemNames.add(new ItemName(Material.valueOf("POWERED_MINECART"), langConfig.getString("item.minecartFurnace.name", "Minecart with Furnace"))); + itemNames.add(new ItemName(Material.valueOf("EGG"), langConfig.getString("item.egg.name", "Egg"))); + itemNames.add(new ItemName(Material.valueOf("COMPASS"), langConfig.getString("item.compass.name", "Compass"))); + itemNames.add(new ItemName(Material.valueOf("FISHING_ROD"), langConfig.getString("item.fishingRod.name", "Fishing Rod"))); + itemNames.add(new ItemName(Material.valueOf("WATCH"), langConfig.getString("item.clock.name", "Clock"))); + itemNames.add(new ItemName(Material.valueOf("GLOWSTONE_DUST"), langConfig.getString("item.yellowDust.name", "Glowstone Dust"))); + itemNames.add(new ItemName(Material.valueOf("RAW_FISH"), langConfig.getString("item.fish.cod.raw.name", "Raw Fish"))); + itemNames.add(new ItemName(Material.valueOf("RAW_FISH"), 1, langConfig.getString("item.fish.salmon.raw.name", "Raw Salmon"))); + itemNames.add(new ItemName(Material.valueOf("RAW_FISH"), 2, langConfig.getString("item.fish.clownfish.raw.name", "Clownfish"))); + itemNames.add(new ItemName(Material.valueOf("RAW_FISH"), 3, langConfig.getString("item.fish.pufferfish.raw.name", "Pufferfish"))); + itemNames.add(new ItemName(Material.valueOf("COOKED_FISH"), langConfig.getString("item.fish.cod.cooked.name", "Cooked Fish"))); + itemNames.add(new ItemName(Material.valueOf("COOKED_FISH"), 1, langConfig.getString("item.fish.salmon.cooked.name", "Cooked Salmon"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), langConfig.getString("item.dyePowder.black.name", "Ink Sac"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 1, langConfig.getString("item.dyePowder.red.name", "Rose Red"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 2, langConfig.getString("item.dyePowder.green.name", "Cactus Green"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 3, langConfig.getString("item.dyePowder.brown.name", "Cocoa Beans"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 4, langConfig.getString("item.dyePowder.blue.name", "Lapis Lazuli"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 5, langConfig.getString("item.dyePowder.purple.name", "Purple Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 6, langConfig.getString("item.dyePowder.cyan.name", "Cyan Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 7, langConfig.getString("item.dyePowder.silver.name", "Light Gray Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 8, langConfig.getString("item.dyePowder.gray.name", "Gray Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 9, langConfig.getString("item.dyePowder.pink.name", "Pink Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 10, langConfig.getString("item.dyePowder.lime.name", "Lime Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 11, langConfig.getString("item.dyePowder.yellow.name", "Dandelion Yellow"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 12, langConfig.getString("item.dyePowder.lightBlue.name", "Light Blue Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 13, langConfig.getString("item.dyePowder.magenta.name", "Magenta Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 14, langConfig.getString("item.dyePowder.orange.name", "Orange Dye"))); + itemNames.add(new ItemName(Material.valueOf("INK_SACK"), 15, langConfig.getString("item.dyePowder.white.name", "Bone Meal"))); + itemNames.add(new ItemName(Material.valueOf("BONE"), langConfig.getString("item.bone.name", "Bone"))); + itemNames.add(new ItemName(Material.valueOf("SUGAR"), langConfig.getString("item.sugar.name", "Sugar"))); + itemNames.add(new ItemName(Material.valueOf("CAKE"), langConfig.getString("item.cake.name", "Cake"))); + itemNames.add(new ItemName(Material.valueOf("DIODE"), langConfig.getString("item.diode.name", "Redstone Repeater"))); + itemNames.add(new ItemName(Material.valueOf("COOKIE"), langConfig.getString("item.cookie.name", "Cookie"))); + itemNames.add(new ItemName(Material.valueOf("MAP"), langConfig.getString("item.map.name", "Map"))); + itemNames.add(new ItemName(Material.valueOf("SHEARS"), langConfig.getString("item.shears.name", "Shears"))); + itemNames.add(new ItemName(Material.valueOf("MELON"), langConfig.getString("item.melon.name", "Melon"))); + itemNames.add(new ItemName(Material.valueOf("PUMPKIN_SEEDS"), langConfig.getString("item.seeds_pumpkin.name", "Pumpkin Seeds"))); + itemNames.add(new ItemName(Material.valueOf("MELON_SEEDS"), langConfig.getString("item.seeds_melon.name", "Melon Seeds"))); + itemNames.add(new ItemName(Material.valueOf("RAW_BEEF"), langConfig.getString("item.beefRaw.name", "Raw Beef"))); + itemNames.add(new ItemName(Material.valueOf("COOKED_BEEF"), langConfig.getString("item.beefCooked.name", "Steak"))); + itemNames.add(new ItemName(Material.valueOf("RAW_CHICKEN"), langConfig.getString("item.chickenRaw.name", "Raw Chicken"))); + itemNames.add(new ItemName(Material.valueOf("COOKED_CHICKEN"), langConfig.getString("item.chickenCooked.name", "Cooked Chicken"))); + itemNames.add(new ItemName(Material.valueOf("ROTTEN_FLESH"), langConfig.getString("item.rottenFlesh.name", "Rotten Flesh"))); + itemNames.add(new ItemName(Material.valueOf("ENDER_PEARL"), langConfig.getString("item.enderPearl.name", "Ender Pearl"))); + itemNames.add(new ItemName(Material.valueOf("BLAZE_ROD"), langConfig.getString("item.blazeRod.name", "Blaze Rod"))); + itemNames.add(new ItemName(Material.valueOf("GHAST_TEAR"), langConfig.getString("item.ghastTear.name", "Ghast Tear"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_NUGGET"), langConfig.getString("item.goldNugget.name", "Gold Nugget"))); + itemNames.add(new ItemName(Material.valueOf("NETHER_WARTS"), langConfig.getString("item.netherStalkSeeds.name", "Nether Wart"))); + itemNames.add(new ItemName(Material.valueOf("POTION"), langConfig.getString("item.potion.name", "Potion"))); + itemNames.add(new ItemName(Material.valueOf("GLASS_BOTTLE"), langConfig.getString("item.glassBottle.name", "Glass Bottle"))); + itemNames.add(new ItemName(Material.valueOf("SPIDER_EYE"), langConfig.getString("item.spiderEye.name", "Spider Eye"))); + itemNames.add(new ItemName(Material.valueOf("FERMENTED_SPIDER_EYE"), langConfig.getString("item.fermentedSpiderEye.name", "Fermented Spider Eye"))); + itemNames.add(new ItemName(Material.valueOf("BLAZE_POWDER"), langConfig.getString("item.blazePowder.name", "Blaze Powder"))); + itemNames.add(new ItemName(Material.valueOf("MAGMA_CREAM"), langConfig.getString("item.magmaCream.name", "Magma Cream"))); + itemNames.add(new ItemName(Material.valueOf("BREWING_STAND_ITEM"), langConfig.getString("item.brewingStand.name", "Brewing Stand"))); + itemNames.add(new ItemName(Material.valueOf("CAULDRON_ITEM"), langConfig.getString("item.cauldron.name", "Cauldron"))); + itemNames.add(new ItemName(Material.valueOf("EYE_OF_ENDER"), langConfig.getString("item.eyeOfEnder.name", "Eye of Ender"))); + itemNames.add(new ItemName(Material.valueOf("SPECKLED_MELON"), langConfig.getString("item.speckledMelon.name", "Glistering Melon"))); + itemNames.add(new ItemName(Material.valueOf("MONSTER_EGG"), langConfig.getString("item.monsterPlacer.name", "Spawn"))); + itemNames.add(new ItemName(Material.valueOf("EXP_BOTTLE"), langConfig.getString("item.expBottle.name", "Bottle o' Enchanting"))); + itemNames.add(new ItemName(Material.valueOf("FIREWORK_CHARGE"), langConfig.getString("item.fireball.name", "Fire Charge"))); + itemNames.add(new ItemName(Material.valueOf("BOOK_AND_QUILL"), langConfig.getString("item.writingBook.name", "Book and Quill"))); + itemNames.add(new ItemName(Material.valueOf("WRITTEN_BOOK"), langConfig.getString("item.writtenBook.name", "Written Book"))); + itemNames.add(new ItemName(Material.valueOf("EMERALD"), langConfig.getString("item.emerald.name", "Emerald"))); + itemNames.add(new ItemName(Material.valueOf("ITEM_FRAME"), langConfig.getString("item.frame.name", "Item Frame"))); + itemNames.add(new ItemName(Material.valueOf("FLOWER_POT_ITEM"), langConfig.getString("item.flowerPot.name", "Flower Pot"))); + itemNames.add(new ItemName(Material.valueOf("CARROT_ITEM"), langConfig.getString("item.carrots.name", "Carrot"))); + itemNames.add(new ItemName(Material.valueOf("POTATO_ITEM"), langConfig.getString("item.potato.name", "Potato"))); + itemNames.add(new ItemName(Material.valueOf("BAKED_POTATO"), langConfig.getString("item.potatoBaked.name", "Baked Potato"))); + itemNames.add(new ItemName(Material.valueOf("POISONOUS_POTATO"), langConfig.getString("item.potatoPoisonous.name", "Poisonous Potato"))); + itemNames.add(new ItemName(Material.valueOf("EMPTY_MAP"), langConfig.getString("item.emptyMap.name", "Empty Map"))); + itemNames.add(new ItemName(Material.valueOf("GOLDEN_CARROT"), langConfig.getString("item.carrotGolden.name", "Golden Carrot"))); + itemNames.add(new ItemName(Material.valueOf("SKULL_ITEM"), langConfig.getString("item.skull.skeleton.name", "Skeleton Skull"))); + itemNames.add(new ItemName(Material.valueOf("SKULL_ITEM"), 1, langConfig.getString("item.skull.wither.name", "Wither Skeleton Skull"))); + itemNames.add(new ItemName(Material.valueOf("SKULL_ITEM"), 2, langConfig.getString("item.skull.zombie.name", "Zombie Head"))); + itemNames.add(new ItemName(Material.valueOf("SKULL_ITEM"), 3, langConfig.getString("item.skull.char.name", "Head"))); + itemNames.add(new ItemName(Material.valueOf("SKULL_ITEM"), 4, langConfig.getString("item.skull.creeper.name", "Creeper Head"))); + itemNames.add(new ItemName(Material.valueOf("SKULL_ITEM"), 5, langConfig.getString("item.skull.dragon.name", "Creeper Head"))); + itemNames.add(new ItemName(Material.valueOf("CARROT_STICK"), langConfig.getString("item.carrotOnAStick.name", "Carrot on a Stick"))); + itemNames.add(new ItemName(Material.valueOf("NETHER_STAR"), langConfig.getString("item.netherStar.name", "Nether Star"))); + itemNames.add(new ItemName(Material.valueOf("PUMPKIN_PIE"), langConfig.getString("item.pumpkinPie.name", "Pumpkin Pie"))); + itemNames.add(new ItemName(Material.valueOf("FIREWORK"), langConfig.getString("item.fireworks.name", "Firework Rocket"))); + itemNames.add(new ItemName(Material.valueOf("FIREWORK_CHARGE"), langConfig.getString("item.fireworksCharge.name", "Firework Star"))); + itemNames.add(new ItemName(Material.valueOf("ENCHANTED_BOOK"), langConfig.getString("item.enchantedBook.name", "Enchanted Book"))); + itemNames.add(new ItemName(Material.valueOf("REDSTONE_COMPARATOR"), langConfig.getString("item.comparator.name", "Redstone Comparator"))); + itemNames.add(new ItemName(Material.valueOf("NETHER_BRICK_ITEM"), langConfig.getString("item.netherbrick.name", "Nether Brick"))); + itemNames.add(new ItemName(Material.valueOf("QUARTZ"), langConfig.getString("item.netherquartz.name", "Nether Quartz"))); + itemNames.add(new ItemName(Material.valueOf("EXPLOSIVE_MINECART"), langConfig.getString("item.minecartTnt.name", "Minecart with TNT"))); + itemNames.add(new ItemName(Material.valueOf("HOPPER_MINECART"), langConfig.getString("item.minecartHopper.name", "Minecart with Hopper"))); + itemNames.add(new ItemName(Material.valueOf("PRISMARINE_SHARD"), langConfig.getString("item.prismarineShard.name", "Prismarine Shard"))); + itemNames.add(new ItemName(Material.valueOf("PRISMARINE_CRYSTALS"), langConfig.getString("item.prismarineCrystals.name", "Prismarine Crystals"))); + itemNames.add(new ItemName(Material.valueOf("RABBIT"), langConfig.getString("item.rabbitRaw.name", "Raw Rabbit"))); + itemNames.add(new ItemName(Material.valueOf("COOKED_RABBIT"), langConfig.getString("item.rabbitCooked.name", "Cooked Rabbit"))); + itemNames.add(new ItemName(Material.valueOf("RABBIT_STEW"), langConfig.getString("item.rabbitStew.name", "Rabbit Stew"))); + itemNames.add(new ItemName(Material.valueOf("RABBIT_FOOT"), langConfig.getString("item.rabbitFoot.name", "Rabbit's Foot"))); + itemNames.add(new ItemName(Material.valueOf("RABBIT_HIDE"), langConfig.getString("item.rabbitHide.name", "Rabbit Hide"))); + itemNames.add(new ItemName(Material.valueOf("ARMOR_STAND"), langConfig.getString("item.armorStand.name", "Armor Stand"))); + itemNames.add(new ItemName(Material.valueOf("IRON_BARDING"), langConfig.getString("item.horsearmormetal.name", "Iron Horse Armor"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_BARDING"), langConfig.getString("item.horsearmorgold.name", "Gold Horse Armor"))); + itemNames.add(new ItemName(Material.valueOf("DIAMOND_BARDING"), langConfig.getString("item.horsearmordiamond.name", "Diamond Horse Armor"))); + itemNames.add(new ItemName(Material.valueOf("LEASH"), langConfig.getString("item.leash.name", "Lead"))); + itemNames.add(new ItemName(Material.valueOf("NAME_TAG"), langConfig.getString("item.nameTag.name", "Name Tag"))); + itemNames.add(new ItemName(Material.valueOf("COMMAND_MINECART"), langConfig.getString("item.minecartCommandBlock.name", "Minecart with Command Block"))); + itemNames.add(new ItemName(Material.valueOf("MUTTON"), langConfig.getString("item.muttonRaw.name", "Raw Mutton"))); + itemNames.add(new ItemName(Material.valueOf("COOKED_MUTTON"), langConfig.getString("item.muttonCooked.name", "Cooked Mutton"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), langConfig.getString("item.banner.black.name", "Black Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 1, langConfig.getString("item.banner.red.name", "Red Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 2, langConfig.getString("item.banner.green.name", "Green Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 3, langConfig.getString("item.banner.brown.name", "Brown Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 4, langConfig.getString("item.banner.blue.name", "Blue Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 5, langConfig.getString("item.banner.purple.name", "Purple Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 6, langConfig.getString("item.banner.cyan.name", "Cyan Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 7, langConfig.getString("item.banner.silver.name", "Light Gray Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 8, langConfig.getString("item.banner.gray.name", "Gray Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 9, langConfig.getString("item.banner.pink.name", "Pink Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 10, langConfig.getString("item.banner.lime.name", "Lime Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 11, langConfig.getString("item.banner.yellow.name", "Yellow Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 12, langConfig.getString("item.banner.lightBlue.name", "Light Blue Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 13, langConfig.getString("item.banner.magenta.name", "Magenta Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 14, langConfig.getString("item.banner.orange.name", "Orange Banner"))); + itemNames.add(new ItemName(Material.valueOf("BANNER"), 15, langConfig.getString("item.banner.white.name", "White Banner"))); + itemNames.add(new ItemName(Material.valueOf("SPRUCE_DOOR_ITEM"), langConfig.getString("item.doorSpruce.name", "Spruce Door"))); + itemNames.add(new ItemName(Material.valueOf("BIRCH_DOOR_ITEM"), langConfig.getString("item.doorBirch.name", "Birch Door"))); + itemNames.add(new ItemName(Material.valueOf("JUNGLE_DOOR_ITEM"), langConfig.getString("item.doorJungle.name", "Jungle Door"))); + itemNames.add(new ItemName(Material.valueOf("ACACIA_DOOR_ITEM"), langConfig.getString("item.doorAcacia.name", "Acacia Door"))); + itemNames.add(new ItemName(Material.valueOf("DARK_OAK_DOOR_ITEM"), langConfig.getString("item.doorDarkOak.name", "Dark Oak Door"))); + itemNames.add(new ItemName(Material.valueOf("GOLD_RECORD"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("GREEN_RECORD"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_3"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_4"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_5"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_6"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_7"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_8"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_9"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_10"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_11"), langConfig.getString("item.record.name", "Music Disc"))); + itemNames.add(new ItemName(Material.valueOf("RECORD_12"), langConfig.getString("item.record.name", "Music Disc"))); + + if (Utils.getMajorVersion() >= 9) { + // Add Item names of 1.9 + itemNames.add(new ItemName(Material.valueOf("END_CRYSTAL"), langConfig.getString("item.end_crystal.name", "End Crystal"))); + itemNames.add(new ItemName(Material.valueOf("CHORUS_FRUIT"), langConfig.getString("item.chorusFruit.name", "Chorus Fruit"))); + itemNames.add(new ItemName(Material.valueOf("CHORUS_FRUIT_POPPED"), langConfig.getString("item.chorusFruitPopped.name", "Popped Chorus Fruit"))); + itemNames.add(new ItemName(Material.valueOf("BEETROOT"), langConfig.getString("item.beetroot.name", "Beetroot"))); + itemNames.add(new ItemName(Material.valueOf("BEETROOT_SEEDS"), langConfig.getString("item.beetroot_seeds.name", "Beetroot Seeds"))); + itemNames.add(new ItemName(Material.valueOf("BEETROOT_SOUP"), langConfig.getString("item.beetroot_soup.name", "Beetroot Soup"))); + itemNames.add(new ItemName(Material.valueOf("DRAGONS_BREATH"), langConfig.getString("item.dragon_breath.name", "Dragon's Breath"))); + itemNames.add(new ItemName(Material.valueOf("SPECTRAL_ARROW"), langConfig.getString("item.spectral_arrow.name", "Spectral Arrow"))); + itemNames.add(new ItemName(Material.valueOf("TIPPED_ARROW"), langConfig.getString("item.tipped_arrow.name", "Tipped Arrow"))); + itemNames.add(new ItemName(Material.valueOf("SHIELD"), langConfig.getString("item.shield.name", "Shield"))); + itemNames.add(new ItemName(Material.valueOf("ELYTRA"), langConfig.getString("item.elytra.name", "Elytra"))); + itemNames.add(new ItemName(Material.valueOf("BOAT_SPRUCE"), langConfig.getString("item.boat.spruce.name", "Spruce Boat"))); + itemNames.add(new ItemName(Material.valueOf("BOAT_BIRCH"), langConfig.getString("item.boat.birch.name", "Birch Boat"))); + itemNames.add(new ItemName(Material.valueOf("BOAT_JUNGLE"), langConfig.getString("item.boat.jungle.name", "Jungle Boat"))); + itemNames.add(new ItemName(Material.valueOf("BOAT_ACACIA"), langConfig.getString("item.boat.acacia.name", "Acacia Boat"))); + itemNames.add(new ItemName(Material.valueOf("BOAT_DARK_OAK"), langConfig.getString("item.boat.dark_oak.name", "Dark Oak Boat"))); + } + + if (Utils.getMajorVersion() >= 11) { + // Add Item Names of 1.11 + itemNames.add(new ItemName(Material.valueOf("TOTEM"), langConfig.getString("item.totem.name", "Totem of Undying"))); + itemNames.add(new ItemName(Material.valueOf("SHULKER_SHELL"), langConfig.getString("item.shulkerShell.name", "Shulker Shell"))); + + if (Utils.getRevision() >= 2 || Utils.getMajorVersion() > 11) { + // Add Item Name of 1.11.2 + itemNames.add(new ItemName(Material.valueOf("IRON_NUGGET"), langConfig.getString("item.ironNugget.name", "Iron Nugget"))); + } + } + + if (Utils.getMajorVersion() >= 12) { + // Add Item Name of 1.12 + itemNames.add(new ItemName(Material.valueOf("KNOWLEDGE_BOOK"), langConfig.getString("item.knowledgeBook.name", "Knowledge Book"))); + itemNames.add(new ItemName(Material.valueOf("BED"), langConfig.getString("item.bed.white.name", "White Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 1, langConfig.getString("item.bed.orange.name", "Orange Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 2, langConfig.getString("item.bed.magenta.name", "Magenta Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 3, langConfig.getString("item.bed.lightBlue.name", "Light Blue Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 4, langConfig.getString("item.bed.yellow.name", "Yellow Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 5, langConfig.getString("item.bed.lime.name", "Lime Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 6, langConfig.getString("item.bed.pink.name", "Pink Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 7, langConfig.getString("item.bed.gray.name", "Gray Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 8, langConfig.getString("item.bed.silver.name", "Light Gray Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 9, langConfig.getString("item.bed.cyan.name", "Cyan Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 10, langConfig.getString("item.bed.purple.name", "Purple Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 11, langConfig.getString("item.bed.blue.name", "Blue Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 12, langConfig.getString("item.bed.brown.name", "Brown Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 13, langConfig.getString("item.bed.green.name", "Green Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 14, langConfig.getString("item.bed.red.name", "Red Bed"))); + itemNames.add(new ItemName(Material.valueOf("BED"), 15, langConfig.getString("item.bed.black.name", "Black Bed"))); + } else { + // Before 1.12, bed is just called "Bed" without colors + itemNames.add(new ItemName(Material.valueOf("BED"), langConfig.getString("item.bed.name", "Bed"))); + } + + // Add Enchantment Names + enchantmentNames.add(new EnchantmentName(Enchantment.ARROW_DAMAGE, langConfig.getString("enchantment.arrowDamage", "Power"))); + enchantmentNames.add(new EnchantmentName(Enchantment.ARROW_FIRE, langConfig.getString("enchantment.arrowFire", "Flame"))); + enchantmentNames.add(new EnchantmentName(Enchantment.ARROW_INFINITE, langConfig.getString("enchantment.arrowInfinite", "Infinity"))); + enchantmentNames.add(new EnchantmentName(Enchantment.ARROW_KNOCKBACK, langConfig.getString("enchantment.arrowKnockback", "Punch"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DAMAGE_ALL, langConfig.getString("enchantment.damage.all", "Sharpness"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DAMAGE_ARTHROPODS, langConfig.getString("enchantment.damage.arthropods", "Bane of Arthropods"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DAMAGE_UNDEAD, langConfig.getString("enchantment.damage.undead", "Smite"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DIG_SPEED, langConfig.getString("enchantment.digging", "Efficiency"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DURABILITY, langConfig.getString("enchantment.durability", "Unbreaking"))); + enchantmentNames.add(new EnchantmentName(Enchantment.FIRE_ASPECT, langConfig.getString("enchantment.fire", "Fire Aspect"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LURE, langConfig.getString("enchantment.fishingSpeed", "Lure"))); + enchantmentNames.add(new EnchantmentName(Enchantment.KNOCKBACK, langConfig.getString("enchantment.knockback", "Knockback"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LOOT_BONUS_MOBS, langConfig.getString("enchantment.lootBonus", "Looting"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LOOT_BONUS_BLOCKS, langConfig.getString("enchantment.lootBonusDigger", "Fortune"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LUCK, langConfig.getString("enchantment.lootBonusFishing", "Luck of the Sea"))); + enchantmentNames.add(new EnchantmentName(Enchantment.OXYGEN, langConfig.getString("enchantment.oxygen", "Respiration"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_ENVIRONMENTAL, langConfig.getString("enchantment.protect.all", "Protection"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_EXPLOSIONS, langConfig.getString("enchantment.protect.explosion", "Blast Protection"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_FALL, langConfig.getString("enchantment.protect.fall", "Feather Falling"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_FIRE, langConfig.getString("enchantment.protect.fire", "Fire Protection"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_PROJECTILE, langConfig.getString("enchantment.protect.projectile", "Projectile Protection"))); + enchantmentNames.add(new EnchantmentName(Enchantment.THORNS, langConfig.getString("enchantment.thorns", "Thorns"))); + enchantmentNames.add(new EnchantmentName(Enchantment.SILK_TOUCH, langConfig.getString("enchantment.untouching", "Silk Touch"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DEPTH_STRIDER, langConfig.getString("enchantment.waterWalker", "Depth Strider"))); + enchantmentNames.add(new EnchantmentName(Enchantment.WATER_WORKER, langConfig.getString("enchantment.waterWorker", "Aqua Affinity"))); + + if (Utils.getMajorVersion() >= 9) { + // Add Enchantment Names of 1.9 + enchantmentNames.add(new EnchantmentName(Enchantment.FROST_WALKER, langConfig.getString("enchantment.frostWalker", "Frost Walker"))); + enchantmentNames.add(new EnchantmentName(Enchantment.MENDING, langConfig.getString("enchantment.mending", "Mending"))); + } + + if (Utils.getMajorVersion() >= 11) { + // Add Enchantment Names of 1.11 + enchantmentNames.add(new EnchantmentName(Enchantment.BINDING_CURSE, langConfig.getString("enchantment.binding_curse", "Curse of Binding"))); + enchantmentNames.add(new EnchantmentName(Enchantment.VANISHING_CURSE, langConfig.getString("enchantment.vanishing_curse", "Curse of Vanishing"))); + + if (Utils.getRevision() >= 2 || Utils.getMajorVersion() > 11) { + // Add Enchantment Name of 1.11.2 + enchantmentNames.add(new EnchantmentName(Enchantment.SWEEPING_EDGE, langConfig.getString("enchantment.sweeping", "Sweeping Edge"))); + } + } + + // Add Enchantment Level Names + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(1, langConfig.getString("enchantment.level.1", "I"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(2, langConfig.getString("enchantment.level.2", "II"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(3, langConfig.getString("enchantment.level.3", "II"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(4, langConfig.getString("enchantment.level.4", "IV"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(5, langConfig.getString("enchantment.level.5", "V"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(6, langConfig.getString("enchantment.level.6", "VI"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(7, langConfig.getString("enchantment.level.7", "VII"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(8, langConfig.getString("enchantment.level.8", "VIII"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(9, langConfig.getString("enchantment.level.9", "IX"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(10, langConfig.getString("enchantment.level.10", "X"))); + + // Add Entity Names + String horseName = (Utils.getMajorVersion() >= 11 ? "entity.Horse.name" : "entity.EntityHorse.name"); + entityNames.add(new EntityName(EntityType.CREEPER, langConfig.getString("entity.Creeper.name", "Creeper"))); + entityNames.add(new EntityName(EntityType.SKELETON, langConfig.getString("entity.Skeleton.name", "Skeleton"))); + entityNames.add(new EntityName(EntityType.SPIDER, langConfig.getString("entity.Spider.name", "Spider"))); + entityNames.add(new EntityName(EntityType.ZOMBIE, langConfig.getString("entity.Zombie.name", "Zombie"))); + entityNames.add(new EntityName(EntityType.SLIME, langConfig.getString("entity.Slime.name", "Slime"))); + entityNames.add(new EntityName(EntityType.GHAST, langConfig.getString("entity.Ghast.name", "Ghast"))); + entityNames.add(new EntityName(EntityType.valueOf("PIG_ZOMBIE"), langConfig.getString("entity.PigZombie.name", "Zombie Pigman"))); + entityNames.add(new EntityName(EntityType.ENDERMAN, langConfig.getString("entity.Enderman.name", "Enderman"))); + entityNames.add(new EntityName(EntityType.CAVE_SPIDER, langConfig.getString("entity.CaveSpider.name", "Cave Spider"))); + entityNames.add(new EntityName(EntityType.SILVERFISH, langConfig.getString("entity.Silverfish.name", "Silverfish"))); + entityNames.add(new EntityName(EntityType.BLAZE, langConfig.getString("entity.Blaze.name", "Blaze"))); + entityNames.add(new EntityName(EntityType.MAGMA_CUBE, langConfig.getString("entity.LavaSlime.name", "Magma Cube"))); + entityNames.add(new EntityName(EntityType.BAT, langConfig.getString("entity.Bat.name", "Bat"))); + entityNames.add(new EntityName(EntityType.WITCH, langConfig.getString("entity.Witch.name", "Witch"))); + entityNames.add(new EntityName(EntityType.ENDERMITE, langConfig.getString("entity.Endermite.name", "Endermite"))); + entityNames.add(new EntityName(EntityType.GUARDIAN, langConfig.getString("entity.Guardian.name", "Guardian"))); + entityNames.add(new EntityName(EntityType.PIG, langConfig.getString("entity.Pig.name", "Pig"))); + entityNames.add(new EntityName(EntityType.SHEEP, langConfig.getString("entity.Sheep.name", "Sheep"))); + entityNames.add(new EntityName(EntityType.COW, langConfig.getString("entity.Cow.name", "Cow"))); + entityNames.add(new EntityName(EntityType.CHICKEN, langConfig.getString("entity.Chicken.name", "Chicken"))); + entityNames.add(new EntityName(EntityType.SQUID, langConfig.getString("entity.Squid.name", "Squid"))); + entityNames.add(new EntityName(EntityType.WOLF, langConfig.getString("entity.Wolf.name", "Wolf"))); + entityNames.add(new EntityName(EntityType.MUSHROOM_COW, langConfig.getString("entity.MushroomCow.name", "Mooshroom"))); + entityNames.add(new EntityName(EntityType.OCELOT, langConfig.getString("entity.Ozelot.name", "Ocelot"))); + entityNames.add(new EntityName(EntityType.HORSE, langConfig.getString(horseName, "Horse"))); + entityNames.add(new EntityName(EntityType.RABBIT, langConfig.getString("entity.Rabbit.name", "Rabbit"))); + entityNames.add(new EntityName(EntityType.VILLAGER, langConfig.getString("entity.Villager.name", "Villager"))); + + if (Utils.getMajorVersion() >= 9) { + // Add Entity Names of 1.9 + entityNames.add(new EntityName(EntityType.SHULKER, langConfig.getString("entity.Shulker.name", "Shulker"))); + } + + if (Utils.getMajorVersion() >= 10) { + // Add Entity Names of 1.10 + entityNames.add(new EntityName(EntityType.POLAR_BEAR, langConfig.getString("entity.PolarBear.name", "Polar Bear"))); + } + + if (Utils.getMajorVersion() >= 11) { + // Add Entity Names of 1.11 + entityNames.add(new EntityName(EntityType.ZOMBIE_VILLAGER, langConfig.getString("entity.ZombieVillager.name", "Zombie Villager"))); + entityNames.add(new EntityName(EntityType.ELDER_GUARDIAN, langConfig.getString("entity.ElderGuardian.name", "Elder Guardian"))); + entityNames.add(new EntityName(EntityType.EVOKER, langConfig.getString("entity.EvocationIllager.name", "Evoker"))); + entityNames.add(new EntityName(EntityType.VEX, langConfig.getString("entity.Vex.name", "Vex"))); + entityNames.add(new EntityName(EntityType.VINDICATOR, langConfig.getString("entity.VindicationIllager.name", "Vindicator"))); + entityNames.add(new EntityName(EntityType.LLAMA, langConfig.getString("entity.Llama.name", "Llama"))); + entityNames.add(new EntityName(EntityType.WITHER_SKELETON, langConfig.getString("entity.WitherSkeleton.name", "Wither Skeleton"))); + entityNames.add(new EntityName(EntityType.STRAY, langConfig.getString("entity.Stray.name", "Stray"))); + entityNames.add(new EntityName(EntityType.ZOMBIE_HORSE, langConfig.getString("entity.ZombieHorse.name", "Zombie Horse"))); + entityNames.add(new EntityName(EntityType.SKELETON_HORSE, langConfig.getString("entity.SkeletonHorse.name", "Skeleton Horse"))); + entityNames.add(new EntityName(EntityType.DONKEY, langConfig.getString("entity.Donkey.name", "Donkey"))); + entityNames.add(new EntityName(EntityType.MULE, langConfig.getString("entity.Mule.name", "Mule"))); + entityNames.add(new EntityName(EntityType.HUSK, langConfig.getString("entity.Husk.name", "Husk"))); + } + + if (Utils.getMajorVersion() >= 12) { + // Add Entity Names of 1.12 + entityNames.add(new EntityName(EntityType.PARROT, langConfig.getString("entity.Parrot.name", "Parrot"))); + entityNames.add(new EntityName(EntityType.ILLUSIONER, langConfig.getString("entity.IllusionIllager.name", "Illusioner"))); + } + + // Add Potion Effect Names + potionEffectNames.add(new PotionEffectName(PotionEffectType.FIRE_RESISTANCE, langConfig.getString("effect.fireResistance", "Fire Resistance"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.HARM, langConfig.getString("effect.harm", "Instant Damage"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.HEAL, langConfig.getString("effect.heal", "Instant Health"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.INVISIBILITY, langConfig.getString("effect.invisibility", "Invisibility"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.JUMP, langConfig.getString("effect.jump", "Jump Boost"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.NIGHT_VISION, langConfig.getString("effect.nightVision", "Night Vision"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.POISON, langConfig.getString("effect.poison", "Poison"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.REGENERATION, langConfig.getString("effect.regeneration", "Regeneration"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.SLOW, langConfig.getString("effect.moveSlowdown", "Slowness"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.SPEED, langConfig.getString("effect.moveSpeed", "Speed"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.INCREASE_DAMAGE, langConfig.getString("effect.damageBoost", "Strength"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.WATER_BREATHING, langConfig.getString("effect.waterBreathing", "Water Breathing"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.WEAKNESS, langConfig.getString("effect.weakness", "Weakness"))); + + if (Utils.getMajorVersion() >= 9) { + // Add Potion Effect Names of 1.9 + potionEffectNames.add(new PotionEffectName(PotionEffectType.LUCK, langConfig.getString("effect.luck", "Luck"))); + } + + // Add Potion Names + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.FIRE_RESISTANCE, langConfig.getString("potion.effect.fire_resistance", "Potion of Fire Resistance"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.INSTANT_DAMAGE, langConfig.getString("potion.effect.harming", "Potion of Harming"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.INSTANT_HEAL, langConfig.getString("potion.effect.healing", "Potion of Healing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.INVISIBILITY, langConfig.getString("potion.effect.invisibility", "Potion of Invisibility"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.JUMP, langConfig.getString("potion.effect.leaping", "Potion of Leaping"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.NIGHT_VISION, langConfig.getString("potion.effect.night_vision", "Potion of Night Vision"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.POISON, langConfig.getString("potion.effect.poison", "Potion of Poison"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.REGEN, langConfig.getString("potion.effect.regeneration", "Potion of Regeneration"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.SLOWNESS, langConfig.getString("potion.effect.slowness", "Potion of Slowness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.SPEED, langConfig.getString("potion.effect.swiftness", "Potion of Swiftness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.STRENGTH, langConfig.getString("potion.effect.strength", "Potion of Strength"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.WATER_BREATHING, langConfig.getString("potion.effect.water_breathing", "Potion of Water Breathing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.WEAKNESS, langConfig.getString("potion.effect.weakness", "Potion of Weakness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.WATER, langConfig.getString("potion.effect.water", "Water Bottle"))); + + if (Utils.getMajorVersion() >= 9) { + // Add Potion Names of 1.9 + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.AWKWARD, langConfig.getString("potion.effect.awkward", "Awkward Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.LUCK, langConfig.getString("potion.effect.luck", "Potion of Luck"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.MUNDANE, langConfig.getString("potion.effect.mundane", "Mundane Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.THICK, langConfig.getString("potion.effect.thick", "Thick Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.UNCRAFTABLE, langConfig.getString("potion.effect.empty", "Uncraftable Potion"))); + } + + if (Utils.getMajorVersion() >= 9) { + // Add Tipped Arrow Names (implemented in Minecraft since 1.9) + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.AWKWARD, langConfig.getString("tipped_arrow.effect.awkward", "Tipped Arrow"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.FIRE_RESISTANCE, langConfig.getString("tipped_arrow.effect.fire_resistance", "Arrow of Fire Resistance"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.INSTANT_DAMAGE, langConfig.getString("tipped_arrow.effect.harming", "Arrow of Harming"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.INSTANT_HEAL, langConfig.getString("tipped_arrow.effect.healing", "Arrow of Healing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.INVISIBILITY, langConfig.getString("tipped_arrow.effect.invisibility", "Arrow of Invisibility"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.JUMP, langConfig.getString("tipped_arrow.effect.leaping", "Arrow of Leaping"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.NIGHT_VISION, langConfig.getString("tipped_arrow.effect.night_vision", "Arrow of Night Vision"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.POISON, langConfig.getString("tipped_arrow.effect.poison", "Arrow of Poison"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.REGEN, langConfig.getString("tipped_arrow.effect.regeneration", "Arrow of Regeneration"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.SLOWNESS, langConfig.getString("tipped_arrow.effect.slowness", "Arrow of Slowness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.SPEED, langConfig.getString("tipped_arrow.effect.swiftness", "Arrow of Swiftness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.STRENGTH, langConfig.getString("tipped_arrow.effect.strength", "Arrow of Strength"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.WATER_BREATHING, langConfig.getString("tipped_arrow.effect.water_breathing", "Arrow of Water Breathing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.WEAKNESS, langConfig.getString("tipped_arrow.effect.weakness", "Arrow of Weakness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.WATER, langConfig.getString("tipped_arrow.effect.water", "Arrow of Splashing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.LUCK, langConfig.getString("tipped_arrow.effect.luck", "Arrow of Luck"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.MUNDANE, langConfig.getString("tipped_arrow.effect.mundane", "Tipped Arrow"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.THICK, langConfig.getString("tipped_arrow.effect.thick", "Tipped Arrow"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.UNCRAFTABLE, langConfig.getString("tipped_arrow.effect.empty", "Uncraftable Tipped Arrow"))); + } + + // Add Splash Potion Names + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.FIRE_RESISTANCE, langConfig.getString("splash_potion.effect.fire_resistance", "Splash Potion of Fire Resistance"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.INSTANT_DAMAGE, langConfig.getString("splash_potion.effect.harming", "Splash Potion of Harming"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.INSTANT_HEAL, langConfig.getString("splash_potion.effect.healing", "Splash Potion of Healing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.INVISIBILITY, langConfig.getString("splash_potion.effect.invisibility", "Splash Potion of Invisibility"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.JUMP, langConfig.getString("splash_potion.effect.leaping", "Splash Potion of Leaping"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.NIGHT_VISION, langConfig.getString("splash_potion.effect.night_vision", "Splash Potion of Night Vision"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.POISON, langConfig.getString("splash_potion.effect.poison", "Splash Potion of Poison"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.REGEN, langConfig.getString("splash_potion.effect.regeneration", "Splash Potion of Regeneration"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.SLOWNESS, langConfig.getString("splash_potion.effect.slowness", "Splash Potion of Slowness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.SPEED, langConfig.getString("splash_potion.effect.swiftness", "Splash Potion of Swiftness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.STRENGTH, langConfig.getString("splash_potion.effect.strength", "Splash Potion of Strength"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.WATER_BREATHING, langConfig.getString("splash_potion.effect.water_breathing", "Splash Potion of Water Breathing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.WEAKNESS, langConfig.getString("splash_potion.effect.weakness", "Splash Potion of Weakness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.WATER, langConfig.getString("splash_potion.effect.water", "Splash Water Bottle"))); + + if (Utils.getMajorVersion() >= 9) { + // Add Splash Potion Names of 1.9 + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.AWKWARD, langConfig.getString("splash_potion.effect.awkward", "Awkward Splash Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.LUCK, langConfig.getString("splash_potion.effect.luck", "Splash Potion of Luck"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.MUNDANE, langConfig.getString("splash_potion.effect.mundane", "Mundane Splash Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.THICK, langConfig.getString("splash_potion.effect.thick", "Thick Splash Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.UNCRAFTABLE, langConfig.getString("splash_potion.effect.empty", "Splash Uncraftable Potion"))); + } + + if (Utils.getMajorVersion() >= 9) { + // Add Lingering Potion Names (implemented in Minecraft since 1.9) + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.AWKWARD, langConfig.getString("lingering_potion.effect.awkward", "Awkward Lingering Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.FIRE_RESISTANCE, langConfig.getString("lingering_potion.effect.fire_resistance", "Lingering Potion of Fire Resistance"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.INSTANT_DAMAGE, langConfig.getString("lingering_potion.effect.harming", "Lingering Potion of Harming"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.INSTANT_HEAL, langConfig.getString("lingering_potion.effect.healing", "Lingering Potion of Healing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.INVISIBILITY, langConfig.getString("lingering_potion.effect.invisibility", "Lingering Potion of Invisibility"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.JUMP, langConfig.getString("lingering_potion.effect.leaping", "Lingering Potion of Leaping"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.NIGHT_VISION, langConfig.getString("lingering_potion.effect.night_vision", "Lingering Potion of Night Vision"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.POISON, langConfig.getString("lingering_potion.effect.poison", "Lingering Potion of Poison"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.REGEN, langConfig.getString("lingering_potion.effect.regeneration", "Lingering Potion of Regeneration"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.SLOWNESS, langConfig.getString("lingering_potion.effect.slowness", "Lingering Potion of Slowness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.SPEED, langConfig.getString("lingering_potion.effect.swiftness", "Lingering Potion of Swiftness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.STRENGTH, langConfig.getString("lingering_potion.effect.strength", "Lingering Potion of Strength"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.WATER_BREATHING, langConfig.getString("lingering_potion.effect.water_breathing", "Lingering Potion of Water Breathing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.WEAKNESS, langConfig.getString("lingering_potion.effect.weakness", "Lingering Potion of Weakness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.WATER, langConfig.getString("lingering_potion.effect.water", "Lingering Water Bottle"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.LUCK, langConfig.getString("lingering_potion.effect.luck", "Lingering Potion of Luck"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.MUNDANE, langConfig.getString("lingering_potion.effect.mundane", "Mundane Lingering Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.THICK, langConfig.getString("lingering_potion.effect.thick", "Thick Lingering Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.UNCRAFTABLE, langConfig.getString("lingering_potion.effect.empty", "Lingering Uncraftable Potion"))); + } + + // Add Music Disc Titles + musicDiscNames.add(new MusicDiscName(Material.valueOf("GOLD_RECORD"), langConfig.getString("item.record.13.desc", "C418 - 13"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("GREEN_RECORD"), langConfig.getString("item.record.cat.desc", "C418 - cat"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_3"), langConfig.getString("item.record.blocks.desc", "C418 - blocks"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_4"), langConfig.getString("item.record.chirp.desc", "C418 - chirp"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_5"), langConfig.getString("item.record.far.desc", "C418 - far"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_6"), langConfig.getString("item.record.mall.desc", "C418 - mall"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_7"), langConfig.getString("item.record.mellohi.desc", "C418 - mellohi"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_8"), langConfig.getString("item.record.stal.desc", "C418 - stal"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_9"), langConfig.getString("item.record.strad.desc", "C418 - strad"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_10"), langConfig.getString("item.record.ward.desc", "C418 - ward"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_11"), langConfig.getString("item.record.11.desc", "C418 - 11"))); + musicDiscNames.add(new MusicDiscName(Material.valueOf("RECORD_12"), langConfig.getString("item.record.wait.desc", "C418 - wait"))); + + // Add Book Generation Names + generationNames.add(new BookGenerationName(CustomBookMeta.Generation.ORIGINAL, langConfig.getString("book.generation.0", "Original"))); + generationNames.add(new BookGenerationName(CustomBookMeta.Generation.COPY_OF_ORIGINAL, langConfig.getString("book.generation.1", "Copy of original"))); + generationNames.add(new BookGenerationName(CustomBookMeta.Generation.COPY_OF_COPY, langConfig.getString("book.generation.2", "Copy of a copy"))); + generationNames.add(new BookGenerationName(CustomBookMeta.Generation.TATTERED, langConfig.getString("book.generation.3", "Tattered"))); + + loadMessages(); + } + + public static void load() { + langConfig = Config.langConfig; + + itemNames.clear(); + enchantmentNames.clear(); + enchantmentLevelNames.clear(); + potionEffectNames.clear(); + entityNames.clear(); + potionNames.clear(); + musicDiscNames.clear(); + generationNames.clear(); + messages.clear(); + + if (Utils.getMajorVersion() < 13) { + loadLegacy(); + return; + } + + // Add Block/Item Names + itemNames.add(new ItemName(Material.AIR, langConfig.getString("block.minecraft.air", "Air"))); + itemNames.add(new ItemName(Material.BARRIER, langConfig.getString("block.minecraft.barrier", "Barrier"))); + itemNames.add(new ItemName(Material.STONE, langConfig.getString("block.minecraft.stone", "Stone"))); + itemNames.add(new ItemName(Material.GRANITE, langConfig.getString("block.minecraft.granite", "Granite"))); + itemNames.add(new ItemName(Material.POLISHED_GRANITE, langConfig.getString("block.minecraft.polished_granite", "Polished Granite"))); + itemNames.add(new ItemName(Material.DIORITE, langConfig.getString("block.minecraft.diorite", "Diorite"))); + itemNames.add(new ItemName(Material.POLISHED_DIORITE, langConfig.getString("block.minecraft.polished_diorite", "Polished Diorite"))); + itemNames.add(new ItemName(Material.ANDESITE, langConfig.getString("block.minecraft.andesite", "Andesite"))); + itemNames.add(new ItemName(Material.POLISHED_ANDESITE, langConfig.getString("block.minecraft.polished_andesite", "Polished Andesite"))); + itemNames.add(new ItemName(Material.HAY_BLOCK, langConfig.getString("block.minecraft.hay_block", "Hay Bale"))); + itemNames.add(new ItemName(Material.GRASS_BLOCK, langConfig.getString("block.minecraft.grass_block", "Grass Block"))); + itemNames.add(new ItemName(Material.DIRT, langConfig.getString("block.minecraft.dirt", "Dirt"))); + itemNames.add(new ItemName(Material.COARSE_DIRT, langConfig.getString("block.minecraft.coarse_dirt", "Coarse Dirt"))); + itemNames.add(new ItemName(Material.PODZOL, langConfig.getString("block.minecraft.podzol", "Podzol"))); + itemNames.add(new ItemName(Material.COBBLESTONE, langConfig.getString("block.minecraft.cobblestone", "Cobblestone"))); + itemNames.add(new ItemName(Material.OAK_PLANKS, langConfig.getString("block.minecraft.oak_planks", "Oak Planks"))); + itemNames.add(new ItemName(Material.SPRUCE_PLANKS, langConfig.getString("block.minecraft.spruce_planks", "Spruce Planks"))); + itemNames.add(new ItemName(Material.BIRCH_PLANKS, langConfig.getString("block.minecraft.birch_planks", "Birch Planks"))); + itemNames.add(new ItemName(Material.JUNGLE_PLANKS, langConfig.getString("block.minecraft.jungle_planks", "Jungle Planks"))); + itemNames.add(new ItemName(Material.ACACIA_PLANKS, langConfig.getString("block.minecraft.acacia_planks", "Acacia Planks"))); + itemNames.add(new ItemName(Material.DARK_OAK_PLANKS, langConfig.getString("block.minecraft.dark_oak_planks", "Dark Oak Planks"))); + itemNames.add(new ItemName(Material.OAK_SAPLING, langConfig.getString("block.minecraft.oak_sapling", "Oak Sapling"))); + itemNames.add(new ItemName(Material.SPRUCE_SAPLING, langConfig.getString("block.minecraft.spruce_sapling", "Spruce Sapling"))); + itemNames.add(new ItemName(Material.BIRCH_SAPLING, langConfig.getString("block.minecraft.birch_sapling", "Birch Sapling"))); + itemNames.add(new ItemName(Material.JUNGLE_SAPLING, langConfig.getString("block.minecraft.jungle_sapling", "Jungle Sapling"))); + itemNames.add(new ItemName(Material.ACACIA_SAPLING, langConfig.getString("block.minecraft.acacia_sapling", "Acacia Sapling"))); + itemNames.add(new ItemName(Material.DARK_OAK_SAPLING, langConfig.getString("block.minecraft.dark_oak_sapling", "Dark Oak Sapling"))); + itemNames.add(new ItemName(Material.OAK_DOOR, langConfig.getString("block.minecraft.oak_door", "Oak Door"))); + itemNames.add(new ItemName(Material.SPRUCE_DOOR, langConfig.getString("block.minecraft.spruce_door", "Spruce Door"))); + itemNames.add(new ItemName(Material.BIRCH_DOOR, langConfig.getString("block.minecraft.birch_door", "Birch Door"))); + itemNames.add(new ItemName(Material.JUNGLE_DOOR, langConfig.getString("block.minecraft.jungle_door", "Jungle Door"))); + itemNames.add(new ItemName(Material.ACACIA_DOOR, langConfig.getString("block.minecraft.acacia_door", "Acacia Door"))); + itemNames.add(new ItemName(Material.DARK_OAK_DOOR, langConfig.getString("block.minecraft.dark_oak_door", "Dark Oak Door"))); + itemNames.add(new ItemName(Material.BEDROCK, langConfig.getString("block.minecraft.bedrock", "Bedrock"))); + itemNames.add(new ItemName(Material.WATER, langConfig.getString("block.minecraft.water", "Water"))); + itemNames.add(new ItemName(Material.LAVA, langConfig.getString("block.minecraft.lava", "Lava"))); + itemNames.add(new ItemName(Material.SAND, langConfig.getString("block.minecraft.sand", "Sand"))); + itemNames.add(new ItemName(Material.RED_SAND, langConfig.getString("block.minecraft.red_sand", "Red Sand"))); + itemNames.add(new ItemName(Material.SANDSTONE, langConfig.getString("block.minecraft.sandstone", "Sandstone"))); + itemNames.add(new ItemName(Material.CHISELED_SANDSTONE, langConfig.getString("block.minecraft.chiseled_sandstone", "Chiseled Sandstone"))); + itemNames.add(new ItemName(Material.CUT_SANDSTONE, langConfig.getString("block.minecraft.cut_sandstone", "Cut Sandstone"))); + itemNames.add(new ItemName(Material.RED_SANDSTONE, langConfig.getString("block.minecraft.red_sandstone", "Red Sandstone"))); + itemNames.add(new ItemName(Material.CHISELED_RED_SANDSTONE, langConfig.getString("block.minecraft.chiseled_red_sandstone", "Chiseled Red Sandstone"))); + itemNames.add(new ItemName(Material.CUT_RED_SANDSTONE, langConfig.getString("block.minecraft.cut_red_sandstone", "Cut Red Sandstone"))); + itemNames.add(new ItemName(Material.GRAVEL, langConfig.getString("block.minecraft.gravel", "Gravel"))); + itemNames.add(new ItemName(Material.GOLD_ORE, langConfig.getString("block.minecraft.gold_ore", "Gold Ore"))); + itemNames.add(new ItemName(Material.IRON_ORE, langConfig.getString("block.minecraft.iron_ore", "Iron Ore"))); + itemNames.add(new ItemName(Material.COAL_ORE, langConfig.getString("block.minecraft.coal_ore", "Coal Ore"))); + itemNames.add(new ItemName(Material.OAK_WOOD, langConfig.getString("block.minecraft.oak_wood", "Oak Wood"))); + itemNames.add(new ItemName(Material.SPRUCE_WOOD, langConfig.getString("block.minecraft.spruce_wood", "Spruce Wood"))); + itemNames.add(new ItemName(Material.BIRCH_WOOD, langConfig.getString("block.minecraft.birch_wood", "Birch Wood"))); + itemNames.add(new ItemName(Material.JUNGLE_WOOD, langConfig.getString("block.minecraft.jungle_wood", "Jungle Wood"))); + itemNames.add(new ItemName(Material.ACACIA_WOOD, langConfig.getString("block.minecraft.acacia_wood", "Acacia Wood"))); + itemNames.add(new ItemName(Material.DARK_OAK_WOOD, langConfig.getString("block.minecraft.dark_oak_wood", "Dark Oak Wood"))); + itemNames.add(new ItemName(Material.OAK_LOG, langConfig.getString("block.minecraft.oak_log", "Oak Log"))); + itemNames.add(new ItemName(Material.SPRUCE_LOG, langConfig.getString("block.minecraft.spruce_log", "Spruce Log"))); + itemNames.add(new ItemName(Material.BIRCH_LOG, langConfig.getString("block.minecraft.birch_log", "Birch Log"))); + itemNames.add(new ItemName(Material.JUNGLE_LOG, langConfig.getString("block.minecraft.jungle_log", "Jungle Log"))); + itemNames.add(new ItemName(Material.ACACIA_LOG, langConfig.getString("block.minecraft.acacia_log", "Acacia Log"))); + itemNames.add(new ItemName(Material.DARK_OAK_LOG, langConfig.getString("block.minecraft.dark_oak_log", "Dark Oak Log"))); + itemNames.add(new ItemName(Material.STRIPPED_OAK_LOG, langConfig.getString("block.minecraft.stripped_oak_log", "Stripped Oak Log"))); + itemNames.add(new ItemName(Material.STRIPPED_SPRUCE_LOG, langConfig.getString("block.minecraft.stripped_spruce_log", "Stripped Spruce Log"))); + itemNames.add(new ItemName(Material.STRIPPED_BIRCH_LOG, langConfig.getString("block.minecraft.stripped_birch_log", "Stripped Birch Log"))); + itemNames.add(new ItemName(Material.STRIPPED_JUNGLE_LOG, langConfig.getString("block.minecraft.stripped_jungle_log", "Stripped Jungle Log"))); + itemNames.add(new ItemName(Material.STRIPPED_ACACIA_LOG, langConfig.getString("block.minecraft.stripped_acacia_log", "Stripped Acacia Log"))); + itemNames.add(new ItemName(Material.STRIPPED_DARK_OAK_LOG, langConfig.getString("block.minecraft.stripped_dark_oak_log", "Stripped Dark Oak Log"))); + itemNames.add(new ItemName(Material.STRIPPED_OAK_WOOD, langConfig.getString("block.minecraft.stripped_oak_wood", "Stripped Oak Wood"))); + itemNames.add(new ItemName(Material.STRIPPED_SPRUCE_WOOD, langConfig.getString("block.minecraft.stripped_spruce_wood", "Stripped Spruce Wood"))); + itemNames.add(new ItemName(Material.STRIPPED_BIRCH_WOOD, langConfig.getString("block.minecraft.stripped_birch_wood", "Stripped Birch Wood"))); + itemNames.add(new ItemName(Material.STRIPPED_JUNGLE_WOOD, langConfig.getString("block.minecraft.stripped_jungle_wood", "Stripped Jungle Wood"))); + itemNames.add(new ItemName(Material.STRIPPED_ACACIA_WOOD, langConfig.getString("block.minecraft.stripped_acacia_wood", "Stripped Acacia Wood"))); + itemNames.add(new ItemName(Material.STRIPPED_DARK_OAK_WOOD, langConfig.getString("block.minecraft.stripped_dark_oak_wood", "Stripped Dark Oak Wood"))); + itemNames.add(new ItemName(Material.OAK_LEAVES, langConfig.getString("block.minecraft.oak_leaves", "Oak Leaves"))); + itemNames.add(new ItemName(Material.SPRUCE_LEAVES, langConfig.getString("block.minecraft.spruce_leaves", "Spruce Leaves"))); + itemNames.add(new ItemName(Material.BIRCH_LEAVES, langConfig.getString("block.minecraft.birch_leaves", "Birch Leaves"))); + itemNames.add(new ItemName(Material.JUNGLE_LEAVES, langConfig.getString("block.minecraft.jungle_leaves", "Jungle Leaves"))); + itemNames.add(new ItemName(Material.ACACIA_LEAVES, langConfig.getString("block.minecraft.acacia_leaves", "Acacia Leaves"))); + itemNames.add(new ItemName(Material.DARK_OAK_LEAVES, langConfig.getString("block.minecraft.dark_oak_leaves", "Dark Oak Leaves"))); + itemNames.add(new ItemName(Material.DEAD_BUSH, langConfig.getString("block.minecraft.dead_bush", "Dead Bush"))); + itemNames.add(new ItemName(Material.GRASS, langConfig.getString("block.minecraft.grass", "Grass"))); + itemNames.add(new ItemName(Material.FERN, langConfig.getString("block.minecraft.fern", "Fern"))); + itemNames.add(new ItemName(Material.SPONGE, langConfig.getString("block.minecraft.sponge", "Sponge"))); + itemNames.add(new ItemName(Material.WET_SPONGE, langConfig.getString("block.minecraft.wet_sponge", "Wet Sponge"))); + itemNames.add(new ItemName(Material.GLASS, langConfig.getString("block.minecraft.glass", "Glass"))); + itemNames.add(new ItemName(Material.KELP_PLANT, langConfig.getString("block.minecraft.kelp_plant", "Kelp Plant"))); + itemNames.add(new ItemName(Material.KELP, langConfig.getString("block.minecraft.kelp", "Kelp"))); + itemNames.add(new ItemName(Material.DRIED_KELP_BLOCK, langConfig.getString("block.minecraft.dried_kelp_block", "Dried Kelp Block"))); + itemNames.add(new ItemName(Material.WHITE_STAINED_GLASS, langConfig.getString("block.minecraft.white_stained_glass", "White Stained Glass"))); + itemNames.add(new ItemName(Material.ORANGE_STAINED_GLASS, langConfig.getString("block.minecraft.orange_stained_glass", "Orange Stained Glass"))); + itemNames.add(new ItemName(Material.MAGENTA_STAINED_GLASS, langConfig.getString("block.minecraft.magenta_stained_glass", "Magenta Stained Glass"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_STAINED_GLASS, langConfig.getString("block.minecraft.light_blue_stained_glass", "Light Blue Stained Glass"))); + itemNames.add(new ItemName(Material.YELLOW_STAINED_GLASS, langConfig.getString("block.minecraft.yellow_stained_glass", "Yellow Stained Glass"))); + itemNames.add(new ItemName(Material.LIME_STAINED_GLASS, langConfig.getString("block.minecraft.lime_stained_glass", "Lime Stained Glass"))); + itemNames.add(new ItemName(Material.PINK_STAINED_GLASS, langConfig.getString("block.minecraft.pink_stained_glass", "Pink Stained Glass"))); + itemNames.add(new ItemName(Material.GRAY_STAINED_GLASS, langConfig.getString("block.minecraft.gray_stained_glass", "Gray Stained Glass"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_STAINED_GLASS, langConfig.getString("block.minecraft.light_gray_stained_glass", "Light Gray Stained Glass"))); + itemNames.add(new ItemName(Material.CYAN_STAINED_GLASS, langConfig.getString("block.minecraft.cyan_stained_glass", "Cyan Stained Glass"))); + itemNames.add(new ItemName(Material.PURPLE_STAINED_GLASS, langConfig.getString("block.minecraft.purple_stained_glass", "Purple Stained Glass"))); + itemNames.add(new ItemName(Material.BLUE_STAINED_GLASS, langConfig.getString("block.minecraft.blue_stained_glass", "Blue Stained Glass"))); + itemNames.add(new ItemName(Material.BROWN_STAINED_GLASS, langConfig.getString("block.minecraft.brown_stained_glass", "Brown Stained Glass"))); + itemNames.add(new ItemName(Material.GREEN_STAINED_GLASS, langConfig.getString("block.minecraft.green_stained_glass", "Green Stained Glass"))); + itemNames.add(new ItemName(Material.RED_STAINED_GLASS, langConfig.getString("block.minecraft.red_stained_glass", "Red Stained Glass"))); + itemNames.add(new ItemName(Material.BLACK_STAINED_GLASS, langConfig.getString("block.minecraft.black_stained_glass", "Black Stained Glass"))); + itemNames.add(new ItemName(Material.WHITE_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.white_stained_glass_pane", "White Stained Glass Pane"))); + itemNames.add(new ItemName(Material.ORANGE_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.orange_stained_glass_pane", "Orange Stained Glass Pane"))); + itemNames.add(new ItemName(Material.MAGENTA_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.magenta_stained_glass_pane", "Magenta Stained Glass Pane"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.light_blue_stained_glass_pane", "Light Blue Stained Glass Pane"))); + itemNames.add(new ItemName(Material.YELLOW_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.yellow_stained_glass_pane", "Yellow Stained Glass Pane"))); + itemNames.add(new ItemName(Material.LIME_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.lime_stained_glass_pane", "Lime Stained Glass Pane"))); + itemNames.add(new ItemName(Material.PINK_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.pink_stained_glass_pane", "Pink Stained Glass Pane"))); + itemNames.add(new ItemName(Material.GRAY_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.gray_stained_glass_pane", "Gray Stained Glass Pane"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.light_gray_stained_glass_pane", "Light Gray Stained Glass Pane"))); + itemNames.add(new ItemName(Material.CYAN_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.cyan_stained_glass_pane", "Cyan Stained Glass Pane"))); + itemNames.add(new ItemName(Material.PURPLE_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.purple_stained_glass_pane", "Purple Stained Glass Pane"))); + itemNames.add(new ItemName(Material.BLUE_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.blue_stained_glass_pane", "Blue Stained Glass Pane"))); + itemNames.add(new ItemName(Material.BROWN_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.brown_stained_glass_pane", "Brown Stained Glass Pane"))); + itemNames.add(new ItemName(Material.GREEN_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.green_stained_glass_pane", "Green Stained Glass Pane"))); + itemNames.add(new ItemName(Material.RED_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.red_stained_glass_pane", "Red Stained Glass Pane"))); + itemNames.add(new ItemName(Material.BLACK_STAINED_GLASS_PANE, langConfig.getString("block.minecraft.black_stained_glass_pane", "Black Stained Glass Pane"))); + itemNames.add(new ItemName(Material.GLASS_PANE, langConfig.getString("block.minecraft.glass_pane", "Glass Pane"))); + itemNames.add(new ItemName(Material.DANDELION, langConfig.getString("block.minecraft.dandelion", "Dandelion"))); + itemNames.add(new ItemName(Material.POPPY, langConfig.getString("block.minecraft.poppy", "Poppy"))); + itemNames.add(new ItemName(Material.BLUE_ORCHID, langConfig.getString("block.minecraft.blue_orchid", "Blue Orchid"))); + itemNames.add(new ItemName(Material.ALLIUM, langConfig.getString("block.minecraft.allium", "Allium"))); + itemNames.add(new ItemName(Material.AZURE_BLUET, langConfig.getString("block.minecraft.azure_bluet", "Azure Bluet"))); + itemNames.add(new ItemName(Material.RED_TULIP, langConfig.getString("block.minecraft.red_tulip", "Red Tulip"))); + itemNames.add(new ItemName(Material.ORANGE_TULIP, langConfig.getString("block.minecraft.orange_tulip", "Orange Tulip"))); + itemNames.add(new ItemName(Material.WHITE_TULIP, langConfig.getString("block.minecraft.white_tulip", "White Tulip"))); + itemNames.add(new ItemName(Material.PINK_TULIP, langConfig.getString("block.minecraft.pink_tulip", "Pink Tulip"))); + itemNames.add(new ItemName(Material.OXEYE_DAISY, langConfig.getString("block.minecraft.oxeye_daisy", "Oxeye Daisy"))); + itemNames.add(new ItemName(Material.SUNFLOWER, langConfig.getString("block.minecraft.sunflower", "Sunflower"))); + itemNames.add(new ItemName(Material.LILAC, langConfig.getString("block.minecraft.lilac", "Lilac"))); + itemNames.add(new ItemName(Material.TALL_GRASS, langConfig.getString("block.minecraft.tall_grass", "Tall Grass"))); + itemNames.add(new ItemName(Material.TALL_SEAGRASS, langConfig.getString("block.minecraft.tall_seagrass", "Tall Seagrass"))); + itemNames.add(new ItemName(Material.LARGE_FERN, langConfig.getString("block.minecraft.large_fern", "Large Fern"))); + itemNames.add(new ItemName(Material.ROSE_BUSH, langConfig.getString("block.minecraft.rose_bush", "Rose Bush"))); + itemNames.add(new ItemName(Material.PEONY, langConfig.getString("block.minecraft.peony", "Peony"))); + itemNames.add(new ItemName(Material.SEAGRASS, langConfig.getString("block.minecraft.seagrass", "Seagrass"))); + itemNames.add(new ItemName(Material.SEA_PICKLE, langConfig.getString("block.minecraft.sea_pickle", "Sea Pickle"))); + itemNames.add(new ItemName(Material.BROWN_MUSHROOM, langConfig.getString("block.minecraft.brown_mushroom", "Brown Mushroom"))); + itemNames.add(new ItemName(Material.RED_MUSHROOM_BLOCK, langConfig.getString("block.minecraft.red_mushroom_block", "Red Mushroom Block"))); + itemNames.add(new ItemName(Material.BROWN_MUSHROOM_BLOCK, langConfig.getString("block.minecraft.brown_mushroom_block", "Brown Mushroom Block"))); + itemNames.add(new ItemName(Material.MUSHROOM_STEM, langConfig.getString("block.minecraft.mushroom_stem", "Mushroom Stem"))); + itemNames.add(new ItemName(Material.GOLD_BLOCK, langConfig.getString("block.minecraft.gold_block", "Block of Gold"))); + itemNames.add(new ItemName(Material.IRON_BLOCK, langConfig.getString("block.minecraft.iron_block", "Block of Iron"))); + itemNames.add(new ItemName(Material.SMOOTH_STONE, langConfig.getString("block.minecraft.smooth_stone", "Smooth Stone"))); + itemNames.add(new ItemName(Material.SMOOTH_SANDSTONE, langConfig.getString("block.minecraft.smooth_sandstone", "Smooth Sandstone"))); + itemNames.add(new ItemName(Material.SMOOTH_RED_SANDSTONE, langConfig.getString("block.minecraft.smooth_red_sandstone", "Smooth Red Sandstone"))); + itemNames.add(new ItemName(Material.SMOOTH_QUARTZ, langConfig.getString("block.minecraft.smooth_quartz", "Smooth Quartz"))); + itemNames.add(new ItemName(Material.STONE_SLAB, langConfig.getString("block.minecraft.stone_slab", "Stone Slab"))); + itemNames.add(new ItemName(Material.SANDSTONE_SLAB, langConfig.getString("block.minecraft.sandstone_slab", "Sandstone Slab"))); + itemNames.add(new ItemName(Material.RED_SANDSTONE_SLAB, langConfig.getString("block.minecraft.red_sandstone_slab", "Red Sandstone Slab"))); + itemNames.add(new ItemName(Material.PETRIFIED_OAK_SLAB, langConfig.getString("block.minecraft.petrified_oak_slab", "Petrified Oak Slab"))); + itemNames.add(new ItemName(Material.COBBLESTONE_SLAB, langConfig.getString("block.minecraft.cobblestone_slab", "Cobblestone Slab"))); + itemNames.add(new ItemName(Material.BRICK_SLAB, langConfig.getString("block.minecraft.brick_slab", "Brick Slab"))); + itemNames.add(new ItemName(Material.STONE_BRICK_SLAB, langConfig.getString("block.minecraft.stone_brick_slab", "Stone Brick Slab"))); + itemNames.add(new ItemName(Material.NETHER_BRICK_SLAB, langConfig.getString("block.minecraft.nether_brick_slab", "Nether Brick Slab"))); + itemNames.add(new ItemName(Material.QUARTZ_SLAB, langConfig.getString("block.minecraft.quartz_slab", "Quartz Slab"))); + itemNames.add(new ItemName(Material.OAK_SLAB, langConfig.getString("block.minecraft.oak_slab", "Oak Slab"))); + itemNames.add(new ItemName(Material.SPRUCE_SLAB, langConfig.getString("block.minecraft.spruce_slab", "Spruce Slab"))); + itemNames.add(new ItemName(Material.BIRCH_SLAB, langConfig.getString("block.minecraft.birch_slab", "Birch Slab"))); + itemNames.add(new ItemName(Material.JUNGLE_SLAB, langConfig.getString("block.minecraft.jungle_slab", "Jungle Slab"))); + itemNames.add(new ItemName(Material.ACACIA_SLAB, langConfig.getString("block.minecraft.acacia_slab", "Acacia Slab"))); + itemNames.add(new ItemName(Material.DARK_OAK_SLAB, langConfig.getString("block.minecraft.dark_oak_slab", "Dark Oak Slab"))); + itemNames.add(new ItemName(Material.DARK_PRISMARINE_SLAB, langConfig.getString("block.minecraft.dark_prismarine_slab", "Dark Prismarine Slab"))); + itemNames.add(new ItemName(Material.PRISMARINE_SLAB, langConfig.getString("block.minecraft.prismarine_slab", "Prismarine Slab"))); + itemNames.add(new ItemName(Material.PRISMARINE_BRICK_SLAB, langConfig.getString("block.minecraft.prismarine_brick_slab", "Prismarine Brick Slab"))); + itemNames.add(new ItemName(Material.BRICKS, langConfig.getString("block.minecraft.bricks", "Bricks"))); + itemNames.add(new ItemName(Material.TNT, langConfig.getString("block.minecraft.tnt", "TNT"))); + itemNames.add(new ItemName(Material.BOOKSHELF, langConfig.getString("block.minecraft.bookshelf", "Bookshelf"))); + itemNames.add(new ItemName(Material.MOSSY_COBBLESTONE, langConfig.getString("block.minecraft.mossy_cobblestone", "Mossy Cobblestone"))); + itemNames.add(new ItemName(Material.OBSIDIAN, langConfig.getString("block.minecraft.obsidian", "Obsidian"))); + itemNames.add(new ItemName(Material.TORCH, langConfig.getString("block.minecraft.torch", "Torch"))); + itemNames.add(new ItemName(Material.WALL_TORCH, langConfig.getString("block.minecraft.wall_torch", "Wall Torch"))); + itemNames.add(new ItemName(Material.FIRE, langConfig.getString("block.minecraft.fire", "Fire"))); + itemNames.add(new ItemName(Material.SPAWNER, langConfig.getString("block.minecraft.spawner", "Spawner"))); + itemNames.add(new ItemName(Material.OAK_STAIRS, langConfig.getString("block.minecraft.oak_stairs", "Oak Stairs"))); + itemNames.add(new ItemName(Material.SPRUCE_STAIRS, langConfig.getString("block.minecraft.spruce_stairs", "Spruce Stairs"))); + itemNames.add(new ItemName(Material.BIRCH_STAIRS, langConfig.getString("block.minecraft.birch_stairs", "Birch Stairs"))); + itemNames.add(new ItemName(Material.JUNGLE_STAIRS, langConfig.getString("block.minecraft.jungle_stairs", "Jungle Stairs"))); + itemNames.add(new ItemName(Material.ACACIA_STAIRS, langConfig.getString("block.minecraft.acacia_stairs", "Acacia Stairs"))); + itemNames.add(new ItemName(Material.DARK_OAK_STAIRS, langConfig.getString("block.minecraft.dark_oak_stairs", "Dark Oak Stairs"))); + itemNames.add(new ItemName(Material.DARK_PRISMARINE_STAIRS, langConfig.getString("block.minecraft.dark_prismarine_stairs", "Dark Prismarine Stairs"))); + itemNames.add(new ItemName(Material.PRISMARINE_STAIRS, langConfig.getString("block.minecraft.prismarine_stairs", "Prismarine Stairs"))); + itemNames.add(new ItemName(Material.PRISMARINE_BRICK_STAIRS, langConfig.getString("block.minecraft.prismarine_brick_stairs", "Prismarine Brick Stairs"))); + itemNames.add(new ItemName(Material.CHEST, langConfig.getString("block.minecraft.chest", "Chest"))); + itemNames.add(new ItemName(Material.TRAPPED_CHEST, langConfig.getString("block.minecraft.trapped_chest", "Trapped Chest"))); + itemNames.add(new ItemName(Material.REDSTONE_WIRE, langConfig.getString("block.minecraft.redstone_wire", "Redstone Dust"))); + itemNames.add(new ItemName(Material.DIAMOND_ORE, langConfig.getString("block.minecraft.diamond_ore", "Diamond Ore"))); + itemNames.add(new ItemName(Material.COAL_BLOCK, langConfig.getString("block.minecraft.coal_block", "Block of Coal"))); + itemNames.add(new ItemName(Material.DIAMOND_BLOCK, langConfig.getString("block.minecraft.diamond_block", "Block of Diamond"))); + itemNames.add(new ItemName(Material.CRAFTING_TABLE, langConfig.getString("block.minecraft.crafting_table", "Crafting Table"))); + itemNames.add(new ItemName(Material.WHEAT, langConfig.getString("block.minecraft.wheat", "Wheat Crops"))); + itemNames.add(new ItemName(Material.FARMLAND, langConfig.getString("block.minecraft.farmland", "Farmland"))); + itemNames.add(new ItemName(Material.FURNACE, langConfig.getString("block.minecraft.furnace", "Furnace"))); + itemNames.add(new ItemName(Material.LADDER, langConfig.getString("block.minecraft.ladder", "Ladder"))); + itemNames.add(new ItemName(Material.RAIL, langConfig.getString("block.minecraft.rail", "Rail"))); + itemNames.add(new ItemName(Material.POWERED_RAIL, langConfig.getString("block.minecraft.powered_rail", "Powered Rail"))); + itemNames.add(new ItemName(Material.ACTIVATOR_RAIL, langConfig.getString("block.minecraft.activator_rail", "Activator Rail"))); + itemNames.add(new ItemName(Material.DETECTOR_RAIL, langConfig.getString("block.minecraft.detector_rail", "Detector Rail"))); + itemNames.add(new ItemName(Material.COBBLESTONE_STAIRS, langConfig.getString("block.minecraft.cobblestone_stairs", "Cobblestone Stairs"))); + itemNames.add(new ItemName(Material.SANDSTONE_STAIRS, langConfig.getString("block.minecraft.sandstone_stairs", "Sandstone Stairs"))); + itemNames.add(new ItemName(Material.RED_SANDSTONE_STAIRS, langConfig.getString("block.minecraft.red_sandstone_stairs", "Red Sandstone Stairs"))); + itemNames.add(new ItemName(Material.LEVER, langConfig.getString("block.minecraft.lever", "Lever"))); + itemNames.add(new ItemName(Material.STONE_PRESSURE_PLATE, langConfig.getString("block.minecraft.stone_pressure_plate", "Stone Pressure Plate"))); + itemNames.add(new ItemName(Material.OAK_PRESSURE_PLATE, langConfig.getString("block.minecraft.oak_pressure_plate", "Oak Pressure Plate"))); + itemNames.add(new ItemName(Material.SPRUCE_PRESSURE_PLATE, langConfig.getString("block.minecraft.spruce_pressure_plate", "Spruce Pressure Plate"))); + itemNames.add(new ItemName(Material.BIRCH_PRESSURE_PLATE, langConfig.getString("block.minecraft.birch_pressure_plate", "Birch Pressure Plate"))); + itemNames.add(new ItemName(Material.JUNGLE_PRESSURE_PLATE, langConfig.getString("block.minecraft.jungle_pressure_plate", "Jungle Pressure Plate"))); + itemNames.add(new ItemName(Material.ACACIA_PRESSURE_PLATE, langConfig.getString("block.minecraft.acacia_pressure_plate", "Acacia Pressure Plate"))); + itemNames.add(new ItemName(Material.DARK_OAK_PRESSURE_PLATE, langConfig.getString("block.minecraft.dark_oak_pressure_plate", "Dark Oak Pressure Plate"))); + itemNames.add(new ItemName(Material.LIGHT_WEIGHTED_PRESSURE_PLATE, langConfig.getString("block.minecraft.light_weighted_pressure_plate", "Light Weighted Pressure Plate"))); + itemNames.add(new ItemName(Material.HEAVY_WEIGHTED_PRESSURE_PLATE, langConfig.getString("block.minecraft.heavy_weighted_pressure_plate", "Heavy Weighted Pressure Plate"))); + itemNames.add(new ItemName(Material.IRON_DOOR, langConfig.getString("block.minecraft.iron_door", "Iron Door"))); + itemNames.add(new ItemName(Material.REDSTONE_ORE, langConfig.getString("block.minecraft.redstone_ore", "Redstone Ore"))); + itemNames.add(new ItemName(Material.REDSTONE_TORCH, langConfig.getString("block.minecraft.redstone_torch", "Redstone Torch"))); + itemNames.add(new ItemName(Material.REDSTONE_WALL_TORCH, langConfig.getString("block.minecraft.redstone_wall_torch", "Redstone Wall Torch"))); + itemNames.add(new ItemName(Material.STONE_BUTTON, langConfig.getString("block.minecraft.stone_button", "Stone Button"))); + itemNames.add(new ItemName(Material.OAK_BUTTON, langConfig.getString("block.minecraft.oak_button", "Oak Button"))); + itemNames.add(new ItemName(Material.SPRUCE_BUTTON, langConfig.getString("block.minecraft.spruce_button", "Spruce Button"))); + itemNames.add(new ItemName(Material.BIRCH_BUTTON, langConfig.getString("block.minecraft.birch_button", "Birch Button"))); + itemNames.add(new ItemName(Material.JUNGLE_BUTTON, langConfig.getString("block.minecraft.jungle_button", "Jungle Button"))); + itemNames.add(new ItemName(Material.ACACIA_BUTTON, langConfig.getString("block.minecraft.acacia_button", "Acacia Button"))); + itemNames.add(new ItemName(Material.DARK_OAK_BUTTON, langConfig.getString("block.minecraft.dark_oak_button", "Dark Oak Button"))); + itemNames.add(new ItemName(Material.SNOW, langConfig.getString("block.minecraft.snow", "Snow"))); + itemNames.add(new ItemName(Material.WHITE_CARPET, langConfig.getString("block.minecraft.white_carpet", "White Carpet"))); + itemNames.add(new ItemName(Material.ORANGE_CARPET, langConfig.getString("block.minecraft.orange_carpet", "Orange Carpet"))); + itemNames.add(new ItemName(Material.MAGENTA_CARPET, langConfig.getString("block.minecraft.magenta_carpet", "Magenta Carpet"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_CARPET, langConfig.getString("block.minecraft.light_blue_carpet", "Light Blue Carpet"))); + itemNames.add(new ItemName(Material.YELLOW_CARPET, langConfig.getString("block.minecraft.yellow_carpet", "Yellow Carpet"))); + itemNames.add(new ItemName(Material.LIME_CARPET, langConfig.getString("block.minecraft.lime_carpet", "Lime Carpet"))); + itemNames.add(new ItemName(Material.PINK_CARPET, langConfig.getString("block.minecraft.pink_carpet", "Pink Carpet"))); + itemNames.add(new ItemName(Material.GRAY_CARPET, langConfig.getString("block.minecraft.gray_carpet", "Gray Carpet"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_CARPET, langConfig.getString("block.minecraft.light_gray_carpet", "Light Gray Carpet"))); + itemNames.add(new ItemName(Material.CYAN_CARPET, langConfig.getString("block.minecraft.cyan_carpet", "Cyan Carpet"))); + itemNames.add(new ItemName(Material.PURPLE_CARPET, langConfig.getString("block.minecraft.purple_carpet", "Purple Carpet"))); + itemNames.add(new ItemName(Material.BLUE_CARPET, langConfig.getString("block.minecraft.blue_carpet", "Blue Carpet"))); + itemNames.add(new ItemName(Material.BROWN_CARPET, langConfig.getString("block.minecraft.brown_carpet", "Brown Carpet"))); + itemNames.add(new ItemName(Material.GREEN_CARPET, langConfig.getString("block.minecraft.green_carpet", "Green Carpet"))); + itemNames.add(new ItemName(Material.RED_CARPET, langConfig.getString("block.minecraft.red_carpet", "Red Carpet"))); + itemNames.add(new ItemName(Material.BLACK_CARPET, langConfig.getString("block.minecraft.black_carpet", "Black Carpet"))); + itemNames.add(new ItemName(Material.ICE, langConfig.getString("block.minecraft.ice", "Ice"))); + itemNames.add(new ItemName(Material.FROSTED_ICE, langConfig.getString("block.minecraft.frosted_ice", "Frosted Ice"))); + itemNames.add(new ItemName(Material.PACKED_ICE, langConfig.getString("block.minecraft.packed_ice", "Packed Ice"))); + itemNames.add(new ItemName(Material.BLUE_ICE, langConfig.getString("block.minecraft.blue_ice", "Blue Ice"))); + itemNames.add(new ItemName(Material.CACTUS, langConfig.getString("block.minecraft.cactus", "Cactus"))); + itemNames.add(new ItemName(Material.CLAY, langConfig.getString("block.minecraft.clay", "Clay"))); + itemNames.add(new ItemName(Material.WHITE_TERRACOTTA, langConfig.getString("block.minecraft.white_terracotta", "White Terracotta"))); + itemNames.add(new ItemName(Material.ORANGE_TERRACOTTA, langConfig.getString("block.minecraft.orange_terracotta", "Orange Terracotta"))); + itemNames.add(new ItemName(Material.MAGENTA_TERRACOTTA, langConfig.getString("block.minecraft.magenta_terracotta", "Magenta Terracotta"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_TERRACOTTA, langConfig.getString("block.minecraft.light_blue_terracotta", "Light Blue Terracotta"))); + itemNames.add(new ItemName(Material.YELLOW_TERRACOTTA, langConfig.getString("block.minecraft.yellow_terracotta", "Yellow Terracotta"))); + itemNames.add(new ItemName(Material.LIME_TERRACOTTA, langConfig.getString("block.minecraft.lime_terracotta", "Lime Terracotta"))); + itemNames.add(new ItemName(Material.PINK_TERRACOTTA, langConfig.getString("block.minecraft.pink_terracotta", "Pink Terracotta"))); + itemNames.add(new ItemName(Material.GRAY_TERRACOTTA, langConfig.getString("block.minecraft.gray_terracotta", "Gray Terracotta"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_TERRACOTTA, langConfig.getString("block.minecraft.light_gray_terracotta", "Light Gray Terracotta"))); + itemNames.add(new ItemName(Material.CYAN_TERRACOTTA, langConfig.getString("block.minecraft.cyan_terracotta", "Cyan Terracotta"))); + itemNames.add(new ItemName(Material.PURPLE_TERRACOTTA, langConfig.getString("block.minecraft.purple_terracotta", "Purple Terracotta"))); + itemNames.add(new ItemName(Material.BLUE_TERRACOTTA, langConfig.getString("block.minecraft.blue_terracotta", "Blue Terracotta"))); + itemNames.add(new ItemName(Material.BROWN_TERRACOTTA, langConfig.getString("block.minecraft.brown_terracotta", "Brown Terracotta"))); + itemNames.add(new ItemName(Material.GREEN_TERRACOTTA, langConfig.getString("block.minecraft.green_terracotta", "Green Terracotta"))); + itemNames.add(new ItemName(Material.RED_TERRACOTTA, langConfig.getString("block.minecraft.red_terracotta", "Red Terracotta"))); + itemNames.add(new ItemName(Material.BLACK_TERRACOTTA, langConfig.getString("block.minecraft.black_terracotta", "Black Terracotta"))); + itemNames.add(new ItemName(Material.TERRACOTTA, langConfig.getString("block.minecraft.terracotta", "Terracotta"))); + itemNames.add(new ItemName(Material.SUGAR_CANE, langConfig.getString("block.minecraft.sugar_cane", "Sugar Cane"))); + itemNames.add(new ItemName(Material.JUKEBOX, langConfig.getString("block.minecraft.jukebox", "Jukebox"))); + itemNames.add(new ItemName(Material.OAK_FENCE, langConfig.getString("block.minecraft.oak_fence", "Oak Fence"))); + itemNames.add(new ItemName(Material.SPRUCE_FENCE, langConfig.getString("block.minecraft.spruce_fence", "Spruce Fence"))); + itemNames.add(new ItemName(Material.BIRCH_FENCE, langConfig.getString("block.minecraft.birch_fence", "Birch Fence"))); + itemNames.add(new ItemName(Material.JUNGLE_FENCE, langConfig.getString("block.minecraft.jungle_fence", "Jungle Fence"))); + itemNames.add(new ItemName(Material.DARK_OAK_FENCE, langConfig.getString("block.minecraft.dark_oak_fence", "Dark Oak Fence"))); + itemNames.add(new ItemName(Material.ACACIA_FENCE, langConfig.getString("block.minecraft.acacia_fence", "Acacia Fence"))); + itemNames.add(new ItemName(Material.OAK_FENCE_GATE, langConfig.getString("block.minecraft.oak_fence_gate", "Oak Fence Gate"))); + itemNames.add(new ItemName(Material.SPRUCE_FENCE_GATE, langConfig.getString("block.minecraft.spruce_fence_gate", "Spruce Fence Gate"))); + itemNames.add(new ItemName(Material.BIRCH_FENCE_GATE, langConfig.getString("block.minecraft.birch_fence_gate", "Birch Fence Gate"))); + itemNames.add(new ItemName(Material.JUNGLE_FENCE_GATE, langConfig.getString("block.minecraft.jungle_fence_gate", "Jungle Fence Gate"))); + itemNames.add(new ItemName(Material.DARK_OAK_FENCE_GATE, langConfig.getString("block.minecraft.dark_oak_fence_gate", "Dark Oak Fence Gate"))); + itemNames.add(new ItemName(Material.ACACIA_FENCE_GATE, langConfig.getString("block.minecraft.acacia_fence_gate", "Acacia Fence Gate"))); + itemNames.add(new ItemName(Material.PUMPKIN_STEM, langConfig.getString("block.minecraft.pumpkin_stem", "Pumpkin Stem"))); + itemNames.add(new ItemName(Material.ATTACHED_PUMPKIN_STEM, langConfig.getString("block.minecraft.attached_pumpkin_stem", "Attached Pumpkin Stem"))); + itemNames.add(new ItemName(Material.PUMPKIN, langConfig.getString("block.minecraft.pumpkin", "Pumpkin"))); + itemNames.add(new ItemName(Material.CARVED_PUMPKIN, langConfig.getString("block.minecraft.carved_pumpkin", "Carved Pumpkin"))); + itemNames.add(new ItemName(Material.JACK_O_LANTERN, langConfig.getString("block.minecraft.jack_o_lantern", "Jack o'Lantern"))); + itemNames.add(new ItemName(Material.NETHERRACK, langConfig.getString("block.minecraft.netherrack", "Netherrack"))); + itemNames.add(new ItemName(Material.SOUL_SAND, langConfig.getString("block.minecraft.soul_sand", "Soul Sand"))); + itemNames.add(new ItemName(Material.GLOWSTONE, langConfig.getString("block.minecraft.glowstone", "Glowstone"))); + itemNames.add(new ItemName(Material.NETHER_PORTAL, langConfig.getString("block.minecraft.nether_portal", "Nether Portal"))); + itemNames.add(new ItemName(Material.WHITE_WOOL, langConfig.getString("block.minecraft.white_wool", "White Wool"))); + itemNames.add(new ItemName(Material.ORANGE_WOOL, langConfig.getString("block.minecraft.orange_wool", "Orange Wool"))); + itemNames.add(new ItemName(Material.MAGENTA_WOOL, langConfig.getString("block.minecraft.magenta_wool", "Magenta Wool"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_WOOL, langConfig.getString("block.minecraft.light_blue_wool", "Light Blue Wool"))); + itemNames.add(new ItemName(Material.YELLOW_WOOL, langConfig.getString("block.minecraft.yellow_wool", "Yellow Wool"))); + itemNames.add(new ItemName(Material.LIME_WOOL, langConfig.getString("block.minecraft.lime_wool", "Lime Wool"))); + itemNames.add(new ItemName(Material.PINK_WOOL, langConfig.getString("block.minecraft.pink_wool", "Pink Wool"))); + itemNames.add(new ItemName(Material.GRAY_WOOL, langConfig.getString("block.minecraft.gray_wool", "Gray Wool"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_WOOL, langConfig.getString("block.minecraft.light_gray_wool", "Light Gray Wool"))); + itemNames.add(new ItemName(Material.CYAN_WOOL, langConfig.getString("block.minecraft.cyan_wool", "Cyan Wool"))); + itemNames.add(new ItemName(Material.PURPLE_WOOL, langConfig.getString("block.minecraft.purple_wool", "Purple Wool"))); + itemNames.add(new ItemName(Material.BLUE_WOOL, langConfig.getString("block.minecraft.blue_wool", "Blue Wool"))); + itemNames.add(new ItemName(Material.BROWN_WOOL, langConfig.getString("block.minecraft.brown_wool", "Brown Wool"))); + itemNames.add(new ItemName(Material.GREEN_WOOL, langConfig.getString("block.minecraft.green_wool", "Green Wool"))); + itemNames.add(new ItemName(Material.RED_WOOL, langConfig.getString("block.minecraft.red_wool", "Red Wool"))); + itemNames.add(new ItemName(Material.BLACK_WOOL, langConfig.getString("block.minecraft.black_wool", "Black Wool"))); + itemNames.add(new ItemName(Material.LAPIS_ORE, langConfig.getString("block.minecraft.lapis_ore", "Lapis Lazuli Ore"))); + itemNames.add(new ItemName(Material.LAPIS_BLOCK, langConfig.getString("block.minecraft.lapis_block", "Lapis Lazuli Block"))); + itemNames.add(new ItemName(Material.DISPENSER, langConfig.getString("block.minecraft.dispenser", "Dispenser"))); + itemNames.add(new ItemName(Material.DROPPER, langConfig.getString("block.minecraft.dropper", "Dropper"))); + itemNames.add(new ItemName(Material.NOTE_BLOCK, langConfig.getString("block.minecraft.note_block", "Note Block"))); + itemNames.add(new ItemName(Material.CAKE, langConfig.getString("block.minecraft.cake", "Cake"))); + itemNames.add(new ItemName(Material.OAK_TRAPDOOR, langConfig.getString("block.minecraft.oak_trapdoor", "Oak Trapdoor"))); + itemNames.add(new ItemName(Material.SPRUCE_TRAPDOOR, langConfig.getString("block.minecraft.spruce_trapdoor", "Spruce Trapdoor"))); + itemNames.add(new ItemName(Material.BIRCH_TRAPDOOR, langConfig.getString("block.minecraft.birch_trapdoor", "Birch Trapdoor"))); + itemNames.add(new ItemName(Material.JUNGLE_TRAPDOOR, langConfig.getString("block.minecraft.jungle_trapdoor", "Jungle Trapdoor"))); + itemNames.add(new ItemName(Material.ACACIA_TRAPDOOR, langConfig.getString("block.minecraft.acacia_trapdoor", "Acacia Trapdoor"))); + itemNames.add(new ItemName(Material.DARK_OAK_TRAPDOOR, langConfig.getString("block.minecraft.dark_oak_trapdoor", "Dark Oak Trapdoor"))); + itemNames.add(new ItemName(Material.IRON_TRAPDOOR, langConfig.getString("block.minecraft.iron_trapdoor", "Iron Trapdoor"))); + itemNames.add(new ItemName(Material.COBWEB, langConfig.getString("block.minecraft.cobweb", "Cobweb"))); + itemNames.add(new ItemName(Material.STONE_BRICKS, langConfig.getString("block.minecraft.stone_bricks", "Stone Bricks"))); + itemNames.add(new ItemName(Material.MOSSY_STONE_BRICKS, langConfig.getString("block.minecraft.mossy_stone_bricks", "Mossy Stone Bricks"))); + itemNames.add(new ItemName(Material.CRACKED_STONE_BRICKS, langConfig.getString("block.minecraft.cracked_stone_bricks", "Cracked Stone Bricks"))); + itemNames.add(new ItemName(Material.CHISELED_STONE_BRICKS, langConfig.getString("block.minecraft.chiseled_stone_bricks", "Chiseled Stone Bricks"))); + itemNames.add(new ItemName(Material.INFESTED_STONE, langConfig.getString("block.minecraft.infested_stone", "Infested Stone"))); + itemNames.add(new ItemName(Material.INFESTED_COBBLESTONE, langConfig.getString("block.minecraft.infested_cobblestone", "Infested Cobblestone"))); + itemNames.add(new ItemName(Material.INFESTED_STONE_BRICKS, langConfig.getString("block.minecraft.infested_stone_bricks", "Infested Stone Bricks"))); + itemNames.add(new ItemName(Material.INFESTED_MOSSY_STONE_BRICKS, langConfig.getString("block.minecraft.infested_mossy_stone_bricks", "Infested Mossy Stone Bricks"))); + itemNames.add(new ItemName(Material.INFESTED_CRACKED_STONE_BRICKS, langConfig.getString("block.minecraft.infested_cracked_stone_bricks", "Infested Cracked Stone Bricks"))); + itemNames.add(new ItemName(Material.INFESTED_CHISELED_STONE_BRICKS, langConfig.getString("block.minecraft.infested_chiseled_stone_bricks", "Infested Chiseled Stone Bricks"))); + itemNames.add(new ItemName(Material.PISTON, langConfig.getString("block.minecraft.piston", "Piston"))); + itemNames.add(new ItemName(Material.STICKY_PISTON, langConfig.getString("block.minecraft.sticky_piston", "Sticky Piston"))); + itemNames.add(new ItemName(Material.IRON_BARS, langConfig.getString("block.minecraft.iron_bars", "Iron Bars"))); + itemNames.add(new ItemName(Material.MELON, langConfig.getString("block.minecraft.melon", "Melon"))); + itemNames.add(new ItemName(Material.BRICK_STAIRS, langConfig.getString("block.minecraft.brick_stairs", "Brick Stairs"))); + itemNames.add(new ItemName(Material.STONE_BRICK_STAIRS, langConfig.getString("block.minecraft.stone_brick_stairs", "Stone Brick Stairs"))); + itemNames.add(new ItemName(Material.VINE, langConfig.getString("block.minecraft.vine", "Vines"))); + itemNames.add(new ItemName(Material.NETHER_BRICKS, langConfig.getString("block.minecraft.nether_bricks", "Nether Bricks"))); + itemNames.add(new ItemName(Material.NETHER_BRICK_FENCE, langConfig.getString("block.minecraft.nether_brick_fence", "Nether Brick Fence"))); + itemNames.add(new ItemName(Material.NETHER_BRICK_STAIRS, langConfig.getString("block.minecraft.nether_brick_stairs", "Nether Brick Stairs"))); + itemNames.add(new ItemName(Material.NETHER_WART, langConfig.getString("block.minecraft.nether_wart", "Nether Wart"))); + itemNames.add(new ItemName(Material.CAULDRON, langConfig.getString("block.minecraft.cauldron", "Cauldron"))); + itemNames.add(new ItemName(Material.ENCHANTING_TABLE, langConfig.getString("block.minecraft.enchanting_table", "Enchanting Table"))); + itemNames.add(new ItemName(Material.ANVIL, langConfig.getString("block.minecraft.anvil", "Anvil"))); + itemNames.add(new ItemName(Material.CHIPPED_ANVIL, langConfig.getString("block.minecraft.chipped_anvil", "Chipped Anvil"))); + itemNames.add(new ItemName(Material.DAMAGED_ANVIL, langConfig.getString("block.minecraft.damaged_anvil", "Damaged Anvil"))); + itemNames.add(new ItemName(Material.END_STONE, langConfig.getString("block.minecraft.end_stone", "End Stone"))); + itemNames.add(new ItemName(Material.END_PORTAL_FRAME, langConfig.getString("block.minecraft.end_portal_frame", "End Portal Frame"))); + itemNames.add(new ItemName(Material.MYCELIUM, langConfig.getString("block.minecraft.mycelium", "Mycelium"))); + itemNames.add(new ItemName(Material.LILY_PAD, langConfig.getString("block.minecraft.lily_pad", "Lily Pad"))); + itemNames.add(new ItemName(Material.DRAGON_EGG, langConfig.getString("block.minecraft.dragon_egg", "Dragon Egg"))); + itemNames.add(new ItemName(Material.REDSTONE_LAMP, langConfig.getString("block.minecraft.redstone_lamp", "Redstone Lamp"))); + itemNames.add(new ItemName(Material.COCOA, langConfig.getString("block.minecraft.cocoa", "Cocoa"))); + itemNames.add(new ItemName(Material.ENDER_CHEST, langConfig.getString("block.minecraft.ender_chest", "Ender Chest"))); + itemNames.add(new ItemName(Material.EMERALD_ORE, langConfig.getString("block.minecraft.emerald_ore", "Emerald Ore"))); + itemNames.add(new ItemName(Material.EMERALD_BLOCK, langConfig.getString("block.minecraft.emerald_block", "Block of Emerald"))); + itemNames.add(new ItemName(Material.REDSTONE_BLOCK, langConfig.getString("block.minecraft.redstone_block", "Block of Redstone"))); + itemNames.add(new ItemName(Material.TRIPWIRE, langConfig.getString("block.minecraft.tripwire", "Tripwire"))); + itemNames.add(new ItemName(Material.TRIPWIRE_HOOK, langConfig.getString("block.minecraft.tripwire_hook", "Tripwire Hook"))); + itemNames.add(new ItemName(Material.COMMAND_BLOCK, langConfig.getString("block.minecraft.command_block", "Command Block"))); + itemNames.add(new ItemName(Material.REPEATING_COMMAND_BLOCK, langConfig.getString("block.minecraft.repeating_command_block", "Repeating Command Block"))); + itemNames.add(new ItemName(Material.CHAIN_COMMAND_BLOCK, langConfig.getString("block.minecraft.chain_command_block", "Chain Command Block"))); + itemNames.add(new ItemName(Material.BEACON, langConfig.getString("block.minecraft.beacon", "Beacon"))); + itemNames.add(new ItemName(Material.COBBLESTONE_WALL, langConfig.getString("block.minecraft.cobblestone_wall", "Cobblestone Wall"))); + itemNames.add(new ItemName(Material.MOSSY_COBBLESTONE_WALL, langConfig.getString("block.minecraft.mossy_cobblestone_wall", "Mossy Cobblestone Wall"))); + itemNames.add(new ItemName(Material.CARROTS, langConfig.getString("block.minecraft.carrots", "Carrots"))); + itemNames.add(new ItemName(Material.POTATOES, langConfig.getString("block.minecraft.potatoes", "Potatoes"))); + itemNames.add(new ItemName(Material.DAYLIGHT_DETECTOR, langConfig.getString("block.minecraft.daylight_detector", "Daylight Detector"))); + itemNames.add(new ItemName(Material.NETHER_QUARTZ_ORE, langConfig.getString("block.minecraft.nether_quartz_ore", "Nether Quartz Ore"))); + itemNames.add(new ItemName(Material.HOPPER, langConfig.getString("block.minecraft.hopper", "Hopper"))); + itemNames.add(new ItemName(Material.QUARTZ_BLOCK, langConfig.getString("block.minecraft.quartz_block", "Block of Quartz"))); + itemNames.add(new ItemName(Material.CHISELED_QUARTZ_BLOCK, langConfig.getString("block.minecraft.chiseled_quartz_block", "Chiseled Quartz Block"))); + itemNames.add(new ItemName(Material.QUARTZ_PILLAR, langConfig.getString("block.minecraft.quartz_pillar", "Quartz Pillar"))); + itemNames.add(new ItemName(Material.QUARTZ_STAIRS, langConfig.getString("block.minecraft.quartz_stairs", "Quartz Stairs"))); + itemNames.add(new ItemName(Material.SLIME_BLOCK, langConfig.getString("block.minecraft.slime_block", "Slime Block"))); + itemNames.add(new ItemName(Material.PRISMARINE, langConfig.getString("block.minecraft.prismarine", "Prismarine"))); + itemNames.add(new ItemName(Material.PRISMARINE_BRICKS, langConfig.getString("block.minecraft.prismarine_bricks", "Prismarine Bricks"))); + itemNames.add(new ItemName(Material.DARK_PRISMARINE, langConfig.getString("block.minecraft.dark_prismarine", "Dark Prismarine"))); + itemNames.add(new ItemName(Material.SEA_LANTERN, langConfig.getString("block.minecraft.sea_lantern", "Sea Lantern"))); + itemNames.add(new ItemName(Material.END_ROD, langConfig.getString("block.minecraft.end_rod", "End Rod"))); + itemNames.add(new ItemName(Material.CHORUS_PLANT, langConfig.getString("block.minecraft.chorus_plant", "Chorus Plant"))); + itemNames.add(new ItemName(Material.CHORUS_FLOWER, langConfig.getString("block.minecraft.chorus_flower", "Chorus Flower"))); + itemNames.add(new ItemName(Material.PURPUR_BLOCK, langConfig.getString("block.minecraft.purpur_block", "Purpur Block"))); + itemNames.add(new ItemName(Material.PURPUR_PILLAR, langConfig.getString("block.minecraft.purpur_pillar", "Purpur Pillar"))); + itemNames.add(new ItemName(Material.PURPUR_STAIRS, langConfig.getString("block.minecraft.purpur_stairs", "Purpur Stairs"))); + itemNames.add(new ItemName(Material.PURPUR_SLAB, langConfig.getString("block.minecraft.purpur_slab", "Purpur Slab"))); + itemNames.add(new ItemName(Material.END_STONE_BRICKS, langConfig.getString("block.minecraft.end_stone_bricks", "End Stone Bricks"))); + itemNames.add(new ItemName(Material.BEETROOTS, langConfig.getString("block.minecraft.beetroots", "Beetroots"))); + itemNames.add(new ItemName(Material.MAGMA_BLOCK, langConfig.getString("block.minecraft.magma_block", "Magma Block"))); + itemNames.add(new ItemName(Material.NETHER_WART_BLOCK, langConfig.getString("block.minecraft.nether_wart_block", "Nether Wart Block"))); + itemNames.add(new ItemName(Material.RED_NETHER_BRICKS, langConfig.getString("block.minecraft.red_nether_bricks", "Red Nether Bricks"))); + itemNames.add(new ItemName(Material.BONE_BLOCK, langConfig.getString("block.minecraft.bone_block", "Bone Block"))); + itemNames.add(new ItemName(Material.OBSERVER, langConfig.getString("block.minecraft.observer", "Observer"))); + itemNames.add(new ItemName(Material.SHULKER_BOX, langConfig.getString("block.minecraft.shulker_box", "Shulker Box"))); + itemNames.add(new ItemName(Material.WHITE_SHULKER_BOX, langConfig.getString("block.minecraft.white_shulker_box", "White Shulker Box"))); + itemNames.add(new ItemName(Material.ORANGE_SHULKER_BOX, langConfig.getString("block.minecraft.orange_shulker_box", "Orange Shulker Box"))); + itemNames.add(new ItemName(Material.MAGENTA_SHULKER_BOX, langConfig.getString("block.minecraft.magenta_shulker_box", "Magenta Shulker Box"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_SHULKER_BOX, langConfig.getString("block.minecraft.light_blue_shulker_box", "Light Blue Shulker Box"))); + itemNames.add(new ItemName(Material.YELLOW_SHULKER_BOX, langConfig.getString("block.minecraft.yellow_shulker_box", "Yellow Shulker Box"))); + itemNames.add(new ItemName(Material.LIME_SHULKER_BOX, langConfig.getString("block.minecraft.lime_shulker_box", "Lime Shulker Box"))); + itemNames.add(new ItemName(Material.PINK_SHULKER_BOX, langConfig.getString("block.minecraft.pink_shulker_box", "Pink Shulker Box"))); + itemNames.add(new ItemName(Material.GRAY_SHULKER_BOX, langConfig.getString("block.minecraft.gray_shulker_box", "Gray Shulker Box"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_SHULKER_BOX, langConfig.getString("block.minecraft.light_gray_shulker_box", "Light Gray Shulker Box"))); + itemNames.add(new ItemName(Material.CYAN_SHULKER_BOX, langConfig.getString("block.minecraft.cyan_shulker_box", "Cyan Shulker Box"))); + itemNames.add(new ItemName(Material.PURPLE_SHULKER_BOX, langConfig.getString("block.minecraft.purple_shulker_box", "Purple Shulker Box"))); + itemNames.add(new ItemName(Material.BLUE_SHULKER_BOX, langConfig.getString("block.minecraft.blue_shulker_box", "Blue Shulker Box"))); + itemNames.add(new ItemName(Material.BROWN_SHULKER_BOX, langConfig.getString("block.minecraft.brown_shulker_box", "Brown Shulker Box"))); + itemNames.add(new ItemName(Material.GREEN_SHULKER_BOX, langConfig.getString("block.minecraft.green_shulker_box", "Green Shulker Box"))); + itemNames.add(new ItemName(Material.RED_SHULKER_BOX, langConfig.getString("block.minecraft.red_shulker_box", "Red Shulker Box"))); + itemNames.add(new ItemName(Material.BLACK_SHULKER_BOX, langConfig.getString("block.minecraft.black_shulker_box", "Black Shulker Box"))); + itemNames.add(new ItemName(Material.WHITE_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.white_glazed_terracotta", "White Glazed Terracotta"))); + itemNames.add(new ItemName(Material.ORANGE_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.orange_glazed_terracotta", "Orange Glazed Terracotta"))); + itemNames.add(new ItemName(Material.MAGENTA_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.magenta_glazed_terracotta", "Magenta Glazed Terracotta"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.light_blue_glazed_terracotta", "Light Blue Glazed Terracotta"))); + itemNames.add(new ItemName(Material.YELLOW_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.yellow_glazed_terracotta", "Yellow Glazed Terracotta"))); + itemNames.add(new ItemName(Material.LIME_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.lime_glazed_terracotta", "Lime Glazed Terracotta"))); + itemNames.add(new ItemName(Material.PINK_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.pink_glazed_terracotta", "Pink Glazed Terracotta"))); + itemNames.add(new ItemName(Material.GRAY_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.gray_glazed_terracotta", "Gray Glazed Terracotta"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.light_gray_glazed_terracotta", "Light Gray Glazed Terracotta"))); + itemNames.add(new ItemName(Material.CYAN_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.cyan_glazed_terracotta", "Cyan Glazed Terracotta"))); + itemNames.add(new ItemName(Material.PURPLE_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.purple_glazed_terracotta", "Purple Glazed Terracotta"))); + itemNames.add(new ItemName(Material.BLUE_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.blue_glazed_terracotta", "Blue Glazed Terracotta"))); + itemNames.add(new ItemName(Material.BROWN_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.brown_glazed_terracotta", "Brown Glazed Terracotta"))); + itemNames.add(new ItemName(Material.GREEN_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.green_glazed_terracotta", "Green Glazed Terracotta"))); + itemNames.add(new ItemName(Material.RED_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.red_glazed_terracotta", "Red Glazed Terracotta"))); + itemNames.add(new ItemName(Material.BLACK_GLAZED_TERRACOTTA, langConfig.getString("block.minecraft.black_glazed_terracotta", "Black Glazed Terracotta"))); + itemNames.add(new ItemName(Material.BLACK_CONCRETE, langConfig.getString("block.minecraft.black_concrete", "Black Concrete"))); + itemNames.add(new ItemName(Material.RED_CONCRETE, langConfig.getString("block.minecraft.red_concrete", "Red Concrete"))); + itemNames.add(new ItemName(Material.GREEN_CONCRETE, langConfig.getString("block.minecraft.green_concrete", "Green Concrete"))); + itemNames.add(new ItemName(Material.BROWN_CONCRETE, langConfig.getString("block.minecraft.brown_concrete", "Brown Concrete"))); + itemNames.add(new ItemName(Material.BLUE_CONCRETE, langConfig.getString("block.minecraft.blue_concrete", "Blue Concrete"))); + itemNames.add(new ItemName(Material.PURPLE_CONCRETE, langConfig.getString("block.minecraft.purple_concrete", "Purple Concrete"))); + itemNames.add(new ItemName(Material.CYAN_CONCRETE, langConfig.getString("block.minecraft.cyan_concrete", "Cyan Concrete"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_CONCRETE, langConfig.getString("block.minecraft.light_gray_concrete", "Light Gray Concrete"))); + itemNames.add(new ItemName(Material.GRAY_CONCRETE, langConfig.getString("block.minecraft.gray_concrete", "Gray Concrete"))); + itemNames.add(new ItemName(Material.PINK_CONCRETE, langConfig.getString("block.minecraft.pink_concrete", "Pink Concrete"))); + itemNames.add(new ItemName(Material.LIME_CONCRETE, langConfig.getString("block.minecraft.lime_concrete", "Lime Concrete"))); + itemNames.add(new ItemName(Material.YELLOW_CONCRETE, langConfig.getString("block.minecraft.yellow_concrete", "Yellow Concrete"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_CONCRETE, langConfig.getString("block.minecraft.light_blue_concrete", "Light Blue Concrete"))); + itemNames.add(new ItemName(Material.MAGENTA_CONCRETE, langConfig.getString("block.minecraft.magenta_concrete", "Magenta Concrete"))); + itemNames.add(new ItemName(Material.ORANGE_CONCRETE, langConfig.getString("block.minecraft.orange_concrete", "Orange Concrete"))); + itemNames.add(new ItemName(Material.WHITE_CONCRETE, langConfig.getString("block.minecraft.white_concrete", "White Concrete"))); + itemNames.add(new ItemName(Material.BLACK_CONCRETE_POWDER, langConfig.getString("block.minecraft.black_concrete_powder", "Black Concrete Powder"))); + itemNames.add(new ItemName(Material.RED_CONCRETE_POWDER, langConfig.getString("block.minecraft.red_concrete_powder", "Red Concrete Powder"))); + itemNames.add(new ItemName(Material.GREEN_CONCRETE_POWDER, langConfig.getString("block.minecraft.green_concrete_powder", "Green Concrete Powder"))); + itemNames.add(new ItemName(Material.BROWN_CONCRETE_POWDER, langConfig.getString("block.minecraft.brown_concrete_powder", "Brown Concrete Powder"))); + itemNames.add(new ItemName(Material.BLUE_CONCRETE_POWDER, langConfig.getString("block.minecraft.blue_concrete_powder", "Blue Concrete Powder"))); + itemNames.add(new ItemName(Material.PURPLE_CONCRETE_POWDER, langConfig.getString("block.minecraft.purple_concrete_powder", "Purple Concrete Powder"))); + itemNames.add(new ItemName(Material.CYAN_CONCRETE_POWDER, langConfig.getString("block.minecraft.cyan_concrete_powder", "Cyan Concrete Powder"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_CONCRETE_POWDER, langConfig.getString("block.minecraft.light_gray_concrete_powder", "Light Gray Concrete Powder"))); + itemNames.add(new ItemName(Material.GRAY_CONCRETE_POWDER, langConfig.getString("block.minecraft.gray_concrete_powder", "Gray Concrete Powder"))); + itemNames.add(new ItemName(Material.PINK_CONCRETE_POWDER, langConfig.getString("block.minecraft.pink_concrete_powder", "Pink Concrete Powder"))); + itemNames.add(new ItemName(Material.LIME_CONCRETE_POWDER, langConfig.getString("block.minecraft.lime_concrete_powder", "Lime Concrete Powder"))); + itemNames.add(new ItemName(Material.YELLOW_CONCRETE_POWDER, langConfig.getString("block.minecraft.yellow_concrete_powder", "Yellow Concrete Powder"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_CONCRETE_POWDER, langConfig.getString("block.minecraft.light_blue_concrete_powder", "Light Blue Concrete Powder"))); + itemNames.add(new ItemName(Material.MAGENTA_CONCRETE_POWDER, langConfig.getString("block.minecraft.magenta_concrete_powder", "Magenta Concrete Powder"))); + itemNames.add(new ItemName(Material.ORANGE_CONCRETE_POWDER, langConfig.getString("block.minecraft.orange_concrete_powder", "Orange Concrete Powder"))); + itemNames.add(new ItemName(Material.WHITE_CONCRETE_POWDER, langConfig.getString("block.minecraft.white_concrete_powder", "White Concrete Powder"))); + itemNames.add(new ItemName(Material.TURTLE_EGG, langConfig.getString("block.minecraft.turtle_egg", "Turtle Egg"))); + itemNames.add(new ItemName(Material.PISTON_HEAD, langConfig.getString("block.minecraft.piston_head", "Piston Head"))); + itemNames.add(new ItemName(Material.MOVING_PISTON, langConfig.getString("block.minecraft.moving_piston", "Moving Piston"))); + itemNames.add(new ItemName(Material.RED_MUSHROOM, langConfig.getString("block.minecraft.red_mushroom", "Red Mushroom"))); + itemNames.add(new ItemName(Material.SNOW_BLOCK, langConfig.getString("block.minecraft.snow_block", "Snow Block"))); + itemNames.add(new ItemName(Material.ATTACHED_MELON_STEM, langConfig.getString("block.minecraft.attached_melon_stem", "Attached Melon Stem"))); + itemNames.add(new ItemName(Material.MELON_STEM, langConfig.getString("block.minecraft.melon_stem", "Melon Stem"))); + itemNames.add(new ItemName(Material.BREWING_STAND, langConfig.getString("block.minecraft.brewing_stand", "Brewing Stand"))); + itemNames.add(new ItemName(Material.END_PORTAL, langConfig.getString("block.minecraft.end_portal", "End Portal"))); + itemNames.add(new ItemName(Material.FLOWER_POT, langConfig.getString("block.minecraft.flower_pot", "Flower Pot"))); + itemNames.add(new ItemName(Material.POTTED_OAK_SAPLING, langConfig.getString("block.minecraft.potted_oak_sapling", "Potted Oak Sapling"))); + itemNames.add(new ItemName(Material.POTTED_SPRUCE_SAPLING, langConfig.getString("block.minecraft.potted_spruce_sapling", "Potted Spruce Sapling"))); + itemNames.add(new ItemName(Material.POTTED_BIRCH_SAPLING, langConfig.getString("block.minecraft.potted_birch_sapling", "Potted Birch Sapling"))); + itemNames.add(new ItemName(Material.POTTED_JUNGLE_SAPLING, langConfig.getString("block.minecraft.potted_jungle_sapling", "Potted Jungle Sapling"))); + itemNames.add(new ItemName(Material.POTTED_ACACIA_SAPLING, langConfig.getString("block.minecraft.potted_acacia_sapling", "Potted Acacia Sapling"))); + itemNames.add(new ItemName(Material.POTTED_DARK_OAK_SAPLING, langConfig.getString("block.minecraft.potted_dark_oak_sapling", "Potted Dark Oak Sapling"))); + itemNames.add(new ItemName(Material.POTTED_FERN, langConfig.getString("block.minecraft.potted_fern", "Potted Fern"))); + itemNames.add(new ItemName(Material.POTTED_DANDELION, langConfig.getString("block.minecraft.potted_dandelion", "Potted Dandelion"))); + itemNames.add(new ItemName(Material.POTTED_POPPY, langConfig.getString("block.minecraft.potted_poppy", "Potted Poppy"))); + itemNames.add(new ItemName(Material.POTTED_BLUE_ORCHID, langConfig.getString("block.minecraft.potted_blue_orchid", "Potted Blue Orchid"))); + itemNames.add(new ItemName(Material.POTTED_ALLIUM, langConfig.getString("block.minecraft.potted_allium", "Potted Allium"))); + itemNames.add(new ItemName(Material.POTTED_AZURE_BLUET, langConfig.getString("block.minecraft.potted_azure_bluet", "Potted Azure Bluet"))); + itemNames.add(new ItemName(Material.POTTED_RED_TULIP, langConfig.getString("block.minecraft.potted_red_tulip", "Potted Red Tulip"))); + itemNames.add(new ItemName(Material.POTTED_ORANGE_TULIP, langConfig.getString("block.minecraft.potted_orange_tulip", "Potted Orange Tulip"))); + itemNames.add(new ItemName(Material.POTTED_WHITE_TULIP, langConfig.getString("block.minecraft.potted_white_tulip", "Potted White Tulip"))); + itemNames.add(new ItemName(Material.POTTED_PINK_TULIP, langConfig.getString("block.minecraft.potted_pink_tulip", "Potted Pink Tulip"))); + itemNames.add(new ItemName(Material.POTTED_OXEYE_DAISY, langConfig.getString("block.minecraft.potted_oxeye_daisy", "Potted Oxeye Daisy"))); + itemNames.add(new ItemName(Material.POTTED_RED_MUSHROOM, langConfig.getString("block.minecraft.potted_red_mushroom", "Potted Red Mushroom"))); + itemNames.add(new ItemName(Material.POTTED_BROWN_MUSHROOM, langConfig.getString("block.minecraft.potted_brown_mushroom", "Potted Brown Mushroom"))); + itemNames.add(new ItemName(Material.POTTED_DEAD_BUSH, langConfig.getString("block.minecraft.potted_dead_bush", "Potted Dead Bush"))); + itemNames.add(new ItemName(Material.POTTED_CACTUS, langConfig.getString("block.minecraft.potted_cactus", "Potted Cactus"))); + itemNames.add(new ItemName(Material.SKELETON_WALL_SKULL, langConfig.getString("block.minecraft.skeleton_wall_skull", "Skeleton Wall Skull"))); + itemNames.add(new ItemName(Material.SKELETON_SKULL, langConfig.getString("block.minecraft.skeleton_skull", "Skeleton Skull"))); + itemNames.add(new ItemName(Material.WITHER_SKELETON_WALL_SKULL, langConfig.getString("block.minecraft.wither_skeleton_wall_skull", "Wither Skeleton Wall Skull"))); + itemNames.add(new ItemName(Material.WITHER_SKELETON_SKULL, langConfig.getString("block.minecraft.wither_skeleton_skull", "Wither Skeleton Skull"))); + itemNames.add(new ItemName(Material.ZOMBIE_WALL_HEAD, langConfig.getString("block.minecraft.zombie_wall_head", "Zombie Wall Head"))); + itemNames.add(new ItemName(Material.ZOMBIE_HEAD, langConfig.getString("block.minecraft.zombie_head", "Zombie Head"))); + itemNames.add(new ItemName(Material.PLAYER_WALL_HEAD, langConfig.getString("block.minecraft.player_wall_head", "Player Wall Head"))); + itemNames.add(new ItemName(Material.PLAYER_HEAD, langConfig.getString("block.minecraft.player_head", "Player Head"))); + itemNames.add(new ItemName(Material.CREEPER_WALL_HEAD, langConfig.getString("block.minecraft.creeper_wall_head", "Creeper Wall Head"))); + itemNames.add(new ItemName(Material.CREEPER_HEAD, langConfig.getString("block.minecraft.creeper_head", "Creeper Head"))); + itemNames.add(new ItemName(Material.DRAGON_WALL_HEAD, langConfig.getString("block.minecraft.dragon_wall_head", "Dragon Wall Head"))); + itemNames.add(new ItemName(Material.DRAGON_HEAD, langConfig.getString("block.minecraft.dragon_head", "Dragon Head"))); + itemNames.add(new ItemName(Material.END_GATEWAY, langConfig.getString("block.minecraft.end_gateway", "End Gateway"))); + itemNames.add(new ItemName(Material.STRUCTURE_VOID, langConfig.getString("block.minecraft.structure_void", "Structure Void"))); + itemNames.add(new ItemName(Material.STRUCTURE_BLOCK, langConfig.getString("block.minecraft.structure_block", "Structure Block"))); + itemNames.add(new ItemName(Material.VOID_AIR, langConfig.getString("block.minecraft.void_air", "Void Air"))); + itemNames.add(new ItemName(Material.CAVE_AIR, langConfig.getString("block.minecraft.cave_air", "Cave Air"))); + itemNames.add(new ItemName(Material.BUBBLE_COLUMN, langConfig.getString("block.minecraft.bubble_column", "Bubble Column"))); + itemNames.add(new ItemName(Material.DEAD_TUBE_CORAL_BLOCK, langConfig.getString("block.minecraft.dead_tube_coral_block", "Dead Tube Coral Block"))); + itemNames.add(new ItemName(Material.DEAD_BRAIN_CORAL_BLOCK, langConfig.getString("block.minecraft.dead_brain_coral_block", "Dead Brain Coral Block"))); + itemNames.add(new ItemName(Material.DEAD_BUBBLE_CORAL_BLOCK, langConfig.getString("block.minecraft.dead_bubble_coral_block", "Dead Bubble Coral Block"))); + itemNames.add(new ItemName(Material.DEAD_FIRE_CORAL_BLOCK, langConfig.getString("block.minecraft.dead_fire_coral_block", "Dead Fire Coral Block"))); + itemNames.add(new ItemName(Material.DEAD_HORN_CORAL_BLOCK, langConfig.getString("block.minecraft.dead_horn_coral_block", "Dead Horn Coral Block"))); + itemNames.add(new ItemName(Material.TUBE_CORAL_BLOCK, langConfig.getString("block.minecraft.tube_coral_block", "Tube Coral Block"))); + itemNames.add(new ItemName(Material.BRAIN_CORAL_BLOCK, langConfig.getString("block.minecraft.brain_coral_block", "Brain Coral Block"))); + itemNames.add(new ItemName(Material.BUBBLE_CORAL_BLOCK, langConfig.getString("block.minecraft.bubble_coral_block", "Bubble Coral Block"))); + itemNames.add(new ItemName(Material.FIRE_CORAL_BLOCK, langConfig.getString("block.minecraft.fire_coral_block", "Fire Coral Block"))); + itemNames.add(new ItemName(Material.HORN_CORAL_BLOCK, langConfig.getString("block.minecraft.horn_coral_block", "Horn Coral Block"))); + itemNames.add(new ItemName(Material.TUBE_CORAL, langConfig.getString("block.minecraft.tube_coral", "Tube Coral"))); + itemNames.add(new ItemName(Material.BRAIN_CORAL, langConfig.getString("block.minecraft.brain_coral", "Brain Coral"))); + itemNames.add(new ItemName(Material.BUBBLE_CORAL, langConfig.getString("block.minecraft.bubble_coral", "Bubble Coral"))); + itemNames.add(new ItemName(Material.FIRE_CORAL, langConfig.getString("block.minecraft.fire_coral", "Fire Coral"))); + itemNames.add(new ItemName(Material.HORN_CORAL, langConfig.getString("block.minecraft.horn_coral", "Horn Coral"))); + itemNames.add(new ItemName(Material.TUBE_CORAL_FAN, langConfig.getString("block.minecraft.tube_coral_fan", "Tube Coral Fan"))); + itemNames.add(new ItemName(Material.BRAIN_CORAL_FAN, langConfig.getString("block.minecraft.brain_coral_fan", "Brain Coral Fan"))); + itemNames.add(new ItemName(Material.BUBBLE_CORAL_FAN, langConfig.getString("block.minecraft.bubble_coral_fan", "Bubble Coral Fan"))); + itemNames.add(new ItemName(Material.FIRE_CORAL_FAN, langConfig.getString("block.minecraft.fire_coral_fan", "Fire Coral Fan"))); + itemNames.add(new ItemName(Material.HORN_CORAL_FAN, langConfig.getString("block.minecraft.horn_coral_fan", "Horn Coral Fan"))); + itemNames.add(new ItemName(Material.CONDUIT, langConfig.getString("block.minecraft.conduit", "Conduit"))); + itemNames.add(new ItemName(Material.NAME_TAG, langConfig.getString("item.minecraft.name_tag", "Name Tag"))); + itemNames.add(new ItemName(Material.LEAD, langConfig.getString("item.minecraft.lead", "Lead"))); + itemNames.add(new ItemName(Material.IRON_SHOVEL, langConfig.getString("item.minecraft.iron_shovel", "Iron Shovel"))); + itemNames.add(new ItemName(Material.IRON_PICKAXE, langConfig.getString("item.minecraft.iron_pickaxe", "Iron Pickaxe"))); + itemNames.add(new ItemName(Material.IRON_AXE, langConfig.getString("item.minecraft.iron_axe", "Iron Axe"))); + itemNames.add(new ItemName(Material.FLINT_AND_STEEL, langConfig.getString("item.minecraft.flint_and_steel", "Flint and Steel"))); + itemNames.add(new ItemName(Material.APPLE, langConfig.getString("item.minecraft.apple", "Apple"))); + itemNames.add(new ItemName(Material.COOKIE, langConfig.getString("item.minecraft.cookie", "Cookie"))); + itemNames.add(new ItemName(Material.BOW, langConfig.getString("item.minecraft.bow", "Bow"))); + itemNames.add(new ItemName(Material.ARROW, langConfig.getString("item.minecraft.arrow", "Arrow"))); + itemNames.add(new ItemName(Material.SPECTRAL_ARROW, langConfig.getString("item.minecraft.spectral_arrow", "Spectral Arrow"))); + itemNames.add(new ItemName(Material.TIPPED_ARROW, langConfig.getString("item.minecraft.tipped_arrow", "Tipped Arrow"))); + itemNames.add(new ItemName(Material.DRIED_KELP, langConfig.getString("item.minecraft.dried_kelp", "Dried Kelp"))); + itemNames.add(new ItemName(Material.COAL, langConfig.getString("item.minecraft.coal", "Coal"))); + itemNames.add(new ItemName(Material.CHARCOAL, langConfig.getString("item.minecraft.charcoal", "Charcoal"))); + itemNames.add(new ItemName(Material.DIAMOND, langConfig.getString("item.minecraft.diamond", "Diamond"))); + itemNames.add(new ItemName(Material.EMERALD, langConfig.getString("item.minecraft.emerald", "Emerald"))); + itemNames.add(new ItemName(Material.IRON_INGOT, langConfig.getString("item.minecraft.iron_ingot", "Iron Ingot"))); + itemNames.add(new ItemName(Material.GOLD_INGOT, langConfig.getString("item.minecraft.gold_ingot", "Gold Ingot"))); + itemNames.add(new ItemName(Material.IRON_SWORD, langConfig.getString("item.minecraft.iron_sword", "Iron Sword"))); + itemNames.add(new ItemName(Material.WOODEN_SWORD, langConfig.getString("item.minecraft.wooden_sword", "Wooden Sword"))); + itemNames.add(new ItemName(Material.WOODEN_SHOVEL, langConfig.getString("item.minecraft.wooden_shovel", "Wooden Shovel"))); + itemNames.add(new ItemName(Material.WOODEN_PICKAXE, langConfig.getString("item.minecraft.wooden_pickaxe", "Wooden Pickaxe"))); + itemNames.add(new ItemName(Material.WOODEN_AXE, langConfig.getString("item.minecraft.wooden_axe", "Wooden Axe"))); + itemNames.add(new ItemName(Material.STONE_SWORD, langConfig.getString("item.minecraft.stone_sword", "Stone Sword"))); + itemNames.add(new ItemName(Material.STONE_SHOVEL, langConfig.getString("item.minecraft.stone_shovel", "Stone Shovel"))); + itemNames.add(new ItemName(Material.STONE_PICKAXE, langConfig.getString("item.minecraft.stone_pickaxe", "Stone Pickaxe"))); + itemNames.add(new ItemName(Material.STONE_AXE, langConfig.getString("item.minecraft.stone_axe", "Stone Axe"))); + itemNames.add(new ItemName(Material.DIAMOND_SWORD, langConfig.getString("item.minecraft.diamond_sword", "Diamond Sword"))); + itemNames.add(new ItemName(Material.DIAMOND_SHOVEL, langConfig.getString("item.minecraft.diamond_shovel", "Diamond Shovel"))); + itemNames.add(new ItemName(Material.DIAMOND_PICKAXE, langConfig.getString("item.minecraft.diamond_pickaxe", "Diamond Pickaxe"))); + itemNames.add(new ItemName(Material.DIAMOND_AXE, langConfig.getString("item.minecraft.diamond_axe", "Diamond Axe"))); + itemNames.add(new ItemName(Material.STICK, langConfig.getString("item.minecraft.stick", "Stick"))); + itemNames.add(new ItemName(Material.BOWL, langConfig.getString("item.minecraft.bowl", "Bowl"))); + itemNames.add(new ItemName(Material.MUSHROOM_STEW, langConfig.getString("item.minecraft.mushroom_stew", "Mushroom Stew"))); + itemNames.add(new ItemName(Material.GOLDEN_SWORD, langConfig.getString("item.minecraft.golden_sword", "Golden Sword"))); + itemNames.add(new ItemName(Material.GOLDEN_SHOVEL, langConfig.getString("item.minecraft.golden_shovel", "Golden Shovel"))); + itemNames.add(new ItemName(Material.GOLDEN_PICKAXE, langConfig.getString("item.minecraft.golden_pickaxe", "Golden Pickaxe"))); + itemNames.add(new ItemName(Material.GOLDEN_AXE, langConfig.getString("item.minecraft.golden_axe", "Golden Axe"))); + itemNames.add(new ItemName(Material.STRING, langConfig.getString("item.minecraft.string", "String"))); + itemNames.add(new ItemName(Material.FEATHER, langConfig.getString("item.minecraft.feather", "Feather"))); + itemNames.add(new ItemName(Material.GUNPOWDER, langConfig.getString("item.minecraft.gunpowder", "Gunpowder"))); + itemNames.add(new ItemName(Material.WOODEN_HOE, langConfig.getString("item.minecraft.wooden_hoe", "Wooden Hoe"))); + itemNames.add(new ItemName(Material.STONE_HOE, langConfig.getString("item.minecraft.stone_hoe", "Stone Hoe"))); + itemNames.add(new ItemName(Material.IRON_HOE, langConfig.getString("item.minecraft.iron_hoe", "Iron Hoe"))); + itemNames.add(new ItemName(Material.DIAMOND_HOE, langConfig.getString("item.minecraft.diamond_hoe", "Diamond Hoe"))); + itemNames.add(new ItemName(Material.GOLDEN_HOE, langConfig.getString("item.minecraft.golden_hoe", "Golden Hoe"))); + itemNames.add(new ItemName(Material.WHEAT_SEEDS, langConfig.getString("item.minecraft.wheat_seeds", "Wheat Seeds"))); + itemNames.add(new ItemName(Material.PUMPKIN_SEEDS, langConfig.getString("item.minecraft.pumpkin_seeds", "Pumpkin Seeds"))); + itemNames.add(new ItemName(Material.MELON_SEEDS, langConfig.getString("item.minecraft.melon_seeds", "Melon Seeds"))); + itemNames.add(new ItemName(Material.MELON_SLICE, langConfig.getString("item.minecraft.melon_slice", "Melon Slice"))); + itemNames.add(new ItemName(Material.WHEAT, langConfig.getString("item.minecraft.wheat", "Wheat"))); + itemNames.add(new ItemName(Material.BREAD, langConfig.getString("item.minecraft.bread", "Bread"))); + itemNames.add(new ItemName(Material.LEATHER_HELMET, langConfig.getString("item.minecraft.leather_helmet", "Leather Cap"))); + itemNames.add(new ItemName(Material.LEATHER_CHESTPLATE, langConfig.getString("item.minecraft.leather_chestplate", "Leather Tunic"))); + itemNames.add(new ItemName(Material.LEATHER_LEGGINGS, langConfig.getString("item.minecraft.leather_leggings", "Leather Pants"))); + itemNames.add(new ItemName(Material.LEATHER_BOOTS, langConfig.getString("item.minecraft.leather_boots", "Leather Boots"))); + itemNames.add(new ItemName(Material.CHAINMAIL_HELMET, langConfig.getString("item.minecraft.chainmail_helmet", "Chainmail Helmet"))); + itemNames.add(new ItemName(Material.CHAINMAIL_CHESTPLATE, langConfig.getString("item.minecraft.chainmail_chestplate", "Chainmail Chestplate"))); + itemNames.add(new ItemName(Material.CHAINMAIL_LEGGINGS, langConfig.getString("item.minecraft.chainmail_leggings", "Chainmail Leggings"))); + itemNames.add(new ItemName(Material.CHAINMAIL_BOOTS, langConfig.getString("item.minecraft.chainmail_boots", "Chainmail Boots"))); + itemNames.add(new ItemName(Material.IRON_HELMET, langConfig.getString("item.minecraft.iron_helmet", "Iron Helmet"))); + itemNames.add(new ItemName(Material.IRON_CHESTPLATE, langConfig.getString("item.minecraft.iron_chestplate", "Iron Chestplate"))); + itemNames.add(new ItemName(Material.IRON_LEGGINGS, langConfig.getString("item.minecraft.iron_leggings", "Iron Leggings"))); + itemNames.add(new ItemName(Material.IRON_BOOTS, langConfig.getString("item.minecraft.iron_boots", "Iron Boots"))); + itemNames.add(new ItemName(Material.DIAMOND_HELMET, langConfig.getString("item.minecraft.diamond_helmet", "Diamond Helmet"))); + itemNames.add(new ItemName(Material.DIAMOND_CHESTPLATE, langConfig.getString("item.minecraft.diamond_chestplate", "Diamond Chestplate"))); + itemNames.add(new ItemName(Material.DIAMOND_LEGGINGS, langConfig.getString("item.minecraft.diamond_leggings", "Diamond Leggings"))); + itemNames.add(new ItemName(Material.DIAMOND_BOOTS, langConfig.getString("item.minecraft.diamond_boots", "Diamond Boots"))); + itemNames.add(new ItemName(Material.GOLDEN_HELMET, langConfig.getString("item.minecraft.golden_helmet", "Golden Helmet"))); + itemNames.add(new ItemName(Material.GOLDEN_CHESTPLATE, langConfig.getString("item.minecraft.golden_chestplate", "Golden Chestplate"))); + itemNames.add(new ItemName(Material.GOLDEN_LEGGINGS, langConfig.getString("item.minecraft.golden_leggings", "Golden Leggings"))); + itemNames.add(new ItemName(Material.GOLDEN_BOOTS, langConfig.getString("item.minecraft.golden_boots", "Golden Boots"))); + itemNames.add(new ItemName(Material.FLINT, langConfig.getString("item.minecraft.flint", "Flint"))); + itemNames.add(new ItemName(Material.PORKCHOP, langConfig.getString("item.minecraft.porkchop", "Raw Porkchop"))); + itemNames.add(new ItemName(Material.COOKED_PORKCHOP, langConfig.getString("item.minecraft.cooked_porkchop", "Cooked Porkchop"))); + itemNames.add(new ItemName(Material.CHICKEN, langConfig.getString("item.minecraft.chicken", "Raw Chicken"))); + itemNames.add(new ItemName(Material.COOKED_CHICKEN, langConfig.getString("item.minecraft.cooked_chicken", "Cooked Chicken"))); + itemNames.add(new ItemName(Material.MUTTON, langConfig.getString("item.minecraft.mutton", "Raw Mutton"))); + itemNames.add(new ItemName(Material.COOKED_MUTTON, langConfig.getString("item.minecraft.cooked_mutton", "Cooked Mutton"))); + itemNames.add(new ItemName(Material.RABBIT, langConfig.getString("item.minecraft.rabbit", "Raw Rabbit"))); + itemNames.add(new ItemName(Material.COOKED_RABBIT, langConfig.getString("item.minecraft.cooked_rabbit", "Cooked Rabbit"))); + itemNames.add(new ItemName(Material.RABBIT_STEW, langConfig.getString("item.minecraft.rabbit_stew", "Rabbit Stew"))); + itemNames.add(new ItemName(Material.RABBIT_FOOT, langConfig.getString("item.minecraft.rabbit_foot", "Rabbit's Foot"))); + itemNames.add(new ItemName(Material.RABBIT_HIDE, langConfig.getString("item.minecraft.rabbit_hide", "Rabbit Hide"))); + itemNames.add(new ItemName(Material.BEEF, langConfig.getString("item.minecraft.beef", "Raw Beef"))); + itemNames.add(new ItemName(Material.COOKED_BEEF, langConfig.getString("item.minecraft.cooked_beef", "Steak"))); + itemNames.add(new ItemName(Material.PAINTING, langConfig.getString("item.minecraft.painting", "Painting"))); + itemNames.add(new ItemName(Material.ITEM_FRAME, langConfig.getString("item.minecraft.item_frame", "Item Frame"))); + itemNames.add(new ItemName(Material.GOLDEN_APPLE, langConfig.getString("item.minecraft.golden_apple", "Golden Apple"))); + itemNames.add(new ItemName(Material.ENCHANTED_GOLDEN_APPLE, langConfig.getString("item.minecraft.enchanted_golden_apple", "Enchanted Golden Apple"))); + itemNames.add(new ItemName(Material.BUCKET, langConfig.getString("item.minecraft.bucket", "Bucket"))); + itemNames.add(new ItemName(Material.WATER_BUCKET, langConfig.getString("item.minecraft.water_bucket", "Water Bucket"))); + itemNames.add(new ItemName(Material.LAVA_BUCKET, langConfig.getString("item.minecraft.lava_bucket", "Lava Bucket"))); + itemNames.add(new ItemName(Material.PUFFERFISH_BUCKET, langConfig.getString("item.minecraft.pufferfish_bucket", "Bucket of Pufferfish"))); + itemNames.add(new ItemName(Material.SALMON_BUCKET, langConfig.getString("item.minecraft.salmon_bucket", "Bucket of Salmon"))); + itemNames.add(new ItemName(Material.COD_BUCKET, langConfig.getString("item.minecraft.cod_bucket", "Bucket of Cod"))); + itemNames.add(new ItemName(Material.TROPICAL_FISH_BUCKET, langConfig.getString("item.minecraft.tropical_fish_bucket", "Bucket of Tropical Fish"))); + itemNames.add(new ItemName(Material.MINECART, langConfig.getString("item.minecraft.minecart", "Minecart"))); + itemNames.add(new ItemName(Material.SADDLE, langConfig.getString("item.minecraft.saddle", "Saddle"))); + itemNames.add(new ItemName(Material.REDSTONE, langConfig.getString("item.minecraft.redstone", "Redstone"))); + itemNames.add(new ItemName(Material.SNOWBALL, langConfig.getString("item.minecraft.snowball", "Snowball"))); + itemNames.add(new ItemName(Material.OAK_BOAT, langConfig.getString("item.minecraft.oak_boat", "Oak Boat"))); + itemNames.add(new ItemName(Material.SPRUCE_BOAT, langConfig.getString("item.minecraft.spruce_boat", "Spruce Boat"))); + itemNames.add(new ItemName(Material.BIRCH_BOAT, langConfig.getString("item.minecraft.birch_boat", "Birch Boat"))); + itemNames.add(new ItemName(Material.JUNGLE_BOAT, langConfig.getString("item.minecraft.jungle_boat", "Jungle Boat"))); + itemNames.add(new ItemName(Material.ACACIA_BOAT, langConfig.getString("item.minecraft.acacia_boat", "Acacia Boat"))); + itemNames.add(new ItemName(Material.DARK_OAK_BOAT, langConfig.getString("item.minecraft.dark_oak_boat", "Dark Oak Boat"))); + itemNames.add(new ItemName(Material.LEATHER, langConfig.getString("item.minecraft.leather", "Leather"))); + itemNames.add(new ItemName(Material.MILK_BUCKET, langConfig.getString("item.minecraft.milk_bucket", "Milk Bucket"))); + itemNames.add(new ItemName(Material.BRICK, langConfig.getString("item.minecraft.brick", "Brick"))); + itemNames.add(new ItemName(Material.CLAY, langConfig.getString("item.minecraft.clay_ball", "Clay"))); + itemNames.add(new ItemName(Material.PAPER, langConfig.getString("item.minecraft.paper", "Paper"))); + itemNames.add(new ItemName(Material.BOOK, langConfig.getString("item.minecraft.book", "Book"))); + itemNames.add(new ItemName(Material.SLIME_BALL, langConfig.getString("item.minecraft.slime_ball", "Slimeball"))); + itemNames.add(new ItemName(Material.CHEST_MINECART, langConfig.getString("item.minecraft.chest_minecart", "Minecart with Chest"))); + itemNames.add(new ItemName(Material.FURNACE_MINECART, langConfig.getString("item.minecraft.furnace_minecart", "Minecart with Furnace"))); + itemNames.add(new ItemName(Material.TNT_MINECART, langConfig.getString("item.minecraft.tnt_minecart", "Minecart with TNT"))); + itemNames.add(new ItemName(Material.HOPPER_MINECART, langConfig.getString("item.minecraft.hopper_minecart", "Minecart with Hopper"))); + itemNames.add(new ItemName(Material.COMMAND_BLOCK_MINECART, langConfig.getString("item.minecraft.command_block_minecart", "Minecart with Command Block"))); + itemNames.add(new ItemName(Material.EGG, langConfig.getString("item.minecraft.egg", "Egg"))); + itemNames.add(new ItemName(Material.COMPASS, langConfig.getString("item.minecraft.compass", "Compass"))); + itemNames.add(new ItemName(Material.FISHING_ROD, langConfig.getString("item.minecraft.fishing_rod", "Fishing Rod"))); + itemNames.add(new ItemName(Material.CLOCK, langConfig.getString("item.minecraft.clock", "Clock"))); + itemNames.add(new ItemName(Material.GLOWSTONE_DUST, langConfig.getString("item.minecraft.glowstone_dust", "Glowstone Dust"))); + itemNames.add(new ItemName(Material.COD, langConfig.getString("item.minecraft.cod", "Raw Cod"))); + itemNames.add(new ItemName(Material.SALMON, langConfig.getString("item.minecraft.salmon", "Raw Salmon"))); + itemNames.add(new ItemName(Material.PUFFERFISH, langConfig.getString("item.minecraft.pufferfish", "Pufferfish"))); + itemNames.add(new ItemName(Material.TROPICAL_FISH, langConfig.getString("item.minecraft.tropical_fish", "Tropical Fish"))); + itemNames.add(new ItemName(Material.COOKED_COD, langConfig.getString("item.minecraft.cooked_cod", "Cooked Cod"))); + itemNames.add(new ItemName(Material.COOKED_SALMON, langConfig.getString("item.minecraft.cooked_salmon", "Cooked Salmon"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_13, langConfig.getString("item.minecraft.music_disc_13", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_CAT, langConfig.getString("item.minecraft.music_disc_cat", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_BLOCKS, langConfig.getString("item.minecraft.music_disc_blocks", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_CHIRP, langConfig.getString("item.minecraft.music_disc_chirp", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_FAR, langConfig.getString("item.minecraft.music_disc_far", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_MALL, langConfig.getString("item.minecraft.music_disc_mall", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_MELLOHI, langConfig.getString("item.minecraft.music_disc_mellohi", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_STAL, langConfig.getString("item.minecraft.music_disc_stal", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_STRAD, langConfig.getString("item.minecraft.music_disc_strad", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_WARD, langConfig.getString("item.minecraft.music_disc_ward", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_11, langConfig.getString("item.minecraft.music_disc_11", "Music Disc"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_WAIT, langConfig.getString("item.minecraft.music_disc_wait", "Music Disc"))); + itemNames.add(new ItemName(Material.BONE, langConfig.getString("item.minecraft.bone", "Bone"))); + itemNames.add(new ItemName(Material.INK_SAC, langConfig.getString("item.minecraft.ink_sac", "Ink Sac"))); + itemNames.add(new ItemName(Material.COCOA_BEANS, langConfig.getString("item.minecraft.cocoa_beans", "Cocoa Beans"))); + itemNames.add(new ItemName(Material.LAPIS_LAZULI, langConfig.getString("item.minecraft.lapis_lazuli", "Lapis Lazuli"))); + itemNames.add(new ItemName(Material.PURPLE_DYE, langConfig.getString("item.minecraft.purple_dye", "Purple Dye"))); + itemNames.add(new ItemName(Material.CYAN_DYE, langConfig.getString("item.minecraft.cyan_dye", "Cyan Dye"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_DYE, langConfig.getString("item.minecraft.light_gray_dye", "Light Gray Dye"))); + itemNames.add(new ItemName(Material.GRAY_DYE, langConfig.getString("item.minecraft.gray_dye", "Gray Dye"))); + itemNames.add(new ItemName(Material.PINK_DYE, langConfig.getString("item.minecraft.pink_dye", "Pink Dye"))); + itemNames.add(new ItemName(Material.LIME_DYE, langConfig.getString("item.minecraft.lime_dye", "Lime Dye"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_DYE, langConfig.getString("item.minecraft.light_blue_dye", "Light Blue Dye"))); + itemNames.add(new ItemName(Material.MAGENTA_DYE, langConfig.getString("item.minecraft.magenta_dye", "Magenta Dye"))); + itemNames.add(new ItemName(Material.ORANGE_DYE, langConfig.getString("item.minecraft.orange_dye", "Orange Dye"))); + itemNames.add(new ItemName(Material.BONE_MEAL, langConfig.getString("item.minecraft.bone_meal", "Bone Meal"))); + itemNames.add(new ItemName(Material.SUGAR, langConfig.getString("item.minecraft.sugar", "Sugar"))); + itemNames.add(new ItemName(Material.BLACK_BED, langConfig.getString("block.minecraft.black_bed", "Black Bed"))); + itemNames.add(new ItemName(Material.RED_BED, langConfig.getString("block.minecraft.red_bed", "Red Bed"))); + itemNames.add(new ItemName(Material.GREEN_BED, langConfig.getString("block.minecraft.green_bed", "Green Bed"))); + itemNames.add(new ItemName(Material.BROWN_BED, langConfig.getString("block.minecraft.brown_bed", "Brown Bed"))); + itemNames.add(new ItemName(Material.BLUE_BED, langConfig.getString("block.minecraft.blue_bed", "Blue Bed"))); + itemNames.add(new ItemName(Material.PURPLE_BED, langConfig.getString("block.minecraft.purple_bed", "Purple Bed"))); + itemNames.add(new ItemName(Material.CYAN_BED, langConfig.getString("block.minecraft.cyan_bed", "Cyan Bed"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_BED, langConfig.getString("block.minecraft.light_gray_bed", "Light Gray Bed"))); + itemNames.add(new ItemName(Material.GRAY_BED, langConfig.getString("block.minecraft.gray_bed", "Gray Bed"))); + itemNames.add(new ItemName(Material.PINK_BED, langConfig.getString("block.minecraft.pink_bed", "Pink Bed"))); + itemNames.add(new ItemName(Material.LIME_BED, langConfig.getString("block.minecraft.lime_bed", "Lime Bed"))); + itemNames.add(new ItemName(Material.YELLOW_BED, langConfig.getString("block.minecraft.yellow_bed", "Yellow Bed"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_BED, langConfig.getString("block.minecraft.light_blue_bed", "Light Blue Bed"))); + itemNames.add(new ItemName(Material.MAGENTA_BED, langConfig.getString("block.minecraft.magenta_bed", "Magenta Bed"))); + itemNames.add(new ItemName(Material.ORANGE_BED, langConfig.getString("block.minecraft.orange_bed", "Orange Bed"))); + itemNames.add(new ItemName(Material.WHITE_BED, langConfig.getString("block.minecraft.white_bed", "White Bed"))); + itemNames.add(new ItemName(Material.REPEATER, langConfig.getString("block.minecraft.repeater", "Redstone Repeater"))); + itemNames.add(new ItemName(Material.COMPARATOR, langConfig.getString("block.minecraft.comparator", "Redstone Comparator"))); + itemNames.add(new ItemName(Material.MAP, langConfig.getString("item.minecraft.filled_map", "Map"))); + itemNames.add(new ItemName(Material.SHEARS, langConfig.getString("item.minecraft.shears", "Shears"))); + itemNames.add(new ItemName(Material.ROTTEN_FLESH, langConfig.getString("item.minecraft.rotten_flesh", "Rotten Flesh"))); + itemNames.add(new ItemName(Material.ENDER_PEARL, langConfig.getString("item.minecraft.ender_pearl", "Ender Pearl"))); + itemNames.add(new ItemName(Material.BLAZE_ROD, langConfig.getString("item.minecraft.blaze_rod", "Blaze Rod"))); + itemNames.add(new ItemName(Material.GHAST_TEAR, langConfig.getString("item.minecraft.ghast_tear", "Ghast Tear"))); + itemNames.add(new ItemName(Material.NETHER_WART, langConfig.getString("item.minecraft.nether_wart", "Nether Wart"))); + itemNames.add(new ItemName(Material.POTION, langConfig.getString("item.minecraft.potion", "Potion"))); + itemNames.add(new ItemName(Material.SPLASH_POTION, langConfig.getString("item.minecraft.splash_potion", "Splash Potion"))); + itemNames.add(new ItemName(Material.LINGERING_POTION, langConfig.getString("item.minecraft.lingering_potion", "Lingering Potion"))); + itemNames.add(new ItemName(Material.END_CRYSTAL, langConfig.getString("item.minecraft.end_crystal", "End Crystal"))); + itemNames.add(new ItemName(Material.GOLD_NUGGET, langConfig.getString("item.minecraft.gold_nugget", "Gold Nugget"))); + itemNames.add(new ItemName(Material.GLASS_BOTTLE, langConfig.getString("item.minecraft.glass_bottle", "Glass Bottle"))); + itemNames.add(new ItemName(Material.SPIDER_EYE, langConfig.getString("item.minecraft.spider_eye", "Spider Eye"))); + itemNames.add(new ItemName(Material.FERMENTED_SPIDER_EYE, langConfig.getString("item.minecraft.fermented_spider_eye", "Fermented Spider Eye"))); + itemNames.add(new ItemName(Material.BLAZE_POWDER, langConfig.getString("item.minecraft.blaze_powder", "Blaze Powder"))); + itemNames.add(new ItemName(Material.MAGMA_CREAM, langConfig.getString("item.minecraft.magma_cream", "Magma Cream"))); + itemNames.add(new ItemName(Material.CAULDRON, langConfig.getString("item.minecraft.cauldron", "Cauldron"))); + itemNames.add(new ItemName(Material.BREWING_STAND, langConfig.getString("item.minecraft.brewing_stand", "Brewing Stand"))); + itemNames.add(new ItemName(Material.ENDER_EYE, langConfig.getString("item.minecraft.ender_eye", "Eye of Ender"))); + itemNames.add(new ItemName(Material.GLISTERING_MELON_SLICE, langConfig.getString("item.minecraft.glistering_melon_slice", "Glistering Melon Slice"))); + itemNames.add(new ItemName(Material.BAT_SPAWN_EGG, langConfig.getString("item.minecraft.bat_spawn_egg", "Bat Spawn Egg"))); + itemNames.add(new ItemName(Material.BLAZE_SPAWN_EGG, langConfig.getString("item.minecraft.blaze_spawn_egg", "Blaze Spawn Egg"))); + itemNames.add(new ItemName(Material.CAVE_SPIDER_SPAWN_EGG, langConfig.getString("item.minecraft.cave_spider_spawn_egg", "Cave Spider Spawn Egg"))); + itemNames.add(new ItemName(Material.CHICKEN_SPAWN_EGG, langConfig.getString("item.minecraft.chicken_spawn_egg", "Chicken Spawn Egg"))); + itemNames.add(new ItemName(Material.COD_SPAWN_EGG, langConfig.getString("item.minecraft.cod_spawn_egg", "Cod Spawn Egg"))); + itemNames.add(new ItemName(Material.COW_SPAWN_EGG, langConfig.getString("item.minecraft.cow_spawn_egg", "Cow Spawn Egg"))); + itemNames.add(new ItemName(Material.CREEPER_SPAWN_EGG, langConfig.getString("item.minecraft.creeper_spawn_egg", "Creeper Spawn Egg"))); + itemNames.add(new ItemName(Material.DOLPHIN_SPAWN_EGG, langConfig.getString("item.minecraft.dolphin_spawn_egg", "Dolphin Spawn Egg"))); + itemNames.add(new ItemName(Material.DONKEY_SPAWN_EGG, langConfig.getString("item.minecraft.donkey_spawn_egg", "Donkey Spawn Egg"))); + itemNames.add(new ItemName(Material.DROWNED_SPAWN_EGG, langConfig.getString("item.minecraft.drowned_spawn_egg", "Drowned Spawn Egg"))); + itemNames.add(new ItemName(Material.ELDER_GUARDIAN_SPAWN_EGG, langConfig.getString("item.minecraft.elder_guardian_spawn_egg", "Elder Guardian Spawn Egg"))); + itemNames.add(new ItemName(Material.ENDERMAN_SPAWN_EGG, langConfig.getString("item.minecraft.enderman_spawn_egg", "Enderman Spawn Egg"))); + itemNames.add(new ItemName(Material.ENDERMITE_SPAWN_EGG, langConfig.getString("item.minecraft.endermite_spawn_egg", "Endermite Spawn Egg"))); + itemNames.add(new ItemName(Material.EVOKER_SPAWN_EGG, langConfig.getString("item.minecraft.evoker_spawn_egg", "Evoker Spawn Egg"))); + itemNames.add(new ItemName(Material.GHAST_SPAWN_EGG, langConfig.getString("item.minecraft.ghast_spawn_egg", "Ghast Spawn Egg"))); + itemNames.add(new ItemName(Material.GUARDIAN_SPAWN_EGG, langConfig.getString("item.minecraft.guardian_spawn_egg", "Guardian Spawn Egg"))); + itemNames.add(new ItemName(Material.HORSE_SPAWN_EGG, langConfig.getString("item.minecraft.horse_spawn_egg", "Horse Spawn Egg"))); + itemNames.add(new ItemName(Material.HUSK_SPAWN_EGG, langConfig.getString("item.minecraft.husk_spawn_egg", "Husk Spawn Egg"))); + itemNames.add(new ItemName(Material.LLAMA_SPAWN_EGG, langConfig.getString("item.minecraft.llama_spawn_egg", "Llama Spawn Egg"))); + itemNames.add(new ItemName(Material.MAGMA_CUBE_SPAWN_EGG, langConfig.getString("item.minecraft.magma_cube_spawn_egg", "Magma Cube Spawn Egg"))); + itemNames.add(new ItemName(Material.MOOSHROOM_SPAWN_EGG, langConfig.getString("item.minecraft.mooshroom_spawn_egg", "Mooshroom Spawn Egg"))); + itemNames.add(new ItemName(Material.MULE_SPAWN_EGG, langConfig.getString("item.minecraft.mule_spawn_egg", "Mule Spawn Egg"))); + itemNames.add(new ItemName(Material.OCELOT_SPAWN_EGG, langConfig.getString("item.minecraft.ocelot_spawn_egg", "Ocelot Spawn Egg"))); + itemNames.add(new ItemName(Material.PARROT_SPAWN_EGG, langConfig.getString("item.minecraft.parrot_spawn_egg", "Parrot Spawn Egg"))); + itemNames.add(new ItemName(Material.PIG_SPAWN_EGG, langConfig.getString("item.minecraft.pig_spawn_egg", "Pig Spawn Egg"))); + itemNames.add(new ItemName(Material.PHANTOM_SPAWN_EGG, langConfig.getString("item.minecraft.phantom_spawn_egg", "Phantom Spawn Egg"))); + itemNames.add(new ItemName(Material.POLAR_BEAR_SPAWN_EGG, langConfig.getString("item.minecraft.polar_bear_spawn_egg", "Polar Bear Spawn Egg"))); + itemNames.add(new ItemName(Material.PUFFERFISH_SPAWN_EGG, langConfig.getString("item.minecraft.pufferfish_spawn_egg", "Pufferfish Spawn Egg"))); + itemNames.add(new ItemName(Material.RABBIT_SPAWN_EGG, langConfig.getString("item.minecraft.rabbit_spawn_egg", "Rabbit Spawn Egg"))); + itemNames.add(new ItemName(Material.SALMON_SPAWN_EGG, langConfig.getString("item.minecraft.salmon_spawn_egg", "Salmon Spawn Egg"))); + itemNames.add(new ItemName(Material.SHEEP_SPAWN_EGG, langConfig.getString("item.minecraft.sheep_spawn_egg", "Sheep Spawn Egg"))); + itemNames.add(new ItemName(Material.SHULKER_SPAWN_EGG, langConfig.getString("item.minecraft.shulker_spawn_egg", "Shulker Spawn Egg"))); + itemNames.add(new ItemName(Material.SILVERFISH_SPAWN_EGG, langConfig.getString("item.minecraft.silverfish_spawn_egg", "Silverfish Spawn Egg"))); + itemNames.add(new ItemName(Material.SKELETON_SPAWN_EGG, langConfig.getString("item.minecraft.skeleton_spawn_egg", "Skeleton Spawn Egg"))); + itemNames.add(new ItemName(Material.SKELETON_HORSE_SPAWN_EGG, langConfig.getString("item.minecraft.skeleton_horse_spawn_egg", "Skeleton Horse Spawn Egg"))); + itemNames.add(new ItemName(Material.SLIME_SPAWN_EGG, langConfig.getString("item.minecraft.slime_spawn_egg", "Slime Spawn Egg"))); + itemNames.add(new ItemName(Material.SPIDER_SPAWN_EGG, langConfig.getString("item.minecraft.spider_spawn_egg", "Spider Spawn Egg"))); + itemNames.add(new ItemName(Material.SQUID_SPAWN_EGG, langConfig.getString("item.minecraft.squid_spawn_egg", "Squid Spawn Egg"))); + itemNames.add(new ItemName(Material.STRAY_SPAWN_EGG, langConfig.getString("item.minecraft.stray_spawn_egg", "Stray Spawn Egg"))); + itemNames.add(new ItemName(Material.TROPICAL_FISH_SPAWN_EGG, langConfig.getString("item.minecraft.tropical_fish_spawn_egg", "Tropical Fish Spawn Egg"))); + itemNames.add(new ItemName(Material.TURTLE_SPAWN_EGG, langConfig.getString("item.minecraft.turtle_spawn_egg", "Turtle Spawn Egg"))); + itemNames.add(new ItemName(Material.VEX_SPAWN_EGG, langConfig.getString("item.minecraft.vex_spawn_egg", "Vex Spawn Egg"))); + itemNames.add(new ItemName(Material.VILLAGER_SPAWN_EGG, langConfig.getString("item.minecraft.villager_spawn_egg", "Villager Spawn Egg"))); + itemNames.add(new ItemName(Material.VINDICATOR_SPAWN_EGG, langConfig.getString("item.minecraft.vindicator_spawn_egg", "Vindicator Spawn Egg"))); + itemNames.add(new ItemName(Material.WITCH_SPAWN_EGG, langConfig.getString("item.minecraft.witch_spawn_egg", "Witch Spawn Egg"))); + itemNames.add(new ItemName(Material.WITHER_SKELETON_SPAWN_EGG, langConfig.getString("item.minecraft.wither_skeleton_spawn_egg", "Wither Skeleton Spawn Egg"))); + itemNames.add(new ItemName(Material.WOLF_SPAWN_EGG, langConfig.getString("item.minecraft.wolf_spawn_egg", "Wolf Spawn Egg"))); + itemNames.add(new ItemName(Material.ZOMBIE_SPAWN_EGG, langConfig.getString("item.minecraft.zombie_spawn_egg", "Zombie Spawn Egg"))); + itemNames.add(new ItemName(Material.ZOMBIE_HORSE_SPAWN_EGG, langConfig.getString("item.minecraft.zombie_horse_spawn_egg", "Zombie Horse Spawn Egg"))); + itemNames.add(new ItemName(Material.ZOMBIE_VILLAGER_SPAWN_EGG, langConfig.getString("item.minecraft.zombie_villager_spawn_egg", "Zombie Villager Spawn Egg"))); + itemNames.add(new ItemName(Material.EXPERIENCE_BOTTLE, langConfig.getString("item.minecraft.experience_bottle", "Bottle o' Enchanting"))); + itemNames.add(new ItemName(Material.FIRE_CHARGE, langConfig.getString("item.minecraft.fire_charge", "Fire Charge"))); + itemNames.add(new ItemName(Material.WRITABLE_BOOK, langConfig.getString("item.minecraft.writable_book", "Book and Quill"))); + itemNames.add(new ItemName(Material.WRITTEN_BOOK, langConfig.getString("item.minecraft.written_book", "Written Book"))); + itemNames.add(new ItemName(Material.FLOWER_POT, langConfig.getString("item.minecraft.flower_pot", "Flower Pot"))); + itemNames.add(new ItemName(Material.MAP, langConfig.getString("item.minecraft.map", "Empty Map"))); + itemNames.add(new ItemName(Material.CARROT, langConfig.getString("item.minecraft.carrot", "Carrot"))); + itemNames.add(new ItemName(Material.GOLDEN_CARROT, langConfig.getString("item.minecraft.golden_carrot", "Golden Carrot"))); + itemNames.add(new ItemName(Material.POTATO, langConfig.getString("item.minecraft.potato", "Potato"))); + itemNames.add(new ItemName(Material.BAKED_POTATO, langConfig.getString("item.minecraft.baked_potato", "Baked Potato"))); + itemNames.add(new ItemName(Material.POISONOUS_POTATO, langConfig.getString("item.minecraft.poisonous_potato", "Poisonous Potato"))); + itemNames.add(new ItemName(Material.SKELETON_SKULL, langConfig.getString("item.minecraft.skeleton_skull", "Skeleton Skull"))); + itemNames.add(new ItemName(Material.WITHER_SKELETON_SKULL, langConfig.getString("item.minecraft.wither_skeleton_skull", "Wither Skeleton Skull"))); + itemNames.add(new ItemName(Material.ZOMBIE_HEAD, langConfig.getString("item.minecraft.zombie_head", "Zombie Head"))); + itemNames.add(new ItemName(Material.CREEPER_HEAD, langConfig.getString("item.minecraft.creeper_head", "Creeper Head"))); + itemNames.add(new ItemName(Material.DRAGON_HEAD, langConfig.getString("item.minecraft.dragon_head", "Dragon Head"))); + itemNames.add(new ItemName(Material.CARROT_ON_A_STICK, langConfig.getString("item.minecraft.carrot_on_a_stick", "Carrot on a Stick"))); + itemNames.add(new ItemName(Material.NETHER_STAR, langConfig.getString("item.minecraft.nether_star", "Nether Star"))); + itemNames.add(new ItemName(Material.PUMPKIN_PIE, langConfig.getString("item.minecraft.pumpkin_pie", "Pumpkin Pie"))); + itemNames.add(new ItemName(Material.ENCHANTED_BOOK, langConfig.getString("item.minecraft.enchanted_book", "Enchanted Book"))); + itemNames.add(new ItemName(Material.FIREWORK_ROCKET, langConfig.getString("item.minecraft.firework_rocket", "Firework Rocket"))); + itemNames.add(new ItemName(Material.FIREWORK_STAR, langConfig.getString("item.minecraft.firework_star", "Firework Star"))); + itemNames.add(new ItemName(Material.NETHER_BRICK, langConfig.getString("item.minecraft.nether_brick", "Nether Brick"))); + itemNames.add(new ItemName(Material.QUARTZ, langConfig.getString("item.minecraft.quartz", "Nether Quartz"))); + itemNames.add(new ItemName(Material.ARMOR_STAND, langConfig.getString("item.minecraft.armor_stand", "Armor Stand"))); + itemNames.add(new ItemName(Material.IRON_HORSE_ARMOR, langConfig.getString("item.minecraft.iron_horse_armor", "Iron Horse Armor"))); + itemNames.add(new ItemName(Material.GOLDEN_HORSE_ARMOR, langConfig.getString("item.minecraft.golden_horse_armor", "Golden Horse Armor"))); + itemNames.add(new ItemName(Material.DIAMOND_HORSE_ARMOR, langConfig.getString("item.minecraft.diamond_horse_armor", "Diamond Horse Armor"))); + itemNames.add(new ItemName(Material.PRISMARINE_SHARD, langConfig.getString("item.minecraft.prismarine_shard", "Prismarine Shard"))); + itemNames.add(new ItemName(Material.PRISMARINE_CRYSTALS, langConfig.getString("item.minecraft.prismarine_crystals", "Prismarine Crystals"))); + itemNames.add(new ItemName(Material.CHORUS_FRUIT, langConfig.getString("item.minecraft.chorus_fruit", "Chorus Fruit"))); + itemNames.add(new ItemName(Material.POPPED_CHORUS_FRUIT, langConfig.getString("item.minecraft.popped_chorus_fruit", "Popped Chorus Fruit"))); + itemNames.add(new ItemName(Material.BEETROOT, langConfig.getString("item.minecraft.beetroot", "Beetroot"))); + itemNames.add(new ItemName(Material.BEETROOT_SEEDS, langConfig.getString("item.minecraft.beetroot_seeds", "Beetroot Seeds"))); + itemNames.add(new ItemName(Material.BEETROOT_SOUP, langConfig.getString("item.minecraft.beetroot_soup", "Beetroot Soup"))); + itemNames.add(new ItemName(Material.DRAGON_BREATH, langConfig.getString("item.minecraft.dragon_breath", "Dragon's Breath"))); + itemNames.add(new ItemName(Material.ELYTRA, langConfig.getString("item.minecraft.elytra", "Elytra"))); + itemNames.add(new ItemName(Material.TOTEM_OF_UNDYING, langConfig.getString("item.minecraft.totem_of_undying", "Totem of Undying"))); + itemNames.add(new ItemName(Material.SHULKER_SHELL, langConfig.getString("item.minecraft.shulker_shell", "Shulker Shell"))); + itemNames.add(new ItemName(Material.IRON_NUGGET, langConfig.getString("item.minecraft.iron_nugget", "Iron Nugget"))); + itemNames.add(new ItemName(Material.KNOWLEDGE_BOOK, langConfig.getString("item.minecraft.knowledge_book", "Knowledge Book"))); + itemNames.add(new ItemName(Material.DEBUG_STICK, langConfig.getString("item.minecraft.debug_stick", "Debug Stick"))); + itemNames.add(new ItemName(Material.TRIDENT, langConfig.getString("item.minecraft.trident", "Trident"))); + itemNames.add(new ItemName(Material.SCUTE, langConfig.getString("item.minecraft.scute", "Scute"))); + itemNames.add(new ItemName(Material.TURTLE_HELMET, langConfig.getString("item.minecraft.turtle_helmet", "Turtle Shell"))); + itemNames.add(new ItemName(Material.PHANTOM_MEMBRANE, langConfig.getString("item.minecraft.phantom_membrane", "Phantom Membrane"))); + itemNames.add(new ItemName(Material.NAUTILUS_SHELL, langConfig.getString("item.minecraft.nautilus_shell", "Nautilus Shell"))); + itemNames.add(new ItemName(Material.HEART_OF_THE_SEA, langConfig.getString("item.minecraft.heart_of_the_sea", "Heart of the Sea"))); + + if (Utils.getMajorVersion() >= 14) { + // Add 1.14 item names + itemNames.add(new ItemName(Material.ACACIA_SIGN, langConfig.getString("block.minecraft.acacia_sign", "Acacia Sign"))); + itemNames.add(new ItemName(Material.ACACIA_WALL_SIGN, langConfig.getString("block.minecraft.acacia_wall_sign", "Acacia Wall Sign"))); + itemNames.add(new ItemName(Material.ANDESITE_SLAB, langConfig.getString("block.minecraft.andesite_slab", "Andesite Slab"))); + itemNames.add(new ItemName(Material.ANDESITE_STAIRS, langConfig.getString("block.minecraft.andesite_stairs", "Andesite Stairs"))); + itemNames.add(new ItemName(Material.ANDESITE_WALL, langConfig.getString("block.minecraft.andesite_wall", "Andesite Wall"))); + itemNames.add(new ItemName(Material.BAMBOO, langConfig.getString("block.minecraft.bamboo", "Bamboo"))); + itemNames.add(new ItemName(Material.BAMBOO_SAPLING, langConfig.getString("block.minecraft.bamboo_sapling", "Bamboo Sapling"))); + itemNames.add(new ItemName(Material.BARREL, langConfig.getString("block.minecraft.barrel", "Barrel"))); + itemNames.add(new ItemName(Material.BELL, langConfig.getString("block.minecraft.bell", "Bell"))); + itemNames.add(new ItemName(Material.BIRCH_SIGN, langConfig.getString("block.minecraft.birch_sign", "Birch Sign"))); + itemNames.add(new ItemName(Material.BIRCH_WALL_SIGN, langConfig.getString("block.minecraft.birch_wall_sign", "Birch Wall Sign"))); + itemNames.add(new ItemName(Material.BLACK_DYE, langConfig.getString("item.minecraft.black_dye", "Black Dye"))); + itemNames.add(new ItemName(Material.BLAST_FURNACE, langConfig.getString("block.minecraft.blast_furnace", "Blast Furnace"))); + itemNames.add(new ItemName(Material.BLUE_DYE, langConfig.getString("item.minecraft.blue_dye", "Blue Dye"))); + itemNames.add(new ItemName(Material.BRICK_WALL, langConfig.getString("block.minecraft.brick_wall", "Brick Wall"))); + itemNames.add(new ItemName(Material.BROWN_DYE, langConfig.getString("item.minecraft.brown_dye", "Brown Dye"))); + itemNames.add(new ItemName(Material.CAMPFIRE, langConfig.getString("block.minecraft.campfire", "Campfire"))); + itemNames.add(new ItemName(Material.CARTOGRAPHY_TABLE, langConfig.getString("block.minecraft.cartography_table", "Cartography Table"))); + itemNames.add(new ItemName(Material.CAT_SPAWN_EGG, langConfig.getString("item.minecraft.cat_spawn_egg", "Cat Spawn Egg"))); + itemNames.add(new ItemName(Material.COMPOSTER, langConfig.getString("block.minecraft.composter", "Composter"))); + itemNames.add(new ItemName(Material.CORNFLOWER, langConfig.getString("block.minecraft.cornflower", "Cornflower"))); + itemNames.add(new ItemName(Material.CREEPER_BANNER_PATTERN, langConfig.getString("item.minecraft.creeper_banner_pattern", "Banner Pattern"))); + itemNames.add(new ItemName(Material.CROSSBOW, langConfig.getString("item.minecraft.crossbow", "Crossbow"))); + itemNames.add(new ItemName(Material.CUT_RED_SANDSTONE_SLAB, langConfig.getString("block.minecraft.cut_red_sandstone_slab", "Cut Red Sandstone Slab"))); + itemNames.add(new ItemName(Material.CUT_SANDSTONE_SLAB, langConfig.getString("block.minecraft.cut_sandstone_slab", "Cut Sandstone Slab"))); + itemNames.add(new ItemName(Material.DARK_OAK_SIGN, langConfig.getString("block.minecraft.dark_oak_sign", "Dark Oak Sign"))); + itemNames.add(new ItemName(Material.DARK_OAK_WALL_SIGN, langConfig.getString("block.minecraft.dark_oak_wall_sign", "Dark Oak Wall Sign"))); + itemNames.add(new ItemName(Material.DEAD_BRAIN_CORAL, langConfig.getString("block.minecraft.dead_brain_coral", "Dead Brain Coral"))); + itemNames.add(new ItemName(Material.DEAD_BUBBLE_CORAL, langConfig.getString("block.minecraft.dead_bubble_coral", "Dead Bubble Coral"))); + itemNames.add(new ItemName(Material.DEAD_FIRE_CORAL, langConfig.getString("block.minecraft.dead_fire_coral", "Dead Fire Coral"))); + itemNames.add(new ItemName(Material.DEAD_HORN_CORAL, langConfig.getString("block.minecraft.dead_horn_coral", "Dead Horn Coral"))); + itemNames.add(new ItemName(Material.DEAD_TUBE_CORAL, langConfig.getString("block.minecraft.dead_tube_coral", "Dead Tube Coral"))); + itemNames.add(new ItemName(Material.DIORITE_SLAB, langConfig.getString("block.minecraft.diorite_slab", "Diorite Slab"))); + itemNames.add(new ItemName(Material.DIORITE_STAIRS, langConfig.getString("block.minecraft.diorite_stairs", "Diorite Stairs"))); + itemNames.add(new ItemName(Material.DIORITE_WALL, langConfig.getString("block.minecraft.diorite_wall", "Diorite Wall"))); + itemNames.add(new ItemName(Material.END_STONE_BRICK_SLAB, langConfig.getString("block.minecraft.end_stone_brick_slab", "End Stone Brick Slab"))); + itemNames.add(new ItemName(Material.END_STONE_BRICK_STAIRS, langConfig.getString("block.minecraft.end_stone_brick_stairs", "End Stone Brick Stairs"))); + itemNames.add(new ItemName(Material.END_STONE_BRICK_WALL, langConfig.getString("block.minecraft.end_stone_brick_wall", "End Stone Brick Wall"))); + itemNames.add(new ItemName(Material.FLETCHING_TABLE, langConfig.getString("block.minecraft.fletching_table", "Fletching Table"))); + itemNames.add(new ItemName(Material.FLOWER_BANNER_PATTERN, langConfig.getString("item.minecraft.flower_banner_pattern", "Banner Pattern"))); + itemNames.add(new ItemName(Material.FOX_SPAWN_EGG, langConfig.getString("item.minecraft.fox_spawn_egg", "Fox Spawn Egg"))); + itemNames.add(new ItemName(Material.GLOBE_BANNER_PATTERN, langConfig.getString("item.minecraft.globe_banner_pattern", "Banner Pattern"))); + itemNames.add(new ItemName(Material.GRANITE_SLAB, langConfig.getString("block.minecraft.granite_slab", "Granite Slab"))); + itemNames.add(new ItemName(Material.GRANITE_STAIRS, langConfig.getString("block.minecraft.granite_stairs", "Granite Stairs"))); + itemNames.add(new ItemName(Material.GRANITE_WALL, langConfig.getString("block.minecraft.granite_wall", "Granite Wall"))); + itemNames.add(new ItemName(Material.GREEN_DYE, langConfig.getString("item.minecraft.green_dye", "Green Dye"))); + itemNames.add(new ItemName(Material.GRINDSTONE, langConfig.getString("block.minecraft.grindstone", "Grindstone"))); + itemNames.add(new ItemName(Material.JIGSAW, langConfig.getString("block.minecraft.jigsaw", "Jigsaw"))); + itemNames.add(new ItemName(Material.JUNGLE_SIGN, langConfig.getString("block.minecraft.jungle_sign", "Jungle Sign"))); + itemNames.add(new ItemName(Material.JUNGLE_WALL_SIGN, langConfig.getString("block.minecraft.jungle_wall_sign", "Jungle Wall Sign"))); + itemNames.add(new ItemName(Material.LANTERN, langConfig.getString("block.minecraft.lantern", "Lantern"))); + itemNames.add(new ItemName(Material.LEATHER_HORSE_ARMOR, langConfig.getString("item.minecraft.leather_horse_armor", "Leather Horse Armor"))); + itemNames.add(new ItemName(Material.LECTERN, langConfig.getString("block.minecraft.lectern", "Lectern"))); + itemNames.add(new ItemName(Material.LILY_OF_THE_VALLEY, langConfig.getString("block.minecraft.lily_of_the_valley", "Lily of the Valley"))); + itemNames.add(new ItemName(Material.LOOM, langConfig.getString("block.minecraft.loom", "Loom"))); + itemNames.add(new ItemName(Material.MOJANG_BANNER_PATTERN, langConfig.getString("item.minecraft.mojang_banner_pattern", "Banner Pattern"))); + itemNames.add(new ItemName(Material.MOSSY_COBBLESTONE_SLAB, langConfig.getString("block.minecraft.mossy_cobblestone_slab", "Mossy Cobblestone Slab"))); + itemNames.add(new ItemName(Material.MOSSY_COBBLESTONE_STAIRS, langConfig.getString("block.minecraft.mossy_cobblestone_stairs", "Mossy Cobblestone Stairs"))); + itemNames.add(new ItemName(Material.MOSSY_STONE_BRICK_SLAB, langConfig.getString("block.minecraft.mossy_stone_brick_slab", "Mossy Stone Brick Slab"))); + itemNames.add(new ItemName(Material.MOSSY_STONE_BRICK_STAIRS, langConfig.getString("block.minecraft.mossy_stone_brick_stairs", "Mossy Stone Brick Stairs"))); + itemNames.add(new ItemName(Material.MOSSY_STONE_BRICK_WALL, langConfig.getString("block.minecraft.mossy_stone_brick_wall", "Mossy Stone Brick Wall"))); + itemNames.add(new ItemName(Material.NETHER_BRICK_WALL, langConfig.getString("block.minecraft.nether_brick_wall", "Nether Brick Wall"))); + itemNames.add(new ItemName(Material.OAK_SIGN, langConfig.getString("block.minecraft.oak_sign", "Oak Sign"))); + itemNames.add(new ItemName(Material.OAK_WALL_SIGN, langConfig.getString("block.minecraft.oak_wall_sign", "Oak Wall Sign"))); + itemNames.add(new ItemName(Material.PANDA_SPAWN_EGG, langConfig.getString("item.minecraft.panda_spawn_egg", "Panda Spawn Egg"))); + itemNames.add(new ItemName(Material.PILLAGER_SPAWN_EGG, langConfig.getString("item.minecraft.pillager_spawn_egg", "Pillager Spawn Egg"))); + itemNames.add(new ItemName(Material.POLISHED_ANDESITE_SLAB, langConfig.getString("block.minecraft.polished_andesite_slab", "Polished Andesite Slab"))); + itemNames.add(new ItemName(Material.POLISHED_ANDESITE_STAIRS, langConfig.getString("block.minecraft.polished_andesite_stairs", "Polished Andesite Stairs"))); + itemNames.add(new ItemName(Material.POLISHED_DIORITE_SLAB, langConfig.getString("block.minecraft.polished_diorite_slab", "Polished Diorite Slab"))); + itemNames.add(new ItemName(Material.POLISHED_DIORITE_STAIRS, langConfig.getString("block.minecraft.polished_diorite_stairs", "Polished Diorite Stairs"))); + itemNames.add(new ItemName(Material.POLISHED_GRANITE_SLAB, langConfig.getString("block.minecraft.polished_granite_slab", "Polished Granite Slab"))); + itemNames.add(new ItemName(Material.POLISHED_GRANITE_STAIRS, langConfig.getString("block.minecraft.polished_granite_stairs", "Polished Granite Stairs"))); + itemNames.add(new ItemName(Material.POTTED_BAMBOO, langConfig.getString("block.minecraft.potted_bamboo", "Potted Bamboo"))); + itemNames.add(new ItemName(Material.POTTED_CORNFLOWER, langConfig.getString("block.minecraft.potted_cornflower", "Potted Cornflower"))); + itemNames.add(new ItemName(Material.POTTED_LILY_OF_THE_VALLEY, langConfig.getString("block.minecraft.potted_lily_of_the_valley", "Potted Lily of the Valley"))); + itemNames.add(new ItemName(Material.POTTED_WITHER_ROSE, langConfig.getString("block.minecraft.potted_wither_rose", "Potted Wither Rose"))); + itemNames.add(new ItemName(Material.PRISMARINE_WALL, langConfig.getString("block.minecraft.prismarine_wall", "Prismarine Wall"))); + itemNames.add(new ItemName(Material.RAVAGER_SPAWN_EGG, langConfig.getString("item.minecraft.ravager_spawn_egg", "Ravager Spawn Egg"))); + itemNames.add(new ItemName(Material.RED_DYE, langConfig.getString("item.minecraft.red_dye", "Red Dye"))); + itemNames.add(new ItemName(Material.RED_NETHER_BRICK_SLAB, langConfig.getString("block.minecraft.red_nether_brick_slab", "Red Nether Brick Slab"))); + itemNames.add(new ItemName(Material.RED_NETHER_BRICK_STAIRS, langConfig.getString("block.minecraft.red_nether_brick_stairs", "Red Nether Brick Stairs"))); + itemNames.add(new ItemName(Material.RED_NETHER_BRICK_WALL, langConfig.getString("block.minecraft.red_nether_brick_wall", "Red Nether Brick Wall"))); + itemNames.add(new ItemName(Material.RED_SANDSTONE_WALL, langConfig.getString("block.minecraft.red_sandstone_wall", "Red Sandstone Wall"))); + itemNames.add(new ItemName(Material.SANDSTONE_WALL, langConfig.getString("block.minecraft.sandstone_wall", "Sandstone Wall"))); + itemNames.add(new ItemName(Material.SCAFFOLDING, langConfig.getString("block.minecraft.scaffolding", "Scaffolding"))); + itemNames.add(new ItemName(Material.SKULL_BANNER_PATTERN, langConfig.getString("item.minecraft.skull_banner_pattern", "Banner Pattern"))); + itemNames.add(new ItemName(Material.SMITHING_TABLE, langConfig.getString("block.minecraft.smithing_table", "Smithing Table"))); + itemNames.add(new ItemName(Material.SMOKER, langConfig.getString("block.minecraft.smoker", "Smoker"))); + itemNames.add(new ItemName(Material.SMOOTH_QUARTZ_SLAB, langConfig.getString("block.minecraft.smooth_quartz_slab", "Smooth Quartz Slab"))); + itemNames.add(new ItemName(Material.SMOOTH_QUARTZ_STAIRS, langConfig.getString("block.minecraft.smooth_quartz_stairs", "Smooth Quartz Stairs"))); + itemNames.add(new ItemName(Material.SMOOTH_RED_SANDSTONE_SLAB, langConfig.getString("block.minecraft.smooth_red_sandstone_slab", "Smooth Red Sandstone Slab"))); + itemNames.add(new ItemName(Material.SMOOTH_RED_SANDSTONE_STAIRS, langConfig.getString("block.minecraft.smooth_red_sandstone_stairs", "Smooth Red Sandstone Stairs"))); + itemNames.add(new ItemName(Material.SMOOTH_SANDSTONE_SLAB, langConfig.getString("block.minecraft.smooth_sandstone_slab", "Smooth Sandstone Slab"))); + itemNames.add(new ItemName(Material.SMOOTH_SANDSTONE_STAIRS, langConfig.getString("block.minecraft.smooth_sandstone_stairs", "Smooth Sandstone Stairs"))); + itemNames.add(new ItemName(Material.SMOOTH_STONE_SLAB, langConfig.getString("block.minecraft.smooth_stone_slab", "Smooth Stone Slab"))); + itemNames.add(new ItemName(Material.SPRUCE_SIGN, langConfig.getString("block.minecraft.spruce_sign", "Spruce Sign"))); + itemNames.add(new ItemName(Material.SPRUCE_WALL_SIGN, langConfig.getString("block.minecraft.spruce_wall_sign", "Spruce Wall Sign"))); + itemNames.add(new ItemName(Material.STONE_BRICK_WALL, langConfig.getString("block.minecraft.stone_brick_wall", "Stone Brick Wall"))); + itemNames.add(new ItemName(Material.STONECUTTER, langConfig.getString("block.minecraft.stonecutter", "Stonecutter"))); + itemNames.add(new ItemName(Material.SUSPICIOUS_STEW, langConfig.getString("item.minecraft.suspicious_stew", "Suspicious Stew"))); + itemNames.add(new ItemName(Material.SWEET_BERRIES, langConfig.getString("item.minecraft.sweet_berries", "Sweet Berries"))); + itemNames.add(new ItemName(Material.SWEET_BERRY_BUSH, langConfig.getString("block.minecraft.sweet_berry_bush", "Sweet Berry Bush"))); + itemNames.add(new ItemName(Material.TRADER_LLAMA_SPAWN_EGG, langConfig.getString("item.minecraft.trader_llama_spawn_egg", "Trader Llama Spawn Egg"))); + itemNames.add(new ItemName(Material.WANDERING_TRADER_SPAWN_EGG, langConfig.getString("item.minecraft.wandering_trader_spawn_egg", "Wandering Trader Spawn Egg"))); + itemNames.add(new ItemName(Material.WHITE_DYE, langConfig.getString("item.minecraft.white_dye", "White Dye"))); + itemNames.add(new ItemName(Material.WITHER_ROSE, langConfig.getString("block.minecraft.wither_rose", "Wither Rose"))); + itemNames.add(new ItemName(Material.YELLOW_DYE, langConfig.getString("item.minecraft.yellow_dye", "Yellow Dye"))); + } else { + // Add pre-1.14 item names that don't exist anymore + itemNames.add(new ItemName(Material.valueOf("CACTUS_GREEN"), langConfig.getString("item.minecraft.cactus_green", "Cactus Green"))); + itemNames.add(new ItemName(Material.valueOf("DANDELION_YELLOW"), langConfig.getString("item.minecraft.dandelion_yellow", "Dandelion Yellow"))); + itemNames.add(new ItemName(Material.valueOf("ROSE_RED"), langConfig.getString("item.minecraft.rose_red", "Rose Red"))); + itemNames.add(new ItemName(Material.valueOf("SIGN"), langConfig.getString("item.minecraft.sign", "Sign"))); + itemNames.add(new ItemName(Material.valueOf("WALL_SIGN"), langConfig.getString("block.minecraft.wall_sign", "Wall Sign"))); + } + + if (Utils.getMajorVersion() >= 15) { + itemNames.add(new ItemName(Material.BEE_NEST, langConfig.getString("block.minecraft.bee_nest", "Bee Nest"))); + itemNames.add(new ItemName(Material.BEE_SPAWN_EGG, langConfig.getString("item.minecraft.bee_spawn_egg", "Bee Spawn Egg"))); + itemNames.add(new ItemName(Material.BEEHIVE, langConfig.getString("block.minecraft.beehive", "Beehive"))); + itemNames.add(new ItemName(Material.HONEY_BLOCK, langConfig.getString("block.minecraft.honey_block", "Honey Block"))); + itemNames.add(new ItemName(Material.HONEY_BOTTLE, langConfig.getString("item.minecraft.honey_bottle", "Honey Bottle"))); + itemNames.add(new ItemName(Material.HONEYCOMB, langConfig.getString("item.minecraft.honeycomb", "Honeycomb"))); + itemNames.add(new ItemName(Material.HONEYCOMB_BLOCK, langConfig.getString("block.minecraft.honeycomb_block", "Honeycomb Block"))); + } + + if (Utils.getMajorVersion() >= 16) { + itemNames.add(new ItemName(Material.ANCIENT_DEBRIS, langConfig.getString("block.minecraft.ancient_debris", "Ancient Debris"))); + itemNames.add(new ItemName(Material.BASALT, langConfig.getString("block.minecraft.basalt", "Basalt"))); + itemNames.add(new ItemName(Material.BLACKSTONE, langConfig.getString("block.minecraft.blackstone", "Blackstone"))); + itemNames.add(new ItemName(Material.BLACKSTONE_SLAB, langConfig.getString("block.minecraft.blackstone_slab", "Blackstone Slab"))); + itemNames.add(new ItemName(Material.BLACKSTONE_STAIRS, langConfig.getString("block.minecraft.blackstone_stairs", "Blackstone Stairs"))); + itemNames.add(new ItemName(Material.BLACKSTONE_WALL, langConfig.getString("block.minecraft.blackstone_wall", "Blackstone Wall"))); + itemNames.add(new ItemName(Material.CHAIN, langConfig.getString("block.minecraft.chain", "Chain"))); + itemNames.add(new ItemName(Material.CHISELED_NETHER_BRICKS, langConfig.getString("block.minecraft.chiseled_nether_bricks", "Chiseled Nether Bricks"))); + itemNames.add(new ItemName(Material.CHISELED_POLISHED_BLACKSTONE, langConfig.getString("block.minecraft.chiseled_polished_blackstone", "Chiseled Polished Blackstone"))); + itemNames.add(new ItemName(Material.CRACKED_NETHER_BRICKS, langConfig.getString("block.minecraft.cracked_nether_bricks", "Cracked Nether Bricks"))); + itemNames.add(new ItemName(Material.CRACKED_POLISHED_BLACKSTONE_BRICKS, langConfig.getString("block.minecraft.cracked_polished_blackstone_bricks", "Cracked Polished Blackstone Bricks"))); + itemNames.add(new ItemName(Material.CRIMSON_BUTTON, langConfig.getString("block.minecraft.crimson_button", "Crimson Button"))); + itemNames.add(new ItemName(Material.CRIMSON_DOOR, langConfig.getString("block.minecraft.crimson_door", "Crimson Door"))); + itemNames.add(new ItemName(Material.CRIMSON_FENCE, langConfig.getString("block.minecraft.crimson_fence", "Crimson Fence"))); + itemNames.add(new ItemName(Material.CRIMSON_FENCE_GATE, langConfig.getString("block.minecraft.crimson_fence_gate", "Crimson Fence Gate"))); + itemNames.add(new ItemName(Material.CRIMSON_FUNGUS, langConfig.getString("block.minecraft.crimson_fungus", "Crimson Fungus"))); + itemNames.add(new ItemName(Material.CRIMSON_HYPHAE, langConfig.getString("block.minecraft.crimson_hyphae", "Crimson Hyphae"))); + itemNames.add(new ItemName(Material.CRIMSON_NYLIUM, langConfig.getString("block.minecraft.crimson_nylium", "Crimson Nylium"))); + itemNames.add(new ItemName(Material.CRIMSON_PLANKS, langConfig.getString("block.minecraft.crimson_planks", "Crimson Planks"))); + itemNames.add(new ItemName(Material.CRIMSON_PRESSURE_PLATE, langConfig.getString("block.minecraft.crimson_pressure_plate", "Crimson Pressure Plate"))); + itemNames.add(new ItemName(Material.CRIMSON_ROOTS, langConfig.getString("block.minecraft.crimson_roots", "Crimson Roots"))); + itemNames.add(new ItemName(Material.CRIMSON_SIGN, langConfig.getString("block.minecraft.crimson_sign", "Crimson Sign"))); + itemNames.add(new ItemName(Material.CRIMSON_SLAB, langConfig.getString("block.minecraft.crimson_slab", "Crimson Slab"))); + itemNames.add(new ItemName(Material.CRIMSON_STAIRS, langConfig.getString("block.minecraft.crimson_stairs", "Crimson Stairs"))); + itemNames.add(new ItemName(Material.CRIMSON_STEM, langConfig.getString("block.minecraft.crimson_stem", "Crimson Stem"))); + itemNames.add(new ItemName(Material.CRIMSON_TRAPDOOR, langConfig.getString("block.minecraft.crimson_trapdoor", "Crimson Trapdoor"))); + itemNames.add(new ItemName(Material.CRIMSON_WALL_SIGN, langConfig.getString("block.minecraft.crimson_wall_sign", "Crimson Wall Sign"))); + itemNames.add(new ItemName(Material.CRYING_OBSIDIAN, langConfig.getString("block.minecraft.crying_obsidian", "Crying Obsidian"))); + itemNames.add(new ItemName(Material.GILDED_BLACKSTONE, langConfig.getString("block.minecraft.gilded_blackstone", "Gilded Blackstone"))); + itemNames.add(new ItemName(Material.HOGLIN_SPAWN_EGG, langConfig.getString("item.minecraft.hoglin_spawn_egg", "Hoglin Spawn Egg"))); + itemNames.add(new ItemName(Material.LODESTONE, langConfig.getString("block.minecraft.lodestone", "Lodestone"))); + // itemNames.add(new ItemName(Material.LODESTONE_COMPASS, langConfig.getString("item.minecraft.lodestone_compass", "Lodestone Compass"))); + itemNames.add(new ItemName(Material.MUSIC_DISC_PIGSTEP, langConfig.getString("item.minecraft.music_disc_pigstep", "Music Disc"))); + itemNames.add(new ItemName(Material.NETHER_GOLD_ORE, langConfig.getString("block.minecraft.nether_gold_ore", "Nether Gold Ore"))); + itemNames.add(new ItemName(Material.NETHER_SPROUTS, langConfig.getString("block.minecraft.nether_sprouts", "Nether Sprouts"))); + itemNames.add(new ItemName(Material.NETHERITE_AXE, langConfig.getString("item.minecraft.netherite_axe", "Netherite Axe"))); + itemNames.add(new ItemName(Material.NETHERITE_BLOCK, langConfig.getString("block.minecraft.netherite_block", "Netherite Block"))); + itemNames.add(new ItemName(Material.NETHERITE_BOOTS, langConfig.getString("item.minecraft.netherite_boots", "Netherite Boots"))); + itemNames.add(new ItemName(Material.NETHERITE_CHESTPLATE, langConfig.getString("item.minecraft.netherite_chestplate", "Netherite Chestplate"))); + itemNames.add(new ItemName(Material.NETHERITE_HELMET, langConfig.getString("item.minecraft.netherite_helmet", "Netherite Helmet"))); + itemNames.add(new ItemName(Material.NETHERITE_HOE, langConfig.getString("item.minecraft.netherite_hoe", "Netherite Hoe"))); + itemNames.add(new ItemName(Material.NETHERITE_INGOT, langConfig.getString("item.minecraft.netherite_ingot", "Netherite Ingot"))); + itemNames.add(new ItemName(Material.NETHERITE_LEGGINGS, langConfig.getString("item.minecraft.netherite_leggings", "Netherite Leggings"))); + itemNames.add(new ItemName(Material.NETHERITE_PICKAXE, langConfig.getString("item.minecraft.netherite_pickaxe", "Netherite Pickaxe"))); + itemNames.add(new ItemName(Material.NETHERITE_SCRAP, langConfig.getString("item.minecraft.netherite_scrap", "Netherite Scrap"))); + itemNames.add(new ItemName(Material.NETHERITE_SHOVEL, langConfig.getString("item.minecraft.netherite_shovel", "Netherite Shovel"))); + itemNames.add(new ItemName(Material.NETHERITE_SWORD, langConfig.getString("item.minecraft.netherite_sword", "Netherite Sword"))); + itemNames.add(new ItemName(Material.PIGLIN_SPAWN_EGG, langConfig.getString("item.minecraft.piglin_spawn_egg", "Piglin Spawn Egg"))); + itemNames.add(new ItemName(Material.POLISHED_BASALT, langConfig.getString("block.minecraft.polished_basalt", "Polished Basalt"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE, langConfig.getString("block.minecraft.polished_blackstone", "Polished Blackstone"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_BRICK_SLAB, langConfig.getString("block.minecraft.polished_blackstone_brick_slab", "Polished Blackstone Brick Slab"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_BRICK_STAIRS, langConfig.getString("block.minecraft.polished_blackstone_brick_stairs", "Polished Blackstone Brick Stairs"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_BRICK_WALL, langConfig.getString("block.minecraft.polished_blackstone_brick_wall", "Polished Blackstone Brick Wall"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_BRICKS, langConfig.getString("block.minecraft.polished_blackstone_bricks", "Polished Blackstone Bricks"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_BUTTON, langConfig.getString("block.minecraft.polished_blackstone_button", "Polished Blackstone Button"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_PRESSURE_PLATE, langConfig.getString("block.minecraft.polished_blackstone_pressure_plate", "Polished Blackstone Pressure Plate"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_SLAB, langConfig.getString("block.minecraft.polished_blackstone_slab", "Polished Blackstone Slab"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_STAIRS, langConfig.getString("block.minecraft.polished_blackstone_stairs", "Polished Blackstone Stairs"))); + itemNames.add(new ItemName(Material.POLISHED_BLACKSTONE_WALL, langConfig.getString("block.minecraft.polished_blackstone_wall", "Polished Blackstone Wall"))); + itemNames.add(new ItemName(Material.POTTED_CRIMSON_FUNGUS, langConfig.getString("block.minecraft.potted_crimson_fungus", "Potted Crimson Fungus"))); + itemNames.add(new ItemName(Material.POTTED_CRIMSON_ROOTS, langConfig.getString("block.minecraft.potted_crimson_roots", "Potted Crimson Roots"))); + itemNames.add(new ItemName(Material.POTTED_WARPED_FUNGUS, langConfig.getString("block.minecraft.potted_warped_fungus", "Potted Warped Fungus"))); + itemNames.add(new ItemName(Material.POTTED_WARPED_ROOTS, langConfig.getString("block.minecraft.potted_warped_roots", "Potted Warped Roots"))); + itemNames.add(new ItemName(Material.QUARTZ_BRICKS, langConfig.getString("block.minecraft.quartz_bricks", "Quartz Bricks"))); + itemNames.add(new ItemName(Material.RESPAWN_ANCHOR, langConfig.getString("block.minecraft.respawn_anchor", "Respawn Anchor"))); + itemNames.add(new ItemName(Material.SHROOMLIGHT, langConfig.getString("block.minecraft.shroomlight", "Shroomlight"))); + itemNames.add(new ItemName(Material.SOUL_CAMPFIRE, langConfig.getString("block.minecraft.soul_campfire", "Soul Campfire"))); + itemNames.add(new ItemName(Material.SOUL_FIRE, langConfig.getString("block.minecraft.soul_fire", "Soul Fire"))); + itemNames.add(new ItemName(Material.SOUL_LANTERN, langConfig.getString("block.minecraft.soul_lantern", "Soul Lantern"))); + itemNames.add(new ItemName(Material.SOUL_SOIL, langConfig.getString("block.minecraft.soul_soil", "Soul Soil"))); + itemNames.add(new ItemName(Material.SOUL_TORCH, langConfig.getString("block.minecraft.soul_torch", "Soul Torch"))); + itemNames.add(new ItemName(Material.SOUL_WALL_TORCH, langConfig.getString("block.minecraft.soul_wall_torch", "Soul Wall Torch"))); + itemNames.add(new ItemName(Material.STRIDER_SPAWN_EGG, langConfig.getString("item.minecraft.strider_spawn_egg", "Strider Spawn Egg"))); + itemNames.add(new ItemName(Material.STRIPPED_CRIMSON_HYPHAE, langConfig.getString("block.minecraft.stripped_crimson_hyphae", "Stripped Crimson Hyphae"))); + itemNames.add(new ItemName(Material.STRIPPED_CRIMSON_STEM, langConfig.getString("block.minecraft.stripped_crimson_stem", "Stripped Crimson Stem"))); + itemNames.add(new ItemName(Material.STRIPPED_WARPED_HYPHAE, langConfig.getString("block.minecraft.stripped_warped_hyphae", "Stripped Warped Hyphae"))); + itemNames.add(new ItemName(Material.STRIPPED_WARPED_STEM, langConfig.getString("block.minecraft.stripped_warped_stem", "Stripped Warped Stem"))); + itemNames.add(new ItemName(Material.TARGET, langConfig.getString("block.minecraft.target", "Target"))); + itemNames.add(new ItemName(Material.TWISTING_VINES, langConfig.getString("block.minecraft.twisting_vines", "Twisting Vines"))); + itemNames.add(new ItemName(Material.TWISTING_VINES_PLANT, langConfig.getString("block.minecraft.twisting_vines_plant", "Twisting Vines Plant"))); + itemNames.add(new ItemName(Material.WARPED_BUTTON, langConfig.getString("block.minecraft.warped_button", "Warped Button"))); + itemNames.add(new ItemName(Material.WARPED_DOOR, langConfig.getString("block.minecraft.warped_door", "Warped Door"))); + itemNames.add(new ItemName(Material.WARPED_FENCE, langConfig.getString("block.minecraft.warped_fence", "Warped Fence"))); + itemNames.add(new ItemName(Material.WARPED_FENCE_GATE, langConfig.getString("block.minecraft.warped_fence_gate", "Warped Fence Gate"))); + itemNames.add(new ItemName(Material.WARPED_FUNGUS, langConfig.getString("block.minecraft.warped_fungus", "Warped Fungus"))); + itemNames.add(new ItemName(Material.WARPED_FUNGUS_ON_A_STICK, langConfig.getString("item.minecraft.warped_fungus_on_a_stick", "Warped Fungus on a Stick"))); + itemNames.add(new ItemName(Material.WARPED_HYPHAE, langConfig.getString("block.minecraft.warped_hyphae", "Warped Hyphae"))); + itemNames.add(new ItemName(Material.WARPED_NYLIUM, langConfig.getString("block.minecraft.warped_nylium", "Warped Nylium"))); + itemNames.add(new ItemName(Material.WARPED_PLANKS, langConfig.getString("block.minecraft.warped_planks", "Warped Planks"))); + itemNames.add(new ItemName(Material.WARPED_PRESSURE_PLATE, langConfig.getString("block.minecraft.warped_pressure_plate", "Warped Pressure Plate"))); + itemNames.add(new ItemName(Material.WARPED_ROOTS, langConfig.getString("block.minecraft.warped_roots", "Warped Roots"))); + itemNames.add(new ItemName(Material.WARPED_SIGN, langConfig.getString("block.minecraft.warped_sign", "Warped Sign"))); + itemNames.add(new ItemName(Material.WARPED_SLAB, langConfig.getString("block.minecraft.warped_slab", "Warped Slab"))); + itemNames.add(new ItemName(Material.WARPED_STAIRS, langConfig.getString("block.minecraft.warped_stairs", "Warped Stairs"))); + itemNames.add(new ItemName(Material.WARPED_STEM, langConfig.getString("block.minecraft.warped_stem", "Warped Stem"))); + itemNames.add(new ItemName(Material.WARPED_TRAPDOOR, langConfig.getString("block.minecraft.warped_trapdoor", "Warped Trapdoor"))); + itemNames.add(new ItemName(Material.WARPED_WALL_SIGN, langConfig.getString("block.minecraft.warped_wall_sign", "Warped Wall Sign"))); + itemNames.add(new ItemName(Material.WARPED_WART_BLOCK, langConfig.getString("block.minecraft.warped_wart_block", "Warped Wart Block"))); + itemNames.add(new ItemName(Material.WEEPING_VINES, langConfig.getString("block.minecraft.weeping_vines", "Weeping Vines"))); + itemNames.add(new ItemName(Material.WEEPING_VINES_PLANT, langConfig.getString("block.minecraft.weeping_vines_plant", "Weeping Vines Plant"))); + itemNames.add(new ItemName(Material.ZOGLIN_SPAWN_EGG, langConfig.getString("item.minecraft.zoglin_spawn_egg", "Zoglin Spawn Egg"))); + itemNames.add(new ItemName(Material.ZOMBIFIED_PIGLIN_SPAWN_EGG, langConfig.getString("item.minecraft.zombified_piglin_spawn_egg", "Zombified Piglin Spawn Egg"))); + + if (Utils.getMajorVersion() > 16 || Utils.getRevision() >= 2) { + // Add 1.16.2 item names + itemNames.add(new ItemName(Material.PIGLIN_BRUTE_SPAWN_EGG, langConfig.getString("item.minecraft.piglin_brute_spawn_egg", "Piglin Brute Spawn Egg"))); + } + } else { + // Add pre-1.16 item names that don't exist anymore + itemNames.add(new ItemName(Material.valueOf("ZOMBIE_PIGMAN_SPAWN_EGG"), langConfig.getString("item.minecraft.zombie_pigman_spawn_egg", "Zombie Pigman Spawn Egg"))); + } + + if (Utils.getMajorVersion() >= 17) { + itemNames.add(new ItemName(Material.AMETHYST_BLOCK, langConfig.getString("block.minecraft.amethyst_block", "Block of Amethyst"))); + itemNames.add(new ItemName(Material.AMETHYST_CLUSTER, langConfig.getString("block.minecraft.amethyst_cluster", "Amethyst Cluster"))); + itemNames.add(new ItemName(Material.AZALEA, langConfig.getString("block.minecraft.azalea", "Azalea"))); + itemNames.add(new ItemName(Material.AZALEA_LEAVES, langConfig.getString("block.minecraft.azalea_leaves", "Azalea Leaves"))); + itemNames.add(new ItemName(Material.BIG_DRIPLEAF, langConfig.getString("block.minecraft.big_dripleaf", "Big Dripleaf"))); + itemNames.add(new ItemName(Material.BIG_DRIPLEAF_STEM, langConfig.getString("block.minecraft.big_dripleaf_stem", "Big Dripleaf Stem"))); + itemNames.add(new ItemName(Material.BLACK_BANNER, langConfig.getString("block.minecraft.black_banner", "Black Banner"))); + itemNames.add(new ItemName(Material.BLACK_CANDLE, langConfig.getString("block.minecraft.black_candle", "Black Candle"))); + itemNames.add(new ItemName(Material.BLACK_CANDLE_CAKE, langConfig.getString("block.minecraft.black_candle_cake", "Cake with Black Candle"))); + itemNames.add(new ItemName(Material.BLUE_BANNER, langConfig.getString("block.minecraft.blue_banner", "Blue Banner"))); + itemNames.add(new ItemName(Material.BLUE_CANDLE, langConfig.getString("block.minecraft.blue_candle", "Blue Candle"))); + itemNames.add(new ItemName(Material.BLUE_CANDLE_CAKE, langConfig.getString("block.minecraft.blue_candle_cake", "Cake with Blue Candle"))); + itemNames.add(new ItemName(Material.BRAIN_CORAL_WALL_FAN, langConfig.getString("block.minecraft.brain_coral_wall_fan", "Brain Coral Wall Fan"))); + itemNames.add(new ItemName(Material.BROWN_BANNER, langConfig.getString("block.minecraft.brown_banner", "Brown Banner"))); + itemNames.add(new ItemName(Material.BROWN_CANDLE, langConfig.getString("block.minecraft.brown_candle", "Brown Candle"))); + itemNames.add(new ItemName(Material.BROWN_CANDLE_CAKE, langConfig.getString("block.minecraft.brown_candle_cake", "Cake with Brown Candle"))); + itemNames.add(new ItemName(Material.BUBBLE_CORAL_WALL_FAN, langConfig.getString("block.minecraft.bubble_coral_wall_fan", "Bubble Coral Wall Fan"))); + itemNames.add(new ItemName(Material.BUDDING_AMETHYST, langConfig.getString("block.minecraft.budding_amethyst", "Budding Amethyst"))); + itemNames.add(new ItemName(Material.CALCITE, langConfig.getString("block.minecraft.calcite", "Calcite"))); + itemNames.add(new ItemName(Material.CANDLE, langConfig.getString("block.minecraft.candle", "Candle"))); + itemNames.add(new ItemName(Material.CANDLE_CAKE, langConfig.getString("block.minecraft.candle_cake", "Cake with Candle"))); + itemNames.add(new ItemName(Material.CAVE_VINES, langConfig.getString("block.minecraft.cave_vines", "Cave Vines"))); + itemNames.add(new ItemName(Material.CAVE_VINES_PLANT, langConfig.getString("block.minecraft.cave_vines_plant", "Cave Vines Plant"))); + itemNames.add(new ItemName(Material.CHISELED_DEEPSLATE, langConfig.getString("block.minecraft.chiseled_deepslate", "Chiseled Deepslate"))); + itemNames.add(new ItemName(Material.COBBLED_DEEPSLATE, langConfig.getString("block.minecraft.cobbled_deepslate", "Cobbled Deepslate"))); + itemNames.add(new ItemName(Material.COBBLED_DEEPSLATE_SLAB, langConfig.getString("block.minecraft.cobbled_deepslate_slab", "Cobbled Deepslate Slab"))); + itemNames.add(new ItemName(Material.COBBLED_DEEPSLATE_STAIRS, langConfig.getString("block.minecraft.cobbled_deepslate_stairs", "Cobbled Deepslate Stairs"))); + itemNames.add(new ItemName(Material.COBBLED_DEEPSLATE_WALL, langConfig.getString("block.minecraft.cobbled_deepslate_wall", "Cobbled Deepslate Wall"))); + itemNames.add(new ItemName(Material.COPPER_BLOCK, langConfig.getString("block.minecraft.copper_block", "Block of Copper"))); + itemNames.add(new ItemName(Material.COPPER_ORE, langConfig.getString("block.minecraft.copper_ore", "Copper Ore"))); + itemNames.add(new ItemName(Material.CRACKED_DEEPSLATE_BRICKS, langConfig.getString("block.minecraft.cracked_deepslate_bricks", "Cracked Deepslate Bricks"))); + itemNames.add(new ItemName(Material.CRACKED_DEEPSLATE_TILES, langConfig.getString("block.minecraft.cracked_deepslate_tiles", "Cracked Deepslate Tiles"))); + itemNames.add(new ItemName(Material.CUT_COPPER, langConfig.getString("block.minecraft.cut_copper", "Cut Copper"))); + itemNames.add(new ItemName(Material.CUT_COPPER_SLAB, langConfig.getString("block.minecraft.cut_copper_slab", "Cut Copper Slab"))); + itemNames.add(new ItemName(Material.CUT_COPPER_STAIRS, langConfig.getString("block.minecraft.cut_copper_stairs", "Cut Copper Stairs"))); + itemNames.add(new ItemName(Material.CYAN_BANNER, langConfig.getString("block.minecraft.cyan_banner", "Cyan Banner"))); + itemNames.add(new ItemName(Material.CYAN_CANDLE, langConfig.getString("block.minecraft.cyan_candle", "Cyan Candle"))); + itemNames.add(new ItemName(Material.CYAN_CANDLE_CAKE, langConfig.getString("block.minecraft.cyan_candle_cake", "Cake with Cyan Candle"))); + itemNames.add(new ItemName(Material.DEAD_BRAIN_CORAL_FAN, langConfig.getString("block.minecraft.dead_brain_coral_fan", "Dead Brain Coral Fan"))); + itemNames.add(new ItemName(Material.DEAD_BRAIN_CORAL_WALL_FAN, langConfig.getString("block.minecraft.dead_brain_coral_wall_fan", "Dead Brain Coral Wall Fan"))); + itemNames.add(new ItemName(Material.DEAD_BUBBLE_CORAL_FAN, langConfig.getString("block.minecraft.dead_bubble_coral_fan", "Dead Bubble Coral Fan"))); + itemNames.add(new ItemName(Material.DEAD_BUBBLE_CORAL_WALL_FAN, langConfig.getString("block.minecraft.dead_bubble_coral_wall_fan", "Dead Bubble Coral Wall Fan"))); + itemNames.add(new ItemName(Material.DEAD_FIRE_CORAL_FAN, langConfig.getString("block.minecraft.dead_fire_coral_fan", "Dead Fire Coral Fan"))); + itemNames.add(new ItemName(Material.DEAD_FIRE_CORAL_WALL_FAN, langConfig.getString("block.minecraft.dead_fire_coral_wall_fan", "Dead Fire Coral Wall Fan"))); + itemNames.add(new ItemName(Material.DEAD_HORN_CORAL_FAN, langConfig.getString("block.minecraft.dead_horn_coral_fan", "Dead Horn Coral Fan"))); + itemNames.add(new ItemName(Material.DEAD_HORN_CORAL_WALL_FAN, langConfig.getString("block.minecraft.dead_horn_coral_wall_fan", "Dead Horn Coral Wall Fan"))); + itemNames.add(new ItemName(Material.DEAD_TUBE_CORAL_FAN, langConfig.getString("block.minecraft.dead_tube_coral_fan", "Dead Tube Coral Fan"))); + itemNames.add(new ItemName(Material.DEAD_TUBE_CORAL_WALL_FAN, langConfig.getString("block.minecraft.dead_tube_coral_wall_fan", "Dead Tube Coral Wall Fan"))); + itemNames.add(new ItemName(Material.DEEPSLATE, langConfig.getString("block.minecraft.deepslate", "Deepslate"))); + itemNames.add(new ItemName(Material.DEEPSLATE_BRICK_SLAB, langConfig.getString("block.minecraft.deepslate_brick_slab", "Deepslate Brick Slab"))); + itemNames.add(new ItemName(Material.DEEPSLATE_BRICK_STAIRS, langConfig.getString("block.minecraft.deepslate_brick_stairs", "Deepslate Brick Stairs"))); + itemNames.add(new ItemName(Material.DEEPSLATE_BRICK_WALL, langConfig.getString("block.minecraft.deepslate_brick_wall", "Deepslate Brick Wall"))); + itemNames.add(new ItemName(Material.DEEPSLATE_BRICKS, langConfig.getString("block.minecraft.deepslate_bricks", "Deepslate Bricks"))); + itemNames.add(new ItemName(Material.DEEPSLATE_COAL_ORE, langConfig.getString("block.minecraft.deepslate_coal_ore", "Deepslate Coal Ore"))); + itemNames.add(new ItemName(Material.DEEPSLATE_COPPER_ORE, langConfig.getString("block.minecraft.deepslate_copper_ore", "Deepslate Copper Ore"))); + itemNames.add(new ItemName(Material.DEEPSLATE_DIAMOND_ORE, langConfig.getString("block.minecraft.deepslate_diamond_ore", "Deepslate Diamond Ore"))); + itemNames.add(new ItemName(Material.DEEPSLATE_EMERALD_ORE, langConfig.getString("block.minecraft.deepslate_emerald_ore", "Deepslate Emerald Ore"))); + itemNames.add(new ItemName(Material.DEEPSLATE_GOLD_ORE, langConfig.getString("block.minecraft.deepslate_gold_ore", "Deepslate Gold Ore"))); + itemNames.add(new ItemName(Material.DEEPSLATE_IRON_ORE, langConfig.getString("block.minecraft.deepslate_iron_ore", "Deepslate Iron Ore"))); + itemNames.add(new ItemName(Material.DEEPSLATE_LAPIS_ORE, langConfig.getString("block.minecraft.deepslate_lapis_ore", "Deepslate Lapis Lazuli Ore"))); + itemNames.add(new ItemName(Material.DEEPSLATE_REDSTONE_ORE, langConfig.getString("block.minecraft.deepslate_redstone_ore", "Deepslate Redstone Ore"))); + itemNames.add(new ItemName(Material.DEEPSLATE_TILE_SLAB, langConfig.getString("block.minecraft.deepslate_tile_slab", "Deepslate Tile Slab"))); + itemNames.add(new ItemName(Material.DEEPSLATE_TILE_STAIRS, langConfig.getString("block.minecraft.deepslate_tile_stairs", "Deepslate Tile Stairs"))); + itemNames.add(new ItemName(Material.DEEPSLATE_TILE_WALL, langConfig.getString("block.minecraft.deepslate_tile_wall", "Deepslate Tile Wall"))); + itemNames.add(new ItemName(Material.DEEPSLATE_TILES, langConfig.getString("block.minecraft.deepslate_tiles", "Deepslate Tiles"))); + itemNames.add(new ItemName(Material.DIRT_PATH, langConfig.getString("block.minecraft.dirt_path", "Dirt Path"))); + itemNames.add(new ItemName(Material.DRIPSTONE_BLOCK, langConfig.getString("block.minecraft.dripstone_block", "Dripstone Block"))); + itemNames.add(new ItemName(Material.EXPOSED_COPPER, langConfig.getString("block.minecraft.exposed_copper", "Exposed Copper"))); + itemNames.add(new ItemName(Material.EXPOSED_CUT_COPPER, langConfig.getString("block.minecraft.exposed_cut_copper", "Exposed Cut Copper"))); + itemNames.add(new ItemName(Material.EXPOSED_CUT_COPPER_SLAB, langConfig.getString("block.minecraft.exposed_cut_copper_slab", "Exposed Cut Copper Slab"))); + itemNames.add(new ItemName(Material.EXPOSED_CUT_COPPER_STAIRS, langConfig.getString("block.minecraft.exposed_cut_copper_stairs", "Exposed Cut Copper Stairs"))); + itemNames.add(new ItemName(Material.FIRE_CORAL_WALL_FAN, langConfig.getString("block.minecraft.fire_coral_wall_fan", "Fire Coral Wall Fan"))); + itemNames.add(new ItemName(Material.FLOWERING_AZALEA, langConfig.getString("block.minecraft.flowering_azalea", "Flowering Azalea"))); + itemNames.add(new ItemName(Material.FLOWERING_AZALEA_LEAVES, langConfig.getString("block.minecraft.flowering_azalea_leaves", "Flowering Azalea Leaves"))); + itemNames.add(new ItemName(Material.GLOW_LICHEN, langConfig.getString("block.minecraft.glow_lichen", "Glow Lichen"))); + itemNames.add(new ItemName(Material.GRAY_BANNER, langConfig.getString("block.minecraft.gray_banner", "Gray Banner"))); + itemNames.add(new ItemName(Material.GRAY_CANDLE, langConfig.getString("block.minecraft.gray_candle", "Gray Candle"))); + itemNames.add(new ItemName(Material.GRAY_CANDLE_CAKE, langConfig.getString("block.minecraft.gray_candle_cake", "Cake with Gray Candle"))); + itemNames.add(new ItemName(Material.GREEN_BANNER, langConfig.getString("block.minecraft.green_banner", "Green Banner"))); + itemNames.add(new ItemName(Material.GREEN_CANDLE, langConfig.getString("block.minecraft.green_candle", "Green Candle"))); + itemNames.add(new ItemName(Material.GREEN_CANDLE_CAKE, langConfig.getString("block.minecraft.green_candle_cake", "Cake with Green Candle"))); + itemNames.add(new ItemName(Material.HANGING_ROOTS, langConfig.getString("block.minecraft.hanging_roots", "Hanging Roots"))); + itemNames.add(new ItemName(Material.HORN_CORAL_WALL_FAN, langConfig.getString("block.minecraft.horn_coral_wall_fan", "Horn Coral Wall Fan"))); + itemNames.add(new ItemName(Material.INFESTED_DEEPSLATE, langConfig.getString("block.minecraft.infested_deepslate", "Infested Deepslate"))); + itemNames.add(new ItemName(Material.LARGE_AMETHYST_BUD, langConfig.getString("block.minecraft.large_amethyst_bud", "Large Amethyst Bud"))); + itemNames.add(new ItemName(Material.LAVA_CAULDRON, langConfig.getString("block.minecraft.lava_cauldron", "Lava Cauldron"))); + itemNames.add(new ItemName(Material.LIGHT, langConfig.getString("block.minecraft.light", "Light"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_BANNER, langConfig.getString("block.minecraft.light_blue_banner", "Light Blue Banner"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_CANDLE, langConfig.getString("block.minecraft.light_blue_candle", "Light Blue Candle"))); + itemNames.add(new ItemName(Material.LIGHT_BLUE_CANDLE_CAKE, langConfig.getString("block.minecraft.light_blue_candle_cake", "Cake with Light Blue Candle"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_BANNER, langConfig.getString("block.minecraft.light_gray_banner", "Light Gray Banner"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_CANDLE, langConfig.getString("block.minecraft.light_gray_candle", "Light Gray Candle"))); + itemNames.add(new ItemName(Material.LIGHT_GRAY_CANDLE_CAKE, langConfig.getString("block.minecraft.light_gray_candle_cake", "Cake with Light Gray Candle"))); + itemNames.add(new ItemName(Material.LIGHTNING_ROD, langConfig.getString("block.minecraft.lightning_rod", "Lightning Rod"))); + itemNames.add(new ItemName(Material.LIME_BANNER, langConfig.getString("block.minecraft.lime_banner", "Lime Banner"))); + itemNames.add(new ItemName(Material.LIME_CANDLE, langConfig.getString("block.minecraft.lime_candle", "Lime Candle"))); + itemNames.add(new ItemName(Material.LIME_CANDLE_CAKE, langConfig.getString("block.minecraft.lime_candle_cake", "Cake with Lime Candle"))); + itemNames.add(new ItemName(Material.MAGENTA_BANNER, langConfig.getString("block.minecraft.magenta_banner", "Magenta Banner"))); + itemNames.add(new ItemName(Material.MAGENTA_CANDLE, langConfig.getString("block.minecraft.magenta_candle", "Magenta Candle"))); + itemNames.add(new ItemName(Material.MAGENTA_CANDLE_CAKE, langConfig.getString("block.minecraft.magenta_candle_cake", "Cake with Magenta Candle"))); + itemNames.add(new ItemName(Material.MEDIUM_AMETHYST_BUD, langConfig.getString("block.minecraft.medium_amethyst_bud", "Medium Amethyst Bud"))); + itemNames.add(new ItemName(Material.MOSS_BLOCK, langConfig.getString("block.minecraft.moss_block", "Moss Block"))); + itemNames.add(new ItemName(Material.MOSS_CARPET, langConfig.getString("block.minecraft.moss_carpet", "Moss Carpet"))); + itemNames.add(new ItemName(Material.ORANGE_BANNER, langConfig.getString("block.minecraft.orange_banner", "Orange Banner"))); + itemNames.add(new ItemName(Material.ORANGE_CANDLE, langConfig.getString("block.minecraft.orange_candle", "Orange Candle"))); + itemNames.add(new ItemName(Material.ORANGE_CANDLE_CAKE, langConfig.getString("block.minecraft.orange_candle_cake", "Cake with Orange Candle"))); + itemNames.add(new ItemName(Material.OXIDIZED_COPPER, langConfig.getString("block.minecraft.oxidized_copper", "Oxidized Copper"))); + itemNames.add(new ItemName(Material.OXIDIZED_CUT_COPPER, langConfig.getString("block.minecraft.oxidized_cut_copper", "Oxidized Cut Copper"))); + itemNames.add(new ItemName(Material.OXIDIZED_CUT_COPPER_SLAB, langConfig.getString("block.minecraft.oxidized_cut_copper_slab", "Oxidized Cut Copper Slab"))); + itemNames.add(new ItemName(Material.OXIDIZED_CUT_COPPER_STAIRS, langConfig.getString("block.minecraft.oxidized_cut_copper_stairs", "Oxidized Cut Copper Stairs"))); + itemNames.add(new ItemName(Material.PINK_BANNER, langConfig.getString("block.minecraft.pink_banner", "Pink Banner"))); + itemNames.add(new ItemName(Material.PINK_CANDLE, langConfig.getString("block.minecraft.pink_candle", "Pink Candle"))); + itemNames.add(new ItemName(Material.PINK_CANDLE_CAKE, langConfig.getString("block.minecraft.pink_candle_cake", "Cake with Pink Candle"))); + itemNames.add(new ItemName(Material.POINTED_DRIPSTONE, langConfig.getString("block.minecraft.pointed_dripstone", "Pointed Dripstone"))); + itemNames.add(new ItemName(Material.POLISHED_DEEPSLATE, langConfig.getString("block.minecraft.polished_deepslate", "Polished Deepslate"))); + itemNames.add(new ItemName(Material.POLISHED_DEEPSLATE_SLAB, langConfig.getString("block.minecraft.polished_deepslate_slab", "Polished Deepslate Slab"))); + itemNames.add(new ItemName(Material.POLISHED_DEEPSLATE_STAIRS, langConfig.getString("block.minecraft.polished_deepslate_stairs", "Polished Deepslate Stairs"))); + itemNames.add(new ItemName(Material.POLISHED_DEEPSLATE_WALL, langConfig.getString("block.minecraft.polished_deepslate_wall", "Polished Deepslate Wall"))); + itemNames.add(new ItemName(Material.POTTED_AZALEA_BUSH, langConfig.getString("block.minecraft.potted_azalea_bush", "Potted Azalea Bush"))); + itemNames.add(new ItemName(Material.POTTED_FLOWERING_AZALEA_BUSH, langConfig.getString("block.minecraft.potted_flowering_azalea_bush", "Potted Flowering Azalea"))); + itemNames.add(new ItemName(Material.POWDER_SNOW, langConfig.getString("block.minecraft.powder_snow", "Powder Snow"))); + itemNames.add(new ItemName(Material.POWDER_SNOW_CAULDRON, langConfig.getString("block.minecraft.powder_snow_cauldron", "Powder Snow Cauldron"))); + itemNames.add(new ItemName(Material.PURPLE_BANNER, langConfig.getString("block.minecraft.purple_banner", "Purple Banner"))); + itemNames.add(new ItemName(Material.PURPLE_CANDLE, langConfig.getString("block.minecraft.purple_candle", "Purple Candle"))); + itemNames.add(new ItemName(Material.PURPLE_CANDLE_CAKE, langConfig.getString("block.minecraft.purple_candle_cake", "Cake with Purple Candle"))); + itemNames.add(new ItemName(Material.RAW_COPPER_BLOCK, langConfig.getString("block.minecraft.raw_copper_block", "Block of Raw Copper"))); + itemNames.add(new ItemName(Material.RAW_GOLD_BLOCK, langConfig.getString("block.minecraft.raw_gold_block", "Block of Raw Gold"))); + itemNames.add(new ItemName(Material.RAW_IRON_BLOCK, langConfig.getString("block.minecraft.raw_iron_block", "Block of Raw Iron"))); + itemNames.add(new ItemName(Material.RED_BANNER, langConfig.getString("block.minecraft.red_banner", "Red Banner"))); + itemNames.add(new ItemName(Material.RED_CANDLE, langConfig.getString("block.minecraft.red_candle", "Red Candle"))); + itemNames.add(new ItemName(Material.RED_CANDLE_CAKE, langConfig.getString("block.minecraft.red_candle_cake", "Cake with Red Candle"))); + itemNames.add(new ItemName(Material.ROOTED_DIRT, langConfig.getString("block.minecraft.rooted_dirt", "Rooted Dirt"))); + itemNames.add(new ItemName(Material.SCULK_SENSOR, langConfig.getString("block.minecraft.sculk_sensor", "Sculk Sensor"))); + itemNames.add(new ItemName(Material.SMALL_AMETHYST_BUD, langConfig.getString("block.minecraft.small_amethyst_bud", "Small Amethyst Bud"))); + itemNames.add(new ItemName(Material.SMALL_DRIPLEAF, langConfig.getString("block.minecraft.small_dripleaf", "Small Dripleaf"))); + itemNames.add(new ItemName(Material.SMOOTH_BASALT, langConfig.getString("block.minecraft.smooth_basalt", "Smooth Basalt"))); + itemNames.add(new ItemName(Material.SPORE_BLOSSOM, langConfig.getString("block.minecraft.spore_blossom", "Spore Blossom"))); + itemNames.add(new ItemName(Material.STONE_STAIRS, langConfig.getString("block.minecraft.stone_stairs", "Stone Stairs"))); + itemNames.add(new ItemName(Material.TINTED_GLASS, langConfig.getString("block.minecraft.tinted_glass", "Tinted Glass"))); + itemNames.add(new ItemName(Material.TUBE_CORAL_WALL_FAN, langConfig.getString("block.minecraft.tube_coral_wall_fan", "Tube Coral Wall Fan"))); + itemNames.add(new ItemName(Material.TUFF, langConfig.getString("block.minecraft.tuff", "Tuff"))); + itemNames.add(new ItemName(Material.WATER_CAULDRON, langConfig.getString("block.minecraft.water_cauldron", "Water Cauldron"))); + itemNames.add(new ItemName(Material.WAXED_COPPER_BLOCK, langConfig.getString("block.minecraft.waxed_copper_block", "Waxed Block of Copper"))); + itemNames.add(new ItemName(Material.WAXED_CUT_COPPER, langConfig.getString("block.minecraft.waxed_cut_copper", "Waxed Cut Copper"))); + itemNames.add(new ItemName(Material.WAXED_CUT_COPPER_SLAB, langConfig.getString("block.minecraft.waxed_cut_copper_slab", "Waxed Cut Copper Slab"))); + itemNames.add(new ItemName(Material.WAXED_CUT_COPPER_STAIRS, langConfig.getString("block.minecraft.waxed_cut_copper_stairs", "Waxed Cut Copper Stairs"))); + itemNames.add(new ItemName(Material.WAXED_EXPOSED_COPPER, langConfig.getString("block.minecraft.waxed_exposed_copper", "Waxed Exposed Copper"))); + itemNames.add(new ItemName(Material.WAXED_EXPOSED_CUT_COPPER, langConfig.getString("block.minecraft.waxed_exposed_cut_copper", "Waxed Exposed Cut Copper"))); + itemNames.add(new ItemName(Material.WAXED_EXPOSED_CUT_COPPER_SLAB, langConfig.getString("block.minecraft.waxed_exposed_cut_copper_slab", "Waxed Exposed Cut Copper Slab"))); + itemNames.add(new ItemName(Material.WAXED_EXPOSED_CUT_COPPER_STAIRS, langConfig.getString("block.minecraft.waxed_exposed_cut_copper_stairs", "Waxed Exposed Cut Copper Stairs"))); + itemNames.add(new ItemName(Material.WAXED_OXIDIZED_COPPER, langConfig.getString("block.minecraft.waxed_oxidized_copper", "Waxed Oxidized Copper"))); + itemNames.add(new ItemName(Material.WAXED_OXIDIZED_CUT_COPPER, langConfig.getString("block.minecraft.waxed_oxidized_cut_copper", "Waxed Oxidized Cut Copper"))); + itemNames.add(new ItemName(Material.WAXED_OXIDIZED_CUT_COPPER_SLAB, langConfig.getString("block.minecraft.waxed_oxidized_cut_copper_slab", "Waxed Oxidized Cut Copper Slab"))); + itemNames.add(new ItemName(Material.WAXED_OXIDIZED_CUT_COPPER_STAIRS, langConfig.getString("block.minecraft.waxed_oxidized_cut_copper_stairs", "Waxed Oxidized Cut Copper Stairs"))); + itemNames.add(new ItemName(Material.WAXED_WEATHERED_COPPER, langConfig.getString("block.minecraft.waxed_weathered_copper", "Waxed Weathered Copper"))); + itemNames.add(new ItemName(Material.WAXED_WEATHERED_CUT_COPPER, langConfig.getString("block.minecraft.waxed_weathered_cut_copper", "Waxed Weathered Cut Copper"))); + itemNames.add(new ItemName(Material.WAXED_WEATHERED_CUT_COPPER_SLAB, langConfig.getString("block.minecraft.waxed_weathered_cut_copper_slab", "Waxed Weathered Cut Copper Slab"))); + itemNames.add(new ItemName(Material.WAXED_WEATHERED_CUT_COPPER_STAIRS, langConfig.getString("block.minecraft.waxed_weathered_cut_copper_stairs", "Waxed Weathered Cut Copper Stairs"))); + itemNames.add(new ItemName(Material.WEATHERED_COPPER, langConfig.getString("block.minecraft.weathered_copper", "Weathered Copper"))); + itemNames.add(new ItemName(Material.WEATHERED_CUT_COPPER, langConfig.getString("block.minecraft.weathered_cut_copper", "Weathered Cut Copper"))); + itemNames.add(new ItemName(Material.WEATHERED_CUT_COPPER_SLAB, langConfig.getString("block.minecraft.weathered_cut_copper_slab", "Weathered Cut Copper Slab"))); + itemNames.add(new ItemName(Material.WEATHERED_CUT_COPPER_STAIRS, langConfig.getString("block.minecraft.weathered_cut_copper_stairs", "Weathered Cut Copper Stairs"))); + itemNames.add(new ItemName(Material.WHITE_BANNER, langConfig.getString("block.minecraft.white_banner", "White Banner"))); + itemNames.add(new ItemName(Material.WHITE_CANDLE, langConfig.getString("block.minecraft.white_candle", "White Candle"))); + itemNames.add(new ItemName(Material.WHITE_CANDLE_CAKE, langConfig.getString("block.minecraft.white_candle_cake", "Cake with White Candle"))); + itemNames.add(new ItemName(Material.YELLOW_BANNER, langConfig.getString("block.minecraft.yellow_banner", "Yellow Banner"))); + itemNames.add(new ItemName(Material.YELLOW_CANDLE, langConfig.getString("block.minecraft.yellow_candle", "Yellow Candle"))); + itemNames.add(new ItemName(Material.YELLOW_CANDLE_CAKE, langConfig.getString("block.minecraft.yellow_candle_cake", "Cake with Yellow Candle"))); + itemNames.add(new ItemName(Material.AMETHYST_SHARD, langConfig.getString("item.minecraft.amethyst_shard", "Amethyst Shard"))); + itemNames.add(new ItemName(Material.AXOLOTL_BUCKET, langConfig.getString("item.minecraft.axolotl_bucket", "Bucket of Axolotl"))); + itemNames.add(new ItemName(Material.AXOLOTL_SPAWN_EGG, langConfig.getString("item.minecraft.axolotl_spawn_egg", "Axolotl Spawn Egg"))); + itemNames.add(new ItemName(Material.BUNDLE, langConfig.getString("item.minecraft.bundle", "Bundle"))); + itemNames.add(new ItemName(Material.COPPER_INGOT, langConfig.getString("item.minecraft.copper_ingot", "Copper Ingot"))); + itemNames.add(new ItemName(Material.GLOW_BERRIES, langConfig.getString("item.minecraft.glow_berries", "Glow Berries"))); + itemNames.add(new ItemName(Material.GLOW_INK_SAC, langConfig.getString("item.minecraft.glow_ink_sac", "Glow Ink Sac"))); + itemNames.add(new ItemName(Material.GLOW_ITEM_FRAME, langConfig.getString("item.minecraft.glow_item_frame", "Glow Item Frame"))); + itemNames.add(new ItemName(Material.GLOW_SQUID_SPAWN_EGG, langConfig.getString("item.minecraft.glow_squid_spawn_egg", "Glow Squid Spawn Egg"))); + itemNames.add(new ItemName(Material.GOAT_SPAWN_EGG, langConfig.getString("item.minecraft.goat_spawn_egg", "Goat Spawn Egg"))); + itemNames.add(new ItemName(Material.PIGLIN_BANNER_PATTERN, langConfig.getString("item.minecraft.piglin_banner_pattern", "Banner Pattern"))); + itemNames.add(new ItemName(Material.POWDER_SNOW_BUCKET, langConfig.getString("item.minecraft.powder_snow_bucket", "Powder Snow Bucket"))); + itemNames.add(new ItemName(Material.RAW_COPPER, langConfig.getString("item.minecraft.raw_copper", "Raw Copper"))); + itemNames.add(new ItemName(Material.RAW_GOLD, langConfig.getString("item.minecraft.raw_gold", "Raw Gold"))); + itemNames.add(new ItemName(Material.RAW_IRON, langConfig.getString("item.minecraft.raw_iron", "Raw Iron"))); + itemNames.add(new ItemName(Material.SHIELD, langConfig.getString("item.minecraft.shield", "Shield"))); + itemNames.add(new ItemName(Material.SPYGLASS, langConfig.getString("item.minecraft.spyglass", "Spyglass"))); + } else { + itemNames.add(new ItemName(Material.valueOf("GRASS_PATH"), langConfig.getString("block.minecraft.grass_path", "Grass Path"))); + } + + // Add Enchantment Names + enchantmentNames.add(new EnchantmentName(Enchantment.DAMAGE_ALL, langConfig.getString("enchantment.minecraft.sharpness", "Sharpness"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DAMAGE_UNDEAD, langConfig.getString("enchantment.minecraft.smite", "Smite"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DAMAGE_ARTHROPODS, langConfig.getString("enchantment.minecraft.bane_of_arthropods", "Bane of Arthropods"))); + enchantmentNames.add(new EnchantmentName(Enchantment.KNOCKBACK, langConfig.getString("enchantment.minecraft.knockback", "Knockback"))); + enchantmentNames.add(new EnchantmentName(Enchantment.FIRE_ASPECT, langConfig.getString("enchantment.minecraft.fire_aspect", "Fire Aspect"))); + enchantmentNames.add(new EnchantmentName(Enchantment.SWEEPING_EDGE, langConfig.getString("enchantment.minecraft.sweeping", "Sweeping Edge"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_ENVIRONMENTAL, langConfig.getString("enchantment.minecraft.protection", "Protection"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_FIRE, langConfig.getString("enchantment.minecraft.fire_protection", "Fire Protection"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_FALL, langConfig.getString("enchantment.minecraft.feather_falling", "Feather Falling"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_EXPLOSIONS, langConfig.getString("enchantment.minecraft.blast_protection", "Blast Protection"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PROTECTION_PROJECTILE, langConfig.getString("enchantment.minecraft.projectile_protection", "Projectile Protection"))); + enchantmentNames.add(new EnchantmentName(Enchantment.OXYGEN, langConfig.getString("enchantment.minecraft.respiration", "Respiration"))); + enchantmentNames.add(new EnchantmentName(Enchantment.WATER_WORKER, langConfig.getString("enchantment.minecraft.aqua_affinity", "Aqua Affinity"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DEPTH_STRIDER, langConfig.getString("enchantment.minecraft.depth_strider", "Depth Strider"))); + enchantmentNames.add(new EnchantmentName(Enchantment.FROST_WALKER, langConfig.getString("enchantment.minecraft.frost_walker", "Frost Walker"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DIG_SPEED, langConfig.getString("enchantment.minecraft.efficiency", "Efficiency"))); + enchantmentNames.add(new EnchantmentName(Enchantment.SILK_TOUCH, langConfig.getString("enchantment.minecraft.silk_touch", "Silk Touch"))); + enchantmentNames.add(new EnchantmentName(Enchantment.DURABILITY, langConfig.getString("enchantment.minecraft.unbreaking", "Unbreaking"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LOOT_BONUS_MOBS, langConfig.getString("enchantment.minecraft.looting", "Looting"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LOOT_BONUS_BLOCKS, langConfig.getString("enchantment.minecraft.fortune", "Fortune"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LUCK, langConfig.getString("enchantment.minecraft.luck_of_the_sea", "Luck of the Sea"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LURE, langConfig.getString("enchantment.minecraft.lure", "Lure"))); + enchantmentNames.add(new EnchantmentName(Enchantment.ARROW_DAMAGE, langConfig.getString("enchantment.minecraft.power", "Power"))); + enchantmentNames.add(new EnchantmentName(Enchantment.ARROW_FIRE, langConfig.getString("enchantment.minecraft.flame", "Flame"))); + enchantmentNames.add(new EnchantmentName(Enchantment.ARROW_KNOCKBACK, langConfig.getString("enchantment.minecraft.punch", "Punch"))); + enchantmentNames.add(new EnchantmentName(Enchantment.ARROW_INFINITE, langConfig.getString("enchantment.minecraft.infinity", "Infinity"))); + enchantmentNames.add(new EnchantmentName(Enchantment.THORNS, langConfig.getString("enchantment.minecraft.thorns", "Thorns"))); + enchantmentNames.add(new EnchantmentName(Enchantment.MENDING, langConfig.getString("enchantment.minecraft.mending", "Mending"))); + enchantmentNames.add(new EnchantmentName(Enchantment.BINDING_CURSE, langConfig.getString("enchantment.minecraft.binding_curse", "Curse of Binding"))); + enchantmentNames.add(new EnchantmentName(Enchantment.VANISHING_CURSE, langConfig.getString("enchantment.minecraft.vanishing_curse", "Curse of Vanishing"))); + enchantmentNames.add(new EnchantmentName(Enchantment.LOYALTY, langConfig.getString("enchantment.minecraft.loyalty", "Loyalty"))); + enchantmentNames.add(new EnchantmentName(Enchantment.IMPALING, langConfig.getString("enchantment.minecraft.impaling", "Impaling"))); + enchantmentNames.add(new EnchantmentName(Enchantment.RIPTIDE, langConfig.getString("enchantment.minecraft.riptide", "Riptide"))); + enchantmentNames.add(new EnchantmentName(Enchantment.CHANNELING, langConfig.getString("enchantment.minecraft.channeling", "Channeling"))); + + if (Utils.getMajorVersion() >= 17) { + // Add 1.17 enchantment name + enchantmentNames.add(new EnchantmentName(Enchantment.SOUL_SPEED, langConfig.getString("enchantment.minecraft.soul_speed", "Soul Speed"))); + } + + if (Utils.getMajorVersion() >= 14) { + // Add 1.14 enchantment names + enchantmentNames.add(new EnchantmentName(Enchantment.MULTISHOT, langConfig.getString("enchantment.minecraft.multishot", "Multishot"))); + enchantmentNames.add(new EnchantmentName(Enchantment.QUICK_CHARGE, langConfig.getString("enchantment.minecraft.quick_charge", "Quick Charge"))); + enchantmentNames.add(new EnchantmentName(Enchantment.PIERCING, langConfig.getString("enchantment.minecraft.piercing", "Piercing"))); + } + + // Add Enchantment Level Names + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(1, langConfig.getString("enchantment.level.1", "I"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(2, langConfig.getString("enchantment.level.2", "II"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(3, langConfig.getString("enchantment.level.3", "II"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(4, langConfig.getString("enchantment.level.4", "IV"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(5, langConfig.getString("enchantment.level.5", "V"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(6, langConfig.getString("enchantment.level.6", "VI"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(7, langConfig.getString("enchantment.level.7", "VII"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(8, langConfig.getString("enchantment.level.8", "VIII"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(9, langConfig.getString("enchantment.level.9", "IX"))); + enchantmentLevelNames.add(new EnchantmentName.EnchantmentLevelName(10, langConfig.getString("enchantment.level.10", "X"))); + + // Add Potion Effect Names + potionEffectNames.add(new PotionEffectName(PotionEffectType.SPEED, langConfig.getString("effect.minecraft.speed", "Speed"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.SLOW, langConfig.getString("effect.minecraft.slowness", "Slowness"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.FAST_DIGGING, langConfig.getString("effect.minecraft.haste", "Haste"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.SLOW_DIGGING, langConfig.getString("effect.minecraft.mining_fatigue", "Mining Fatigue"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.INCREASE_DAMAGE, langConfig.getString("effect.minecraft.strength", "Strength"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.HEAL, langConfig.getString("effect.minecraft.instant_health", "Instant Health"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.HARM, langConfig.getString("effect.minecraft.instant_damage", "Instant Damage"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.JUMP, langConfig.getString("effect.minecraft.jump_boost", "Jump Boost"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.CONFUSION, langConfig.getString("effect.minecraft.nausea", "Nausea"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.REGENERATION, langConfig.getString("effect.minecraft.regeneration", "Regeneration"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.DAMAGE_RESISTANCE, langConfig.getString("effect.minecraft.resistance", "Resistance"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.FIRE_RESISTANCE, langConfig.getString("effect.minecraft.fire_resistance", "Fire Resistance"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.WATER_BREATHING, langConfig.getString("effect.minecraft.water_breathing", "Water Breathing"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.INVISIBILITY, langConfig.getString("effect.minecraft.invisibility", "Invisibility"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.BLINDNESS, langConfig.getString("effect.minecraft.blindness", "Blindness"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.NIGHT_VISION, langConfig.getString("effect.minecraft.night_vision", "Night Vision"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.HUNGER, langConfig.getString("effect.minecraft.hunger", "Hunger"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.WEAKNESS, langConfig.getString("effect.minecraft.weakness", "Weakness"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.POISON, langConfig.getString("effect.minecraft.poison", "Poison"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.WITHER, langConfig.getString("effect.minecraft.wither", "Wither"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.HEALTH_BOOST, langConfig.getString("effect.minecraft.health_boost", "Health Boost"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.ABSORPTION, langConfig.getString("effect.minecraft.absorption", "Absorption"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.SATURATION, langConfig.getString("effect.minecraft.saturation", "Saturation"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.GLOWING, langConfig.getString("effect.minecraft.glowing", "Glowing"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.LUCK, langConfig.getString("effect.minecraft.luck", "Luck"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.UNLUCK, langConfig.getString("effect.minecraft.unluck", "Bad Luck"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.LEVITATION, langConfig.getString("effect.minecraft.levitation", "Levitation"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.SLOW_FALLING, langConfig.getString("effect.minecraft.slow_falling", "Slow Falling"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.CONDUIT_POWER, langConfig.getString("effect.minecraft.conduit_power", "Conduit Power"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.DOLPHINS_GRACE, langConfig.getString("effect.minecraft.dolphins_grace", "Dolphin's Grace"))); + + + if (Utils.getMajorVersion() >= 14) { + // Add 1.14 potion effect names + potionEffectNames.add(new PotionEffectName(PotionEffectType.BAD_OMEN, langConfig.getString("effect.minecraft.bad_omen", "Bad Omen"))); + potionEffectNames.add(new PotionEffectName(PotionEffectType.HERO_OF_THE_VILLAGE, langConfig.getString("effect.minecraft.hero_of_the_village", "Hero of the Village"))); + + } + + // Add Potion Names + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.UNCRAFTABLE, langConfig.getString("item.minecraft.potion.effect.empty", "Uncraftable Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.WATER, langConfig.getString("item.minecraft.potion.effect.water", "Water Bottle"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.MUNDANE, langConfig.getString("item.minecraft.potion.effect.mundane", "Mundane Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.THICK, langConfig.getString("item.minecraft.potion.effect.thick", "Thick Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.AWKWARD, langConfig.getString("item.minecraft.potion.effect.awkward", "Awkward Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.NIGHT_VISION, langConfig.getString("item.minecraft.potion.effect.night_vision", "Potion of Night Vision"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.INVISIBILITY, langConfig.getString("item.minecraft.potion.effect.invisibility", "Potion of Invisibility"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.JUMP, langConfig.getString("item.minecraft.potion.effect.leaping", "Potion of Leaping"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.FIRE_RESISTANCE, langConfig.getString("item.minecraft.potion.effect.fire_resistance", "Potion of Fire Resistance"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.SPEED, langConfig.getString("item.minecraft.potion.effect.swiftness", "Potion of Swiftness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.SLOWNESS, langConfig.getString("item.minecraft.potion.effect.slowness", "Potion of Slowness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.WATER_BREATHING, langConfig.getString("item.minecraft.potion.effect.water_breathing", "Potion of Water Breathing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.INSTANT_HEAL, langConfig.getString("item.minecraft.potion.effect.healing", "Potion of Healing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.INSTANT_DAMAGE, langConfig.getString("item.minecraft.potion.effect.harming", "Potion of Harming"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.POISON, langConfig.getString("item.minecraft.potion.effect.poison", "Potion of Poison"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.REGEN, langConfig.getString("item.minecraft.potion.effect.regeneration", "Potion of Regeneration"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.STRENGTH, langConfig.getString("item.minecraft.potion.effect.strength", "Potion of Strength"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.WEAKNESS, langConfig.getString("item.minecraft.potion.effect.weakness", "Potion of Weakness"))); + //potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.LEVITATION, langConfig.getString("item.minecraft.potion.effect.levitation", "Potion of Levitation"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.LUCK, langConfig.getString("item.minecraft.potion.effect.luck", "Potion of Luck"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.TURTLE_MASTER, langConfig.getString("item.minecraft.potion.effect.turtle_master", "Potion of the Turtle Master"))); + potionNames.add(new PotionName(PotionName.PotionItemType.POTION, PotionType.SLOW_FALLING, langConfig.getString("item.minecraft.potion.effect.slow_falling", "Potion of Slow Falling"))); + + // Add Splash Potion Names + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.UNCRAFTABLE, langConfig.getString("item.minecraft.splash_potion.effect.empty", "Splash Uncraftable Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.WATER, langConfig.getString("item.minecraft.splash_potion.effect.water", "Splash Water Bottle"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.MUNDANE, langConfig.getString("item.minecraft.splash_potion.effect.mundane", "Mundane Splash Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.THICK, langConfig.getString("item.minecraft.splash_potion.effect.thick", "Thick Splash Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.AWKWARD, langConfig.getString("item.minecraft.splash_potion.effect.awkward", "Awkward Splash Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.NIGHT_VISION, langConfig.getString("item.minecraft.splash_potion.effect.night_vision", "Splash Potion of Night Vision"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.INVISIBILITY, langConfig.getString("item.minecraft.splash_potion.effect.invisibility", "Splash Potion of Invisibility"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.JUMP, langConfig.getString("item.minecraft.splash_potion.effect.leaping", "Splash Potion of Leaping"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.FIRE_RESISTANCE, langConfig.getString("item.minecraft.splash_potion.effect.fire_resistance", "Splash Potion of Fire Resistance"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.SPEED, langConfig.getString("item.minecraft.splash_potion.effect.swiftness", "Splash Potion of Swiftness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.SLOWNESS, langConfig.getString("item.minecraft.splash_potion.effect.slowness", "Splash Potion of Slowness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.WATER_BREATHING, langConfig.getString("item.minecraft.splash_potion.effect.water_breathing", "Splash Potion of Water Breathing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.INSTANT_HEAL, langConfig.getString("item.minecraft.splash_potion.effect.healing", "Splash Potion of Healing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.INSTANT_DAMAGE, langConfig.getString("item.minecraft.splash_potion.effect.harming", "Splash Potion of Harming"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.POISON, langConfig.getString("item.minecraft.splash_potion.effect.poison", "Splash Potion of Poison"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.REGEN, langConfig.getString("item.minecraft.splash_potion.effect.regeneration", "Splash Potion of Regeneration"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.STRENGTH, langConfig.getString("item.minecraft.splash_potion.effect.strength", "Splash Potion of Strength"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.WEAKNESS, langConfig.getString("item.minecraft.splash_potion.effect.weakness", "Splash Potion of Weakness"))); + //potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.LEVITATION, langConfig.getString("item.minecraft.splash_potion.effect.levitation", "Splash Potion of Levitation"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.LUCK, langConfig.getString("item.minecraft.splash_potion.effect.luck", "Splash Potion of Luck"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.TURTLE_MASTER, langConfig.getString("item.minecraft.splash_potion.effect.turtle_master", "Splash Potion of the Turtle Master"))); + potionNames.add(new PotionName(PotionName.PotionItemType.SPLASH_POTION, PotionType.SLOW_FALLING, langConfig.getString("item.minecraft.splash_potion.effect.slow_falling", "Splash Potion of Slow Falling"))); + + // Add Lingering Potion Names + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.UNCRAFTABLE, langConfig.getString("item.minecraft.lingering_potion.effect.empty", "Lingering Uncraftable Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.WATER, langConfig.getString("item.minecraft.lingering_potion.effect.water", "Lingering Water Bottle"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.MUNDANE, langConfig.getString("item.minecraft.lingering_potion.effect.mundane", "Mundane Lingering Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.THICK, langConfig.getString("item.minecraft.lingering_potion.effect.thick", "Thick Lingering Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.AWKWARD, langConfig.getString("item.minecraft.lingering_potion.effect.awkward", "Awkward Lingering Potion"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.NIGHT_VISION, langConfig.getString("item.minecraft.lingering_potion.effect.night_vision", "Lingering Potion of Night Vision"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.INVISIBILITY, langConfig.getString("item.minecraft.lingering_potion.effect.invisibility", "Lingering Potion of Invisibility"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.JUMP, langConfig.getString("item.minecraft.lingering_potion.effect.leaping", "Lingering Potion of Leaping"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.FIRE_RESISTANCE, langConfig.getString("item.minecraft.lingering_potion.effect.fire_resistance", "Lingering Potion of Fire Resistance"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.SPEED, langConfig.getString("item.minecraft.lingering_potion.effect.swiftness", "Lingering Potion of Swiftness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.SLOWNESS, langConfig.getString("item.minecraft.lingering_potion.effect.slowness", "Lingering Potion of Slowness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.WATER_BREATHING, langConfig.getString("item.minecraft.lingering_potion.effect.water_breathing", "Lingering Potion of Water Breathing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.INSTANT_HEAL, langConfig.getString("item.minecraft.lingering_potion.effect.healing", "Lingering Potion of Healing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.INSTANT_DAMAGE, langConfig.getString("item.minecraft.lingering_potion.effect.harming", "Lingering Potion of Harming"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.POISON, langConfig.getString("item.minecraft.lingering_potion.effect.poison", "Lingering Potion of Poison"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.REGEN, langConfig.getString("item.minecraft.lingering_potion.effect.regeneration", "Lingering Potion of Regeneration"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.STRENGTH, langConfig.getString("item.minecraft.lingering_potion.effect.strength", "Lingering Potion of Strength"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.WEAKNESS, langConfig.getString("item.minecraft.lingering_potion.effect.weakness", "Lingering Potion of Weakness"))); + //potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.LEVITATION, langConfig.getString("item.minecraft.lingering_potion.effect.levitation", "Lingering Potion of Levitation"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.LUCK, langConfig.getString("item.minecraft.lingering_potion.effect.luck", "Lingering Potion of Luck"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.TURTLE_MASTER, langConfig.getString("item.minecraft.lingering_potion.effect.turtle_master", "Lingering Potion of the Turtle Master"))); + potionNames.add(new PotionName(PotionName.PotionItemType.LINGERING_POTION, PotionType.SLOW_FALLING, langConfig.getString("item.minecraft.lingering_potion.effect.slow_falling", "Lingering Potion of Slow Falling"))); + + // Add Tipped Arrow Names + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.UNCRAFTABLE, langConfig.getString("item.minecraft.tipped_arrow.effect.empty", "Uncraftable Tipped Arrow"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.WATER, langConfig.getString("item.minecraft.tipped_arrow.effect.water", "Arrow of Splashing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.MUNDANE, langConfig.getString("item.minecraft.tipped_arrow.effect.mundane", "Tipped Arrow"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.THICK, langConfig.getString("item.minecraft.tipped_arrow.effect.thick", "Tipped Arrow"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.AWKWARD, langConfig.getString("item.minecraft.tipped_arrow.effect.awkward", "Tipped Arrow"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.NIGHT_VISION, langConfig.getString("item.minecraft.tipped_arrow.effect.night_vision", "Arrow of Night Vision"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.INVISIBILITY, langConfig.getString("item.minecraft.tipped_arrow.effect.invisibility", "Arrow of Invisibility"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.JUMP, langConfig.getString("item.minecraft.tipped_arrow.effect.leaping", "Arrow of Leaping"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.FIRE_RESISTANCE, langConfig.getString("item.minecraft.tipped_arrow.effect.fire_resistance", "Arrow of Fire Resistance"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.SPEED, langConfig.getString("item.minecraft.tipped_arrow.effect.swiftness", "Arrow of Swiftness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.SLOWNESS, langConfig.getString("item.minecraft.tipped_arrow.effect.slowness", "Arrow of Slowness"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.WATER_BREATHING, langConfig.getString("item.minecraft.tipped_arrow.effect.water_breathing", "Arrow of Water Breathing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.INSTANT_HEAL, langConfig.getString("item.minecraft.tipped_arrow.effect.healing", "Arrow of Healing"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.INSTANT_DAMAGE, langConfig.getString("item.minecraft.tipped_arrow.effect.harming", "Arrow of Harming"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.POISON, langConfig.getString("item.minecraft.tipped_arrow.effect.poison", "Arrow of Poison"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.REGEN, langConfig.getString("item.minecraft.tipped_arrow.effect.regeneration", "Arrow of Regeneration"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.STRENGTH, langConfig.getString("item.minecraft.tipped_arrow.effect.strength", "Arrow of Strength"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.WEAKNESS, langConfig.getString("item.minecraft.tipped_arrow.effect.weakness", "Arrow of Weakness"))); + //potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.LEVITATION, langConfig.getString("item.minecraft.tipped_arrow.effect.levitation", "Arrow of Levitation"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.LUCK, langConfig.getString("item.minecraft.tipped_arrow.effect.luck", "Arrow of Luck"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.TURTLE_MASTER, langConfig.getString("item.minecraft.tipped_arrow.effect.turtle_master", "Arrow of the Turtle Master"))); + potionNames.add(new PotionName(PotionName.PotionItemType.TIPPED_ARROW, PotionType.SLOW_FALLING, langConfig.getString("item.minecraft.tipped_arrow.effect.slow_falling", "Arrow of Slow Falling"))); + + // Add Music Disc Titles + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_13, langConfig.getString("item.minecraft.music_disc_13.desc", "C418 - 13"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_CAT, langConfig.getString("item.minecraft.music_disc_cat.desc", "C418 - cat"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_BLOCKS, langConfig.getString("item.minecraft.music_disc_blocks.desc", "C418 - blocks"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_CHIRP, langConfig.getString("item.minecraft.music_disc_chirp.desc", "C418 - chirp"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_FAR, langConfig.getString("item.minecraft.music_disc_far.desc", "C418 - far"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_MALL, langConfig.getString("item.minecraft.music_disc_mall.desc", "C418 - mall"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_MELLOHI, langConfig.getString("item.minecraft.music_disc_mellohi.desc", "C418 - mellohi"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_STAL, langConfig.getString("item.minecraft.music_disc_stal.desc", "C418 - stal"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_STRAD, langConfig.getString("item.minecraft.music_disc_strad.desc", "C418 - strad"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_WARD, langConfig.getString("item.minecraft.music_disc_ward.desc", "C418 - ward"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_11, langConfig.getString("item.minecraft.music_disc_11.desc", "C418 - 11"))); + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_WAIT, langConfig.getString("item.minecraft.music_disc_wait.desc", "C418 - wait"))); + + if (Utils.getMajorVersion() >= 16) { + musicDiscNames.add(new MusicDiscName(Material.MUSIC_DISC_PIGSTEP, langConfig.getString("item.minecraft.music_disc_pigstep.desc", "Lena Raine - Pigstep"))); + } + + if (Utils.getMajorVersion() >= 14) { + // Add Banner Pattern Names + bannerPatternNames.add(new BannerPatternName(Material.CREEPER_BANNER_PATTERN, langConfig.getString("item.minecraft.creeper_banner_pattern.desc", "Creeper Charge"))); + bannerPatternNames.add(new BannerPatternName(Material.SKULL_BANNER_PATTERN, langConfig.getString("item.minecraft.skull_banner_pattern.desc", "Skull Charge"))); + bannerPatternNames.add(new BannerPatternName(Material.FLOWER_BANNER_PATTERN, langConfig.getString("item.minecraft.flower_banner_pattern.desc", "Flower Charge"))); + bannerPatternNames.add(new BannerPatternName(Material.MOJANG_BANNER_PATTERN, langConfig.getString("item.minecraft.mojang_banner_pattern.desc", "Thing"))); + bannerPatternNames.add(new BannerPatternName(Material.GLOBE_BANNER_PATTERN, langConfig.getString("item.minecraft.globe_banner_pattern.desc", "Globe"))); + + if (Utils.getMajorVersion() >= 16) { + bannerPatternNames.add(new BannerPatternName(Material.PIGLIN_BANNER_PATTERN, langConfig.getString("item.minecraft.piglin_banner_pattern.desc", "Snout"))); + } + } + + // Add Book Generation Names + generationNames.add(new BookGenerationName(CustomBookMeta.Generation.ORIGINAL, langConfig.getString("book.generation.0", "Original"))); + generationNames.add(new BookGenerationName(CustomBookMeta.Generation.COPY_OF_ORIGINAL, langConfig.getString("book.generation.1", "Copy of original"))); + generationNames.add(new BookGenerationName(CustomBookMeta.Generation.COPY_OF_COPY, langConfig.getString("book.generation.2", "Copy of a copy"))); + generationNames.add(new BookGenerationName(CustomBookMeta.Generation.TATTERED, langConfig.getString("book.generation.3", "Tattered"))); + + loadMessages(); + } + + private static void loadMessages() { + // Add ShopChest Messages + messages.add(new LocalizedMessage(Message.SHOP_CREATED, langConfig.getString("message.shop-created", "&6You were withdrawn &c%CREATION-PRICE% &6to create this shop."))); + messages.add(new LocalizedMessage(Message.ADMIN_SHOP_CREATED, langConfig.getString("message.admin-shop-created", "&6You were withdrawn &c%CREATION-PRICE% &6to create this admin shop."))); + messages.add(new LocalizedMessage(Message.CHEST_ALREADY_SHOP, langConfig.getString("message.chest-already-shop", "&cChest already shop."))); + messages.add(new LocalizedMessage(Message.CHEST_BLOCKED, langConfig.getString("message.chest-blocked", "&cThere must not be a block above the chest."))); + messages.add(new LocalizedMessage(Message.DOUBLE_CHEST_BLOCKED, langConfig.getString("message.double-chest-blocked", "&cThere must not be a block above the chest."))); + messages.add(new LocalizedMessage(Message.SHOP_REMOVED, langConfig.getString("message.shop-removed", "&6Shop removed."))); + messages.add(new LocalizedMessage(Message.SHOP_REMOVED_REFUND, langConfig.getString("message.shop-removed-refund", "&6Shop removed. You were refunded &c%CREATION-PRICE%&6."))); + messages.add(new LocalizedMessage(Message.ALL_SHOPS_REMOVED, langConfig.getString("message.all-shops-removed", "&6Removed all (&c%AMOUNT%&6) shop/s of &c%VENDOR%&6."))); + messages.add(new LocalizedMessage(Message.CHEST_NO_SHOP, langConfig.getString("message.chest-no-shop", "&cChest is not a shop."))); + messages.add(new LocalizedMessage(Message.SHOP_CREATE_NOT_ENOUGH_MONEY, langConfig.getString("message.shop-create-not-enough-money", "&cNot enough money. You need &6%CREATION-PRICE% &cto create a shop."))); + messages.add(new LocalizedMessage(Message.SHOP_INFO_VENDOR, langConfig.getString("message.shopInfo.vendor", "&6Vendor: &e%VENDOR%"))); + messages.add(new LocalizedMessage(Message.SHOP_INFO_PRODUCT, langConfig.getString("message.shopInfo.product", "&6Product: &e%AMOUNT% x %ITEMNAME%"))); + messages.add(new LocalizedMessage(Message.SHOP_INFO_STOCK, langConfig.getString("message.shopInfo.stock", "&6In Stock: &e%STOCK%"))); + messages.add(new LocalizedMessage(Message.SHOP_INFO_CHEST_SPACE, langConfig.getString("message.shopInfo.chest-space", "&6Space in chest: &e%CHEST-SPACE%"))); + messages.add(new LocalizedMessage(Message.SHOP_INFO_PRICE, langConfig.getString("message.shopInfo.price", "&6Price: Buy: &e%BUY-PRICE%&6 Sell: &e%SELL-PRICE%"))); + messages.add(new LocalizedMessage(Message.SHOP_INFO_DISABLED, langConfig.getString("message.shopInfo.disabled", "&7Disabled"))); + messages.add(new LocalizedMessage(Message.SHOP_INFO_NORMAL, langConfig.getString("message.shopInfo.is-normal", "&6Type: &eNormal"))); + messages.add(new LocalizedMessage(Message.SHOP_INFO_ADMIN, langConfig.getString("message.shopInfo.is-admin", "&6Type: &eAdmin"))); + messages.add(new LocalizedMessage(Message.BUY_SELL_DISABLED, langConfig.getString("message.buy-and-sell-disabled", "&cYou can't create a shop with buying and selling disabled."))); + messages.add(new LocalizedMessage(Message.BUY_SUCCESS, langConfig.getString("message.buy-success", "&aYou bought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a from &6%VENDOR%&a."))); + messages.add(new LocalizedMessage(Message.BUY_SUCCESS_ADMIN, langConfig.getString("message.buy-success-admin", "&aYou bought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a."))); + messages.add(new LocalizedMessage(Message.SELL_SUCCESS, langConfig.getString("message.sell-success", "&aYou sold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to &6%VENDOR%&a."))); + messages.add(new LocalizedMessage(Message.SELL_SUCCESS_ADMIN, langConfig.getString("message.sell-success-admin", "&aYou sold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a."))); + messages.add(new LocalizedMessage(Message.SOMEONE_BOUGHT, langConfig.getString("message.someone-bought", "&6%PLAYER% &abought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a from your shop."))); + messages.add(new LocalizedMessage(Message.SOMEONE_SOLD, langConfig.getString("message.someone-sold", "&6%PLAYER% &asold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to your shop."))); + messages.add(new LocalizedMessage(Message.REVENUE_WHILE_OFFLINE, langConfig.getString("message.revenue-while-offline", "&6While you were offline, your shops have made a revenue of &c%REVENUE%&6."))); + messages.add(new LocalizedMessage(Message.NOT_ENOUGH_INVENTORY_SPACE, langConfig.getString("message.not-enough-inventory-space", "&cNot enough space in inventory."))); + messages.add(new LocalizedMessage(Message.CHEST_NOT_ENOUGH_INVENTORY_SPACE, langConfig.getString("message.chest-not-enough-inventory-space", "&cShop is full."))); + messages.add(new LocalizedMessage(Message.NOT_ENOUGH_MONEY, langConfig.getString("message.not-enough-money", "&cNot enough money."))); + messages.add(new LocalizedMessage(Message.NOT_ENOUGH_ITEMS, langConfig.getString("message.not-enough-items", "&cNot enough items."))); + messages.add(new LocalizedMessage(Message.VENDOR_NOT_ENOUGH_MONEY, langConfig.getString("message.vendor-not-enough-money", "&cVendor has not enough money."))); + messages.add(new LocalizedMessage(Message.OUT_OF_STOCK, langConfig.getString("message.out-of-stock", "&cShop out of stock."))); + messages.add(new LocalizedMessage(Message.VENDOR_OUT_OF_STOCK, langConfig.getString("message.vendor-out-of-stock", "&cYour shop that sells &6%AMOUNT% x %ITEMNAME% &cis out of stock."))); + messages.add(new LocalizedMessage(Message.ERROR_OCCURRED, langConfig.getString("message.error-occurred", "&cAn error occurred: %ERROR%"))); + messages.add(new LocalizedMessage(Message.AMOUNT_PRICE_NOT_NUMBER, langConfig.getString("message.amount-and-price-not-number", "&cAmount and price must be a number."))); + messages.add(new LocalizedMessage(Message.AMOUNT_IS_ZERO, langConfig.getString("message.amount-is-zero", "&cAmount must be greater than 0."))); + messages.add(new LocalizedMessage(Message.PRICES_CONTAIN_DECIMALS, langConfig.getString("message.prices-contain-decimals", "&cPrices must not contain decimals."))); + messages.add(new LocalizedMessage(Message.NO_ITEM_IN_HAND, langConfig.getString("message.no-item-in-hand", "&cNo item in hand"))); + messages.add(new LocalizedMessage(Message.CLICK_CHEST_CREATE, langConfig.getString("message.click-chest-to-create-shop", "&aClick a chest within 15 seconds to create a shop."))); + messages.add(new LocalizedMessage(Message.CLICK_CHEST_REMOVE, langConfig.getString("message.click-chest-to-remove-shop", "&aClick a shop within 15 seconds to remove it."))); + messages.add(new LocalizedMessage(Message.CLICK_CHEST_INFO, langConfig.getString("message.click-chest-for-info", "&aClick a shop within 15 seconds to retrieve information."))); + messages.add(new LocalizedMessage(Message.CLICK_CHEST_OPEN, langConfig.getString("message.click-chest-to-open-shop", "&aClick a shop within 15 seconds to open it."))); + messages.add(new LocalizedMessage(Message.CLICK_TO_CONFIRM, langConfig.getString("message.click-to-confirm", "&aClick again to confirm."))); + messages.add(new LocalizedMessage(Message.OPENED_SHOP, langConfig.getString("message.opened-shop", "&aYou opened %VENDOR%'s shop."))); + messages.add(new LocalizedMessage(Message.CANNOT_BREAK_SHOP, langConfig.getString("message.cannot-break-shop", "&cYou can't break a shop."))); + messages.add(new LocalizedMessage(Message.CANNOT_SELL_BROKEN_ITEM, langConfig.getString("message.cannot-sell-broken-item", "&cYou can't sell a broken item."))); + messages.add(new LocalizedMessage(Message.BUY_PRICE_TOO_LOW, langConfig.getString("message.buy-price-too-low", "&cThe buy price must be higher than %MIN-PRICE%."))); + messages.add(new LocalizedMessage(Message.SELL_PRICE_TOO_LOW, langConfig.getString("message.sell-price-too-low", "&cThe sell price must be higher than %MIN-PRICE%."))); + messages.add(new LocalizedMessage(Message.BUY_PRICE_TOO_HIGH, langConfig.getString("message.buy-price-too-high", "&cThe buy price must be lower than %MAX-PRICE%."))); + messages.add(new LocalizedMessage(Message.SELL_PRICE_TOO_HIGH, langConfig.getString("message.sell-price-too-high", "&cThe sell price must be lower than %MAX-PRICE%."))); + messages.add(new LocalizedMessage(Message.BUYING_DISABLED, langConfig.getString("message.buying-disabled", "&cBuying is disabled at this shop."))); + messages.add(new LocalizedMessage(Message.SELLING_DISABLED, langConfig.getString("message.selling-disabled", "&cSelling is disabled at this shop."))); + messages.add(new LocalizedMessage(Message.RELOADED_SHOPS, langConfig.getString("message.reloaded-shops", "&aSuccessfully reloaded %AMOUNT% shop/s."))); + messages.add(new LocalizedMessage(Message.SHOP_LIMIT_REACHED, langConfig.getString("message.shop-limit-reached", "&cYou reached your limit of &6%LIMIT% &cshop/s."))); + messages.add(new LocalizedMessage(Message.OCCUPIED_SHOP_SLOTS, langConfig.getString("message.occupied-shop-slots", "&6You have &c%AMOUNT%/%LIMIT% &6shop slot/s occupied."))); + messages.add(new LocalizedMessage(Message.CANNOT_SELL_ITEM, langConfig.getString("message.cannot-sell-item", "&cYou cannot create a shop with this item."))); + messages.add(new LocalizedMessage(Message.USE_IN_CREATIVE, langConfig.getString("message.use-in-creative", "&cYou cannot use a shop in creative mode."))); + messages.add(new LocalizedMessage(Message.SELECT_ITEM, langConfig.getString("message.select-item", "&aOpen your inventory, and drop an item to select it."))); + messages.add(new LocalizedMessage(Message.ITEM_SELECTED, langConfig.getString("message.item-selected", "&aItem has been selected: &6%ITEMNAME%"))); + messages.add(new LocalizedMessage(Message.CREATION_CANCELLED, langConfig.getString("message.creation-cancelled", "&cShop creation has been cancelled."))); + messages.add(new LocalizedMessage(Message.UPDATE_AVAILABLE, langConfig.getString("message.update.update-available", "&6&lVersion &c%VERSION% &6of &cShopChest &6is available &chere."))); + messages.add(new LocalizedMessage(Message.UPDATE_CLICK_TO_DOWNLOAD, langConfig.getString("message.update.click-to-download", "Click to download"))); + messages.add(new LocalizedMessage(Message.UPDATE_NO_UPDATE, langConfig.getString("message.update.no-update", "&6&lNo new update available."))); + messages.add(new LocalizedMessage(Message.UPDATE_CHECKING, langConfig.getString("message.update.checking", "&6&lChecking for updates..."))); + messages.add(new LocalizedMessage(Message.UPDATE_ERROR, langConfig.getString("message.update.error", "&c&lError while checking for updates."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_CREATE, langConfig.getString("message.noPermission.create", "&cYou don't have permission to create a shop."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_CREATE_ADMIN, langConfig.getString("message.noPermission.create-admin", "&cYou don't have permission to create an admin shop."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_CREATE_PROTECTED, langConfig.getString("message.noPermission.create-protected", "&cYou don't have permission to create a shop on a protected chest."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_OPEN_OTHERS, langConfig.getString("message.noPermission.open-others", "&cYou don't have permission to open this chest."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_BUY, langConfig.getString("message.noPermission.buy", "&cYou don't have permission to buy something."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_SELL, langConfig.getString("message.noPermission.sell", "&cYou don't have permission to sell something."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_BUY_HERE, langConfig.getString("message.noPermission.buy-here", "&cYou don't have permission to buy something here."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_SELL_HERE, langConfig.getString("message.noPermission.sell-here", "&cYou don't have permission to sell something here."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_REMOVE_OTHERS, langConfig.getString("message.noPermission.remove-others", "&cYou don't have permission to remove this shop."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_REMOVE_ADMIN, langConfig.getString("message.noPermission.remove-admin", "&cYou don't have permission to remove an admin shop."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_RELOAD, langConfig.getString("message.noPermission.reload", "&cYou don't have permission to reload the shops."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_UPDATE, langConfig.getString("message.noPermission.update", "&cYou don't have permission to check for updates."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_CONFIG, langConfig.getString("message.noPermission.config", "&cYou don't have permission to change configuration values."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_EXTEND_OTHERS, langConfig.getString("message.noPermission.extend-others", "&cYou don't have permission to extend this chest."))); + messages.add(new LocalizedMessage(Message.NO_PERMISSION_EXTEND_PROTECTED, langConfig.getString("message.noPermission.extend-protected", "&cYou don't have permission to extend this chest to here."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_HEADER, langConfig.getString("message.commandDescription.header", "&6==== &c/%COMMAND% &6Help"))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_FOOTER, langConfig.getString("message.commandDescription.footer", "&6==== End"))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_CREATE, langConfig.getString("message.commandDescription.create", "&a/%COMMAND% create - Create a shop."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_CREATE_ADMIN, langConfig.getString("message.commandDescription.create-admin", "&a/%COMMAND% create [admin] - Create a shop."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_REMOVE, langConfig.getString("message.commandDescription.remove", "&a/%COMMAND% remove - Remove a shop."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_INFO, langConfig.getString("message.commandDescription.info", "&a/%COMMAND% info - Retrieve shop information."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_REMOVEALL, langConfig.getString("message.commandDescription.removeall", "&a/%COMMAND% removeall - Remove all shops of a player."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_RELOAD, langConfig.getString("message.commandDescription.reload", "&a/%COMMAND% reload - Reload shops."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_UPDATE, langConfig.getString("message.commandDescription.update", "&a/%COMMAND% update - Check for Updates."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_LIMITS, langConfig.getString("message.commandDescription.limits", "&a/%COMMAND% limits - View shop limits."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_OPEN, langConfig.getString("message.commandDescription.open", "&a/%COMMAND% open - Open a shop."))); + messages.add(new LocalizedMessage(Message.COMMAND_DESC_CONFIG, langConfig.getString("message.commandDescription.config", "&a/%COMMAND% config - Change configuration values."))); + messages.add(new LocalizedMessage(Message.CHANGED_CONFIG_SET, langConfig.getString("message.config.set", "&6Changed &a%PROPERTY% &6to &a%VALUE%&6."))); + messages.add(new LocalizedMessage(Message.CHANGED_CONFIG_REMOVED, langConfig.getString("message.config.removed", "&6Removed &a%VALUE% &6from &a%PROPERTY%&6."))); + messages.add(new LocalizedMessage(Message.CHANGED_CONFIG_ADDED, langConfig.getString("message.config.added", "&6Added &a%VALUE% &6to &a%PROPERTY%&6."))); + } + + /** + * @param stack Item whose name to lookup + * @return Localized Name of the Item, the custom name, or if stack is a book, the title of the book + */ + public static String getItemName(ItemStack stack) { + if (stack == null) return null; + + if (stack.hasItemMeta()) { + ItemMeta meta = stack.getItemMeta(); + if (meta.getDisplayName() != null && !meta.getDisplayName().isEmpty()) { + return meta.getDisplayName(); + } else if (meta instanceof BookMeta && ((BookMeta) meta).hasTitle()) { + return ((BookMeta) meta).getTitle(); + } else if (meta instanceof SkullMeta) { + if (((SkullMeta) meta).hasOwner()) { + if (Utils.getMajorVersion() >= 13) { + return String.format(langConfig.getString("block.minecraft.player_head.named", "%s's Head"), ((SkullMeta) meta).getOwningPlayer().getName()); + } else { + return String.format(langConfig.getString("item.skull.player.name", "%s's Head"), ((SkullMeta) meta).getOwner()); + } + } + } + } + + Material material = stack.getType(); + + if (stack.getItemMeta() instanceof PotionMeta) { + PotionMeta meta = (PotionMeta) stack.getItemMeta(); + PotionType potionType; + String upgradeString; + + if (Utils.getMajorVersion() < 9) { + Potion potion = Potion.fromItemStack(stack); + potionType = potion.getType(); + upgradeString = potion.getLevel() == 2 && Config.appendPotionLevelToItemName ? " II" : ""; + } else { + potionType = meta.getBasePotionData().getType(); + upgradeString = (meta.getBasePotionData().isUpgraded() && Config.appendPotionLevelToItemName ? " II" : ""); + } + + for (PotionName potionName : potionNames) { + if (material == Material.POTION) { + if (Utils.getMajorVersion() < 9) { + if (Potion.fromItemStack(stack).isSplash()) { + if (potionName.getPotionItemType() == PotionName.PotionItemType.SPLASH_POTION && potionName.getPotionType() == potionType) { + return potionName.getLocalizedName() + upgradeString; + } + } else { + if (potionName.getPotionItemType() == PotionName.PotionItemType.POTION && potionName.getPotionType() == potionType) { + return potionName.getLocalizedName() + upgradeString; + } + } + } else { + if (potionName.getPotionItemType() == PotionName.PotionItemType.POTION && potionName.getPotionType() == potionType) { + return potionName.getLocalizedName() + upgradeString; + } + } + } else { + if (Utils.getMajorVersion() >= 9) { + if (material == Material.LINGERING_POTION) { + if (potionName.getPotionItemType() == PotionName.PotionItemType.LINGERING_POTION && potionName.getPotionType() == potionType) { + return potionName.getLocalizedName() + upgradeString; + } + } else if (material == Material.TIPPED_ARROW) { + if (potionName.getPotionItemType() == PotionName.PotionItemType.TIPPED_ARROW && potionName.getPotionType() == potionType) { + return potionName.getLocalizedName() + upgradeString; + } + } else if (material == Material.SPLASH_POTION) { + if (potionName.getPotionItemType() == PotionName.PotionItemType.SPLASH_POTION && potionName.getPotionType() == potionType) { + return potionName.getLocalizedName() + upgradeString; + } + } + } + } + } + } + + for (ItemName itemName : itemNames) { + if (itemName.getMaterial() != material) { + continue; + } + + if (Utils.getMajorVersion() < 13) { + if (material.toString().equals("MONSTER_EGG")) { + EntityType spawnedType = SpawnEggMeta.getEntityTypeFromItemStack(plugin, stack); + + for (EntityName entityName : entityNames) { + if (entityName.getEntityType() == spawnedType) { + return itemName.getLocalizedName() + " " + entityName.getLocalizedName(); + } + } + + return itemName.getLocalizedName() + " " + formatDefaultString(String.valueOf(spawnedType)); + } + + if (itemName.getSubId() == stack.getDurability()) { + return itemName.getLocalizedName(); + } + } else { + return itemName.getLocalizedName(); + } + } + + return formatDefaultString(String.valueOf(material)); + } + + /** + * @param enchantment Enchantment whose name should be looked up + * @param level Level of the enchantment + * @return Localized Name of the enchantment with the given level afterwards + */ + public static String getEnchantmentName(Enchantment enchantment, int level) { + if (enchantment == null) return null; + + String levelString = langConfig.getString("enchantment.level." + level, String.valueOf(level)); + String enchantmentString = formatDefaultString(Utils.getMajorVersion() < 13 + ? enchantment.getName() : enchantment.getKey().getKey()); + + for (EnchantmentName enchantmentName : enchantmentNames) { + if (enchantmentName.getEnchantment().equals(enchantment)) { + enchantmentString = enchantmentName.getLocalizedName(); + } + } + + for (EnchantmentName.EnchantmentLevelName enchantmentLevelName : enchantmentLevelNames) { + if (enchantmentLevelName.getLevel() == level) { + levelString = enchantmentLevelName.getLocalizedName(); + } + } + + return enchantmentString + " " + levelString; + } + + /** + * @param enchantmentMap Map of enchantments of an item + * @return Comma separated list of localized enchantments + */ + public static String getEnchantmentString(Map enchantmentMap) { + if (enchantmentMap == null) return null; + StringJoiner joiner = new StringJoiner(", "); + + for (Enchantment enchantment : enchantmentMap.keySet()) { + joiner.add(LanguageUtils.getEnchantmentName(enchantment, enchantmentMap.get(enchantment))); + } + + return joiner.toString(); + } + + /** + * @param itemStack Potion Item whose base effect name should be looked up + * @return Localized name of the base potion effect + */ + public static String getPotionEffectName(ItemStack itemStack) { + if (itemStack == null) return null; + if (!(itemStack.getItemMeta() instanceof PotionMeta)) return ""; + + PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta(); + PotionEffectType potionEffect; + boolean upgraded; + + if (Utils.getMajorVersion() < 9) { + Potion potion = Potion.fromItemStack(itemStack); + potionEffect = potion.getType().getEffectType(); + upgraded = potion.getLevel() == 2; + } else { + potionEffect = potionMeta.getBasePotionData().getType().getEffectType(); + upgraded = potionMeta.getBasePotionData().isUpgraded(); + } + + String potionEffectString = formatDefaultString(String.valueOf(potionEffect)); + + for (PotionEffectName potionEffectName : potionEffectNames) { + if (potionEffectName.getEffect() == potionEffect) { + potionEffectString = potionEffectName.getLocalizedName(); + } + } + + return potionEffectString + (upgraded ? " II" : ""); + } + + /** + * @param musicDiscMaterial Material of the Music Disc whose name should be looked up + * @return Localized title of the Music Disc + */ + public static String getMusicDiscName(Material musicDiscMaterial) { + if (musicDiscMaterial == null) return null; + for (MusicDiscName musicDiscName : musicDiscNames) { + if (musicDiscMaterial == musicDiscName.getMusicDiscMaterial()) { + return musicDiscName.getLocalizedName(); + } + } + + return ""; + } + + /** + * @param bannerPatternMaterial Material of the Music Disc whose name should be looked up + * @return Localized title of the Music Disc + */ + public static String getBannerPatternName(Material bannerPatternMaterial) { + if (bannerPatternMaterial == null) return null; + for (BannerPatternName bannerPatternName : bannerPatternNames) { + if (bannerPatternMaterial == bannerPatternName.getBannerPatternMaterial()) { + return bannerPatternName.getLocalizedName(); + } + } + + return ""; + } + + /** + * @param is ItemStack that should be of type {@link Material#WRITTEN_BOOK} + * @return Localized name of the generation or {@code null} if the item is not a written book + */ + public static String getBookGenerationName(ItemStack is) { + if (is.getType() != Material.WRITTEN_BOOK) { + return null; + } + + BookMeta meta = (BookMeta) is.getItemMeta(); + CustomBookMeta.Generation generation = null; + + if ((Utils.getMajorVersion() == 9 && Utils.getRevision() == 1) || Utils.getMajorVersion() == 8) { + generation = CustomBookMeta.getGeneration(is); + } else if (meta.getGeneration() != null) { + generation = CustomBookMeta.Generation.valueOf(meta.getGeneration().toString()); + } + + if (generation == null) { + generation = CustomBookMeta.Generation.ORIGINAL; + } + + for (BookGenerationName generationName : generationNames) { + if (generation == generationName.getGeneration()) { + return generationName.getLocalizedName(); + } + } + + return formatDefaultString(String.valueOf(generation)); + } + + /** + * @param message Message which should be translated + * @param replacements Replacements of placeholders which might be required to be replaced in the message + * @return Localized Message + */ + public static String getMessage(Message message, Replacement... replacements) { + String finalMessage = ChatColor.RED + "An error occurred: Message not found: " + message.toString(); + + for (LocalizedMessage localizedMessage : messages) { + if (localizedMessage.getMessage() == message) { + finalMessage = localizedMessage.getLocalizedString(); + + for (Replacement replacement : replacements) { + Placeholder placeholder = replacement.getPlaceholder(); + String toReplace = replacement.getReplacement(); + + if (placeholder == Placeholder.BUY_PRICE || placeholder == Placeholder.SELL_PRICE || placeholder == Placeholder.MIN_PRICE || placeholder == Placeholder.CREATION_PRICE || placeholder == Placeholder.REVENUE) { + if (!toReplace.equals(getMessage(Message.SHOP_INFO_DISABLED))) { + double price = Double.parseDouble(toReplace); + toReplace = plugin.getEconomy().format(price); + } + } + + finalMessage = finalMessage.replace(placeholder.toString(), toReplace); + } + } + } + + return finalMessage; + } + + /** + * Underscores will be replaced by spaces and the first letter of each word will be capitalized + * + * @param string String to format + * @return Formatted String with underscores replaced by spaces and the first letter of each word capitalized + */ + private static String formatDefaultString(String string) { + string = string.replace("_", " "); + String newString = ""; + + if (string.contains(" ")) { + for (int i = 0; i < string.split(" ").length; i++) { + String part = string.split(" ")[i].toLowerCase(); + part = part.substring(0, 1).toUpperCase() + part.substring(1); + newString = newString + part + (i == string.split(" ").length - 1 ? "" : " "); + } + + return newString; + } else { + newString = string.substring(0, 1).toUpperCase() + string.substring(1).toLowerCase(); + } + + return newString; + } + + +} + diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/LocalizedMessage.java b/plugin/src/main/java/de/epiceric/shopchest/language/LocalizedMessage.java new file mode 100644 index 0000000..2c699d7 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/LocalizedMessage.java @@ -0,0 +1,29 @@ +package de.epiceric.shopchest.language; + +import org.bukkit.ChatColor; + +public class LocalizedMessage { + + private Message message; + private String localizedString; + + public LocalizedMessage(Message message, String localizedString) { + this.message = message; + this.localizedString = ChatColor.translateAlternateColorCodes('&', localizedString); + } + + /** + * @return {@link Message} linked to this object + */ + public Message getMessage() { + return message; + } + + /** + * @return Localized Message + */ + public String getLocalizedString() { + return localizedString; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/Message.java b/plugin/src/main/java/de/epiceric/shopchest/language/Message.java new file mode 100644 index 0000000..db168a5 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/Message.java @@ -0,0 +1,99 @@ +package de.epiceric.shopchest.language; + +public enum Message { + SHOP_CREATED, + ADMIN_SHOP_CREATED, + CHEST_ALREADY_SHOP, + CHEST_BLOCKED, + DOUBLE_CHEST_BLOCKED, + SHOP_REMOVED, + SHOP_REMOVED_REFUND, + ALL_SHOPS_REMOVED, + CHEST_NO_SHOP, + SHOP_CREATE_NOT_ENOUGH_MONEY, + SHOP_INFO_VENDOR, + SHOP_INFO_PRODUCT, + SHOP_INFO_STOCK, + SHOP_INFO_CHEST_SPACE, + SHOP_INFO_PRICE, + SHOP_INFO_DISABLED, + SHOP_INFO_NORMAL, + SHOP_INFO_ADMIN, + BUY_SELL_DISABLED, + BUY_SUCCESS, + BUY_SUCCESS_ADMIN, + SELL_SUCCESS, + SELL_SUCCESS_ADMIN, + SOMEONE_BOUGHT, + SOMEONE_SOLD, + REVENUE_WHILE_OFFLINE, + NOT_ENOUGH_INVENTORY_SPACE, + CHEST_NOT_ENOUGH_INVENTORY_SPACE, + NOT_ENOUGH_MONEY, + NOT_ENOUGH_ITEMS, + VENDOR_NOT_ENOUGH_MONEY, + OUT_OF_STOCK, + VENDOR_OUT_OF_STOCK, + ERROR_OCCURRED, + AMOUNT_PRICE_NOT_NUMBER, + AMOUNT_IS_ZERO, + PRICES_CONTAIN_DECIMALS, + NO_ITEM_IN_HAND, + CLICK_CHEST_CREATE, + CLICK_CHEST_REMOVE, + CLICK_CHEST_INFO, + CLICK_CHEST_OPEN, + CLICK_TO_CONFIRM, + OPENED_SHOP, + CANNOT_BREAK_SHOP, + CANNOT_SELL_BROKEN_ITEM, + BUY_PRICE_TOO_LOW, + SELL_PRICE_TOO_LOW, + BUY_PRICE_TOO_HIGH, + SELL_PRICE_TOO_HIGH, + BUYING_DISABLED, + SELLING_DISABLED, + RELOADED_SHOPS, + SHOP_LIMIT_REACHED, + OCCUPIED_SHOP_SLOTS, + CANNOT_SELL_ITEM, + USE_IN_CREATIVE, + SELECT_ITEM, + ITEM_SELECTED, + CREATION_CANCELLED, + UPDATE_AVAILABLE, + UPDATE_CLICK_TO_DOWNLOAD, + UPDATE_NO_UPDATE, + UPDATE_CHECKING, + UPDATE_ERROR, + NO_PERMISSION_CREATE, + NO_PERMISSION_CREATE_ADMIN, + NO_PERMISSION_CREATE_PROTECTED, + NO_PERMISSION_OPEN_OTHERS, + NO_PERMISSION_BUY, + NO_PERMISSION_SELL, + NO_PERMISSION_BUY_HERE, + NO_PERMISSION_SELL_HERE, + NO_PERMISSION_REMOVE_OTHERS, + NO_PERMISSION_REMOVE_ADMIN, + NO_PERMISSION_RELOAD, + NO_PERMISSION_UPDATE, + NO_PERMISSION_CONFIG, + NO_PERMISSION_EXTEND_OTHERS, + NO_PERMISSION_EXTEND_PROTECTED, + COMMAND_DESC_HEADER, + COMMAND_DESC_FOOTER, + COMMAND_DESC_CREATE, + COMMAND_DESC_CREATE_ADMIN, + COMMAND_DESC_REMOVE, + COMMAND_DESC_INFO, + COMMAND_DESC_REMOVEALL, + COMMAND_DESC_RELOAD, + COMMAND_DESC_UPDATE, + COMMAND_DESC_LIMITS, + COMMAND_DESC_OPEN, + COMMAND_DESC_CONFIG, + CHANGED_CONFIG_SET, + CHANGED_CONFIG_REMOVED, + CHANGED_CONFIG_ADDED +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/MusicDiscName.java b/plugin/src/main/java/de/epiceric/shopchest/language/MusicDiscName.java new file mode 100644 index 0000000..4c2ff18 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/MusicDiscName.java @@ -0,0 +1,29 @@ +package de.epiceric.shopchest.language; + +import org.bukkit.Material; + +public class MusicDiscName { + + private Material musicDiscMaterial; + private String localizedName; + + public MusicDiscName(Material musicDiscMaterial, String localizedName) { + this.musicDiscMaterial = musicDiscMaterial; + this.localizedName = localizedName; + } + + /** + * @return Localized Title of the Music Disc + */ + public String getLocalizedName() { + return localizedName; + } + + /** + * @return Material of the Music Disc + */ + public Material getMusicDiscMaterial() { + return musicDiscMaterial; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/PotionEffectName.java b/plugin/src/main/java/de/epiceric/shopchest/language/PotionEffectName.java new file mode 100644 index 0000000..e6dbe9f --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/PotionEffectName.java @@ -0,0 +1,29 @@ +package de.epiceric.shopchest.language; + +import org.bukkit.potion.PotionEffectType; + +public class PotionEffectName { + + private PotionEffectType effect; + private String localizedName; + + public PotionEffectName(PotionEffectType effect, String localizedName) { + this.effect = effect; + this.localizedName = localizedName; + } + + /** + * @return Potion Effect linked to the name + */ + public PotionEffectType getEffect() { + return effect; + } + + /** + * @return Localized Name of the potion effect + */ + public String getLocalizedName() { + return localizedName; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/PotionName.java b/plugin/src/main/java/de/epiceric/shopchest/language/PotionName.java new file mode 100644 index 0000000..3e3211d --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/PotionName.java @@ -0,0 +1,44 @@ +package de.epiceric.shopchest.language; + +import org.bukkit.potion.PotionType; + +public class PotionName { + + private String localizedName; + private PotionItemType potionItemType; + private PotionType potionType; + + public PotionName(PotionItemType potionItemType, PotionType potionType, String localizedName) { + this.potionItemType = potionItemType; + this.localizedName = localizedName; + this.potionType = potionType; + } + + /** + * @return {@link PotionItemType} linked to the Potion name + */ + public PotionItemType getPotionItemType() { + return potionItemType; + } + + /** + * @return Potion Type linked to the Potion name + */ + public PotionType getPotionType() { + return potionType; + } + + /** + * @return Localized Name of the Potion + */ + public String getLocalizedName() { + return localizedName; + } + + public enum PotionItemType { + POTION, + LINGERING_POTION, + SPLASH_POTION, + TIPPED_ARROW + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/language/Replacement.java b/plugin/src/main/java/de/epiceric/shopchest/language/Replacement.java new file mode 100644 index 0000000..9eb4591 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/language/Replacement.java @@ -0,0 +1,29 @@ +package de.epiceric.shopchest.language; + +import de.epiceric.shopchest.config.Placeholder; + +public class Replacement { + + private Placeholder placeholder; + private String replacement; + + public Replacement(Placeholder placeholder, Object replacement) { + this.placeholder = placeholder; + this.replacement = String.valueOf(replacement); + } + + /** + * @return String which will replace the placeholder + */ + public String getReplacement() { + return replacement; + } + + /** + * @return Placeholder that will be replaced + */ + public Placeholder getPlaceholder() { + return placeholder; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/AreaShopListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/AreaShopListener.java new file mode 100644 index 0000000..e431b15 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/AreaShopListener.java @@ -0,0 +1,69 @@ +package de.epiceric.shopchest.listeners; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.codemc.worldguardwrapper.WorldGuardWrapper; +import org.codemc.worldguardwrapper.region.IWrappedRegion; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.shop.Shop; +import me.wiefferink.areashop.events.notify.DeletedRegionEvent; +import me.wiefferink.areashop.events.notify.ResoldRegionEvent; +import me.wiefferink.areashop.events.notify.SoldRegionEvent; +import me.wiefferink.areashop.events.notify.UnrentedRegionEvent; +import me.wiefferink.areashop.regions.GeneralRegion; + +public class AreaShopListener implements Listener { + + private ShopChest plugin; + + public AreaShopListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onRegionDeleted(DeletedRegionEvent e) { + if (Config.enableAreaShopIntegration && Config.areashopRemoveShopEvents.contains("DELETE")) { + removeShopsInRegion(e.getRegion()); + } + } + + @EventHandler + public void onRegionUnrented(UnrentedRegionEvent e) { + if (Config.enableAreaShopIntegration && Config.areashopRemoveShopEvents.contains("UNRENT")) { + removeShopsInRegion(e.getRegion()); + } + } + + @EventHandler + public void onRegionResold(ResoldRegionEvent e) { + if (Config.enableAreaShopIntegration && Config.areashopRemoveShopEvents.contains("RESELL")) { + removeShopsInRegion(e.getRegion()); + } + } + + @EventHandler + public void onRegionSold(SoldRegionEvent e) { + if (Config.enableAreaShopIntegration && Config.areashopRemoveShopEvents.contains("SELL")) { + removeShopsInRegion(e.getRegion()); + } + } + + private void removeShopsInRegion(GeneralRegion generalRegion) { + if (!plugin.hasWorldGuard()) return; + + for (Shop shop : plugin.getShopUtils().getShops()) { + if (!shop.getLocation().getWorld().getName().equals(generalRegion.getWorldName())) continue; + + for (IWrappedRegion r : WorldGuardWrapper.getInstance().getRegions(shop.getLocation())) { + if (generalRegion.getLowerCaseName().equals(r.getId())) { + plugin.getShopUtils().removeShopById(shop.getID(), true); + break; + } + } + } + + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/BentoBoxListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/BentoBoxListener.java new file mode 100644 index 0000000..4170250 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/BentoBoxListener.java @@ -0,0 +1,91 @@ +package de.epiceric.shopchest.listeners; + +import java.util.Collection; +import java.util.UUID; + +import org.bukkit.World; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.util.BoundingBox; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.shop.Shop; +import world.bentobox.bentobox.api.events.island.IslandBanEvent; +import world.bentobox.bentobox.api.events.island.IslandDeleteChunksEvent; +import world.bentobox.bentobox.api.events.island.IslandDeletedEvent; +import world.bentobox.bentobox.api.events.island.IslandResettedEvent; +import world.bentobox.bentobox.api.events.team.TeamKickEvent; +import world.bentobox.bentobox.api.events.team.TeamLeaveEvent; +import world.bentobox.bentobox.database.objects.Island; +import world.bentobox.bentobox.database.objects.IslandDeletion; + +public class BentoBoxListener implements Listener { + private ShopChest plugin; + + public BentoBoxListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onIslandDeleted(IslandDeletedEvent e) { + deleteShops(e.getDeletedIslandInfo()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onIslandDeleteChunks(IslandDeleteChunksEvent e) { + deleteShops(e.getDeletedIslandInfo()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onIslandResetted(IslandResettedEvent e) { + deleteShops(e.getIsland(), null); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onIslandBan(IslandBanEvent e) { + deleteShops(e.getIsland(), e.getPlayerUUID()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onTeamKick(TeamKickEvent e) { + deleteShops(e.getIsland(), e.getPlayerUUID()); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onTeamLeave(TeamLeaveEvent e) { + deleteShops(e.getIsland(), e.getPlayerUUID()); + } + + private void deleteShops(IslandDeletion deletedIsland) { + deleteShops(deletedIsland.getWorld(), deletedIsland.getBox(), null); + } + + private void deleteShops(Island island, UUID vendorUuid) { + deleteShops(island.getWorld(), island.getBoundingBox(), vendorUuid); + } + + private void deleteShops(World world, BoundingBox box, UUID vendorUuid) { + if (!Config.enableBentoBoxIntegration) + return; + + Collection shops = plugin.getShopUtils().getShops(); + for (Shop shop : shops) { + if (!shop.getLocation().getWorld().getName().equals(world.getName())) { + continue; + } + + if (vendorUuid != null && !shop.getVendor().getUniqueId().equals(vendorUuid)) { + continue; + } + + int x = shop.getLocation().getBlockX(); + int z = shop.getLocation().getBlockZ(); + if (box.contains(x, 0, z)) { + plugin.getShopUtils().removeShop(shop, true); + } + } + } + +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/BlockExplodeListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/BlockExplodeListener.java new file mode 100644 index 0000000..55e0a4f --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/BlockExplodeListener.java @@ -0,0 +1,31 @@ +package de.epiceric.shopchest.listeners; + +import java.util.ArrayList; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockExplodeEvent; + +import de.epiceric.shopchest.ShopChest; + +public class BlockExplodeListener implements Listener { + + private ShopChest plugin; + + public BlockExplodeListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onBlockExplode(BlockExplodeEvent e) { + ArrayList bl = new ArrayList<>(e.blockList()); + for (Block b : bl) { + if (b.getType().equals(Material.CHEST) || b.getType().equals(Material.TRAPPED_CHEST)) { + if (plugin.getShopUtils().isShop(b.getLocation())) e.blockList().remove(b); + } + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java new file mode 100644 index 0000000..b7af654 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/ChestProtectListener.java @@ -0,0 +1,248 @@ +package de.epiceric.shopchest.listeners; + +import java.util.ArrayList; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.block.data.type.Chest.Type; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.inventory.InventoryMoveItemEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.InventoryHolder; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.event.ShopExtendEvent; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.language.Message; +import de.epiceric.shopchest.language.Replacement; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.shop.Shop.ShopType; +import de.epiceric.shopchest.utils.Callback; +import de.epiceric.shopchest.utils.ItemUtils; +import de.epiceric.shopchest.utils.Permissions; +import de.epiceric.shopchest.utils.ShopUtils; +import de.epiceric.shopchest.utils.Utils; +import net.milkbowl.vault.economy.EconomyResponse; + +public class ChestProtectListener implements Listener { + + private ShopChest plugin; + private ShopUtils shopUtils; + + public ChestProtectListener(ShopChest plugin) { + this.plugin = plugin; + this.shopUtils = plugin.getShopUtils(); + } + + private void remove(final Shop shop, final Block b, final Player p) { + if (shop.getInventoryHolder() instanceof DoubleChest) { + DoubleChest dc = (DoubleChest) shop.getInventoryHolder(); + final Chest l = (Chest) dc.getLeftSide(); + final Chest r = (Chest) dc.getRightSide(); + + Location loc = (b.getLocation().equals(l.getLocation()) ? r.getLocation() : l.getLocation()); + final Shop newShop = new Shop(shop.getID(), plugin, shop.getVendor(), shop.getProduct(), loc, shop.getBuyPrice(), shop.getSellPrice(), shop.getShopType()); + + shopUtils.removeShop(shop, true, new Callback(plugin) { + @Override + public void onResult(Void result) { + newShop.create(true); + shopUtils.addShop(newShop, true); + } + }); + } else { + double creationPrice = shop.getShopType() == ShopType.ADMIN ? Config.shopCreationPriceAdmin : Config.shopCreationPriceNormal; + if (creationPrice > 0 && Config.refundShopCreation && p.getUniqueId().equals(shop.getVendor().getUniqueId())) { + EconomyResponse r = plugin.getEconomy().depositPlayer(p, shop.getLocation().getWorld().getName(), creationPrice); + if (!r.transactionSuccess()) { + plugin.debug("Economy transaction failed: " + r.errorMessage); + p.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, + new Replacement(Placeholder.ERROR, r.errorMessage))); + p.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED_REFUND, + new Replacement(Placeholder.CREATION_PRICE, 0))); + } else { + p.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED_REFUND, + new Replacement(Placeholder.CREATION_PRICE, creationPrice))); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED)); + } + + shopUtils.removeShop(shop, true); + plugin.debug(String.format("%s broke %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); + } + } + + @EventHandler(ignoreCancelled = true) + public void onBlockBreak(BlockBreakEvent e) { + final Block b = e.getBlock(); + + if (shopUtils.isShop(b.getLocation())) { + final Shop shop = shopUtils.getShop(e.getBlock().getLocation()); + Player p = e.getPlayer(); + + if (p.isSneaking() && Utils.hasAxeInHand(p)) { + plugin.debug(String.format("%s tries to break %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); + + if (shop.getShopType() == Shop.ShopType.ADMIN) { + if (p.hasPermission(Permissions.REMOVE_ADMIN)) { + remove(shop, b, p); + return; + } + } else { + if (shop.getVendor().getUniqueId().equals(p.getUniqueId()) || p.hasPermission(Permissions.REMOVE_OTHER)) { + remove(shop, b, p); + return; + } + } + } + + if (shop.getItem() != null) { + shop.getItem().resetForPlayer(p); + } + + e.setCancelled(true); + e.getPlayer().sendMessage(LanguageUtils.getMessage(Message.CANNOT_BREAK_SHOP)); + } + } + + @EventHandler(ignoreCancelled = true) + public void onEntityExplode(EntityExplodeEvent e) { + ArrayList bl = new ArrayList<>(e.blockList()); + for (Block b : bl) { + if (b.getType().equals(Material.CHEST) || b.getType().equals(Material.TRAPPED_CHEST)) { + if (shopUtils.isShop(b.getLocation())) e.blockList().remove(b); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent e) { + final Player p = e.getPlayer(); + final Block b = e.getBlockPlaced(); + + if (!b.getType().equals(Material.CHEST) && !b.getType().equals(Material.TRAPPED_CHEST)) { + return; + } + + Chest c = (Chest) b.getState(); + Block b2; + + // Can't use Utils::getChestLocations since inventory holder + // has not been updated yet in this event (for 1.13+) + + if (Utils.getMajorVersion() < 13) { + InventoryHolder ih = c.getInventory().getHolder(); + if (!(ih instanceof DoubleChest)) { + return; + } + + DoubleChest dc = (DoubleChest) ih; + Chest l = (Chest) dc.getLeftSide(); + Chest r = (Chest) dc.getRightSide(); + + if (b.getLocation().equals(l.getLocation())) { + b2 = r.getBlock(); + } else { + b2 = l.getBlock(); + } + } else { + org.bukkit.block.data.type.Chest data = (org.bukkit.block.data.type.Chest) c.getBlockData(); + + if (data.getType() == Type.SINGLE) { + return; + } + + BlockFace neighborFacing; + + switch (data.getFacing()) { + case NORTH: + neighborFacing = data.getType() == Type.LEFT ? BlockFace.EAST : BlockFace.WEST; + break; + case EAST: + neighborFacing = data.getType() == Type.LEFT ? BlockFace.SOUTH : BlockFace.NORTH; + break; + case SOUTH: + neighborFacing = data.getType() == Type.LEFT ? BlockFace.WEST : BlockFace.EAST; + break; + case WEST: + neighborFacing = data.getType() == Type.LEFT ? BlockFace.NORTH : BlockFace.SOUTH; + break; + default: + neighborFacing = null; + } + + b2 = b.getRelative(neighborFacing); + } + + final Shop shop = shopUtils.getShop(b2.getLocation()); + if (shop == null) + return; + + plugin.debug(String.format("%s tries to extend %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); + + ShopExtendEvent event = new ShopExtendEvent(p, shop, b.getLocation()); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled() && !p.hasPermission(Permissions.EXTEND_PROTECTED)) { + e.setCancelled(true); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_EXTEND_PROTECTED)); + return; + } + + if (!p.getUniqueId().equals(shop.getVendor().getUniqueId()) && !p.hasPermission(Permissions.EXTEND_OTHER)) { + e.setCancelled(true); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_EXTEND_OTHERS)); + return; + } + + if (!ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) { + e.setCancelled(true); + p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED)); + return; + } + + final Shop newShop = new Shop(shop.getID(), plugin, shop.getVendor(), shop.getProduct(), shop.getLocation(), shop.getBuyPrice(), shop.getSellPrice(), shop.getShopType()); + + shopUtils.removeShop(shop, true, new Callback(plugin) { + @Override + public void onResult(Void result) { + newShop.create(true); + shopUtils.addShop(newShop, true); + plugin.debug(String.format("%s extended %s's shop (#%d)", p.getName(), shop.getVendor().getName(), shop.getID())); + } + }); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onItemMove(InventoryMoveItemEvent e) { + if ((e.getSource().getType().equals(InventoryType.CHEST)) && (!e.getInitiator().getType().equals(InventoryType.PLAYER))) { + + if (e.getSource().getHolder() instanceof DoubleChest) { + DoubleChest dc = (DoubleChest) e.getSource().getHolder(); + Chest r = (Chest) dc.getRightSide(); + Chest l = (Chest) dc.getLeftSide(); + + if (shopUtils.isShop(r.getLocation()) || shopUtils.isShop(l.getLocation())) e.setCancelled(true); + + } else if (e.getSource().getHolder() instanceof Chest) { + Chest c = (Chest) e.getSource().getHolder(); + + if (shopUtils.isShop(c.getLocation())) e.setCancelled(true); + } + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/CreativeModeListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/CreativeModeListener.java new file mode 100644 index 0000000..8f33887 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/CreativeModeListener.java @@ -0,0 +1,179 @@ +package de.epiceric.shopchest.listeners; + +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockMultiPlaceEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.event.inventory.InventoryMoveItemEvent; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.language.Message; +import de.epiceric.shopchest.language.Replacement; +import de.epiceric.shopchest.utils.ClickType; +import de.epiceric.shopchest.utils.ClickType.SelectClickType; + +public class CreativeModeListener implements Listener { + private ShopChest plugin; + + public CreativeModeListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onInventoryClick(InventoryClickEvent e) { + HumanEntity entity = e.getWhoClicked(); + if (!(entity instanceof Player)) + return; + + Player p = (Player) entity; + + ClickType clickType = ClickType.getPlayerClickType(p); + if (clickType instanceof SelectClickType) { + e.setCancelled(true); + + if (e.getCursor() == null || e.getCursor().getType() == Material.AIR) + return; + + ClickType.removePlayerClickType(p); + ((SelectClickType) clickType).setItem(e.getCursor()); + p.closeInventory(); + + p.sendMessage(LanguageUtils.getMessage(Message.ITEM_SELECTED, + new Replacement(Placeholder.ITEM_NAME, LanguageUtils.getItemName(e.getCursor())))); + plugin.getShopCommand().createShopAfterSelected(p, (SelectClickType) clickType); + } + } + + @EventHandler + public void onPlayerCloseInventory(InventoryCloseEvent e) { + HumanEntity entity = e.getPlayer(); + if (!(entity instanceof Player)) + return; + + Player p = (Player) entity; + + ClickType clickType = ClickType.getPlayerClickType(p); + if (!(clickType instanceof SelectClickType)) + return; + + ClickType.removePlayerClickType(p); + p.sendMessage(LanguageUtils.getMessage(Message.CREATION_CANCELLED)); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent e) { + // Reset game mode on quit if SelectClickType is set + Player p = e.getPlayer(); + ClickType.removePlayerClickType(p); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onInventoryDrag(InventoryDragEvent e) { + // Cancel any inventory drags if SelectClickType is set + HumanEntity entity = e.getWhoClicked(); + if (!(entity instanceof Player)) + return; + + ClickType clickType = ClickType.getPlayerClickType((Player) entity); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onInventoryMove(InventoryMoveItemEvent e) { + // Cancel any inventory movement if SelectClickType is set + if (e.getSource().getHolder() instanceof Player) { + Player p = (Player) e.getSource().getHolder(); + + ClickType clickType = ClickType.getPlayerClickType(p); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerPickup(PlayerPickupItemEvent e) { + // Cancel any item pickups if SelectClickType is set + ClickType clickType = ClickType.getPlayerClickType(e.getPlayer()); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onBlockBreak(BlockBreakEvent e) { + // Cancel any block breaks if SelectClickType is set + ClickType clickType = ClickType.getPlayerClickType(e.getPlayer()); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onBlockPlace(BlockPlaceEvent e) { + // Cancel any block places if SelectClickType is set + ClickType clickType = ClickType.getPlayerClickType(e.getPlayer()); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onBlockMultiPlace(BlockMultiPlaceEvent e) { + // Cancel any block places if SelectClickType is set + ClickType clickType = ClickType.getPlayerClickType(e.getPlayer()); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerInteract(PlayerInteractEvent e) { + // Cancel any interactions if SelectClickType is set + ClickType clickType = ClickType.getPlayerClickType(e.getPlayer()); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent e) { + // Cancel any entity interactions if SelectClickType is set + ClickType clickType = ClickType.getPlayerClickType(e.getPlayer()); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerDamageEntity(EntityDamageByEntityEvent e) { + // Cancel any entity damaging if SelectClickType is set + Entity entity = e.getDamager(); + if (!(entity instanceof Player)) + return; + + ClickType clickType = ClickType.getPlayerClickType((Player) entity); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onPlayerMove(PlayerMoveEvent e) { + // Cancel any player movement if SelectClickType is set + ClickType clickType = ClickType.getPlayerClickType(e.getPlayer()); + if (clickType instanceof SelectClickType) + e.setCancelled(true); + } + +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/NotifyPlayerOnJoinListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/NotifyPlayerOnJoinListener.java new file mode 100644 index 0000000..eab4345 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/NotifyPlayerOnJoinListener.java @@ -0,0 +1,63 @@ +package de.epiceric.shopchest.listeners; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.language.Message; +import de.epiceric.shopchest.language.Replacement; +import de.epiceric.shopchest.utils.Callback; +import de.epiceric.shopchest.utils.Permissions; +import de.epiceric.shopchest.utils.Utils; + +public class NotifyPlayerOnJoinListener implements Listener { + + private ShopChest plugin; + + public NotifyPlayerOnJoinListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) { + final Player p = e.getPlayer(); + + if (plugin.isUpdateNeeded() && Config.enableUpdateChecker) { + if (p.hasPermission(Permissions.UPDATE_NOTIFICATION)) { + Utils.sendUpdateMessage(plugin, p); + } + } + + plugin.getShopDatabase().getLastLogout(p, new Callback(plugin) { + @Override + public void onResult(Long result) { + if (result < 0) { + // No logout saved, probably first time joining. + return; + } + + plugin.getShopDatabase().getRevenue(p, result, new Callback(plugin) { + @Override + public void onResult(Double result) { + if (result != 0) { + p.sendMessage(LanguageUtils.getMessage(Message.REVENUE_WHILE_OFFLINE, + new Replacement(Placeholder.REVENUE, String.valueOf(result)))); + } + } + }); + } + }); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent e) { + plugin.getShopDatabase().logLogout(e.getPlayer(), null); + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java new file mode 100644 index 0000000..40e315b --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopInteractListener.java @@ -0,0 +1,1213 @@ +package de.epiceric.shopchest.listeners; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.google.gson.JsonPrimitive; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.scheduler.BukkitRunnable; +import org.codemc.worldguardwrapper.WorldGuardWrapper; +import org.codemc.worldguardwrapper.flag.IWrappedFlag; +import org.codemc.worldguardwrapper.flag.WrappedState; +import org.inventivetalent.reflection.resolver.minecraft.NMSClassResolver; +import org.inventivetalent.reflection.resolver.minecraft.OBCClassResolver; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.event.ShopBuySellEvent; +import de.epiceric.shopchest.event.ShopCreateEvent; +import de.epiceric.shopchest.event.ShopInfoEvent; +import de.epiceric.shopchest.event.ShopOpenEvent; +import de.epiceric.shopchest.event.ShopRemoveEvent; +import de.epiceric.shopchest.external.PlotSquaredOldShopFlag; +import de.epiceric.shopchest.external.PlotSquaredShopFlag; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.language.Message; +import de.epiceric.shopchest.language.Replacement; +import de.epiceric.shopchest.nms.JsonBuilder; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.shop.Shop.ShopType; +import de.epiceric.shopchest.shop.ShopProduct; +import de.epiceric.shopchest.sql.Database; +import de.epiceric.shopchest.utils.ClickType; +import de.epiceric.shopchest.utils.ClickType.CreateClickType; +import de.epiceric.shopchest.utils.ItemUtils; +import de.epiceric.shopchest.utils.Permissions; +import de.epiceric.shopchest.utils.ShopUtils; +import de.epiceric.shopchest.utils.Utils; +import fr.xephi.authme.api.v3.AuthMeApi; +import net.milkbowl.vault.economy.Economy; +import net.milkbowl.vault.economy.EconomyResponse; + +public class ShopInteractListener implements Listener { + private static final Pattern COLOR_CODE_PATTERN = Pattern.compile(".*([§]([a-fA-F0-9]))"); + private static final Pattern FORMAT_CODE_PATTERN = Pattern.compile(".*([§]([l-oL-OkK]))"); + + private ShopChest plugin; + private Economy econ; + private Database database; + private ShopUtils shopUtils; + + public ShopInteractListener(ShopChest plugin) { + this.plugin = plugin; + this.econ = plugin.getEconomy(); + this.database = plugin.getShopDatabase(); + this.shopUtils = plugin.getShopUtils(); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInventoryClick(InventoryClickEvent e) { + if (!plugin.getHologramFormat().isDynamic()) return; + + Inventory chestInv = e.getInventory(); + + if (!(chestInv.getHolder() instanceof Chest || chestInv.getHolder() instanceof DoubleChest)) { + return; + } + + Location loc = null; + if (chestInv.getHolder() instanceof Chest) { + loc = ((Chest) chestInv.getHolder()).getLocation(); + } else if (chestInv.getHolder() instanceof DoubleChest) { + loc = ((DoubleChest) chestInv.getHolder()).getLocation(); + } + + final Shop shop = plugin.getShopUtils().getShop(loc); + if (shop == null) return; + + new BukkitRunnable() { + @Override + public void run() { + shop.updateHologramText(); + } + }.runTaskLater(plugin, 1L); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerInteractCreate(PlayerInteractEvent e) { + Player p = e.getPlayer(); + Block b = e.getClickedBlock(); + + if (e.getAction() != Action.RIGHT_CLICK_BLOCK) + return; + + if (!(ClickType.getPlayerClickType(p) instanceof CreateClickType)) + return; + + if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) + return; + + if (ClickType.getPlayerClickType(p).getClickType() != ClickType.EnumClickType.CREATE) + return; + + if (Config.enableAuthMeIntegration && plugin.hasAuthMe() && !AuthMeApi.getInstance().isAuthenticated(p)) + return; + + if (e.isCancelled() && !p.hasPermission(Permissions.CREATE_PROTECTED)) { + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_PROTECTED)); + plugin.debug(p.getName() + " is not allowed to create a shop on the selected chest"); + } else if (shopUtils.isShop(b.getLocation())) { + p.sendMessage(LanguageUtils.getMessage(Message.CHEST_ALREADY_SHOP)); + plugin.debug("Chest is already a shop"); + } else if (!ItemUtils.isAir(b.getRelative(BlockFace.UP).getType())) { + p.sendMessage(LanguageUtils.getMessage(Message.CHEST_BLOCKED)); + plugin.debug("Chest is blocked"); + } else { + CreateClickType clickType = (CreateClickType) ClickType.getPlayerClickType(p); + ShopProduct product = clickType.getProduct(); + double buyPrice = clickType.getBuyPrice(); + double sellPrice = clickType.getSellPrice(); + ShopType shopType = clickType.getShopType(); + + create(p, b.getLocation(), product, buyPrice, sellPrice, shopType); + } + + e.setCancelled(true); + ClickType.removePlayerClickType(p); + } + + private Map> needsConfirmation = new HashMap<>(); + + private void handleInteractEvent(PlayerInteractEvent e) { + Block b = e.getClickedBlock(); + Player p = e.getPlayer(); + boolean inverted = Config.invertMouseButtons; + + if (Utils.getMajorVersion() >= 9 && e.getHand() == EquipmentSlot.OFF_HAND) + return; + + if (e.getAction() != Action.RIGHT_CLICK_BLOCK && e.getAction() != Action.LEFT_CLICK_BLOCK) + return; + + if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) + return; + + ClickType clickType = ClickType.getPlayerClickType(p); + if (clickType != null) { + if (e.getAction() != Action.RIGHT_CLICK_BLOCK) + return; + + Shop shop = shopUtils.getShop(b.getLocation()); + switch (clickType.getClickType()) { + case CREATE: + case SELECT_ITEM: + break; + default: + if (shop == null) { + p.sendMessage(LanguageUtils.getMessage(Message.CHEST_NO_SHOP)); + plugin.debug("Chest is not a shop"); + return; + } + } + + switch (clickType.getClickType()) { + case INFO: + info(p, shop); + break; + case REMOVE: + remove(p, shop); + break; + case OPEN: + open(p, shop, true); + break; + default: return; + } + + e.setCancelled(true); + ClickType.removePlayerClickType(p); + } else { + Shop shop = shopUtils.getShop(b.getLocation()); + + if (shop == null) + return; + + boolean confirmed = needsConfirmation.containsKey(p.getUniqueId()) && needsConfirmation.get(p.getUniqueId()).contains(shop.getID()); + + if (e.getAction() == Action.LEFT_CLICK_BLOCK && p.isSneaking() && Utils.hasAxeInHand(p)) { + return; + } + + ItemStack infoItem = Config.shopInfoItem; + if (infoItem != null) { + if (e.getAction() == Action.RIGHT_CLICK_BLOCK || e.getAction() == Action.LEFT_CLICK_BLOCK) { + ItemStack item = Utils.getItemInMainHand(p); + + if (item == null || !(infoItem.getType() == item.getType() && infoItem.getDurability() == item.getDurability())) { + item = Utils.getItemInOffHand(p); + + if (item != null && infoItem.getType() == item.getType() && infoItem.getDurability() == item.getDurability()) { + e.setCancelled(true); + info(p, shop); + return; + } + } else { + e.setCancelled(true); + info(p, shop); + return; + } + } + } + + if (e.getAction() == Action.RIGHT_CLICK_BLOCK && p.getUniqueId().equals(shop.getVendor().getUniqueId()) && shop.getShopType() != ShopType.ADMIN) { + return; + } + + if (p.getGameMode() == GameMode.CREATIVE) { + e.setCancelled(true); + p.sendMessage(LanguageUtils.getMessage(Message.USE_IN_CREATIVE)); + return; + } + + if ((e.getAction() == Action.RIGHT_CLICK_BLOCK && !inverted) || (e.getAction() == Action.LEFT_CLICK_BLOCK && inverted)) { + e.setCancelled(true); + + if (shop.getShopType() == ShopType.ADMIN || !shop.getVendor().getUniqueId().equals(p.getUniqueId())) { + plugin.debug(p.getName() + " wants to buy"); + + if (shop.getBuyPrice() > 0) { + if (p.hasPermission(Permissions.BUY)) { + // TODO: Outsource shop use external permission + boolean externalPluginsAllowed = true; + + if (plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) { + try { + Class.forName("com.plotsquared.core.PlotSquared"); + com.plotsquared.core.location.Location plotLocation = + com.plotsquared.core.location.Location.at(b.getWorld().getName(), b.getX(), b.getY(), b.getZ()); + com.plotsquared.core.plot.Plot plot = plotLocation.getOwnedPlot(); + externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredShopFlag.USE_SHOP, p); + } catch (ClassNotFoundException ex) { + com.github.intellectualsites.plotsquared.plot.object.Location plotLocation = + new com.github.intellectualsites.plotsquared.plot.object.Location(b.getWorld().getName(), b.getX(), b.getY(), b.getZ()); + com.github.intellectualsites.plotsquared.plot.object.Plot plot = plotLocation.getOwnedPlot(); + externalPluginsAllowed = PlotSquaredOldShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredOldShopFlag.USE_SHOP, p); + } + } + + if (externalPluginsAllowed && plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) { + String flagName = (shop.getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop"); + WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); + Optional> flag = wgWrapper.getFlag(flagName, WrappedState.class); + if (!flag.isPresent()) plugin.debug("WorldGuard flag '" + flagName + "' is not present!"); + WrappedState state = flag.map(f -> wgWrapper.queryFlag(p, b.getLocation(), f).orElse(WrappedState.DENY)).orElse(WrappedState.DENY); + externalPluginsAllowed = state == WrappedState.ALLOW; + } + + if (shop.getShopType() == ShopType.ADMIN) { + if (externalPluginsAllowed || p.hasPermission(Permissions.BYPASS_EXTERNAL_PLUGIN)) { + if (confirmed || !Config.confirmShopping) { + buy(p, shop, p.isSneaking()); + if (Config.confirmShopping) { + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.remove(shop.getID()); + if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId()); + else needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + plugin.debug("Needs confirmation"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM)); + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + plugin.debug(p.getName() + " doesn't have external plugin's permission"); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY_HERE)); + } + } else { + if (externalPluginsAllowed || p.hasPermission(Permissions.BYPASS_EXTERNAL_PLUGIN)) { + Chest c = (Chest) b.getState(); + ItemStack itemStack = shop.getProduct().getItemStack(); + int amount = (p.isSneaking() ? itemStack.getMaxStackSize() : shop.getProduct().getAmount()); + + if (Utils.getAmount(c.getInventory(), itemStack) >= amount) { + if (confirmed || !Config.confirmShopping) { + buy(p, shop, p.isSneaking()); + if (Config.confirmShopping) { + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.remove(shop.getID()); + if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId()); + else needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + plugin.debug("Needs confirmation"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM)); + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + if (Config.autoCalculateItemAmount && Utils.getAmount(c.getInventory(), itemStack) > 0) { + if (confirmed || !Config.confirmShopping) { + buy(p, shop, p.isSneaking()); + if (Config.confirmShopping) { + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.remove(shop.getID()); + if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId()); + else needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + plugin.debug("Needs confirmation"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM)); + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.OUT_OF_STOCK)); + if (shop.getVendor().isOnline() && Config.enableVendorMessages) { + shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.VENDOR_OUT_OF_STOCK, + new Replacement(Placeholder.AMOUNT, String.valueOf(shop.getProduct().getAmount())), + new Replacement(Placeholder.ITEM_NAME, shop.getProduct().getLocalizedName()))); + } else if(!shop.getVendor().isOnline() && Config.enableVendorBungeeMessages){ + String message = LanguageUtils.getMessage(Message.VENDOR_OUT_OF_STOCK, + new Replacement(Placeholder.AMOUNT, String.valueOf(shop.getProduct().getAmount())), + new Replacement(Placeholder.ITEM_NAME, shop.getProduct().getLocalizedName())); + sendBungeeMessage(shop.getVendor().getName(), message); + } + plugin.debug("Shop is out of stock"); + } + } + } else { + plugin.debug(p.getName() + " doesn't have external plugin's permission"); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY_HERE)); + } + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_BUY)); + plugin.debug(p.getName() + " is not permitted to buy"); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.BUYING_DISABLED)); + plugin.debug("Buying is disabled"); + } + } + + } else if ((e.getAction() == Action.LEFT_CLICK_BLOCK && !inverted) || (e.getAction() == Action.RIGHT_CLICK_BLOCK && inverted)) { + e.setCancelled(true); + + if ((shop.getShopType() == ShopType.ADMIN) || (!shop.getVendor().getUniqueId().equals(p.getUniqueId()))) { + plugin.debug(p.getName() + " wants to sell"); + + if (shop.getSellPrice() > 0) { + if (p.hasPermission(Permissions.SELL)) { + // TODO: Outsource shop use external permission + boolean externalPluginsAllowed = true; + + if (plugin.hasPlotSquared() && Config.enablePlotsquaredIntegration) { + try { + Class.forName("com.plotsquared.core.PlotSquared"); + com.plotsquared.core.location.Location plotLocation = + com.plotsquared.core.location.Location.at(b.getWorld().getName(), b.getX(), b.getY(), b.getZ()); + com.plotsquared.core.plot.Plot plot = plotLocation.getOwnedPlot(); + externalPluginsAllowed = PlotSquaredShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredShopFlag.USE_SHOP, p); + } catch (ClassNotFoundException ex) { + com.github.intellectualsites.plotsquared.plot.object.Location plotLocation = + new com.github.intellectualsites.plotsquared.plot.object.Location(b.getWorld().getName(), b.getX(), b.getY(), b.getZ()); + com.github.intellectualsites.plotsquared.plot.object.Plot plot = plotLocation.getOwnedPlot(); + externalPluginsAllowed = PlotSquaredOldShopFlag.isFlagAllowedOnPlot(plot, PlotSquaredOldShopFlag.USE_SHOP, p); + } + } + + if (externalPluginsAllowed && plugin.hasWorldGuard() && Config.enableWorldGuardIntegration) { + String flagName = (shop.getShopType() == ShopType.ADMIN ? "use-admin-shop" : "use-shop"); + WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); + Optional> flag = wgWrapper.getFlag(flagName, WrappedState.class); + if (!flag.isPresent()) plugin.debug("WorldGuard flag '" + flagName + "' is not present!"); + WrappedState state = flag.map(f -> wgWrapper.queryFlag(p, b.getLocation(), f).orElse(WrappedState.DENY)).orElse(WrappedState.DENY); + externalPluginsAllowed = state == WrappedState.ALLOW; + } + + ItemStack itemStack = shop.getProduct().getItemStack(); + + if (externalPluginsAllowed || p.hasPermission(Permissions.BYPASS_EXTERNAL_PLUGIN)) { + boolean stack = p.isSneaking() && !Utils.hasAxeInHand(p); + int amount = stack ? itemStack.getMaxStackSize() : shop.getProduct().getAmount(); + + if (Utils.getAmount(p.getInventory(), itemStack) >= amount) { + if (confirmed || !Config.confirmShopping) { + sell(p, shop, stack); + if (Config.confirmShopping) { + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.remove(shop.getID()); + if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId()); + else needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + plugin.debug("Needs confirmation"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM)); + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + if (Config.autoCalculateItemAmount && Utils.getAmount(p.getInventory(), itemStack) > 0) { + if (confirmed || !Config.confirmShopping) { + sell(p, shop, stack); + if (Config.confirmShopping) { + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.remove(shop.getID()); + if (ids.isEmpty()) needsConfirmation.remove(p.getUniqueId()); + else needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + plugin.debug("Needs confirmation"); + p.sendMessage(LanguageUtils.getMessage(Message.CLICK_TO_CONFIRM)); + Set ids = needsConfirmation.containsKey(p.getUniqueId()) ? needsConfirmation.get(p.getUniqueId()) : new HashSet(); + ids.add(shop.getID()); + needsConfirmation.put(p.getUniqueId(), ids); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_ITEMS)); + plugin.debug(p.getName() + " doesn't have enough items"); + } + } + } else { + plugin.debug(p.getName() + " doesn't have external plugin's permission"); + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_SELL_HERE)); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_SELL)); + plugin.debug(p.getName() + " is not permitted to sell"); + } + } else { + p.sendMessage(LanguageUtils.getMessage(Message.SELLING_DISABLED)); + plugin.debug("Selling is disabled"); + } + } + } + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent e) { + if (Config.enableAuthMeIntegration && plugin.hasAuthMe() && !AuthMeApi.getInstance().isAuthenticated(e.getPlayer())) return; + handleInteractEvent(e); + } + + /** + * Create a new shop + * + * @param executor Player, who executed the command, will receive the message and become the vendor of the shop + * @param location Where the shop will be located + * @param product Product of the Shop + * @param buyPrice Buy price + * @param sellPrice Sell price + * @param shopType Type of the shop + */ + private void create(final Player executor, final Location location, final ShopProduct product, final double buyPrice, final double sellPrice, final ShopType shopType) { + plugin.debug(executor.getName() + " is creating new shop..."); + + if (!executor.hasPermission(Permissions.CREATE)) { + executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE)); + plugin.debug(executor.getName() + " is not permitted to create the shop"); + return; + } + + double creationPrice = (shopType == ShopType.NORMAL) ? Config.shopCreationPriceNormal : Config.shopCreationPriceAdmin; + Shop shop = new Shop(plugin, executor, product, location, buyPrice, sellPrice, shopType); + + ShopCreateEvent event = new ShopCreateEvent(executor, shop, creationPrice); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled() && !executor.hasPermission(Permissions.CREATE_PROTECTED)) { + plugin.debug("Create event cancelled"); + executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_CREATE_PROTECTED)); + return; + } + + if (creationPrice > 0) { + EconomyResponse r = plugin.getEconomy().withdrawPlayer(executor, location.getWorld().getName(), creationPrice); + if (!r.transactionSuccess()) { + plugin.debug("Economy transaction failed: " + r.errorMessage); + executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r.errorMessage))); + return; + } + } + + shop.create(true); + + plugin.debug("Shop created"); + shopUtils.addShop(shop, true); + + Message message = shopType == ShopType.ADMIN ? Message.ADMIN_SHOP_CREATED : Message.SHOP_CREATED; + executor.sendMessage(LanguageUtils.getMessage(message, new Replacement(Placeholder.CREATION_PRICE, creationPrice))); + } + + /** + * Remove a shop + * @param executor Player, who executed the command and will receive the message + * @param shop Shop to be removed + */ + private void remove(Player executor, Shop shop) { + if (shop.getShopType() == ShopType.ADMIN && !executor.hasPermission(Permissions.REMOVE_ADMIN)) { + executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_REMOVE_ADMIN)); + return; + } + + if (shop.getShopType() == ShopType.NORMAL && !executor.getUniqueId().equals(shop.getVendor().getUniqueId()) + && !executor.hasPermission(Permissions.REMOVE_OTHER)) { + executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_REMOVE_OTHERS)); + return; + } + + plugin.debug(executor.getName() + " is removing " + shop.getVendor().getName() + "'s shop (#" + shop.getID() + ")"); + ShopRemoveEvent event = new ShopRemoveEvent(executor, shop); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + plugin.debug("Remove event cancelled (#" + shop.getID() + ")"); + return; + } + + double creationPrice = shop.getShopType() == ShopType.ADMIN ? Config.shopCreationPriceAdmin : Config.shopCreationPriceNormal; + if (creationPrice > 0 && Config.refundShopCreation && executor.getUniqueId().equals(shop.getVendor().getUniqueId())) { + EconomyResponse r = plugin.getEconomy().depositPlayer(executor, shop.getLocation().getWorld().getName(), creationPrice); + if (!r.transactionSuccess()) { + plugin.debug("Economy transaction failed: " + r.errorMessage); + executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, + new Replacement(Placeholder.ERROR, r.errorMessage))); + executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED_REFUND, + new Replacement(Placeholder.CREATION_PRICE, 0))); + } else { + executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED_REFUND, + new Replacement(Placeholder.CREATION_PRICE, creationPrice))); + } + } else { + executor.sendMessage(LanguageUtils.getMessage(Message.SHOP_REMOVED)); + } + + shopUtils.removeShop(shop, true); + plugin.debug("Removed shop (#" + shop.getID() + ")"); + } + + /** + * Open a shop + * @param executor Player, who executed the command and will receive the message + * @param shop Shop to be opened + * @param message Whether the player should receive the {@link Message#OPENED_SHOP} message + */ + private void open(Player executor, Shop shop, boolean message) { + if (!executor.getUniqueId().equals(shop.getVendor().getUniqueId()) && !executor.hasPermission(Permissions.OPEN_OTHER)) { + executor.sendMessage(LanguageUtils.getMessage(Message.NO_PERMISSION_OPEN_OTHERS)); + return; + } + + plugin.debug(executor.getName() + " is opening " + shop.getVendor().getName() + "'s shop (#" + shop.getID() + ")"); + ShopOpenEvent event = new ShopOpenEvent(executor, shop); + Bukkit.getPluginManager().callEvent(event); + if (event.isCancelled()) { + plugin.debug("Open event cancelled (#" + shop.getID() + ")"); + return; + } + + executor.openInventory(shop.getInventoryHolder().getInventory()); + plugin.debug("Opened shop (#" + shop.getID() + ")"); + if (message) executor.sendMessage(LanguageUtils.getMessage(Message.OPENED_SHOP, + new Replacement(Placeholder.VENDOR, shop.getVendor().getName()))); + } + + /** + * + * @param executor Player, who executed the command and will retrieve the information + * @param shop Shop from which the information will be retrieved + */ + private void info(Player executor, Shop shop) { + plugin.debug(executor.getName() + " is retrieving shop info (#" + shop.getID() + ")"); + ShopInfoEvent event = new ShopInfoEvent(executor, shop); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + plugin.debug("Info event cancelled (#" + shop.getID() + ")"); + return; + } + + Chest c = (Chest) shop.getLocation().getBlock().getState(); + ItemStack itemStack = shop.getProduct().getItemStack(); + int amount = Utils.getAmount(c.getInventory(), itemStack); + int space = Utils.getFreeSpaceForItem(c.getInventory(), itemStack); + + String vendorName = (shop.getVendor().getName() == null ? + shop.getVendor().getUniqueId().toString() : shop.getVendor().getName()); + + String vendorString = LanguageUtils.getMessage(Message.SHOP_INFO_VENDOR, + new Replacement(Placeholder.VENDOR, vendorName)); + + // Make JSON message with item preview + JsonBuilder jb = getProductJson(shop.getProduct()); + + String disabled = LanguageUtils.getMessage(Message.SHOP_INFO_DISABLED); + + String priceString = LanguageUtils.getMessage(Message.SHOP_INFO_PRICE, + new Replacement(Placeholder.BUY_PRICE, (shop.getBuyPrice() > 0 ? String.valueOf(shop.getBuyPrice()) : disabled)), + new Replacement(Placeholder.SELL_PRICE, (shop.getSellPrice() > 0 ? String.valueOf(shop.getSellPrice()) : disabled))); + + String shopType = LanguageUtils.getMessage(shop.getShopType() == ShopType.NORMAL ? + Message.SHOP_INFO_NORMAL : Message.SHOP_INFO_ADMIN); + + String stock = LanguageUtils.getMessage(Message.SHOP_INFO_STOCK, + new Replacement(Placeholder.STOCK, amount)); + + String chestSpace = LanguageUtils.getMessage(Message.SHOP_INFO_CHEST_SPACE, + new Replacement(Placeholder.CHEST_SPACE, space)); + + executor.sendMessage(" "); + if (shop.getShopType() != ShopType.ADMIN) executor.sendMessage(vendorString); + jb.sendJson(executor); + if (shop.getShopType() != ShopType.ADMIN && shop.getBuyPrice() > 0) executor.sendMessage(stock); + if (shop.getShopType() != ShopType.ADMIN && shop.getSellPrice() > 0) executor.sendMessage(chestSpace); + executor.sendMessage(priceString); + executor.sendMessage(shopType); + executor.sendMessage(" "); + } + + /** + * Create a {@link JsonBuilder} containing the shop info message for the product + * in which you can hover the item name to get a preview. + * @param product The product of the shop + * @return A {@link JsonBuilder} that can send the message via {@link JsonBuilder#sendJson(Player)} + */ + private JsonBuilder getProductJson(ShopProduct product) { + // Add spaces at start and end, so there will always be a part before and after + // the item name after splitting at Placeholder.ITEM_NAME + String productString = " " + LanguageUtils.getMessage(Message.SHOP_INFO_PRODUCT, + new Replacement(Placeholder.AMOUNT, String.valueOf(product.getAmount()))) + " "; + + String[] parts = productString.split(Placeholder.ITEM_NAME.toString()); + String productName = product.getLocalizedName(); + String jsonItem = ""; + JsonBuilder jb = new JsonBuilder(plugin); + JsonBuilder.PartArray rootArray = new JsonBuilder.PartArray(); + + try { + OBCClassResolver obcClassResolver = new OBCClassResolver(); + NMSClassResolver nmsClassResolver = new NMSClassResolver(); + + Class craftItemStackClass = obcClassResolver.resolveSilent("inventory.CraftItemStack"); + Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, product.getItemStack()); + Class nbtTagCompoundClass = nmsClassResolver.resolveSilent("nbt.NBTTagCompound"); + Object nbtTagCompound = nbtTagCompoundClass.getConstructor().newInstance(); + nmsStack.getClass().getMethod("save", nbtTagCompoundClass).invoke(nmsStack, nbtTagCompound); + jsonItem = new JsonPrimitive(nbtTagCompound.toString()).toString(); + } catch (Exception e) { + plugin.getLogger().severe("Failed to create JSON from item. Product preview will not be available."); + plugin.debug("Failed to create JSON from item:"); + plugin.debug(e); + jb.setRootPart(new JsonBuilder.Part(productString.replace(Placeholder.ITEM_NAME.toString(), productName))); + return jb; + } + + for (int i = 0; i < parts.length; i++) { + String part = parts[i]; + + // Remove spaces at start and end that were added before + if (i == 0 && part.startsWith(" ")) { + part = part.substring(1); + } else if (i == parts.length - 1 && part.endsWith(" ")) { + part = part.substring(0, part.length() - 1); + } + + String formatPrefix = ""; + + // A color code resets all format codes, so only format codes + // after the last color code have to be found. + int lastColorGroupEndIndex = 0; + + Matcher colorMatcher = COLOR_CODE_PATTERN.matcher(part); + if (colorMatcher.find()) { + formatPrefix = colorMatcher.group(1); + lastColorGroupEndIndex = colorMatcher.end(); + } + + Matcher formatMatcher = FORMAT_CODE_PATTERN.matcher(part); + while (formatMatcher.find(lastColorGroupEndIndex)) { + formatPrefix += formatMatcher.group(1); + } + + rootArray.addPart(new JsonBuilder.Part(part)); + + if (i < parts.length - 1) { + JsonBuilder.PartMap hoverEvent = new JsonBuilder.PartMap(); + hoverEvent.setValue("action", new JsonBuilder.Part("show_item")); + hoverEvent.setValue("value", new JsonBuilder.Part(jsonItem, false)); + + JsonBuilder.PartMap itemNameMap = JsonBuilder.parse(formatPrefix + productName).toMap(); + itemNameMap.setValue("hoverEvent", hoverEvent); + + rootArray.addPart(itemNameMap); + } + } + + jb.setRootPart(rootArray); + return jb; + } + + /** + * A player buys from a shop + * @param executor Player, who executed the command and will buy the product + * @param shop Shop, from which the player buys + * @param stack Whether a whole stack should be bought + */ + private void buy(Player executor, final Shop shop, boolean stack) { + plugin.debug(executor.getName() + " is buying (#" + shop.getID() + ")"); + + ItemStack itemStack = shop.getProduct().getItemStack(); + int amount = shop.getProduct().getAmount(); + if (stack) amount = itemStack.getMaxStackSize(); + + String worldName = shop.getLocation().getWorld().getName(); + + double price = shop.getBuyPrice(); + if (stack) price = (price / shop.getProduct().getAmount()) * amount; + + if (econ.getBalance(executor, worldName) >= price || Config.autoCalculateItemAmount) { + + int amountForMoney = (int) (amount / price * econ.getBalance(executor, worldName)); + + if (amountForMoney == 0 && Config.autoCalculateItemAmount) { + executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_MONEY)); + return; + } + + plugin.debug(executor.getName() + " has enough money for " + amountForMoney + " item(s) (#" + shop.getID() + ")"); + + Block b = shop.getLocation().getBlock(); + Chest c = (Chest) b.getState(); + + int amountForChestItems = Utils.getAmount(c.getInventory(), itemStack); + + if (amountForChestItems == 0 && shop.getShopType() != ShopType.ADMIN) { + executor.sendMessage(LanguageUtils.getMessage(Message.OUT_OF_STOCK)); + return; + } + + ItemStack product = new ItemStack(itemStack); + if (stack) product.setAmount(amount); + + Inventory inventory = executor.getInventory(); + + int freeSpace = Utils.getFreeSpaceForItem(inventory, product); + + if (freeSpace == 0) { + executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_INVENTORY_SPACE)); + return; + } + + int newAmount = amount; + + if (Config.autoCalculateItemAmount) { + if (shop.getShopType() == ShopType.ADMIN) + newAmount = Math.min(amountForMoney, freeSpace); + else + newAmount = Math.min(Math.min(amountForMoney, amountForChestItems), freeSpace); + } + + if (newAmount > amount) newAmount = amount; + + ShopProduct newProduct = new ShopProduct(product, newAmount); + double newPrice = (price / amount) * newAmount; + + if (freeSpace >= newAmount) { + plugin.debug(executor.getName() + " has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")"); + + EconomyResponse r = econ.withdrawPlayer(executor, worldName, newPrice); + + if (r.transactionSuccess()) { + EconomyResponse r2 = (shop.getShopType() != ShopType.ADMIN) ? econ.depositPlayer(shop.getVendor(), worldName, newPrice) : null; + + if (r2 != null) { + if (r2.transactionSuccess()) { + ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.BUY, newAmount, newPrice); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + econ.depositPlayer(executor, worldName, newPrice); + econ.withdrawPlayer(shop.getVendor(), worldName, newPrice); + plugin.debug("Buy event cancelled (#" + shop.getID() + ")"); + return; + } + + database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.BUY, null); + + addToInventory(inventory, newProduct); + removeFromInventory(c.getInventory(), newProduct); + executor.updateInventory(); + + new BukkitRunnable() { + @Override + public void run() { + if (plugin.getHologramFormat().isDynamic()) { + shop.updateHologramText(); + } + } + }.runTaskLater(plugin, 1L); + + String vendorName = (shop.getVendor().getName() == null ? shop.getVendor().getUniqueId().toString() : shop.getVendor().getName()); + executor.sendMessage(LanguageUtils.getMessage(Message.BUY_SUCCESS, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)), + new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice)), + new Replacement(Placeholder.VENDOR, vendorName))); + + plugin.debug(executor.getName() + " successfully bought (#" + shop.getID() + ")"); + + if (shop.getVendor().isOnline() && Config.enableVendorMessages) { + shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.SOMEONE_BOUGHT, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)), + new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice)), + new Replacement(Placeholder.PLAYER, executor.getName()))); + } else if(!shop.getVendor().isOnline() && Config.enableVendorBungeeMessages){ + String message = LanguageUtils.getMessage( Message.SOMEONE_BOUGHT, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)), + new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice)), + new Replacement(Placeholder.PLAYER, executor.getName())); + sendBungeeMessage(shop.getVendor().getName(),message); + } + + } else { + plugin.debug("Economy transaction failed (r2): " + r2.errorMessage + " (#" + shop.getID() + ")"); + executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r2.errorMessage))); + econ.withdrawPlayer(shop.getVendor(), worldName, newPrice); + econ.depositPlayer(executor, worldName, newPrice); + } + } else { + ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.BUY, newAmount, newPrice); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + econ.depositPlayer(executor, worldName, newPrice); + plugin.debug("Buy event cancelled (#" + shop.getID() + ")"); + return; + } + + database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.BUY, null); + + addToInventory(inventory, newProduct); + executor.updateInventory(); + + new BukkitRunnable() { + @Override + public void run() { + if (plugin.getHologramFormat().isDynamic()) { + shop.updateHologramText(); + } + } + }.runTaskLater(plugin, 1L); + + executor.sendMessage(LanguageUtils.getMessage(Message.BUY_SUCCESS_ADMIN, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)), + new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.BUY_PRICE, String.valueOf(newPrice)))); + + plugin.debug(executor.getName() + " successfully bought (#" + shop.getID() + ")"); + } + } else { + plugin.debug("Economy transaction failed (r): " + r.errorMessage + " (#" + shop.getID() + ")"); + executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r.errorMessage))); + econ.depositPlayer(executor, worldName, newPrice); + } + } else { + executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_INVENTORY_SPACE)); + } + } else { + executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_MONEY)); + } + } + + /** + * A player sells to a shop + * @param executor Player, who executed the command and will sell the product + * @param shop Shop, to which the player sells + */ + private void sell(Player executor, final Shop shop, boolean stack) { + plugin.debug(executor.getName() + " is selling (#" + shop.getID() + ")"); + + ItemStack itemStack = shop.getProduct().getItemStack(); + int amount = shop.getProduct().getAmount(); + if (stack) amount = itemStack.getMaxStackSize(); + + double price = shop.getSellPrice(); + if (stack) price = (price / shop.getProduct().getAmount()) * amount; + + String worldName = shop.getLocation().getWorld().getName(); + + if (shop.getShopType() == ShopType.ADMIN || econ.getBalance(shop.getVendor(), worldName) >= price || Config.autoCalculateItemAmount) { + int amountForMoney = 1; + + if (shop.getShopType() != ShopType.ADMIN) { + amountForMoney = (int) (amount / price * econ.getBalance(shop.getVendor(), worldName)); + } + + plugin.debug("Vendor has enough money for " + amountForMoney + " item(s) (#" + shop.getID() + ")"); + + if (amountForMoney == 0 && Config.autoCalculateItemAmount && shop.getShopType() != ShopType.ADMIN) { + executor.sendMessage(LanguageUtils.getMessage(Message.VENDOR_NOT_ENOUGH_MONEY)); + return; + } + + Block block = shop.getLocation().getBlock(); + Chest chest = (Chest) block.getState(); + + int amountForItemCount = Utils.getAmount(executor.getInventory(), itemStack); + + if (amountForItemCount == 0) { + executor.sendMessage(LanguageUtils.getMessage(Message.NOT_ENOUGH_ITEMS)); + return; + } + + ItemStack product = new ItemStack(itemStack); + if (stack) product.setAmount(amount); + + Inventory inventory = chest.getInventory(); + + int freeSpace = Utils.getFreeSpaceForItem(inventory, product); + + if (freeSpace == 0 && shop.getShopType() != ShopType.ADMIN) { + executor.sendMessage(LanguageUtils.getMessage(Message.CHEST_NOT_ENOUGH_INVENTORY_SPACE)); + return; + } + + int newAmount = amount; + + if (Config.autoCalculateItemAmount) { + if (shop.getShopType() == ShopType.ADMIN) + newAmount = amountForItemCount; + else + newAmount = Math.min(Math.min(amountForMoney, amountForItemCount), freeSpace); + } + + if (newAmount > amount) newAmount = amount; + + ShopProduct newProduct = new ShopProduct(product, newAmount); + double newPrice = (price / amount) * newAmount; + + if (freeSpace >= newAmount || shop.getShopType() == ShopType.ADMIN) { + plugin.debug("Chest has enough inventory space for " + freeSpace + " items (#" + shop.getID() + ")"); + + EconomyResponse r = econ.depositPlayer(executor, worldName, newPrice); + + if (r.transactionSuccess()) { + EconomyResponse r2 = (shop.getShopType() != ShopType.ADMIN) ? econ.withdrawPlayer(shop.getVendor(), worldName, newPrice) : null; + + if (r2 != null) { + if (r2.transactionSuccess()) { + ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.SELL, newAmount, newPrice); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + econ.withdrawPlayer(executor, worldName, newPrice); + econ.depositPlayer(shop.getVendor(), worldName, newPrice); + plugin.debug("Sell event cancelled (#" + shop.getID() + ")"); + return; + } + + database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.SELL, null); + + addToInventory(inventory, newProduct); + removeFromInventory(executor.getInventory(), newProduct); + executor.updateInventory(); + + new BukkitRunnable() { + @Override + public void run() { + if (plugin.getHologramFormat().isDynamic()) { + shop.updateHologramText(); + } + } + }.runTaskLater(plugin, 1L); + + String vendorName = (shop.getVendor().getName() == null ? shop.getVendor().getUniqueId().toString() : shop.getVendor().getName()); + executor.sendMessage(LanguageUtils.getMessage(Message.SELL_SUCCESS, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)), + new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice)), + new Replacement(Placeholder.VENDOR, vendorName))); + + plugin.debug(executor.getName() + " successfully sold (#" + shop.getID() + ")"); + + if (shop.getVendor().isOnline() && Config.enableVendorMessages) { + shop.getVendor().getPlayer().sendMessage(LanguageUtils.getMessage(Message.SOMEONE_SOLD, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)), + new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice)), + new Replacement(Placeholder.PLAYER, executor.getName()))); + } else if(!shop.getVendor().isOnline() && Config.enableVendorBungeeMessages){ + String message = LanguageUtils.getMessage( Message.SOMEONE_SOLD, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)), + new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice)), + new Replacement(Placeholder.PLAYER, executor.getName())); + sendBungeeMessage(shop.getVendor().getName(),message); + } + + } else { + plugin.debug("Economy transaction failed (r2): " + r2.errorMessage + " (#" + shop.getID() + ")"); + executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r2.errorMessage))); + econ.withdrawPlayer(executor, worldName, newPrice); + econ.depositPlayer(shop.getVendor(), worldName, newPrice); + } + + } else { + ShopBuySellEvent event = new ShopBuySellEvent(executor, shop, ShopBuySellEvent.Type.SELL, newAmount, newPrice); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + econ.withdrawPlayer(executor, worldName, newPrice); + plugin.debug("Sell event cancelled (#" + shop.getID() + ")"); + return; + } + + database.logEconomy(executor, shop, newProduct, newPrice, ShopBuySellEvent.Type.SELL, null); + + removeFromInventory(executor.getInventory(), newProduct); + executor.updateInventory(); + + new BukkitRunnable() { + @Override + public void run() { + if (plugin.getHologramFormat().isDynamic()) { + shop.updateHologramText(); + } + } + }.runTaskLater(plugin, 1L); + + executor.sendMessage(LanguageUtils.getMessage(Message.SELL_SUCCESS_ADMIN, new Replacement(Placeholder.AMOUNT, String.valueOf(newAmount)), + new Replacement(Placeholder.ITEM_NAME, newProduct.getLocalizedName()), new Replacement(Placeholder.SELL_PRICE, String.valueOf(newPrice)))); + + plugin.debug(executor.getName() + " successfully sold (#" + shop.getID() + ")"); + } + + } else { + plugin.debug("Economy transaction failed (r): " + r.errorMessage + " (#" + shop.getID() + ")"); + executor.sendMessage(LanguageUtils.getMessage(Message.ERROR_OCCURRED, new Replacement(Placeholder.ERROR, r.errorMessage))); + econ.withdrawPlayer(executor, worldName, newPrice); + } + + } else { + executor.sendMessage(LanguageUtils.getMessage(Message.CHEST_NOT_ENOUGH_INVENTORY_SPACE)); + } + + } else { + executor.sendMessage(LanguageUtils.getMessage(Message.VENDOR_NOT_ENOUGH_MONEY)); + } + } + + /** + * Adds items to an inventory + * @param inventory The inventory, to which the items will be added + * @param itemStack Items to add + * @return Whether all items were added to the inventory + */ + private boolean addToInventory(Inventory inventory, ShopProduct product) { + plugin.debug("Adding items to inventory..."); + + HashMap inventoryItems = new HashMap<>(); + ItemStack itemStack = product.getItemStack(); + int amount = product.getAmount(); + int added = 0; + + if (inventory instanceof PlayerInventory) { + if (Utils.getMajorVersion() >= 9) { + inventoryItems.put(40, inventory.getItem(40)); + } + + for (int i = 0; i < 36; i++) { + inventoryItems.put(i, inventory.getItem(i)); + } + + } else { + for (int i = 0; i < inventory.getSize(); i++) { + inventoryItems.put(i, inventory.getItem(i)); + } + } + + slotLoop: + for (int slot : inventoryItems.keySet()) { + while (added < amount) { + ItemStack item = inventory.getItem(slot); + + if (item != null && item.getType() != Material.AIR) { + if (Utils.isItemSimilar(item, itemStack)) { + if (item.getAmount() != item.getMaxStackSize()) { + ItemStack newItemStack = new ItemStack(item); + newItemStack.setAmount(item.getAmount() + 1); + inventory.setItem(slot, newItemStack); + added++; + } else { + continue slotLoop; + } + } else { + continue slotLoop; + } + } else { + ItemStack newItemStack = new ItemStack(itemStack); + newItemStack.setAmount(1); + inventory.setItem(slot, newItemStack); + added++; + } + } + } + + return (added == amount); + } + + /** + * Removes items to from an inventory + * @param inventory The inventory, from which the items will be removed + * @param itemStack Items to remove + * @return Whether all items were removed from the inventory + */ + private boolean removeFromInventory(Inventory inventory, ShopProduct product) { + plugin.debug("Removing items from inventory..."); + + HashMap inventoryItems = new HashMap<>(); + ItemStack itemStack = product.getItemStack(); + int amount = product.getAmount(); + int removed = 0; + + if (inventory instanceof PlayerInventory) { + if (Utils.getMajorVersion() >= 9) { + inventoryItems.put(40, inventory.getItem(40)); + } + + for (int i = 0; i < 36; i++) { + inventoryItems.put(i, inventory.getItem(i)); + } + + } else { + for (int i = 0; i < inventory.getSize(); i++) { + inventoryItems.put(i, inventory.getItem(i)); + } + } + + slotLoop: + for (int slot : inventoryItems.keySet()) { + while (removed < amount) { + ItemStack item = inventory.getItem(slot); + + if (item != null && item.getType() != Material.AIR) { + if (Utils.isItemSimilar(item, itemStack)) { + if (item.getAmount() > 0) { + int newAmount = item.getAmount() - 1; + + ItemStack newItemStack = new ItemStack(item); + newItemStack.setAmount(newAmount); + + if (newAmount == 0) + inventory.setItem(slot, null); + else + inventory.setItem(slot, newItemStack); + + removed++; + } else { + continue slotLoop; + } + } else { + continue slotLoop; + } + } else { + continue slotLoop; + } + + } + } + + return (removed == amount); + } + + public void sendBungeeMessage(String player, String message) { + try { + ByteArrayOutputStream b = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(b); + + out.writeUTF("Message"); + out.writeUTF(player); + out.writeUTF(message); + + if (!plugin.getServer().getOnlinePlayers().isEmpty()) { + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { + Player p = plugin.getServer().getOnlinePlayers().iterator().next(); + p.sendPluginMessage(plugin, "BungeeCord", b.toByteArray()); + }); + } + } catch (Exception e) { + plugin.debug("Failed to send bungee message"); + plugin.debug(e); + plugin.getLogger().warning("Failed to send BungeeCord message"); + } + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopItemListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopItemListener.java new file mode 100644 index 0000000..13679b1 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopItemListener.java @@ -0,0 +1,157 @@ +package de.epiceric.shopchest.listeners; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockFromToEvent; +import org.bukkit.event.block.BlockGrowEvent; +import org.bukkit.event.block.BlockMultiPlaceEvent; +import org.bukkit.event.block.BlockPistonExtendEvent; +import org.bukkit.event.block.BlockPistonRetractEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.BlockSpreadEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.world.StructureGrowEvent; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.utils.ShopUtils; + +public class ShopItemListener implements Listener { + + private ShopUtils shopUtils; + + public ShopItemListener(ShopChest plugin) { + this.shopUtils = plugin.getShopUtils(); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onBlockPlace(BlockPlaceEvent e) { + Block b = e.getBlockPlaced(); + Block below = b.getRelative(BlockFace.DOWN); + + if (shopUtils.isShop(below.getLocation())) { + Shop shop = shopUtils.getShop(below.getLocation()); + if (shop.getItem() != null) { + shop.getItem().resetForPlayer(e.getPlayer()); + } + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onMultiBlockPlace(BlockMultiPlaceEvent e) { + for (BlockState blockState : e.getReplacedBlockStates()) { + Block below = blockState.getBlock().getRelative(BlockFace.DOWN); + + if (shopUtils.isShop(below.getLocation())) { + Shop shop = shopUtils.getShop(below.getLocation()); + if (shop.getItem() != null) { + shop.getItem().resetForPlayer(e.getPlayer()); + } + e.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onPistonExtend(BlockPistonExtendEvent e) { + // If the piston would only move itself + Block airAfterPiston = e.getBlock().getRelative(e.getDirection()); + Block belowAir = airAfterPiston.getRelative(BlockFace.DOWN); + if (shopUtils.isShop(belowAir.getLocation())) { + e.setCancelled(true); + return; + } + + for (Block b : e.getBlocks()) { + Block newBlock = b.getRelative(e.getDirection()); + Block belowNewBlock = newBlock.getRelative(BlockFace.DOWN); + if (shopUtils.isShop(belowNewBlock.getLocation())) e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onPistonRetract(BlockPistonRetractEvent e) { + for (Block b : e.getBlocks()) { + Block newBlock = b.getRelative(e.getDirection()); + Block belowNewBlock = newBlock.getRelative(BlockFace.DOWN); + if (shopUtils.isShop(belowNewBlock.getLocation())) { + e.setCancelled(true); + for (Player p : Bukkit.getOnlinePlayers()) { + Shop shop = shopUtils.getShop(belowNewBlock.getLocation()); + if (shop.getItem() != null) { + shop.getItem().resetForPlayer(p); + } + } + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onLiquidFlow(BlockFromToEvent e) { + Block b = e.getToBlock(); + Block below = b.getRelative(BlockFace.DOWN); + + if (shopUtils.isShop(below.getLocation())) e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onBucketEmpty(PlayerBucketEmptyEvent e) { + Block clicked = e.getBlockClicked(); + Block underWater = clicked.getRelative(BlockFace.DOWN).getRelative(e.getBlockFace()); + + if (shopUtils.isShop(clicked.getLocation())) { + if (e.getBucket() == Material.LAVA_BUCKET) { + Shop shop = shopUtils.getShop(clicked.getLocation()); + if (shop.getItem() != null) { + shop.getItem().resetForPlayer(e.getPlayer()); + } + } + } else if (shopUtils.isShop(underWater.getLocation())) { + if (e.getBucket() == Material.LAVA_BUCKET) { + Shop shop = shopUtils.getShop(underWater.getLocation()); + if (shop.getItem() != null) { + shop.getItem().resetForPlayer(e.getPlayer()); + } + } + } else { + return; + } + + e.setCancelled(true); + } + + @EventHandler(priority = EventPriority.HIGH) + public void onStructureGrow(StructureGrowEvent e) { + for (BlockState state : e.getBlocks()) { + Block newBlock = state.getBlock(); + if (shopUtils.isShop(newBlock.getLocation()) || shopUtils.isShop(newBlock.getRelative(BlockFace.DOWN).getLocation())) { + e.setCancelled(true); + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onBlockGrow(BlockGrowEvent e) { + Block newBlock = e.getNewState().getBlock(); + if (shopUtils.isShop(newBlock.getLocation()) || shopUtils.isShop(newBlock.getRelative(BlockFace.DOWN).getLocation())) { + e.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onBlockSpread(BlockSpreadEvent e) { + Block newBlock = e.getNewState().getBlock(); + if (shopUtils.isShop(newBlock.getLocation()) || shopUtils.isShop(newBlock.getRelative(BlockFace.DOWN).getLocation())) { + e.setCancelled(true); + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java new file mode 100644 index 0000000..449713d --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/ShopUpdateListener.java @@ -0,0 +1,153 @@ +package de.epiceric.shopchest.listeners; + +import java.util.HashSet; +import java.util.Set; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryMoveItemEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.utils.Callback; + +public class ShopUpdateListener implements Listener { + + private final ShopChest plugin; + private final Set newLoadedChunks = new HashSet<>(); + + public ShopUpdateListener(ShopChest plugin) { + this.plugin = plugin; + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onInventoryUpdate(InventoryMoveItemEvent e) { + if (!plugin.getHologramFormat().isDynamic()) return; + + Location loc = null; + + if (e.getSource().getHolder() instanceof Chest) { + loc = ((Chest) e.getSource().getHolder()).getLocation(); + } else if (e.getSource().getHolder() instanceof DoubleChest) { + loc = ((DoubleChest) e.getSource().getHolder()).getLocation(); + } else if (e.getDestination().getHolder() instanceof Chest) { + loc = ((Chest) e.getDestination().getHolder()).getLocation(); + } else if (e.getDestination().getHolder() instanceof DoubleChest) { + loc = ((DoubleChest) e.getDestination().getHolder()).getLocation(); + } + + if (loc != null) { + Shop shop = plugin.getShopUtils().getShop(loc); + if (shop != null) shop.updateHologramText(); + } + } + + @EventHandler + public void onPlayerLeave(PlayerQuitEvent e) { + // If done without delay, Bukkit#getOnlinePlayers() would still + // contain the player even though he left, so the shop updater + // would show the shop again. + new BukkitRunnable(){ + @Override + public void run() { + for (Shop shop : plugin.getShopUtils().getShops()) { + if (shop.hasItem()) { + shop.getItem().resetVisible(e.getPlayer()); + } + if (shop.hasHologram()) { + shop.getHologram().resetVisible(e.getPlayer()); + } + } + + plugin.getShopUtils().resetPlayerLocation(e.getPlayer()); + } + }.runTaskLater(plugin, 1L); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerTeleport(PlayerTeleportEvent e) { + Location from = e.getFrom(); + Location to = e.getTo(); + final Player p = e.getPlayer(); + + // Wait till the chunk should have loaded on the client + if (!from.getWorld().getName().equals(to.getWorld().getName()) + || from.getChunk().getX() != to.getChunk().getX() + || from.getChunk().getZ() != to.getChunk().getZ()) { + new BukkitRunnable() { + @Override + public void run() { + plugin.getUpdater().queue(() -> { + if (p.isOnline()) { + for (Shop shop : plugin.getShopUtils().getShops()) { + if (shop.hasItem()) { + shop.getItem().hidePlayer(p); + } + if (shop.hasHologram()) { + shop.getHologram().hidePlayer(p); + } + } + plugin.getShopUtils().resetPlayerLocation(p); + } + }); + plugin.getUpdater().updateShops(p); + } + }.runTaskLater(plugin, 15L); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerMove(PlayerMoveEvent e) { + plugin.getUpdater().updateShops(e.getPlayer()); + } + + @EventHandler + public void onChunkLoad(ChunkLoadEvent e) { + if (!plugin.getShopDatabase().isInitialized()) { + return; + } + + // Wait 10 ticks after first event is triggered, so that multiple + // chunk loads can be handled at the same time without having to + // send a database request for each chunk. + if (newLoadedChunks.isEmpty()) { + new BukkitRunnable(){ + @Override + public void run() { + int chunkCount = newLoadedChunks.size(); + plugin.getShopUtils().loadShops(newLoadedChunks.toArray(new Chunk[chunkCount]), new Callback(plugin) { + @Override + public void onResult(Integer result) { + if (result == 0) { + return; + } + plugin.debug("Loaded " + result + " shops in " + chunkCount + " chunks"); + } + + @Override + public void onError(Throwable throwable) { + // Database connection probably failed => disable plugin to prevent more errors + plugin.getLogger().severe("Failed to load shops in newly loaded chunks"); + plugin.debug("Failed to load shops in newly loaded chunks"); + if (throwable != null) plugin.debug(throwable); + } + }); + newLoadedChunks.clear(); + } + }.runTaskLater(plugin, 10L); + } + + newLoadedChunks.add(e.getChunk()); + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/listeners/WorldGuardListener.java b/plugin/src/main/java/de/epiceric/shopchest/listeners/WorldGuardListener.java new file mode 100644 index 0000000..b81aef3 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/listeners/WorldGuardListener.java @@ -0,0 +1,89 @@ +package de.epiceric.shopchest.listeners; + +import java.util.Optional; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.Chest; +import org.bukkit.entity.Player; +import org.bukkit.event.Event.Result; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.codemc.worldguardwrapper.WorldGuardWrapper; +import org.codemc.worldguardwrapper.event.WrappedUseBlockEvent; +import org.codemc.worldguardwrapper.flag.IWrappedFlag; +import org.codemc.worldguardwrapper.flag.WrappedState; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.utils.ClickType; +import de.epiceric.shopchest.utils.ClickType.EnumClickType; + +public class WorldGuardListener implements Listener { + + private ShopChest plugin; + + public WorldGuardListener(ShopChest plugin) { + this.plugin = plugin; + } + + + private boolean isAllowed(Player player, Location location) { + ClickType clickType = ClickType.getPlayerClickType(player); + + if (clickType != null && clickType.getClickType() == EnumClickType.CREATE) { + // If the player is about to create a shop, but does not have + // access to the chest, show the 'permission denied' message + // (if not previously set to allowed by another plugin). + // If the player can open the chest, that message should be hidden. + WorldGuardWrapper wgWrapper = WorldGuardWrapper.getInstance(); + Optional> flag = wgWrapper.getFlag("chest-access", WrappedState.class); + if (!flag.isPresent()) plugin.debug("WorldGuard flag 'chest-access' is not present!"); + WrappedState state = flag.map(f -> wgWrapper.queryFlag(player, location, f).orElse(WrappedState.DENY)).orElse(WrappedState.DENY); + return state == WrappedState.ALLOW; + } + + Shop shop = plugin.getShopUtils().getShop(location); + + if (shop != null) { + // Don't show 'permission denied' messages for any kind of + // shop interaction even if block interaction is not + // allowed in the region. + return true; + } + + return false; + } + + @EventHandler(priority = EventPriority.LOW) + public void onUseBlock(WrappedUseBlockEvent event) { + if (Config.enableWorldGuardIntegration) { + Player player = event.getPlayer(); + + if (event.getOriginalEvent() instanceof PlayerInteractEvent) { + Block block = event.getBlocks().get(0); + Material type = block.getType(); + + if (type == Material.CHEST || type == Material.TRAPPED_CHEST) { + if (isAllowed(player, block.getLocation())) { + event.setResult(Result.ALLOW); + } + } + } else if (event.getOriginalEvent() instanceof InventoryOpenEvent) { + InventoryOpenEvent orig = (InventoryOpenEvent) event.getOriginalEvent(); + + if (orig.getInventory().getHolder() instanceof Chest) { + if (isAllowed(player, ((Chest) orig.getInventory().getHolder()).getLocation())) { + event.setResult(Result.ALLOW); + } + } + } + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/nms/ArmorStandWrapper.java b/plugin/src/main/java/de/epiceric/shopchest/nms/ArmorStandWrapper.java new file mode 100644 index 0000000..56ea9c4 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/nms/ArmorStandWrapper.java @@ -0,0 +1,159 @@ +package de.epiceric.shopchest.nms; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.inventivetalent.reflection.resolver.minecraft.NMSClassResolver; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.utils.Utils; + +public class ArmorStandWrapper { + private final NMSClassResolver nmsClassResolver = new NMSClassResolver(); + private final Class packetDataSerializerClass = nmsClassResolver.resolveSilent("network.PacketDataSerializer"); + private final Class packetPlayOutEntityDestroyClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityDestroy"); + private final Class packetPlayOutEntityMetadataClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityMetadata"); + private final Class packetPlayOutEntityTeleportClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityTeleport"); + private final Class dataWatcherClass = nmsClassResolver.resolveSilent("network.syncher.DataWatcher"); + + private final UUID uuid = UUID.randomUUID(); + private final int entityId; + + private ShopChest plugin; + private Location location; + private String customName; + + public ArmorStandWrapper(ShopChest plugin, Location location, String customName) { + this.plugin = plugin; + this.location = location; + this.customName = customName; + this.entityId = Utils.getFreeEntityId(); + } + + public void setVisible(Player player, boolean visible) { + try { + if (visible) { + Object dataWatcher = Utils.createDataWatcher(customName, null); + Utils.sendPacket(plugin, Utils.createPacketSpawnEntity(plugin, entityId, uuid, location, EntityType.ARMOR_STAND), player); + Utils.sendPacket(plugin, packetPlayOutEntityMetadataClass.getConstructor(int.class, dataWatcherClass, boolean.class) + .newInstance(entityId, dataWatcher, true), player); + } else if (entityId != -1) { + Utils.sendPacket(plugin, packetPlayOutEntityDestroyClass.getConstructor(int[].class).newInstance((Object) new int[]{entityId}), player); + } + } catch (ReflectiveOperationException e) { + plugin.getLogger().severe("Could not change hologram visibility"); + plugin.debug("Could not change armor stand visibility"); + plugin.debug(e); + } + } + + public void setLocation(Location location) { + this.location = location; + double y = location.getY() + (Utils.getServerVersion().equals("v1_8_R1") ? 0 : 1.975); + Object packet; + + try { + if (Utils.getMajorVersion() >= 17) { + // Empty constructor does not exist anymore in 1.17+ so create packet via serializer + Class byteBufClass = Class.forName("io.netty.buffer.ByteBuf"); + Class unpooledClass = Class.forName("io.netty.buffer.Unpooled"); + Object buffer = unpooledClass.getMethod("buffer").invoke(null); + Object serializer = packetDataSerializerClass.getConstructor(byteBufClass).newInstance(buffer); + + Method d = packetDataSerializerClass.getMethod("d", int.class); + Method writeDouble = packetDataSerializerClass.getMethod("writeDouble", double.class); + Method writeByte = packetDataSerializerClass.getMethod("writeByte", int.class); + Method writeBoolean = packetDataSerializerClass.getMethod("writeBoolean", boolean.class); + + d.invoke(serializer, getEntityId()); + writeDouble.invoke(serializer, location.getX()); + writeDouble.invoke(serializer, y); + writeDouble.invoke(serializer, location.getZ()); + writeByte.invoke(serializer, 0); + writeByte.invoke(serializer, 0); + writeBoolean.invoke(serializer, false); + + packet = packetPlayOutEntityTeleportClass.getConstructor(packetDataSerializerClass).newInstance(serializer); + } else { + packet = packetPlayOutEntityTeleportClass.getConstructor().newInstance(); + Field[] fields = packetPlayOutEntityTeleportClass.getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + } + + boolean isPre9 = Utils.getMajorVersion() < 9; + fields[0].set(packet, entityId); + + if (isPre9) { + fields[1].set(packet, (int)(location.getX() * 32)); + fields[2].set(packet, (int)(y * 32)); + fields[3].set(packet, (int)(location.getZ() * 32)); + } else { + fields[1].set(packet, location.getX()); + fields[2].set(packet, y); + fields[3].set(packet, location.getZ()); + } + fields[4].set(packet, (byte) 0); + fields[5].set(packet, (byte) 0); + fields[6].set(packet, true); + } + + if (packet == null) { + plugin.getLogger().severe("Could not set hologram location"); + plugin.debug("Could not set armor stand location: Packet is null"); + return; + } + + for (Player player : location.getWorld().getPlayers()) { + Utils.sendPacket(plugin, packet, player); + } + } catch (ReflectiveOperationException e) { + plugin.getLogger().severe("Could not set hologram location"); + plugin.debug("Could not set armor stand location"); + plugin.debug(e); + } + } + + public void setCustomName(String customName) { + this.customName = customName; + Object dataWatcher = Utils.createDataWatcher(customName, null); + try { + Object packet = packetPlayOutEntityMetadataClass.getConstructor(int.class, dataWatcherClass, boolean.class) + .newInstance(entityId, dataWatcher, true); + + for (Player player : location.getWorld().getPlayers()) { + Utils.sendPacket(plugin, packet, player); + } + } catch (ReflectiveOperationException e) { + plugin.getLogger().severe("Could not set hologram text"); + plugin.debug("Could not set armor stand custom name"); + plugin.debug(e); + } + } + + public void remove() { + for (Player player : location.getWorld().getPlayers()) { + setVisible(player, false); + } + } + + public int getEntityId() { + return entityId; + } + + public UUID getUuid() { + return uuid; + } + + public Location getLocation() { + return location.clone(); + } + + public String getCustomName() { + return customName; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/nms/CustomBookMeta.java b/plugin/src/main/java/de/epiceric/shopchest/nms/CustomBookMeta.java new file mode 100644 index 0000000..290015f --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/nms/CustomBookMeta.java @@ -0,0 +1,92 @@ +package de.epiceric.shopchest.nms; + +import java.lang.reflect.InvocationTargetException; + +import org.bukkit.inventory.ItemStack; +import org.inventivetalent.reflection.resolver.minecraft.OBCClassResolver; + +import de.epiceric.shopchest.ShopChest; + +// For versions below 1.9.4, since Bukkit's BookMeta +// didn't have generations in those versions + +public class CustomBookMeta { + private static final OBCClassResolver obcClassResolver = new OBCClassResolver(); + + public enum Generation { + ORIGINAL, + COPY_OF_ORIGINAL, + COPY_OF_COPY, + TATTERED + } + + public static Generation getGeneration(ItemStack book) { + try { + Class craftItemStackClass = obcClassResolver.resolveSilent("inventory.CraftItemStack"); + + if (craftItemStackClass == null) { + ShopChest.getInstance().debug("Failed to get NBTGeneration: Could not find CraftItemStack class"); + return null; + } + + Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, book); + + Object nbtTagCompound = nmsStack.getClass().getMethod("getTag").invoke(nmsStack); + if (nbtTagCompound == null) { + ShopChest.getInstance().debug("Failed to get NBTGeneration: getTag returned null"); + return null; + } + + Object generationObject = nbtTagCompound.getClass().getMethod("getInt", String.class).invoke(nbtTagCompound, "generation"); + if (generationObject == null) { + ShopChest.getInstance().debug("Failed to get NBTGeneration: getInt returned null"); + return null; + } + + if (generationObject instanceof Integer) { + int generation = (Integer) generationObject; + + if (generation > 3) generation = 3; + + return Generation.values()[generation]; + } + + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + ShopChest.getInstance().getLogger().severe("Failed to get NBTEntityID with reflection"); + ShopChest.getInstance().debug("Failed to get NBTEntityID with reflection"); + ShopChest.getInstance().debug(e); + } + + return null; + } + + public static void setGeneration(ItemStack book, Generation generation) { + try { + Class craftItemStackClass = obcClassResolver.resolveSilent("inventory.CraftItemStack"); + + if (craftItemStackClass == null) { + ShopChest.getInstance().debug("Failed to get NBTGeneration: Could not find CraftItemStack class"); + return; + } + + Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, book); + + Object nbtTagCompound = nmsStack.getClass().getMethod("getTag").invoke(nmsStack); + if (nbtTagCompound == null) { + ShopChest.getInstance().debug("Failed to get NBTGeneration: getTag returned null"); + return; + } + + nbtTagCompound.getClass().getMethod("setInt", String.class, int.class) + .invoke(nbtTagCompound, "generation", generation.ordinal()); + + nmsStack.getClass().getMethod("setTag", nbtTagCompound.getClass()).invoke(nmsStack, nbtTagCompound); + + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + ShopChest.getInstance().getLogger().severe("Failed to get NBTEntityID with reflection"); + ShopChest.getInstance().debug("Failed to get NBTEntityID with reflection"); + ShopChest.getInstance().debug(e); + } + } + +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/nms/Hologram.java b/plugin/src/main/java/de/epiceric/shopchest/nms/Hologram.java new file mode 100644 index 0000000..08b0320 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/nms/Hologram.java @@ -0,0 +1,253 @@ +package de.epiceric.shopchest.nms; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Player; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; + +public class Hologram { + // concurrent since update task is in async thread + private final Set viewers = ConcurrentHashMap.newKeySet(); + private final List wrappers = new ArrayList<>(); + private final Location location; + private final ShopChest plugin; + + private boolean exists; + + public Hologram(ShopChest plugin, String[] lines, Location location) { + this.plugin = plugin; + this.location = location; + + for (int i = 0; i < lines.length; i++) { + addLine(i, lines[i]); + } + + this.exists = true; + } + + /** + * @return Location of the hologram + */ + public Location getLocation() { + return location.clone(); + } + + /** + * @return Whether the hologram exists and is not dead + */ + public boolean exists() { + return exists; + } + + /** + * @param armorStand Armor stand to check + * @return Whether the given armor stand is part of the hologram + */ + public boolean contains(ArmorStand armorStand) { + for (ArmorStandWrapper wrapper : wrappers) { + if (armorStand.getUniqueId().equals(wrapper.getUuid())) { + return true; + } + } + return false; + } + + /** + * @return A list of {@link ArmorStandWrapper}s of this hologram + */ + public List getArmorStandWrappers() { + return wrappers; + } + + /** + * @param p Player to check + * @return Whether the hologram is visible to the player + */ + public boolean isVisible(Player p) { + return viewers.contains(p.getUniqueId()); + } + + /** + * @param p Player to which the hologram should be shown + */ + public void showPlayer(Player p) { + showPlayer(p, false); + } + + /** + * @param p Player to which the hologram should be shown + * @param force Whether to force showing the hologram + */ + public void showPlayer(Player p, boolean force) { + if (viewers.add(p.getUniqueId()) || force) { + togglePlayer(p, true); + } + } + + /** + * @param p Player from which the hologram should be hidden + */ + public void hidePlayer(Player p) { + hidePlayer(p, false); + } + + /** + * @param p Player from which the hologram should be hidden + * @param force Whether to force hiding the hologram + */ + public void hidePlayer(Player p, boolean force) { + if (viewers.remove(p.getUniqueId()) || force) { + togglePlayer(p, false); + } + } + + /** + *

Removes the hologram.

+ * + * Hologram will be hidden from all players and all + * ArmorStand entities will be killed. + */ + public void remove() { + viewers.clear(); + + for (ArmorStandWrapper wrapper : wrappers) { + wrapper.remove(); + } + wrappers.clear(); + + exists = false; + } + + /** + * Remove the player from the list of viewers. The hologram is + * then counted as hidden, but no packets are sent to the player. + * @param p Player whose visibility status will be reset + */ + public void resetVisible(Player p) { + viewers.remove(p.getUniqueId()); + } + + private void togglePlayer(Player p, boolean visible) { + for (ArmorStandWrapper wrapper : wrappers) { + wrapper.setVisible(p, visible); + } + } + + /** + * Get all hologram lines + * + * @return Hologram lines + */ + public String[] getLines() { + List lines = new ArrayList<>(); + for (ArmorStandWrapper wrapper : wrappers) { + lines.add(wrapper.getCustomName()); + } + + return lines.toArray(new String[lines.size()]); + } + + /** + * Add a line + * + * @param line where to insert + * @param text text to display + */ + public void addLine(int line, String text) { + addLine(line, text, false); + } + + private void addLine(int line, String text, boolean forceUpdateLine) { + if (text == null || text.isEmpty()) return; + + if (line >= wrappers.size()) { + line = wrappers.size(); + } + + text = ChatColor.translateAlternateColorCodes('&', text); + + if (Config.hologramFixedBottom) { + for (int i = 0; i < line; i++) { + ArmorStandWrapper wrapper = wrappers.get(i); + wrapper.setLocation(wrapper.getLocation().add(0, 0.25, 0)); + } + } else { + for (int i = line; i < wrappers.size(); i++) { + ArmorStandWrapper wrapper = wrappers.get(i); + wrapper.setLocation(wrapper.getLocation().subtract(0, 0.25, 0)); + } + } + + Location loc = getLocation(); + + if (!Config.hologramFixedBottom) { + loc.subtract(0, line * 0.25, 0); + } + + ArmorStandWrapper wrapper = new ArmorStandWrapper(plugin, loc, text); + wrappers.add(line, wrapper); + + if (forceUpdateLine) { + for (Player player : location.getWorld().getPlayers()) { + if (viewers.contains(player.getUniqueId())) { + wrapper.setVisible(player, true); + } + } + } + } + + /** + * Set a line + * + * @param line index to change + * @param text text to display + */ + public void setLine(int line, String text) { + if (text == null ||text.isEmpty()) { + removeLine(line); + return; + } + + text = ChatColor.translateAlternateColorCodes('&', text); + + if (line >= wrappers.size()) { + addLine(line, text, true); + return; + } + + wrappers.get(line).setCustomName(text); + } + + /** + * Remove a line + * + * @param line index to remove + */ + public void removeLine(int line) { + if (line < wrappers.size()) { + if (Config.hologramFixedBottom) { + for (int i = 0; i < line; i++) { + ArmorStandWrapper wrapper = wrappers.get(i); + wrapper.setLocation(wrapper.getLocation().subtract(0, 0.25, 0)); + } + } else { + for (int i = line + 1; i < wrappers.size(); i++) { + ArmorStandWrapper wrapper = wrappers.get(i); + wrapper.setLocation(wrapper.getLocation().add(0, 0.25, 0)); + } + } + + wrappers.get(line).remove(); + wrappers.remove(line); + } + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/nms/JsonBuilder.java b/plugin/src/main/java/de/epiceric/shopchest/nms/JsonBuilder.java new file mode 100644 index 0000000..946d20c --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/nms/JsonBuilder.java @@ -0,0 +1,252 @@ +package de.epiceric.shopchest.nms; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.inventivetalent.reflection.resolver.FieldResolver; +import org.inventivetalent.reflection.resolver.minecraft.NMSClassResolver; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.utils.Utils; + +public class JsonBuilder { + + public static class Part { + private String value; + + public Part() { + this("", true); + } + + public Part(Object value) { + this(value, value instanceof CharSequence); + } + + public Part(Object value, boolean appendQuotes) { + if (appendQuotes) { + this.value = "\"" + value + "\""; + } else { + this.value = String.valueOf(value); + } + } + + @Override + public String toString() { + return value; + } + + public PartArray toArray() { + return new PartArray(this); + } + + public PartMap toMap() { + PartMap map = new PartMap(); + map.setValue("text", new Part()); + map.setValue("extra", toArray()); + return map; + } + } + + public static class PartMap extends Part { + private Map values = new HashMap<>(); + + public PartMap() { + } + + public PartMap(Map values) { + this.values.putAll(values); + } + + public void setValue(String key, Part value) { + values.put(key, value); + } + + public void removeValue(String key) { + values.remove(key); + } + + @Override + public String toString() { + StringJoiner joiner = new StringJoiner(",", "{", "}"); + values.forEach((key, value) -> joiner.add("\"" + key + "\":" + value.toString())); + return joiner.toString(); + } + + @Override + public PartMap toMap() { + return this; + } + } + + public static class PartArray extends Part { + private List parts = new ArrayList<>(); + + public PartArray(Part... parts) { + this.parts.addAll(Arrays.asList(parts)); + } + + public void addPart(Part part) { + parts.add(part); + } + + @Override + public String toString() { + StringJoiner joiner = new StringJoiner(",", "[", "]"); + parts.forEach(part -> joiner.add(part.toString())); + return joiner.toString(); + } + + @Override + public PartArray toArray() { + return this; + } + } + + private static final Pattern PART_PATTERN = Pattern.compile("((§(?:[a-fA-Fk-oK-OrR0-9]|#[a-fA-F0-9]{6}))+)([^§]*)"); + private static final Pattern HEX_PATTERN = Pattern.compile("(§[a-fA-F0-9]){6}"); + + private Part rootPart; + private ShopChest plugin; + + private final NMSClassResolver nmsClassResolver = new NMSClassResolver(); + private Class iChatBaseComponentClass = nmsClassResolver.resolveSilent("network.chat.IChatBaseComponent"); + private Class packetPlayOutChatClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutChat"); + private Class chatSerializerClass = nmsClassResolver.resolveSilent("ChatSerializer", "network.chat.IChatBaseComponent$ChatSerializer"); + private Class chatMessageTypeClass; + + public JsonBuilder(ShopChest plugin) { + this.plugin = plugin; + + if (Utils.getMajorVersion() >= 16) { + chatMessageTypeClass = nmsClassResolver.resolveSilent("network.chat.ChatMessageType"); + } + + Class[] requiredClasses = new Class[] { + iChatBaseComponentClass, packetPlayOutChatClass, chatSerializerClass + }; + + for (Class c : requiredClasses) { + if (c == null) { + plugin.debug("Failed to instantiate JsonBuilder: Could not find all required classes"); + return; + } + } + } + + public static Part parse(String text) { + Matcher hexMatcher = HEX_PATTERN.matcher(text); + while (hexMatcher.find()) { + String hexCode = hexMatcher.group(0).replace("§", ""); + text = text.replace(hexMatcher.group(0), "§#" + hexCode); + } + + Matcher matcher = PART_PATTERN.matcher(text); + + if (!matcher.find()) { + return new Part(text); + } + + matcher.reset(); + + PartArray array = new PartArray(new Part()); + int lastEndIndex = 0; + + while (matcher.find()) { + int startIndex = matcher.start(); + int endIndex = matcher.end(); + + if (lastEndIndex != startIndex) { + String betweenMatches = text.substring(lastEndIndex, startIndex); + array.addPart(new Part(betweenMatches)); + } + + String format = matcher.group(1); + String value = matcher.group(3); + + PartMap part = new PartMap(); + part.setValue("text", new Part(value)); + + String[] formats = format.split("§"); + for (String f : formats) { + switch (f.toLowerCase()) { + case "": + break; + case "k": + part.setValue("obuscated", new Part(true)); + break; + case "l": + part.setValue("bold", new Part(true)); + break; + case "m": + part.setValue("strikethrough", new Part(true)); + break; + case "n": + part.setValue("underlined", new Part(true)); + break; + case "o": + part.setValue("italic", new Part(true)); + break; + case "r": + part.removeValue("obfuscated"); + part.removeValue("bold"); + part.removeValue("strikethrough"); + part.removeValue("underlined"); + part.removeValue("italic"); + part.removeValue("color"); + break; + default: + if (f.startsWith("#")) { + part.setValue("color", new Part(f)); + } else { + part.setValue("color", new Part(ChatColor.getByChar(f).name().toLowerCase())); + } + } + } + + array.addPart(part); + lastEndIndex = endIndex; + } + + return array; + } + + @Override + public String toString() { + return rootPart.toString(); + } + + public Part getRootPart() { + return rootPart; + } + + public void setRootPart(Part rootPart) { + this.rootPart = rootPart; + } + + public void sendJson(Player p) { + try { + Object iChatBaseComponent = chatSerializerClass.getMethod("a", String.class).invoke(null, toString()); + Object packetPlayOutChat = Utils.getMajorVersion() < 16 + ? packetPlayOutChatClass.getConstructor(iChatBaseComponentClass).newInstance(iChatBaseComponent) + : packetPlayOutChatClass.getConstructor(iChatBaseComponentClass, chatMessageTypeClass, UUID.class) + .newInstance(iChatBaseComponent, (new FieldResolver(chatMessageTypeClass)).resolve("CHAT", "a").get(null), UUID.randomUUID()); + + Utils.sendPacket(plugin, packetPlayOutChat, p); + plugin.debug("Sent JSON: " + toString()); + } catch (ReflectiveOperationException e) { + plugin.getLogger().severe("Failed to send JSON with reflection"); + plugin.debug("Failed to send JSON with reflection: " + toString()); + plugin.debug(e); + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/nms/SpawnEggMeta.java b/plugin/src/main/java/de/epiceric/shopchest/nms/SpawnEggMeta.java new file mode 100644 index 0000000..45de850 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/nms/SpawnEggMeta.java @@ -0,0 +1,93 @@ +package de.epiceric.shopchest.nms; + +import java.lang.reflect.InvocationTargetException; + +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.ItemStack; +import org.inventivetalent.reflection.resolver.minecraft.OBCClassResolver; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.utils.Utils; + +public class SpawnEggMeta { + + private static String getNBTEntityID(ShopChest plugin, ItemStack stack) { + try { + OBCClassResolver obcClassResolver = new OBCClassResolver(); + Class craftItemStackClass = obcClassResolver.resolveSilent("inventory.CraftItemStack"); + + if (craftItemStackClass == null) { + plugin.debug("Failed to get NBTEntityID: Could not find CraftItemStack class"); + return null; + } + + Object nmsStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, stack); + + Object nbtTagCompound = nmsStack.getClass().getMethod("getTag").invoke(nmsStack); + if (nbtTagCompound == null) return null; + + Object entityTagCompound = nbtTagCompound.getClass().getMethod("getCompound", String.class).invoke(nbtTagCompound, "EntityTag"); + if (entityTagCompound == null) return null; + + Object id = entityTagCompound.getClass().getMethod("getString", String.class).invoke(entityTagCompound, "id"); + if (id instanceof String) return (String) id; + + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + plugin.getLogger().severe("Failed to get NBTEntityID with reflection"); + plugin.debug("Failed to get NBTEntityID with reflection"); + plugin.debug(e); + } + + return null; + } + + /** + * @param plugin An instance of the {@link ShopChest} plugin + * @param stack {@link ItemStack} (Spawn Egg) of which the Entity should be gotten + * @return The {@link EntityType} the Spawn Egg will spawn or null if nbtEntityID is null + */ + public static EntityType getEntityTypeFromItemStack(ShopChest plugin, ItemStack stack) { + if (Utils.getMajorVersion() == 8) { + EntityType type = null; + + for (EntityType entityType : EntityType.values()) { + if (entityType.getTypeId() == stack.getDurability()) { + type = entityType; + break; + } + } + + return type; + } + + String nbtEntityID = getNBTEntityID(plugin, stack); + + if (nbtEntityID == null) return null; + + if (Utils.getMajorVersion() >= 11) { + if (nbtEntityID.contains(":")) nbtEntityID = nbtEntityID.split(":")[1]; + return EntityType.fromName(nbtEntityID); + } + + switch (nbtEntityID) { + case "PigZombie": + return EntityType.valueOf("PIG_ZOMBIE"); + case "CaveSpider": + return EntityType.CAVE_SPIDER; + case "LavaSlime": + return EntityType.MAGMA_CUBE; + case "MushroomCow": + return EntityType.MUSHROOM_COW; + case "EntityHorse": + return EntityType.HORSE; + case "PolarBear": + return EntityType.POLAR_BEAR; + case "Ozelot": + return EntityType.OCELOT; + default: + return EntityType.valueOf(nbtEntityID.toUpperCase()); + + } + } + +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/shop/Shop.java b/plugin/src/main/java/de/epiceric/shopchest/shop/Shop.java new file mode 100644 index 0000000..586da8e --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/shop/Shop.java @@ -0,0 +1,480 @@ +package de.epiceric.shopchest.shop; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.block.data.Directional; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.config.HologramFormat; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.exceptions.ChestNotFoundException; +import de.epiceric.shopchest.exceptions.NotEnoughSpaceException; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.nms.Hologram; +import de.epiceric.shopchest.utils.ItemUtils; +import de.epiceric.shopchest.utils.Utils; + +public class Shop { + + public enum ShopType { + NORMAL, + ADMIN, + } + + private static class PreCreateResult { + private final Inventory inventory; + private final Chest[] chests; + private final BlockFace face; + + private PreCreateResult(Inventory inventory, Chest[] chests, BlockFace face) { + this.inventory = inventory; + this.chests = chests; + this.face = face; + } + } + + private final ShopChest plugin; + private final OfflinePlayer vendor; + private final ShopProduct product; + private final Location location; + private final double buyPrice; + private final double sellPrice; + private final ShopType shopType; + + private boolean created; + private int id; + private Hologram hologram; + private Location holoLocation; + private ShopItem item; + + public Shop(int id, ShopChest plugin, OfflinePlayer vendor, ShopProduct product, Location location, double buyPrice, double sellPrice, ShopType shopType) { + this.id = id; + this.plugin = plugin; + this.vendor = vendor; + this.product = product; + this.location = location; + this.buyPrice = buyPrice; + this.sellPrice = sellPrice; + this.shopType = shopType; + } + + public Shop(ShopChest plugin, OfflinePlayer vendor, ShopProduct product, Location location, double buyPrice, double sellPrice, ShopType shopType) { + this(-1, plugin, vendor, product, location, buyPrice, sellPrice, shopType); + } + + /** + * Test if this shop is equals to another + * + * @param o Other object to test against + * @return true if we are sure they are the same, false otherwise + */ + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Shop shop = (Shop) o; + + // id = -1 means temp shop + return id != -1 && id == shop.id; + } + + @Override + public int hashCode() { + return id != -1 ? id : super.hashCode(); + } + + /** + * Create the shop + * + * @param showConsoleMessages to log exceptions to console + * @return Whether is was created or not + */ + public boolean create(boolean showConsoleMessages) { + if (created) return false; + + plugin.debug("Creating shop (#" + id + ")"); + + Block b = location.getBlock(); + if (b.getType() != Material.CHEST && b.getType() != Material.TRAPPED_CHEST) { + ChestNotFoundException ex = new ChestNotFoundException(String.format("No Chest found in world '%s' at location: %d; %d; %d", + b.getWorld().getName(), b.getX(), b.getY(), b.getZ())); + plugin.getShopUtils().removeShop(this, Config.removeShopOnError); + if (showConsoleMessages) plugin.getLogger().severe(ex.getMessage()); + plugin.debug("Failed to create shop (#" + id + ")"); + plugin.debug(ex); + return false; + } else if ((!ItemUtils.isAir(b.getRelative(BlockFace.UP).getType()))) { + NotEnoughSpaceException ex = new NotEnoughSpaceException(String.format("No space above chest in world '%s' at location: %d; %d; %d", + b.getWorld().getName(), b.getX(), b.getY(), b.getZ())); + plugin.getShopUtils().removeShop(this, Config.removeShopOnError); + if (showConsoleMessages) plugin.getLogger().severe(ex.getMessage()); + plugin.debug("Failed to create shop (#" + id + ")"); + plugin.debug(ex); + return false; + } + + PreCreateResult preResult = preCreateHologram(); + + if (preResult == null) { + return false; + } + + plugin.getShopCreationThreadPool().execute(() -> { + if (hologram == null || !hologram.exists()) createHologram(preResult); + if (item == null) createItem(); + + // Update shops for players in the same world after creation has finished + plugin.getUpdater().queue(() -> { + for (Player player : location.getWorld().getPlayers()) { + plugin.getShopUtils().resetPlayerLocation(player); + } + }); + plugin.getUpdater().updateShops(location.getWorld()); + }); + + created = true; + return true; + } + + /** + * Removes the hologram of the shop + */ + public void removeHologram() { + if (hologram != null && hologram.exists()) { + plugin.debug("Removing hologram (#" + id + ")"); + hologram.remove(); + } + } + + /** + * Removes the floating item of the shop + */ + public void removeItem() { + if (item != null) { + plugin.debug("Removing shop item (#" + id + ")"); + item.remove(); + } + } + + /** + *

Creates the floating item of the shop

+ * Call this after {@link #createHologram()}, because it depends on the hologram's location + */ + private void createItem() { + plugin.debug("Creating item (#" + id + ")"); + + Location itemLocation; + + itemLocation = new Location(location.getWorld(), holoLocation.getX(), location.getY() + 0.9, holoLocation.getZ()); + item = new ShopItem(plugin, product.getItemStack(), itemLocation); + } + + /** + * Runs everything that needs to be called synchronously in order + * to prepare creating the hologram. + */ + private PreCreateResult preCreateHologram() { + plugin.debug("Creating hologram (#" + id + ")"); + + InventoryHolder ih = getInventoryHolder(); + + if (ih == null) return null; + + Chest[] chests = new Chest[2]; + BlockFace face; + + if (ih instanceof DoubleChest) { + DoubleChest dc = (DoubleChest) ih; + Chest r = (Chest) dc.getRightSide(); + Chest l = (Chest) dc.getLeftSide(); + + chests[0] = r; + chests[1] = l; + } else { + chests[0] = (Chest) ih; + } + + if (Utils.getMajorVersion() < 13) { + face = ((org.bukkit.material.Directional) chests[0].getData()).getFacing(); + } else { + face = ((Directional) chests[0].getBlockData()).getFacing(); + } + + return new PreCreateResult(ih.getInventory(), chests, face); + } + + /** + * Acuatlly creates the hologram (async) + */ + private void createHologram(PreCreateResult preResult) { + String[] holoText = getHologramText(preResult.inventory); + holoLocation = getHologramLocation(preResult.chests, preResult.face); + + new BukkitRunnable(){ + @Override + public void run() { + hologram = new Hologram(plugin, holoText, holoLocation); + } + }.runTask(plugin); + } + + /** + * Keep hologram text up to date. + *

Has to be called synchronously!

+ */ + public void updateHologramText() { + String[] lines = getHologramText(getInventoryHolder().getInventory()); + String[] currentLines = hologram.getLines(); + + int max = Math.max(lines.length, currentLines.length); + + for (int i = 0; i < max; i++) { + if (i < lines.length) { + hologram.setLine(i, lines[i]); + } else { + hologram.removeLine(i); + } + } + } + + private String[] getHologramText(Inventory inventory) { + List lines = new ArrayList<>(); + + ItemStack itemStack = getProduct().getItemStack(); + + Map requirements = new EnumMap<>(HologramFormat.Requirement.class); + requirements.put(HologramFormat.Requirement.VENDOR, getVendor().getName()); + requirements.put(HologramFormat.Requirement.AMOUNT, getProduct().getAmount()); + requirements.put(HologramFormat.Requirement.ITEM_TYPE, itemStack.getType() + (itemStack.getDurability() > 0 ? ":" + itemStack.getDurability() : "")); + requirements.put(HologramFormat.Requirement.ITEM_NAME, itemStack.hasItemMeta() ? itemStack.getItemMeta().getDisplayName() : null); + requirements.put(HologramFormat.Requirement.HAS_ENCHANTMENT, !LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(itemStack)).isEmpty()); + requirements.put(HologramFormat.Requirement.BUY_PRICE, getBuyPrice()); + requirements.put(HologramFormat.Requirement.SELL_PRICE, getSellPrice()); + requirements.put(HologramFormat.Requirement.HAS_POTION_EFFECT, ItemUtils.getPotionEffect(itemStack) != null); + requirements.put(HologramFormat.Requirement.IS_MUSIC_DISC, itemStack.getType().isRecord()); + requirements.put(HologramFormat.Requirement.IS_POTION_EXTENDED, ItemUtils.isExtendedPotion(itemStack)); + requirements.put(HologramFormat.Requirement.IS_WRITTEN_BOOK, itemStack.getType() == Material.WRITTEN_BOOK); + requirements.put(HologramFormat.Requirement.IS_BANNER_PATTERN, ItemUtils.isBannerPattern(itemStack)); + requirements.put(HologramFormat.Requirement.ADMIN_SHOP, getShopType() == ShopType.ADMIN); + requirements.put(HologramFormat.Requirement.NORMAL_SHOP, getShopType() == ShopType.NORMAL); + requirements.put(HologramFormat.Requirement.IN_STOCK, Utils.getAmount(inventory, itemStack)); + requirements.put(HologramFormat.Requirement.MAX_STACK, itemStack.getMaxStackSize()); + requirements.put(HologramFormat.Requirement.CHEST_SPACE, Utils.getFreeSpaceForItem(inventory, itemStack)); + requirements.put(HologramFormat.Requirement.DURABILITY, itemStack.getDurability()); + + Map placeholders = new EnumMap<>(Placeholder.class); + placeholders.put(Placeholder.VENDOR, getVendor().getName()); + placeholders.put(Placeholder.AMOUNT, getProduct().getAmount()); + placeholders.put(Placeholder.ITEM_NAME, getProduct().getLocalizedName()); + placeholders.put(Placeholder.ENCHANTMENT, LanguageUtils.getEnchantmentString(ItemUtils.getEnchantments(itemStack))); + placeholders.put(Placeholder.BUY_PRICE, getBuyPrice()); + placeholders.put(Placeholder.SELL_PRICE, getSellPrice()); + placeholders.put(Placeholder.POTION_EFFECT, LanguageUtils.getPotionEffectName(itemStack)); + placeholders.put(Placeholder.MUSIC_TITLE, LanguageUtils.getMusicDiscName(itemStack.getType())); + placeholders.put(Placeholder.BANNER_PATTERN_NAME, LanguageUtils.getBannerPatternName(itemStack.getType())); + placeholders.put(Placeholder.GENERATION, LanguageUtils.getBookGenerationName(itemStack)); + placeholders.put(Placeholder.STOCK, Utils.getAmount(inventory, itemStack)); + placeholders.put(Placeholder.MAX_STACK, itemStack.getMaxStackSize()); + placeholders.put(Placeholder.CHEST_SPACE, Utils.getFreeSpaceForItem(inventory, itemStack)); + placeholders.put(Placeholder.DURABILITY, itemStack.getDurability()); + + int lineCount = plugin.getHologramFormat().getLineCount(); + + for (int i = 0; i < lineCount; i++) { + String format = plugin.getHologramFormat().getFormat(i, requirements, placeholders); + for (Placeholder placeholder : placeholders.keySet()) { + String replace; + + switch (placeholder) { + case BUY_PRICE: + replace = plugin.getEconomy().format(getBuyPrice()); + break; + case SELL_PRICE: + replace = plugin.getEconomy().format(getSellPrice()); + break; + default: + replace = String.valueOf(placeholders.get(placeholder)); + } + + format = format.replace(placeholder.toString(), replace); + } + + if (!format.isEmpty()) { + lines.add(format); + } + } + + return lines.toArray(new String[0]); + } + + private Location getHologramLocation(Chest[] chests, BlockFace face) { + World w = location.getWorld(); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + Location holoLocation = new Location(w, x, y, z); + + double deltaY = -0.6; + + if (Config.hologramFixedBottom) deltaY = -0.85; + + if (chests[1] != null) { + Chest c1 = Utils.getMajorVersion() >= 13 && (face == BlockFace.NORTH || face == BlockFace.EAST) ? chests[1] : chests[0]; + Chest c2 = Utils.getMajorVersion() >= 13 && (face == BlockFace.NORTH || face == BlockFace.EAST) ? chests[0] : chests[1]; + + if (holoLocation.equals(c1.getLocation())) { + if (c1.getX() != c2.getX()) { + holoLocation.add(0, deltaY, 0.5); + } else if (c1.getZ() != c2.getZ()) { + holoLocation.add(0.5, deltaY, 0); + } else { + holoLocation.add(0.5, deltaY, 0.5); + } + } else { + if (c1.getX() != c2.getX()) { + holoLocation.add(1, deltaY, 0.5); + } else if (c1.getZ() != c2.getZ()) { + holoLocation.add(0.5, deltaY, 1); + } else { + holoLocation.add(0.5, deltaY, 0.5); + } + } + } else { + holoLocation.add(0.5, deltaY, 0.5); + } + + holoLocation.add(0, Config.hologramLift, 0); + + return holoLocation; + } + + /** + * @return Whether an ID has been assigned to the shop + */ + public boolean hasId() { + return id != -1; + } + + /** + *

Assign an ID to the shop.

+ * Only works for the first time! + * @param id ID to set for this shop + */ + public void setId(int id) { + if (this.id == -1) { + this.id = id; + } + } + + /** + * @return Whether the shop has already been created + */ + public boolean isCreated() { + return created; + } + + /** + * @return The ID of the shop + */ + public int getID() { + return id; + } + + /** + * @return Vendor of the shop; probably the creator of it + */ + public OfflinePlayer getVendor() { + return vendor; + } + + /** + * @return Product the shop sells (or buys) + */ + public ShopProduct getProduct() { + return product; + } + + /** + * @return Location of (one of) the shop's chest + */ + public Location getLocation() { + return location; + } + + /** + * @return Buy price of the shop + */ + public double getBuyPrice() { + return buyPrice; + } + + /** + * @return Sell price of the shop + */ + public double getSellPrice() { + return sellPrice; + } + + /** + * @return Type of the shop + */ + public ShopType getShopType() { + return shopType; + } + + /** + * @return Hologram of the shop + */ + public Hologram getHologram() { + return hologram; + } + + /** + * @return Floating {@link ShopItem} of the shop + */ + public ShopItem getItem() { + return item; + } + + public boolean hasHologram() { + return hologram != null; + } + + public boolean hasItem() { + return item != null; + } + + /** + * @return {@link InventoryHolder} of the shop or null if the shop has no chest. + */ + public InventoryHolder getInventoryHolder() { + Block b = getLocation().getBlock(); + + if (b.getType() == Material.CHEST || b.getType() == Material.TRAPPED_CHEST) { + Chest chest = (Chest) b.getState(); + return chest.getInventory().getHolder(); + } + + return null; + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/shop/ShopItem.java b/plugin/src/main/java/de/epiceric/shopchest/shop/ShopItem.java new file mode 100644 index 0000000..9acda03 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/shop/ShopItem.java @@ -0,0 +1,164 @@ +package de.epiceric.shopchest.shop; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.inventivetalent.reflection.resolver.minecraft.NMSClassResolver; +import org.inventivetalent.reflection.resolver.minecraft.OBCClassResolver; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.utils.Utils; + +public class ShopItem { + private final ShopChest plugin; + + // concurrent since update task is in async thread + private final Set viewers = ConcurrentHashMap.newKeySet(); + private final ItemStack itemStack; + private final Location location; + private final UUID uuid = UUID.randomUUID(); + private final int entityId; + + private final NMSClassResolver nmsClassResolver = new NMSClassResolver(); + private final OBCClassResolver obcClassResolver = new OBCClassResolver(); + private final Class packetPlayOutEntityDestroyClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityDestroy"); + private final Class packetPlayOutEntityVelocityClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityVelocity"); + private final Class packetPlayOutEntityMetadataClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutEntityMetadata"); + private final Class dataWatcherClass = nmsClassResolver.resolveSilent("network.syncher.DataWatcher"); + private final Class vec3dClass = nmsClassResolver.resolveSilent("world.phys.Vec3D"); + private final Class craftItemStackClass = obcClassResolver.resolveSilent("inventory.CraftItemStack"); + private final Class nmsItemStackClass = nmsClassResolver.resolveSilent("world.item.ItemStack"); + + public ShopItem(ShopChest plugin, ItemStack itemStack, Location location) { + this.plugin = plugin; + this.itemStack = itemStack; + this.location = location; + this.entityId = Utils.getFreeEntityId(); + + Class[] requiredClasses = new Class[] { + nmsItemStackClass, craftItemStackClass, packetPlayOutEntityMetadataClass, dataWatcherClass, + packetPlayOutEntityDestroyClass, packetPlayOutEntityVelocityClass, + }; + + for (Class c : requiredClasses) { + if (c == null) { + plugin.debug("Failed to create shop item: Could not find all required classes"); + return; + } + } + } + + /** + * @return Clone of the location, where the shop item should be (it could have been moved by something, even though it shouldn't) + */ + public Location getLocation() { + return location.clone(); + } + + /** + * @return A clone of this Item's {@link ItemStack} + */ + public ItemStack getItemStack() { + return itemStack.clone(); + } + + /** + * @param p Player to check + * @return Whether the item is visible to the player + */ + public boolean isVisible(Player p) { + return viewers.contains(p.getUniqueId()); + } + + /** + * @param p Player to which the item should be shown + */ + public void showPlayer(Player p) { + showPlayer(p, false); + } + + /** + * @param p Player to which the item should be shown + * @param force whether to force or not + */ + public void showPlayer(Player p, boolean force) { + if (viewers.add(p.getUniqueId()) || force) { + try { + Object nmsItemStack = craftItemStackClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemStack); + Object dataWatcher = Utils.createDataWatcher(null, nmsItemStack); + Utils.sendPacket(plugin, Utils.createPacketSpawnEntity(plugin, entityId, uuid, location, EntityType.DROPPED_ITEM), p); + Utils.sendPacket(plugin, packetPlayOutEntityMetadataClass.getConstructor(int.class, dataWatcherClass, boolean.class).newInstance(entityId, dataWatcher, true), p); + if (Utils.getMajorVersion() < 14) { + Utils.sendPacket(plugin, packetPlayOutEntityVelocityClass.getConstructor(int.class, double.class, double.class, double.class).newInstance(entityId, 0D, 0D, 0D), p); + } else { + Object vec3d = vec3dClass.getConstructor(double.class, double.class, double.class).newInstance(0D, 0D, 0D); + Utils.sendPacket(plugin, packetPlayOutEntityVelocityClass.getConstructor(int.class, vec3dClass).newInstance(entityId, vec3d), p); + } + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException | InstantiationException e) { + plugin.getLogger().severe("Failed to create item!"); + plugin.debug("Failed to create item!"); + plugin.debug(e); + } + } + } + + /** + * @param p Player from which the item should be hidden + */ + public void hidePlayer(Player p) { + hidePlayer(p, false); + } + + /** + * @param p Player from which the item should be hidden + * @param force whether to force or not + */ + public void hidePlayer(Player p, boolean force) { + if (viewers.remove(p.getUniqueId()) || force) { + try { + if (p.isOnline()) { + Object packetPlayOutEntityDestroy = packetPlayOutEntityDestroyClass.getConstructor(int[].class).newInstance((Object) new int[]{entityId}); + Utils.sendPacket(plugin, packetPlayOutEntityDestroy, p); + } + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) { + plugin.getLogger().severe("Failed to destroy shop item"); + plugin.debug("Failed to destroy shop item with reflection"); + plugin.debug(e); + } + } + } + + public void resetVisible(Player p) { + viewers.remove(p.getUniqueId()); + } + + /** + * Removes the item.
+ * Item will be hidden from all players + */ + public void remove() { + // Avoid ConcurrentModificationException + for (UUID uuid : new ArrayList<>(viewers)) { + Player p = Bukkit.getPlayer(uuid); + if (p != null) hidePlayer(p); + } + } + + /** + * Respawns the item at the set location for a player + * @param p Player, for which the item should be reset + */ + public void resetForPlayer(Player p) { + hidePlayer(p); + showPlayer(p); + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/shop/ShopProduct.java b/plugin/src/main/java/de/epiceric/shopchest/shop/ShopProduct.java new file mode 100644 index 0000000..b0030ad --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/shop/ShopProduct.java @@ -0,0 +1,43 @@ +package de.epiceric.shopchest.shop; + +import org.bukkit.inventory.ItemStack; + +import de.epiceric.shopchest.language.LanguageUtils; + +public class ShopProduct { + + private final ItemStack itemStack; + private final int amount; + + public ShopProduct(ItemStack itemStack, int amount) { + this.itemStack = new ItemStack(itemStack); + this.itemStack.setAmount(1); + this.amount = amount; + } + + public ShopProduct(ItemStack itemStack) { + this(itemStack, itemStack.getAmount()); + } + + /** + * @return The localized name of the product's {@link ItemStack} in the selected language file. + */ + public String getLocalizedName() { + return LanguageUtils.getItemName(getItemStack()); + } + + /** + * @return The {@link ItemStack} with an amount of {@code 1}. + */ + public ItemStack getItemStack() { + return itemStack; + } + + /** + * @return The amount + */ + public int getAmount() { + return amount; + } + +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/sql/Database.java b/plugin/src/main/java/de/epiceric/shopchest/sql/Database.java new file mode 100644 index 0000000..c96d975 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/sql/Database.java @@ -0,0 +1,877 @@ +package de.epiceric.shopchest.sql; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import com.zaxxer.hikari.HikariDataSource; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopBuySellEvent; +import de.epiceric.shopchest.event.ShopBuySellEvent.Type; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.shop.Shop.ShopType; +import de.epiceric.shopchest.shop.ShopProduct; +import de.epiceric.shopchest.utils.Callback; +import de.epiceric.shopchest.utils.Utils; + +public abstract class Database { + private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + private boolean initialized; + + String tableShops; + String tableLogs; + String tableLogouts; + String tableFields; + + ShopChest plugin; + HikariDataSource dataSource; + + protected Database(ShopChest plugin) { + this.plugin = plugin; + } + + abstract HikariDataSource getDataSource(); + + abstract String getQueryCreateTableShops(); + + abstract String getQueryCreateTableLog(); + + abstract String getQueryCreateTableLogout(); + + abstract String getQueryCreateTableFields(); + + abstract String getQueryGetTable(); + + private int getDatabaseVersion() throws SQLException { + try (Connection con = dataSource.getConnection()) { + try (Statement s = con.createStatement()) { + ResultSet rs = s.executeQuery("SELECT value FROM " + tableFields + " WHERE field='version'"); + if (rs.next()) { + return rs.getInt("value"); + } + } + } + return 0; + } + + private void setDatabaseVersion(int version) throws SQLException { + String queryUpdateVersion = "REPLACE INTO " + tableFields + " VALUES ('version', ?)"; + try (Connection con = dataSource.getConnection()) { + try (PreparedStatement ps = con.prepareStatement(queryUpdateVersion)) { + ps.setInt(1, version); + ps.executeUpdate(); + } + } + } + + private boolean update() throws SQLException { + String queryGetTable = getQueryGetTable(); + + try (Connection con = dataSource.getConnection()) { + boolean needsUpdate1 = false; // update "shop_log" to "economy_logs" and update "shops" with prefixes + boolean needsUpdate2 = false; // create field table and set database version + + try (PreparedStatement ps = con.prepareStatement(queryGetTable)) { + ps.setString(1, "shop_log"); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + needsUpdate1 = true; + } + } + + try (PreparedStatement ps = con.prepareStatement(queryGetTable)) { + ps.setString(1, tableFields); + ResultSet rs = ps.executeQuery(); + if (!rs.next()) { + needsUpdate2 = true; + } + } + + if (needsUpdate1) { + String queryRenameTableLogouts = "ALTER TABLE player_logout RENAME TO " + tableLogouts; + String queryRenameTableLogs = "ALTER TABLE shop_log RENAME TO backup_shop_log"; // for backup + String queryRenameTableShops = "ALTER TABLE shops RENAME TO backup_shops"; // for backup + + plugin.getLogger().info("Updating database... (#1)"); + + // Rename logout table + try (Statement s = con.createStatement()) { + s.executeUpdate(queryRenameTableLogouts); + } + + // Backup shops table + try (Statement s = con.createStatement()) { + s.executeUpdate(queryRenameTableShops); + } + + // Backup log table + try (Statement s = con.createStatement()) { + s.executeUpdate(queryRenameTableLogs); + } + + // Create new shops table + try (Statement s = con.createStatement()) { + s.executeUpdate(getQueryCreateTableShops()); + } + + // Create new log table + try (Statement s = con.createStatement()) { + s.executeUpdate(getQueryCreateTableLog()); + } + + // Convert shop table + try (Statement s = con.createStatement()) { + ResultSet rs = s.executeQuery("SELECT id,product FROM backup_shops"); + while (rs.next()) { + ItemStack is = Utils.decode(rs.getString("product")); + int amount = is.getAmount(); + is.setAmount(1); + String product = Utils.encode(is); + + String insertQuery = "INSERT INTO " + tableShops + " SELECT id,vendor,?,?,world,x,y,z,buyprice,sellprice,shoptype FROM backup_shops WHERE id = ?"; + try (PreparedStatement ps = con.prepareStatement(insertQuery)) { + ps.setString(1, product); + ps.setInt(2, amount); + ps.setInt(3, rs.getInt("id")); + ps.executeUpdate(); + } + } + } + + // Convert log table + try (Statement s = con.createStatement()) { + ResultSet rs = s.executeQuery("SELECT id,timestamp,executor,product,vendor FROM backup_shop_log"); + while (rs.next()) { + String timestamp = rs.getString("timestamp"); + long time = 0L; + + try { + time = dateFormat.parse(timestamp).getTime(); + } catch (ParseException e) { + plugin.debug("Failed to parse timestamp '" + timestamp + "': Time is set to 0"); + plugin.debug(e); + } + + String player = rs.getString("executor"); + String playerUuid = player.substring(0, 36); + String playerName = player.substring(38, player.length() - 1); + + String oldProduct = rs.getString("product"); + String product = oldProduct.split(" x ")[1]; + int amount = Integer.valueOf(oldProduct.split(" x ")[0]); + + String vendor = rs.getString("vendor"); + String vendorUuid = vendor.substring(0, 36); + String vendorName = vendor.substring(38).replaceAll("\\)( \\(ADMIN\\))?", ""); + boolean admin = vendor.endsWith("(ADMIN)"); + + String insertQuery = "INSERT INTO " + tableLogs + " SELECT id,-1,timestamp,?,?,?,?,'Unknown',?,?,?,?,world,x,y,z,price,type FROM backup_shop_log WHERE id = ?"; + try (PreparedStatement ps = con.prepareStatement(insertQuery)) { + ps.setLong(1, time); + ps.setString(2, playerName); + ps.setString(3, playerUuid); + ps.setString(4, product); + ps.setInt(5, amount); + ps.setString(6, vendorName); + ps.setString(7, vendorUuid); + ps.setBoolean(8, admin); + ps.setInt(9, rs.getInt("id")); + ps.executeUpdate(); + } + } + } + } + + if (needsUpdate2) { + plugin.getLogger().info("Updating database... (#2)"); + + // Create fields table + try (Statement s = con.createStatement()) { + s.executeUpdate(getQueryCreateTableFields()); + } + + setDatabaseVersion(2); + } + + int databaseVersion = getDatabaseVersion(); + + if (databaseVersion < 3) { + // plugin.getLogger().info("Updating database... (#3)"); + + // Update database structure... + + // setDatabaseVersion(3); + } + + int newDatabaseVersion = getDatabaseVersion(); + return needsUpdate1 || needsUpdate2 || newDatabaseVersion > databaseVersion; + } + } + + /** + *

(Re-)Connects to the the database and initializes it.

+ * + * All tables are created if necessary and if the database + * structure has to be updated, that is done as well. + * + * @param callback Callback that - if succeeded - returns the amount of shops + * that were found (as {@code int}) + */ + public void connect(final Callback callback) { + if (!Config.databaseTablePrefix.matches("^([a-zA-Z0-9\\-\\_]+)?$")) { + // Only letters, numbers dashes and underscores are allowed + plugin.getLogger().severe("Database table prefix contains illegal letters, using 'shopchest_' prefix."); + Config.databaseTablePrefix = "shopchest_"; + } + + this.tableShops = Config.databaseTablePrefix + "shops"; + this.tableLogs = Config.databaseTablePrefix + "economy_logs"; + this.tableLogouts = Config.databaseTablePrefix + "player_logouts"; + this.tableFields = Config.databaseTablePrefix + "fields"; + + new BukkitRunnable() { + @Override + public void run() { + disconnect(); + + try { + dataSource = getDataSource(); + } catch (Exception e) { + callback.onError(e); + plugin.debug(e); + return; + } + + if (dataSource == null) { + Exception e = new IllegalStateException("Data source is null"); + callback.onError(e); + plugin.debug(e); + return; + } + + try (Connection con = dataSource.getConnection()) { + // Update database structure if necessary + if (update()) { + plugin.getLogger().info("Updating database finished"); + } + + // Create shop table + try (Statement s = con.createStatement()) { + s.executeUpdate(getQueryCreateTableShops()); + } + + // Create log table + try (Statement s = con.createStatement()) { + s.executeUpdate(getQueryCreateTableLog()); + } + + // Create logout table + try (Statement s = con.createStatement()) { + s.executeUpdate(getQueryCreateTableLogout()); + } + + // Create fields table + try (Statement s = con.createStatement()) { + s.executeUpdate(getQueryCreateTableFields()); + } + + // Clean up economy log + if (Config.cleanupEconomyLogDays > 0) { + cleanUpEconomy(false); + } + + // Count shops entries in database + try (Statement s = con.createStatement()) { + ResultSet rs = s.executeQuery("SELECT COUNT(id) FROM " + tableShops); + if (rs.next()) { + int count = rs.getInt(1); + initialized = true; + + plugin.debug("Initialized database with " + count + " entries"); + + if (callback != null) { + callback.callSyncResult(count); + } + } else { + throw new SQLException("Count result set has no entries"); + } + } + } catch (SQLException e) { + if (callback != null) { + callback.callSyncError(e); + } + + plugin.getLogger().severe("Failed to initialize or connect to database"); + plugin.debug("Failed to initialize or connect to database"); + plugin.debug(e); + } + } + }.runTaskAsynchronously(plugin); + } + + /** + * Remove a shop from the database + * + * @param shop Shop to remove + * @param callback Callback that - if succeeded - returns {@code null} + */ + public void removeShop(final Shop shop, final Callback callback) { + new BukkitRunnable() { + @Override + public void run() { + try (Connection con = dataSource.getConnection(); + PreparedStatement ps = con.prepareStatement("DELETE FROM " + tableShops + " WHERE id = ?")) { + ps.setInt(1, shop.getID()); + ps.executeUpdate(); + + plugin.debug("Removing shop from database (#" + shop.getID() + ")"); + + if (callback != null) { + callback.callSyncResult(null); + } + } catch (SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to remove shop from database"); + plugin.debug("Failed to remove shop from database (#" + shop.getID() + ")"); + plugin.debug(ex); + } + } + }.runTaskAsynchronously(plugin); + } + + /** + * Get shop amounts for each player + * + * @param callback Callback that returns a map of each player's shop amount + */ + public void getShopAmounts(final Callback> callback) { + new BukkitRunnable(){ + @Override + public void run() { + try (Connection con = dataSource.getConnection(); + Statement s = con.createStatement()) { + ResultSet rs = s.executeQuery("SELECT vendor, COUNT(*) AS count FROM " + tableShops + " WHERE shoptype = 'NORMAL' GROUP BY vendor"); + + plugin.debug("Getting shop amounts from database"); + + Map result = new HashMap<>(); + while (rs.next()) { + UUID uuid = UUID.fromString(rs.getString("vendor")); + result.put(uuid, rs.getInt("count")); + } + + if (callback != null) { + callback.callSyncResult(result); + } + } catch (SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to get shop amounts from database"); + plugin.debug("Failed to get shop amounts from database"); + plugin.debug(ex); + } + } + }.runTaskAsynchronously(plugin); + } + + /** + * Get all shops of a player, including admin shops + * + * @param callback Callback that returns a set of shops of the given player + */ + public void getShops(UUID playerUuid, final Callback> callback) { + new BukkitRunnable(){ + @Override + public void run() { + try (Connection con = dataSource.getConnection(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM " + tableShops + " WHERE vendor = ?")) { + ps.setString(1, playerUuid.toString()); + ResultSet rs = ps.executeQuery(); + + plugin.debug("Getting a player's shops from database"); + + Set result = new HashSet<>(); + while (rs.next()) { + int id = rs.getInt("id"); + + plugin.debug("Getting Shop... (#" + id + ")"); + + int x = rs.getInt("x"); + int y = rs.getInt("y"); + int z = rs.getInt("z"); + + World world = plugin.getServer().getWorld(rs.getString("world")); + Location location = new Location(world, x, y, z); + OfflinePlayer vendor = Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("vendor"))); + ItemStack itemStack = Utils.decode(rs.getString("product")); + int amount = rs.getInt("amount"); + ShopProduct product = new ShopProduct(itemStack, amount); + double buyPrice = rs.getDouble("buyprice"); + double sellPrice = rs.getDouble("sellprice"); + ShopType shopType = ShopType.valueOf(rs.getString("shoptype")); + + plugin.debug("Initializing new shop... (#" + id + ")"); + + result.add(new Shop(id, plugin, vendor, product, location, buyPrice, sellPrice, shopType)); + } + + if (callback != null) { + callback.callSyncResult(result); + } + } catch (SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to get player's shops from database"); + plugin.debug("Failed to get player's shops from database"); + plugin.debug(ex); + } + } + }.runTaskAsynchronously(plugin); + } + + /** + * Get all shops from the database that are located in the given chunks + * + * @param chunks Shops in these chunks are retrieved + * @param callback Callback that returns an immutable collection of shops if succeeded + */ + public void getShopsInChunks(final Chunk[] chunks, final Callback> callback) { + // Split chunks into packages containing each {splitSize} chunks at max + int splitSize = 80; + int parts = (int) Math.ceil(chunks.length / (double) splitSize); + Chunk[][] splitChunks = new Chunk[parts][]; + for (int i = 0; i < parts; i++) { + int size = i < parts - 1 ? splitSize : chunks.length % splitSize; + Chunk[] tmp = new Chunk[size]; + System.arraycopy(chunks, i * splitSize, tmp, 0, size); + splitChunks[i] = tmp; + } + + new BukkitRunnable(){ + @Override + public void run() { + List shops = new ArrayList<>(); + + // Send a request for each chunk package + for (Chunk[] newChunks : splitChunks) { + + // Map chunks by world + Map> chunksByWorld = new HashMap<>(); + for (Chunk chunk : newChunks) { + String world = chunk.getWorld().getName(); + Set chunksForWorld = chunksByWorld.getOrDefault(world, new HashSet<>()); + chunksForWorld.add(chunk); + chunksByWorld.put(world, chunksForWorld); + } + + // Create query dynamically + String query = "SELECT * FROM " + tableShops + " WHERE "; + for (String world : chunksByWorld.keySet()) { + query += "(world = ? AND ("; + int chunkNum = chunksByWorld.get(world).size(); + for (int i = 0; i < chunkNum; i++) { + query += "((x BETWEEN ? AND ?) AND (z BETWEEN ? AND ?)) OR "; + } + query += "1=0)) OR "; + } + query += "1=0"; + + try (Connection con = dataSource.getConnection(); + PreparedStatement ps = con.prepareStatement(query)) { + int index = 0; + for (String world : chunksByWorld.keySet()) { + ps.setString(++index, world); + for (Chunk chunk : chunksByWorld.get(world)) { + int minX = chunk.getX() * 16; + int minZ = chunk.getZ() * 16; + ps.setInt(++index, minX); + ps.setInt(++index, minX + 15); + ps.setInt(++index, minZ); + ps.setInt(++index, minZ + 15); + } + } + + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + int id = rs.getInt("id"); + + plugin.debug("Getting Shop... (#" + id + ")"); + + int x = rs.getInt("x"); + int y = rs.getInt("y"); + int z = rs.getInt("z"); + + World world = plugin.getServer().getWorld(rs.getString("world")); + Location location = new Location(world, x, y, z); + OfflinePlayer vendor = Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("vendor"))); + ItemStack itemStack = Utils.decode(rs.getString("product")); + int amount = rs.getInt("amount"); + ShopProduct product = new ShopProduct(itemStack, amount); + double buyPrice = rs.getDouble("buyprice"); + double sellPrice = rs.getDouble("sellprice"); + ShopType shopType = ShopType.valueOf(rs.getString("shoptype")); + + plugin.debug("Initializing new shop... (#" + id + ")"); + + shops.add(new Shop(id, plugin, vendor, product, location, buyPrice, sellPrice, shopType)); + } + } catch (SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to get shops from database"); + plugin.debug("Failed to get shops"); + plugin.debug(ex); + + return; + } + } + + if (callback != null) { + callback.callSyncResult(Collections.unmodifiableCollection(shops)); + } + }; + }.runTaskAsynchronously(plugin); + } + + /** + * Adds a shop to the database + * + * @param shop Shop to add + * @param callback Callback that - if succeeded - returns the ID the shop was + * given (as {@code int}) + */ + public void addShop(final Shop shop, final Callback callback) { + final String queryNoId = "REPLACE INTO " + tableShops + " (vendor,product,amount,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?,?)"; + final String queryWithId = "REPLACE INTO " + tableShops + " (id,vendor,product,amount,world,x,y,z,buyprice,sellprice,shoptype) VALUES(?,?,?,?,?,?,?,?,?,?,?)"; + + new BukkitRunnable() { + @Override + public void run() { + String query = shop.hasId() ? queryWithId : queryNoId; + + try (Connection con = dataSource.getConnection(); + PreparedStatement ps = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) { + int i = 0; + if (shop.hasId()) { + i = 1; + ps.setInt(1, shop.getID()); + } + + ps.setString(i+1, shop.getVendor().getUniqueId().toString()); + ps.setString(i+2, Utils.encode(shop.getProduct().getItemStack())); + ps.setInt(i+3, shop.getProduct().getAmount()); + ps.setString(i+4, shop.getLocation().getWorld().getName()); + ps.setInt(i+5, shop.getLocation().getBlockX()); + ps.setInt(i+6, shop.getLocation().getBlockY()); + ps.setInt(i+7, shop.getLocation().getBlockZ()); + ps.setDouble(i+8, shop.getBuyPrice()); + ps.setDouble(i+9, shop.getSellPrice()); + ps.setString(i+10, shop.getShopType().toString()); + ps.executeUpdate(); + + if (!shop.hasId()) { + int shopId = -1; + ResultSet rs = ps.getGeneratedKeys(); + if (rs.next()) { + shopId = rs.getInt(1); + } + + shop.setId(shopId); + } + + if (callback != null) { + callback.callSyncResult(shop.getID()); + } + + plugin.debug("Adding shop to database (#" + shop.getID() + ")"); + } catch (SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to add shop to database"); + plugin.debug("Failed to add shop to database (#" + shop.getID() + ")"); + plugin.debug(ex); + } + } + }.runTaskAsynchronously(plugin); + } + + /** + * Log an economy transaction to the database + * + * @param executor Player who bought/sold something + * @param shop The {@link Shop} the player bought from or sold to + * @param product The {@link ItemStack} that was bought/sold + * @param price The price the product was bought or sold for + * @param type Whether the executor bought or sold + * @param callback Callback that - if succeeded - returns {@code null} + */ + public void logEconomy(final Player executor, Shop shop, ShopProduct product, double price, Type type, final Callback callback) { + final String query = "INSERT INTO " + tableLogs + " (shop_id,timestamp,time,player_name,player_uuid,product_name,product,amount," + + "vendor_name,vendor_uuid,admin,world,x,y,z,price,type) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + + if (Config.enableEconomyLog) { + new BukkitRunnable() { + @Override + public void run() { + try (Connection con = dataSource.getConnection(); + PreparedStatement ps = con.prepareStatement(query)) { + + long millis = System.currentTimeMillis(); + + ps.setInt(1, shop.getID()); + ps.setString(2, dateFormat.format(millis)); + ps.setLong(3, millis); + ps.setString(4, executor.getName()); + ps.setString(5, executor.getUniqueId().toString()); + ps.setString(6, product.getLocalizedName()); + ps.setString(7, Utils.encode(product.getItemStack())); + ps.setInt(8, product.getAmount()); + ps.setString(9, shop.getVendor().getName()); + ps.setString(10, shop.getVendor().getUniqueId().toString()); + ps.setBoolean(11, shop.getShopType() == ShopType.ADMIN); + ps.setString(12, shop.getLocation().getWorld().getName()); + ps.setInt(13, shop.getLocation().getBlockX()); + ps.setInt(14, shop.getLocation().getBlockY()); + ps.setInt(15, shop.getLocation().getBlockZ()); + ps.setDouble(16, price); + ps.setString(17, type.toString()); + ps.executeUpdate(); + + if (callback != null) { + callback.callSyncResult(null); + } + + plugin.debug("Logged economy transaction to database"); + } catch (SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to log economy transaction to database"); + plugin.debug("Failed to log economy transaction to database"); + plugin.debug(ex); + } + } + }.runTaskAsynchronously(plugin); + } else { + if (callback != null) { + callback.callSyncResult(null); + } + } + } + + /** + * Cleans up the economy log to reduce file size + * + * @param async Whether the call should be executed asynchronously + */ + public void cleanUpEconomy(boolean async) { + BukkitRunnable runnable = new BukkitRunnable() { + @Override + public void run() { + long time = System.currentTimeMillis() - Config.cleanupEconomyLogDays * 86400000L; + String queryCleanUpLog = "DELETE FROM " + tableLogs + " WHERE time < " + time; + String queryCleanUpPlayers = "DELETE FROM " + tableLogouts + " WHERE time < " + time; + + try (Connection con = dataSource.getConnection(); + Statement s = con.createStatement(); + Statement s2 = con.createStatement()) { + s.executeUpdate(queryCleanUpLog); + s2.executeUpdate(queryCleanUpPlayers); + + plugin.getLogger().info("Cleaned up economy log"); + plugin.debug("Cleaned up economy log"); + } catch (SQLException ex) { + plugin.getLogger().severe("Failed to clean up economy log"); + plugin.debug("Failed to clean up economy log"); + plugin.debug(ex); + } + } + }; + + if (async) { + runnable.runTaskAsynchronously(plugin); + } else { + runnable.run(); + } + } + + /** + * Get the revenue a player got while he was offline + * + * @param player Player whose revenue to get + * @param logoutTime Time in milliseconds when he logged out the last time + * @param callback Callback that - if succeeded - returns the revenue the + * player made while offline (as {@code double}) + */ + public void getRevenue(final Player player, final long logoutTime, final Callback callback) { + new BukkitRunnable() { + @Override + public void run() { + double revenue = 0; + + try (Connection con = dataSource.getConnection(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM " + tableLogs + " WHERE vendor_uuid = ?")) { + ps.setString(1, player.getUniqueId().toString()); + ResultSet rs = ps.executeQuery(); + + while (rs.next()) { + long timestamp = rs.getLong("time"); + double singleRevenue = rs.getDouble("price"); + ShopBuySellEvent.Type type = ShopBuySellEvent.Type.valueOf(rs.getString("type")); + + if (type == ShopBuySellEvent.Type.SELL) { + singleRevenue = -singleRevenue; + } + + if (timestamp > logoutTime) { + revenue += singleRevenue; + } + } + + if (callback != null) { + callback.callSyncResult(revenue); + } + } catch (SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to get revenue from database"); + plugin.debug("Failed to get revenue from player \"" + player.getUniqueId().toString() + "\""); + plugin.debug(ex); + } + } + }.runTaskAsynchronously(plugin); + } + + /** + * Log a logout to the database + * + * @param player Player who logged out + * @param callback Callback that - if succeeded - returns {@code null} + */ + public void logLogout(final Player player, final Callback callback) { + new BukkitRunnable() { + @Override + public void run() { + try (Connection con = dataSource.getConnection(); + PreparedStatement ps = con.prepareStatement("REPLACE INTO " + tableLogouts + " (player,time) VALUES(?,?)")) { + ps.setString(1, player.getUniqueId().toString()); + ps.setLong(2, System.currentTimeMillis()); + ps.executeUpdate(); + + if (callback != null) { + callback.callSyncResult(null); + } + + plugin.debug("Logged logout to database"); + } catch (final SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to log last logout to database"); + plugin.debug("Failed to log logout to database"); + plugin.debug(ex); + } + } + }.runTaskAsynchronously(plugin); + } + + /** + * Get the last logout of a player + * + * @param player Player who logged out + * @param callback Callback that - if succeeded - returns the time in + * milliseconds the player logged out (as {@code long}) + * or {@code -1} if the player has not logged out yet. + */ + public void getLastLogout(final Player player, final Callback callback) { + new BukkitRunnable() { + @Override + public void run() { + try (Connection con = dataSource.getConnection(); + PreparedStatement ps = con.prepareStatement("SELECT * FROM " + tableLogouts + " WHERE player = ?")) { + ps.setString(1, player.getUniqueId().toString()); + ResultSet rs = ps.executeQuery(); + + if (rs.next()) { + if (callback != null) { + callback.callSyncResult(rs.getLong("time")); + } + } + + if (callback != null) { + callback.callSyncResult(-1L); + } + } catch (SQLException ex) { + if (callback != null) { + callback.callSyncError(ex); + } + + plugin.getLogger().severe("Failed to get last logout from database"); + plugin.debug("Failed to get last logout from player \"" + player.getName() + "\""); + plugin.debug(ex); + } + } + }.runTaskAsynchronously(plugin); + } + + /** + * Closes the data source + */ + public void disconnect() { + if (dataSource != null) { + dataSource.close(); + dataSource = null; + } + } + + /** + * Returns whether a connection to the database has been established + */ + public boolean isInitialized() { + return initialized; + } + + public enum DatabaseType { + SQLite, MySQL + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/sql/MySQL.java b/plugin/src/main/java/de/epiceric/shopchest/sql/MySQL.java new file mode 100644 index 0000000..3a6df4e --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/sql/MySQL.java @@ -0,0 +1,110 @@ +package de.epiceric.shopchest.sql; + +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import org.bukkit.scheduler.BukkitRunnable; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; + +public class MySQL extends Database { + + public MySQL(ShopChest plugin) { + super(plugin); + } + + @Override + HikariDataSource getDataSource() { + HikariConfig config = new HikariConfig(); + config.setJdbcUrl(String.format("jdbc:mysql://%s:%d/%s?autoReconnect=true&useSSL=false&serverTimezone=UTC", + Config.databaseMySqlHost, Config.databaseMySqlPort, Config.databaseMySqlDatabase)); + config.setUsername(Config.databaseMySqlUsername); + config.setPassword(Config.databaseMySqlPassword); + config.setConnectionTestQuery("SELECT 1"); + + return new HikariDataSource(config); + } + + /** + * Sends an asynchronous ping to the database + */ + public void ping() { + new BukkitRunnable() { + @Override + public void run() { + try (Connection con = dataSource.getConnection(); + Statement s = con.createStatement()) { + plugin.debug("Pinging to MySQL server..."); + s.execute("/* ping */ SELECT 1"); + } catch (SQLException ex) { + plugin.getLogger().severe("Failed to ping to MySQL server. Trying to reconnect..."); + plugin.debug("Failed to ping to MySQL server. Trying to reconnect..."); + connect(null); + } + } + }.runTaskAsynchronously(plugin); + } + + @Override + String getQueryCreateTableShops() { + return "CREATE TABLE IF NOT EXISTS " + tableShops + " (" + + "id INTEGER PRIMARY KEY AUTO_INCREMENT," + + "vendor TINYTEXT NOT NULL," + + "product TEXT NOT NULL," + + "amount INTEGER NOT NULL," + + "world TINYTEXT NOT NULL," + + "x INTEGER NOT NULL," + + "y INTEGER NOT NULL," + + "z INTEGER NOT NULL," + + "buyprice FLOAT NOT NULL," + + "sellprice FLOAT NOT NULL," + + "shoptype TINYTEXT NOT NULL)"; + } + + @Override + String getQueryCreateTableLog() { + return "CREATE TABLE IF NOT EXISTS " + tableLogs + " (" + + "id INTEGER PRIMARY KEY AUTO_INCREMENT," + + "shop_id INTEGER NOT NULL," + + "timestamp TINYTEXT NOT NULL," + + "time LONG NOT NULL," + + "player_name TINYTEXT NOT NULL," + + "player_uuid TINYTEXT NOT NULL," + + "product_name TINYTEXT NOT NULL," + + "product TEXT NOT NULL," + + "amount INTEGER NOT NULL," + + "vendor_name TINYTEXT NOT NULL," + + "vendor_uuid TINYTEXT NOT NULL," + + "admin BIT NOT NULL," + + "world TINYTEXT NOT NULL," + + "x INTEGER NOT NULL," + + "y INTEGER NOT NULL," + + "z INTEGER NOT NULL," + + "price FLOAT NOT NULL," + + "type TINYTEXT NOT NULL)"; + } + + @Override + String getQueryCreateTableLogout() { + return "CREATE TABLE IF NOT EXISTS " + tableLogouts + " (" + + "player VARCHAR(36) PRIMARY KEY NOT NULL," + + "time LONG NOT NULL)"; + } + + @Override + String getQueryCreateTableFields() { + return "CREATE TABLE IF NOT EXISTS " + tableFields + " (" + + "field VARCHAR(32) PRIMARY KEY NOT NULL," + + "value INTEGER NOT NULL)"; + } + + @Override + String getQueryGetTable() { + return "SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME=?"; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/sql/SQLite.java b/plugin/src/main/java/de/epiceric/shopchest/sql/SQLite.java new file mode 100644 index 0000000..97eb665 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/sql/SQLite.java @@ -0,0 +1,126 @@ +package de.epiceric.shopchest.sql; + +import java.io.File; +import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import de.epiceric.shopchest.ShopChest; + +public class SQLite extends Database { + + public SQLite(ShopChest plugin) { + super(plugin); + } + + @Override + HikariDataSource getDataSource() { + try { + // Initialize driver class so HikariCP can find it + Class.forName("org.sqlite.JDBC"); + } catch (ClassNotFoundException e) { + plugin.getLogger().severe("Failed to initialize SQLite driver"); + plugin.debug("Failed to initialize SQLite driver"); + plugin.debug(e); + return null; + } + + File folder = plugin.getDataFolder(); + File dbFile = new File(folder, "shops.db"); + + if (!dbFile.exists()) { + try { + dbFile.createNewFile(); + } catch (IOException ex) { + plugin.getLogger().severe("Failed to create database file"); + plugin.debug("Failed to create database file"); + plugin.debug(ex); + return null; + } + } + + HikariConfig config = new HikariConfig(); + config.setJdbcUrl(String.format("jdbc:sqlite:" + dbFile)); + config.setConnectionTestQuery("SELECT 1"); + + return new HikariDataSource(config); + } + + /** + * Vacuums the database synchronously to reduce file size + */ + public void vacuum() { + try (Connection con = dataSource.getConnection(); + Statement s = con.createStatement()) { + s.executeUpdate("VACUUM"); + + plugin.debug("Vacuumed SQLite database"); + } catch (final SQLException ex) { + plugin.getLogger().warning("Failed to vacuum database"); + plugin.debug("Failed to vacuum database"); + plugin.debug(ex); + } + } + + @Override + String getQueryCreateTableShops() { + return "CREATE TABLE IF NOT EXISTS " + tableShops + " (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT," + + "vendor TINYTEXT NOT NULL," + + "product TEXT NOT NULL," + + "amount INTEGER NOT NULL," + + "world TINYTEXT NOT NULL," + + "x INTEGER NOT NULL," + + "y INTEGER NOT NULL," + + "z INTEGER NOT NULL," + + "buyprice FLOAT NOT NULL," + + "sellprice FLOAT NOT NULL," + + "shoptype TINYTEXT NOT NULL)"; + } + + @Override + String getQueryCreateTableLog() { + return "CREATE TABLE IF NOT EXISTS " + tableLogs + " (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT," + + "shop_id INTEGER NOT NULL," + + "timestamp TINYTEXT NOT NULL," + + "time LONG NOT NULL," + + "player_name TINYTEXT NOT NULL," + + "player_uuid TINYTEXT NOT NULL," + + "product_name TINYTEXT NOT NULL," + + "product TEXT NOT NULL," + + "amount INTEGER NOT NULL," + + "vendor_name TINYTEXT NOT NULL," + + "vendor_uuid TINYTEXT NOT NULL," + + "admin BIT NOT NULL," + + "world TINYTEXT NOT NULL," + + "x INTEGER NOT NULL," + + "y INTEGER NOT NULL," + + "z INTEGER NOT NULL," + + "price FLOAT NOT NULL," + + "type TINYTEXT NOT NULL)"; + } + + @Override + String getQueryCreateTableLogout() { + return "CREATE TABLE IF NOT EXISTS " + tableLogouts + " (" + + "player VARCHAR(36) PRIMARY KEY NOT NULL," + + "time LONG NOT NULL)"; + } + + @Override + String getQueryCreateTableFields() { + return "CREATE TABLE IF NOT EXISTS " + tableFields + " (" + + "field VARCHAR(32) PRIMARY KEY NOT NULL," + + "value INTEGER NOT NULL)"; + } + + @Override + String getQueryGetTable() { + return "SELECT name FROM sqlite_master WHERE type='table' AND name=?"; + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/Callback.java b/plugin/src/main/java/de/epiceric/shopchest/utils/Callback.java new file mode 100644 index 0000000..bb638d6 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/Callback.java @@ -0,0 +1,35 @@ +package de.epiceric.shopchest.utils; + +import org.bukkit.scheduler.BukkitRunnable; + +import de.epiceric.shopchest.ShopChest; + +public abstract class Callback { + private ShopChest plugin; + + public Callback(ShopChest plugin) { + this.plugin = plugin; + } + + public void onResult(T result) {} + + public void onError(Throwable throwable) {} + + public final void callSyncResult(final T result) { + new BukkitRunnable() { + @Override + public void run() { + onResult(result); + } + }.runTask(plugin); + } + + public final void callSyncError(final Throwable throwable) { + new BukkitRunnable() { + @Override + public void run() { + onError(throwable); + } + }.runTask(plugin); + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/ClickType.java b/plugin/src/main/java/de/epiceric/shopchest/utils/ClickType.java new file mode 100644 index 0000000..0e5a98d --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/ClickType.java @@ -0,0 +1,222 @@ +package de.epiceric.shopchest.utils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.shop.Shop.ShopType; +import de.epiceric.shopchest.shop.ShopProduct; + +public class ClickType { + private static Map playerClickType = new HashMap<>(); + private static Map playerTimers = new HashMap<>(); + + private EnumClickType enumClickType; + + public ClickType(EnumClickType enumClickType) { + this.enumClickType = enumClickType; + } + + /** + * Clear click types, cancel timers, and reset game modes + */ + public static void clear() { + playerClickType.forEach((uuid, ct) -> { + if (ct instanceof SelectClickType) { + Player p = Bukkit.getPlayer(uuid); + if (p != null) + p.setGameMode(((SelectClickType) ct).getGameMode()); + } + }); + playerTimers.forEach((uuid, timer) -> timer.cancel()); + } + + /** + * Gets the click type of a player + * + * @param player Player whose click type should be gotten + * @return The Player's click type or null if he doesn't have one + */ + public static ClickType getPlayerClickType(OfflinePlayer player) { + return playerClickType.get(player.getUniqueId()); + } + + /** + * Removes the click type from a player and cancels the 15 second timer + * + * @param player Player to remove the click type from + */ + public static void removePlayerClickType(OfflinePlayer player) { + UUID uuid = player.getUniqueId(); + if (playerClickType.get(uuid) instanceof SelectClickType && player instanceof Player) { + // Reset gamemode player has select click type + ((Player) player).setGameMode(((SelectClickType) playerClickType.get(uuid)).gameMode); + } + playerClickType.remove(uuid); + + // If a timer is still running, cancel it + Optional.ofNullable(playerTimers.get(uuid)).ifPresent(task -> task.cancel()); + playerTimers.remove(uuid); + } + + /** + * Sets the click type of a player and removes it after 15 seconds + * + * @param player Player whose click type should be set + * @param clickType Click type to set + */ + public static void setPlayerClickType(OfflinePlayer player, ClickType clickType) { + UUID uuid = player.getUniqueId(); + if (playerClickType.get(uuid) instanceof SelectClickType && player instanceof Player) { + // Reset gamemode player has select click type + ((Player) player).setGameMode(((SelectClickType) playerClickType.get(uuid)).gameMode); + } + playerClickType.put(uuid, clickType); + + // If a timer is already running, cancel it + Optional.ofNullable(playerTimers.get(uuid)).ifPresent(task -> task.cancel()); + + if (clickType.getClickType() != EnumClickType.SELECT_ITEM) { + // Remove ClickType after 15 seconds if player has not clicked a chest + playerTimers.put(uuid, new BukkitRunnable() { + @Override + public void run() { + playerClickType.remove(uuid); + } + }.runTaskLater(ShopChest.getInstance(), 300)); + } + } + + /** + * @return Type of the click type + */ + public EnumClickType getClickType() { + return enumClickType; + } + + public enum EnumClickType { + CREATE, REMOVE, INFO, OPEN, SELECT_ITEM + } + + public static class CreateClickType extends ClickType { + private ShopProduct product; + private double buyPrice; + private double sellPrice; + private ShopType shopType; + + public CreateClickType(ShopProduct product, double buyPrice, double sellPrice, ShopType shopType) { + super(EnumClickType.CREATE); + this.product = product; + this.sellPrice = sellPrice; + this.buyPrice = buyPrice; + this.shopType = shopType; + } + + /** + * Returns the item, the player has hold in his hands + */ + public ShopProduct getProduct() { + return product; + } + + /** + * Returns the buy price, the player has entered + */ + public double getBuyPrice() { + return buyPrice; + } + + /** + * Returns the sell price, the player has entered + */ + public double getSellPrice() { + return sellPrice; + } + + /** + * Returns the shop type, the player has entered + */ + public ShopType getShopType() { + return shopType; + } + } + + public static class SelectClickType extends ClickType { + private ItemStack itemStack; + private GameMode gameMode; + private int amount; + private double buyPrice; + private double sellPrice; + private ShopType shopType; + + public SelectClickType(GameMode gameMode, int amount, double buyPrice, double sellPrice, ShopType shopType) { + super(EnumClickType.SELECT_ITEM); + this.gameMode = gameMode; + this.amount = amount; + this.sellPrice = sellPrice; + this.buyPrice = buyPrice; + this.shopType = shopType; + } + + /** + * Returns the selected item (or {@code null} if no item has been selected) + */ + public ItemStack getItem() { + return itemStack; + } + + /** + * Sets the selected item + * @param itemStack The item to set as selected + */ + public void setItem(ItemStack itemStack) { + this.itemStack = itemStack; + } + + /** + * Returns the gamemode, the player was in before entering creative mode + */ + public GameMode getGameMode() { + return gameMode; + } + + /** + * Returns the amount, the player has entered + */ + public int getAmount() { + return amount; + } + + /** + * Returns the buy price, the player has entered + */ + public double getBuyPrice() { + return buyPrice; + } + + /** + * Returns the sell price, the player has entered + */ + public double getSellPrice() { + return sellPrice; + } + + /** + * Returns the shop type, the player has entered + */ + public ShopType getShopType() { + return shopType; + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/Counter.java b/plugin/src/main/java/de/epiceric/shopchest/utils/Counter.java new file mode 100644 index 0000000..c466c93 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/Counter.java @@ -0,0 +1,55 @@ +package de.epiceric.shopchest.utils; + +/** + * Represents a counter for integers greather than or equal to zero. + */ +public final class Counter { + private int value; + + /** + * Creates a counter with a starting value of zero + */ + public Counter() { + this(0); + } + + /** + * Creates a counter with the given starting value + * @param value the starting value of this counter + */ + public Counter(int value) { + set(value); + } + + /** + * Increments the counter by one and returns itself + */ + public final Counter increment() { + this.value++; + return this; + } + + /** + * Decrements the counter by one if its value is greater than zero and returns itself + */ + public final Counter decrement() { + this.value = Math.max(0, this.value - 1); + return this; + } + + /** + * Sets the counter's value to the given value or zero if the given value is negative + * @param value the value to set the counter to + */ + public final Counter set(int value) { + this.value = Math.max(0, value); + return this; + } + + /** + * Returns the current value + */ + public final int get() { + return value; + } +} \ No newline at end of file diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/FastMath.java b/plugin/src/main/java/de/epiceric/shopchest/utils/FastMath.java new file mode 100644 index 0000000..a99d8a4 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/FastMath.java @@ -0,0 +1,42 @@ +package de.epiceric.shopchest.utils; + +public class FastMath { + + /** + * Fast sqrt, 1.57% precision + * + * @param n value to calculate square root from + * @return the square root of n + */ + public static double sqrt(double n) { + return n * Double.longBitsToDouble(6910470738111508698L - (Double.doubleToRawLongBits(n) >> 1)); + } + + /** + * Fast acos, 2.9% precision + * + * @param n value to calculate arc cosine from + * @return the arc cosine of n + */ + public static double acos(double n) { + int v = (int) (n * MULTIPLIER + OFFSET); + while (v > PRECISION) v -= PRECISION; + while (v < 0) v += PRECISION; + return acos[v]; + } + + // Below is lookup table generation + // It is only executed once at initialization + + private static final int PRECISION = 512; + private static final double MULTIPLIER = PRECISION / 2D; + private static final double OFFSET = MULTIPLIER + 0.5D; // + 0.5 as cast truncate and don't round + private static final double[] acos = new double[PRECISION + 1]; + + static { + for (int i = 0; i <= PRECISION; i++) { + acos[i] = Math.acos(i * (2D / PRECISION) - 1); + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/ItemUtils.java b/plugin/src/main/java/de/epiceric/shopchest/utils/ItemUtils.java new file mode 100644 index 0000000..d7949d4 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/ItemUtils.java @@ -0,0 +1,76 @@ +package de.epiceric.shopchest.utils; + +import java.util.Arrays; +import java.util.Map; + +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.potion.Potion; +import org.bukkit.potion.PotionType; + +public class ItemUtils { + + public static Map getEnchantments(ItemStack itemStack) { + if (itemStack.getItemMeta() instanceof EnchantmentStorageMeta) { + EnchantmentStorageMeta esm = (EnchantmentStorageMeta) itemStack.getItemMeta(); + return esm.getStoredEnchants(); + } else { + return itemStack.getEnchantments(); + } + } + + public static PotionType getPotionEffect(ItemStack itemStack) { + if (itemStack.getItemMeta() instanceof PotionMeta) { + if (Utils.getMajorVersion() < 9) { + return Potion.fromItemStack(itemStack).getType(); + } else { + return ((PotionMeta) itemStack.getItemMeta()).getBasePotionData().getType(); + } + } + + return null; + } + + public static boolean isExtendedPotion(ItemStack itemStack) { + if (itemStack.getItemMeta() instanceof PotionMeta) { + if (Utils.getMajorVersion() < 9) { + return Potion.fromItemStack(itemStack).hasExtendedDuration(); + } else { + return ((PotionMeta) itemStack.getItemMeta()).getBasePotionData().isExtended(); + } + } + + return false; + } + + public static boolean isBannerPattern(ItemStack itemStack) { + return itemStack.getType().name().endsWith("BANNER_PATTERN"); + } + + public static boolean isAir(Material type) { + return Arrays.asList("AIR", "CAVE_AIR", "VOID_AIR").contains(type.name()); + } + + /** + * Get the {@link ItemStack} from a String + * @param item Serialized ItemStack e.g. {@code "STONE"} or {@code "STONE:1"} + * @return The de-serialized ItemStack or {@code null} if the serialized item is invalid + */ + public static ItemStack getItemStack(String item) { + if (item.trim().isEmpty()) return null; + + if (item.contains(":")) { + Material mat = Material.getMaterial(item.split(":")[0]); + if (mat == null) return null; + return new ItemStack(mat, 1, Short.parseShort(item.split(":")[1])); + } else { + Material mat = Material.getMaterial(item); + if (mat == null) return null; + return new ItemStack(mat, 1); + } + } + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/Operator.java b/plugin/src/main/java/de/epiceric/shopchest/utils/Operator.java new file mode 100644 index 0000000..ebb7f96 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/Operator.java @@ -0,0 +1,75 @@ +package de.epiceric.shopchest.utils; + +public enum Operator { + + EQUAL("==") { + @Override + public boolean compare(double a, double b) { + return Double.compare(a, b) == 0; + } + @Override + public boolean compare(String a, String b) { + return a.equals(b); + } + }, + + NOT_EQUAL("!=") { + @Override + public boolean compare(double a, double b) { + return Double.compare(a, b) != 0; + } + @Override + public boolean compare(String a, String b) { + return !a.equals(b); + } + }, + + GREATER_THAN(">") { + @Override + public boolean compare(double a, double b) { + return a > b; + } + }, + + GREATER_THAN_OR_EQUAL(">=") { + @Override + public boolean compare(double a, double b) { + return a >= b; + } + }, + + LESS_THAN("<") { + @Override + public boolean compare(double a, double b) { + return a < b; + } + }, + + LESS_THAN_OR_EQUAL("<=") { + @Override + public boolean compare(double a, double b) { + return a <= b; + } + }; + + private final String symbol; + + Operator(String symbol) { + this.symbol = symbol; + } + + public static Operator from(String symbol) { + for (Operator operator : values()) { + if (operator.symbol.equals(symbol)) { + return operator; + } + } + throw new IllegalArgumentException(); + } + + public abstract boolean compare(double a, double b); + + public boolean compare(String a, String b) { + throw new UnsupportedOperationException(); + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/Permissions.java b/plugin/src/main/java/de/epiceric/shopchest/utils/Permissions.java new file mode 100644 index 0000000..de95347 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/Permissions.java @@ -0,0 +1,24 @@ +package de.epiceric.shopchest.utils; + +public class Permissions { + + public static final String CREATE = "shopchest.create"; + public static final String CREATE_BUY = "shopchest.create.buy"; + public static final String CREATE_SELL = "shopchest.create.sell"; + public static final String CREATE_ADMIN = "shopchest.create.admin"; + public static final String CREATE_PROTECTED = "shopchest.create.protected"; + public static final String REMOVE_OTHER = "shopchest.remove.other"; + public static final String REMOVE_ADMIN = "shopchest.remove.admin"; + public static final String BUY = "shopchest.buy"; + public static final String SELL = "shopchest.sell"; + public static final String OPEN_OTHER = "shopchest.openOther"; + public static final String UPDATE_NOTIFICATION = "shopchest.notification.update"; + public static final String RELOAD = "shopchest.reload"; + public static final String UPDATE = "shopchest.update"; + public static final String NO_LIMIT = "shopchest.limit.*"; + public static final String CONFIG = "shopchest.config"; + public static final String EXTEND_OTHER = "shopchest.extend.other"; + public static final String EXTEND_PROTECTED = "shopchest.extend.protected"; + public static final String BYPASS_EXTERNAL_PLUGIN = "shopchest.external.bypass"; + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java b/plugin/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java new file mode 100644 index 0000000..3c7f98d --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/ShopUpdater.java @@ -0,0 +1,107 @@ +package de.epiceric.shopchest.utils; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; + +import de.epiceric.shopchest.ShopChest; + +public class ShopUpdater { + + private final ShopChest plugin; + private final BlockingQueue queue = new LinkedBlockingQueue<>(); + + private volatile Thread thread; + + public ShopUpdater(ShopChest plugin) { + this.plugin = plugin; + } + + /** + * Start task, except if it is already + */ + public void start() { + if (!isRunning()) { + thread = new Thread(() -> { + while (!Thread.interrupted()) { + try { + queue.take().run(); + } catch (InterruptedException e) { + break; + } + } + }, "Shop Updater"); + thread.start(); + } + } + + /** + * Stop any running task then start it again + */ + public void restart() { + stop(); + start(); + } + + /** + * Stop task properly + */ + public void stop() { + if (thread != null) { + thread.interrupt(); + thread = null; + } + } + + /** + * @return whether task is running or not + */ + public boolean isRunning() { + return thread != null; + } + + /** + * Queue a task to update shops for the given player + * + * @param player Player to show updates + */ + public void updateShops(Player player) { + queue(() -> plugin.getShopUtils().updateShops(player)); + } + + /** + * Queue a task to update shops for players in the given world + * + * @param world World in whose players to show updates + */ + public void updateShops(World world) { + queue(() -> { + for (Player player : world.getPlayers()) { + plugin.getShopUtils().updateShops(player); + } + }); + } + + /** + * Queue a task to update shops for all players + */ + public void updateShops() { + queue(() -> { + for (Player player : Bukkit.getOnlinePlayers()) { + plugin.getShopUtils().updateShops(player); + } + }); + } + + /** + * Register a task to run before next loop + * + * @param runnable task to run + */ + public void queue(Runnable runnable) { + queue.add(runnable); + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java b/plugin/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java new file mode 100644 index 0000000..88960ee --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/ShopUtils.java @@ -0,0 +1,524 @@ +package de.epiceric.shopchest.utils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.permissions.PermissionAttachmentInfo; +import org.bukkit.util.Vector; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Config; +import de.epiceric.shopchest.event.ShopsLoadedEvent; +import de.epiceric.shopchest.shop.Shop; +import de.epiceric.shopchest.shop.Shop.ShopType; + +public class ShopUtils { + + private final Map playerShopAmount = new HashMap<>(); + + // concurrent since it is updated in async task + private final Map playerLocation = new ConcurrentHashMap<>(); + private final Map shopLocation = new ConcurrentHashMap<>(); + private final Collection shopLocationValues = Collections.unmodifiableCollection(shopLocation.values()); + private final ShopChest plugin; + + public ShopUtils(ShopChest plugin) { + this.plugin = plugin; + } + + /** + * Get the shop at a given location + * + * @param location Location of the shop + * @return Shop at the given location or null if no shop is found there + */ + public Shop getShop(Location location) { + Location newLocation = new Location(location.getWorld(), location.getBlockX(), + location.getBlockY(), location.getBlockZ()); + + return shopLocation.get(newLocation); + } + + /** + * Checks whether there is a shop at a given location + * @param location Location to check + * @return Whether there is a shop at the given location + */ + public boolean isShop(Location location) { + return getShop(location) != null; + } + + /** + * Get a collection of all loaded shops + *

+ * This collection is safe to use for looping over and removing shops. + * + * @return Read-only collection of all shops, may contain duplicates for double chests + */ + public Collection getShops() { + return Collections.unmodifiableCollection(new ArrayList<>(shopLocationValues)); + } + + /** + * Get all shops + * + * @see #getShops() + * @return Copy of collection of all shops, may contain duplicates + * @deprecated Use {@link #getShops()} instead + */ + @Deprecated + public Collection getShopsCopy() { + return new ArrayList<>(getShops()); + } + + /** + * Add a shop + * @param shop Shop to add + * @param addToDatabase Whether the shop should also be added to the database + * @param callback Callback that - if succeeded - returns the ID the shop had or was given (as {@code int}) + */ + public void addShop(Shop shop, boolean addToDatabase, Callback callback) { + InventoryHolder ih = shop.getInventoryHolder(); + plugin.debug("Adding shop... (#" + shop.getID() + ")"); + + if (ih instanceof DoubleChest) { + DoubleChest dc = (DoubleChest) ih; + Chest r = (Chest) dc.getRightSide(); + Chest l = (Chest) dc.getLeftSide(); + + plugin.debug("Added shop as double chest. (#" + shop.getID() + ")"); + + shopLocation.put(r.getLocation(), shop); + shopLocation.put(l.getLocation(), shop); + } else { + plugin.debug("Added shop as single chest. (#" + shop.getID() + ")"); + + shopLocation.put(shop.getLocation(), shop); + } + + if (addToDatabase) { + if (shop.getShopType() != ShopType.ADMIN) { + playerShopAmount.compute(shop.getVendor().getUniqueId(), (uuid, amount) -> amount == null ? new Counter(1) : amount.increment()); + } + plugin.getShopDatabase().addShop(shop, callback); + } else { + if (callback != null) callback.callSyncResult(shop.getID()); + } + + } + + /** + * Add a shop + * @param shop Shop to add + * @param addToDatabase Whether the shop should also be added to the database + */ + public void addShop(Shop shop, boolean addToDatabase) { + addShop(shop, addToDatabase, null); + } + + /** + * Removes (i.e. unloads) all currently loaded shops + */ + public void removeShops() { + shopLocation.forEach((location, shop) -> { + if (!shop.isCreated()) return; + + plugin.debug("Removing shop " + shop.getID()); + shop.removeItem(); + shop.removeHologram(); + }); + shopLocation.clear(); + } + + /** Remove a shop. May not work properly if double chest doesn't exist! + * @param shop Shop to remove + * @param removeFromDatabase Whether the shop should also be removed from the database + * @param callback Callback that - if succeeded - returns null + * @see ShopUtils#removeShopById(int, boolean, Callback) + */ + public void removeShop(Shop shop, boolean removeFromDatabase, Callback callback) { + plugin.debug("Removing shop (#" + shop.getID() + ")"); + + if (shop.isCreated()) { + InventoryHolder ih = shop.getInventoryHolder(); + + if (ih instanceof DoubleChest) { + DoubleChest dc = (DoubleChest) ih; + Chest r = (Chest) dc.getRightSide(); + Chest l = (Chest) dc.getLeftSide(); + + shopLocation.remove(r.getLocation()); + shopLocation.remove(l.getLocation()); + } else { + shopLocation.remove(shop.getLocation()); + } + + shop.removeItem(); + shop.removeHologram(); + } + + if (removeFromDatabase) { + if (shop.getShopType() != ShopType.ADMIN) { + playerShopAmount.compute(shop.getVendor().getUniqueId(), (uuid, amount) -> amount == null ? new Counter() : amount.decrement()); + } + plugin.getShopDatabase().removeShop(shop, callback); + } else { + if (callback != null) callback.callSyncResult(null); + } + } + + /** + * Remove a shop. May not work properly if double chest doesn't exist! + * @param shop Shop to remove + * @param removeFromDatabase Whether the shop should also be removed from the database + * @see ShopUtils#removeShopById(int, boolean) + */ + public void removeShop(Shop shop, boolean removeFromDatabase) { + removeShop(shop, removeFromDatabase, null); + } + + /** + * Remove a shop by its ID + * @param shopId ID of the shop to remove + * @param removeFromDatabase Whether the shop should also be removed from the database + * @param callback Callback that - if succeeded - returns null + */ + public void removeShopById(int shopId, boolean removeFromDatabase, Callback callback) { + Map toRemove = shopLocation.entrySet().stream() + .filter(e -> e.getValue().getID() == shopId) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + plugin.debug(String.format("Removing %d shop(s) with ID %d", toRemove.size(), shopId)); + + if (toRemove.isEmpty()) { + if (callback != null) callback.callSyncResult(null); + return; + } + + toRemove.forEach((loc, shop) -> { + shopLocation.remove(loc); + + shop.removeItem(); + shop.removeHologram(); + }); + + Shop first = toRemove.values().iterator().next(); + boolean isAdmin = first.getShopType() == ShopType.ADMIN; + UUID vendorUuid = first.getVendor().getUniqueId(); + + // Database#removeShop removes shop by ID so this only needs to be called once + if (removeFromDatabase) { + if (!isAdmin) { + playerShopAmount.compute(vendorUuid, (uuid, amount) -> amount == null ? new Counter() : amount.decrement()); + } + plugin.getShopDatabase().removeShop(toRemove.values().iterator().next(), callback); + } else { + if (callback != null) callback.callSyncResult(null); + } + } + + /** + * Remove a shop by its ID + * @param shopId ID of the shop to remove + * @param removeFromDatabase Whether the shop should also be removed from the database + */ + public void removeShopById(int shopId, boolean removeFromDatabase) { + removeShopById(shopId, removeFromDatabase, null); + } + + /** + * Get the shop limits of a player + * @param p Player, whose shop limits should be returned + * @return The shop limits of the given player + */ + public int getShopLimit(Player p) { + int limit = 0; + boolean useDefault = true; + + for (PermissionAttachmentInfo permInfo : p.getEffectivePermissions()) { + if (permInfo.getPermission().startsWith("shopchest.limit.") && p.hasPermission(permInfo.getPermission())) { + if (permInfo.getPermission().equalsIgnoreCase(Permissions.NO_LIMIT)) { + limit = -1; + useDefault = false; + break; + } else { + String[] spl = permInfo.getPermission().split("shopchest.limit."); + + if (spl.length > 1) { + try { + int newLimit = Integer.valueOf(spl[1]); + + if (newLimit < 0) { + limit = -1; + break; + } + + limit = Math.max(limit, newLimit); + useDefault = false; + } catch (NumberFormatException ignored) { + /* Ignore and continue */ + } + } + } + } + } + + if (limit < -1) limit = -1; + return (useDefault ?Config.defaultLimit : limit); + } + + /** + * Get the amount of shops of a player + * @param p Player, whose shops should be counted + * @return The amount of a shops a player has (if {@link Config#excludeAdminShops} is true, admin shops won't be counted) + */ + public int getShopAmount(OfflinePlayer p) { + return playerShopAmount.getOrDefault(p.getUniqueId(), new Counter()).get(); + } + + /** + * Get all shops of a player from the database without loading them + * @param p Player, whose shops should be get + * @param callback Callback that returns a collection of the given player's shops + */ + public void getShops(OfflinePlayer p, Callback> callback) { + plugin.getShopDatabase().getShops(p.getUniqueId(), new Callback>(plugin) { + @Override + public void onResult(Collection result) { + Set shops = new HashSet<>(); + for (Shop playerShop : result) { + Shop loadedShop = getShop(playerShop.getLocation()); + if (loadedShop != null && loadedShop.equals(playerShop)) { + shops.add(loadedShop); + } else { + shops.add(playerShop); + } + } + if (callback != null) callback.onResult(shops); + } + + @Override + public void onError(Throwable throwable) { + if (callback != null) callback.onError(throwable); + } + }); + } + + /** + * Loads the amount of shops for each player + * @param callback Callback that returns the amount of shops for each player + */ + public void loadShopAmounts(final Callback> callback) { + plugin.getShopDatabase().getShopAmounts(new Callback>(plugin) { + @Override + public void onResult(Map result) { + playerShopAmount.clear(); + result.forEach((uuid, amount) -> playerShopAmount.put(uuid, new Counter(amount))); + if (callback != null) callback.onResult(result); + } + + @Override + public void onError(Throwable throwable) { + if (callback != null) callback.onError(throwable); + } + }); + } + + /** + * Gets all shops in the given chunk from the database and adds them to the server + * @param chunk The chunk to load shops from + * @param callback Callback that returns the amount of shops added if succeeded + * @see ShopUtils#loadShops(Chunk[], Callback) + */ + public void loadShops(final Chunk chunk, final Callback callback) { + loadShops(new Chunk[] {chunk}, callback); + } + + /** + * Gets all shops in the given chunks from the database and adds them to the server + * @param chunk The chunks to load shops from + * @param callback Callback that returns the amount of shops added if succeeded + * @see ShopUtils#loadShops(Chunk Callback) + */ + public void loadShops(final Chunk[] chunks, final Callback callback) { + plugin.getShopDatabase().getShopsInChunks(chunks, new Callback>(plugin) { + @Override + public void onResult(Collection result) { + Collection loadedShops = new HashSet<>(); + + for (Shop shop : result) { + Location loc = shop.getLocation(); + + // Don't add shop if shop is already loaded + if (shopLocation.containsKey(loc)) { + continue; + } + + int x = loc.getBlockX() / 16; + int z = loc.getBlockZ() / 16; + + // Don't add shop if chunk is no longer loaded + if (!loc.getWorld().isChunkLoaded(x, z)) { + continue; + } + + if (shop.create(true)) { + addShop(shop, false); + loadedShops.add(shop); + } + } + + if (callback != null) callback.onResult(loadedShops.size()); + + Bukkit.getPluginManager().callEvent(new ShopsLoadedEvent(Collections.unmodifiableCollection(loadedShops))); + } + + @Override + public void onError(Throwable throwable) { + if (callback != null) callback.onError(throwable); + } + }); + } + + /** + * Update hologram and item of all shops for a player + * @param player Player to show the updates + */ + public void updateShops(Player player) { + updateShops(player, false); + } + + /** + * Update hologram and item of all shops for a player + * @param player Player to show the updates + * @param force Whether update should be forced even if player has not moved + */ + public void updateShops(Player player, boolean force) { + if (!force && player.getLocation().equals(playerLocation.get(player.getUniqueId()))) { + // Player has not moved, so don't calculate shops again. + return; + } + + if (Config.onlyShowShopsInSight) { + updateVisibleShops(player); + } else { + updateNearestShops(player); + } + + playerLocation.put(player.getUniqueId(), player.getLocation()); + } + + /** + * Remove a saved location of a player to force a recalculation + * of whether the hologram should be visible. + * This should only be called when really needed + * @param player Player whose saved location will be reset + */ + public void resetPlayerLocation(Player player) { + playerLocation.remove(player.getUniqueId()); + } + + private void updateVisibleShops(Player player) { + double itemDistSquared = Math.pow(Config.maximalItemDistance, 2); + double maxDist = Config.maximalDistance; + + double nearestDistSquared = Double.MAX_VALUE; + Shop nearestShop = null; + + Location pLoc = player.getEyeLocation(); + Vector pDir = pLoc.getDirection(); + + // Display holograms based on sight + for (double i = 0; i <= maxDist; i++) { + Location loc = pLoc.clone(); + Vector dir = pDir.clone(); + double factor = Math.min(i, maxDist); + + loc.add(dir.multiply(factor)); + Location locBelow = loc.clone().subtract(0, 1, 0); + + // Check block below as player may look at hologram + Shop shop = getShop(loc); + if (shop == null) { + shop = getShop(locBelow); + } + + if (shop != null && shop.hasHologram()) { + double distSquared = pLoc.distanceSquared(loc); + if (distSquared < nearestDistSquared) { + nearestDistSquared = distSquared; + nearestShop = shop; + } + } + } + + for (Shop shop : getShops()) { + if (!shop.equals(nearestShop) && shop.hasHologram()) { + shop.getHologram().hidePlayer(player); + } + + // Display item based on distance + Location shopLocation = shop.getLocation(); + if (shopLocation.getWorld().getName().equals(player.getWorld().getName())) { + double distSquared = shop.getLocation().distanceSquared(player.getLocation()); + + if (shop.hasItem()) { + if (distSquared <= itemDistSquared) { + shop.getItem().showPlayer(player); + } else { + shop.getItem().hidePlayer(player); + } + } + } + } + + if (nearestShop != null) { + nearestShop.getHologram().showPlayer(player); + } + } + + private void updateNearestShops(Player p) { + double holoDistSqr = Math.pow(Config.maximalDistance, 2); + double itemDistSqr = Math.pow(Config.maximalItemDistance, 2); + + Location playerLocation = p.getLocation(); + + for (Shop shop : getShops()) { + if (playerLocation.getWorld().getName().equals(shop.getLocation().getWorld().getName())) { + double distSqr = shop.getLocation().distanceSquared(playerLocation); + + if (shop.hasHologram()) { + if (distSqr <= holoDistSqr) { + shop.getHologram().showPlayer(p); + } else { + shop.getHologram().hidePlayer(p); + } + } + + if (shop.hasItem()) { + if (distSqr <= itemDistSqr) { + shop.getItem().showPlayer(p); + } else { + shop.getItem().hidePlayer(p); + } + } + } + } + } +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/UpdateChecker.java b/plugin/src/main/java/de/epiceric/shopchest/utils/UpdateChecker.java new file mode 100644 index 0000000..96715aa --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/UpdateChecker.java @@ -0,0 +1,88 @@ +package de.epiceric.shopchest.utils; + +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import de.epiceric.shopchest.ShopChest; + +public class UpdateChecker { + + private ShopChest plugin; + private String version; + private String link; + + public UpdateChecker(ShopChest plugin) { + this.plugin = plugin; + } + + /** + * Check if an update is needed + * + * @return {@link UpdateCheckerResult#TRUE} if an update is available, + * {@link UpdateCheckerResult#FALSE} if no update is needed or + * {@link UpdateCheckerResult#ERROR} if an error occurred + */ + public UpdateCheckerResult check() { + try { + plugin.debug("Checking for updates..."); + + URL url = new URL("https://api.spiget.org/v2/resources/11431/versions?size=1&page=1&sort=-releaseDate"); + URLConnection conn = url.openConnection(); + conn.setRequestProperty("User-Agent", "ShopChest/UpdateChecker"); + + InputStreamReader reader = new InputStreamReader(conn.getInputStream()); + JsonElement element = new JsonParser().parse(reader); + + if (element.isJsonArray()) { + JsonObject result = element.getAsJsonArray().get(0).getAsJsonObject(); + String id = result.get("id").getAsString(); + version = result.get("name").getAsString(); + link = "https://www.spigotmc.org/resources/shopchest.11431/download?version=" + id; + } else { + plugin.debug("Failed to check for updates"); + plugin.debug("Result: " + element.toString()); + return UpdateCheckerResult.ERROR; + } + + if (plugin.getDescription().getVersion().equals(version)) { + plugin.debug("No update found"); + return UpdateCheckerResult.FALSE; + } else { + plugin.debug("Update found: " + version); + return UpdateCheckerResult.TRUE; + } + + } catch (Exception e) { + plugin.debug("Failed to check for updates"); + plugin.debug(e); + return UpdateCheckerResult.ERROR; + } + } + + /** + * @return Latest Version or null if no update is available + */ + public String getVersion() { + return version; + } + + /** + * @return Download Link of the latest version of null if no update is available + */ + public String getLink() { + return link; + } + + public enum UpdateCheckerResult { + TRUE, + FALSE, + ERROR + } + + +} diff --git a/plugin/src/main/java/de/epiceric/shopchest/utils/Utils.java b/plugin/src/main/java/de/epiceric/shopchest/utils/Utils.java new file mode 100644 index 0000000..ebdd9e1 --- /dev/null +++ b/plugin/src/main/java/de/epiceric/shopchest/utils/Utils.java @@ -0,0 +1,649 @@ +package de.epiceric.shopchest.utils; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.BookMeta; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.util.Vector; +import org.inventivetalent.reflection.resolver.FieldResolver; +import org.inventivetalent.reflection.resolver.minecraft.NMSClassResolver; + +import de.epiceric.shopchest.ShopChest; +import de.epiceric.shopchest.config.Placeholder; +import de.epiceric.shopchest.language.LanguageUtils; +import de.epiceric.shopchest.language.Message; +import de.epiceric.shopchest.language.Replacement; +import de.epiceric.shopchest.nms.CustomBookMeta; +import de.epiceric.shopchest.nms.JsonBuilder; +import de.epiceric.shopchest.shop.Shop; + +public class Utils { + static NMSClassResolver nmsClassResolver = new NMSClassResolver(); + static Class entityClass = nmsClassResolver.resolveSilent("world.entity.Entity"); + static Class entityArmorStandClass = nmsClassResolver.resolveSilent("world.entity.decoration.EntityArmorStand"); + static Class entityItemClass = nmsClassResolver.resolveSilent("world.entity.item.EntityItem"); + static Class dataWatcherClass = nmsClassResolver.resolveSilent("network.syncher.DataWatcher"); + static Class dataWatcherObjectClass = nmsClassResolver.resolveSilent("network.syncher.DataWatcherObject"); + static Class chatSerializerClass = nmsClassResolver.resolveSilent("ChatSerializer", "network.chat.IChatBaseComponent$ChatSerializer"); + + private Utils() {} + + /** + * Check if two items are similar to each other + * @param itemStack1 The first item + * @param itemStack2 The second item + * @return {@code true} if the given items are similar or {@code false} if not + */ + public static boolean isItemSimilar(ItemStack itemStack1, ItemStack itemStack2) { + if (itemStack1 == null || itemStack2 == null) { + return false; + } + + ItemMeta itemMeta1 = itemStack1.getItemMeta(); + ItemMeta itemMeta2 = itemStack2.getItemMeta(); + + if (itemMeta1 instanceof BookMeta && itemMeta2 instanceof BookMeta) { + BookMeta bookMeta1 = (BookMeta) itemStack1.getItemMeta(); + BookMeta bookMeta2 = (BookMeta) itemStack2.getItemMeta(); + + if ((getMajorVersion() == 9 && getRevision() == 1) || getMajorVersion() == 8) { + CustomBookMeta.Generation generation1 = CustomBookMeta.getGeneration(itemStack1); + CustomBookMeta.Generation generation2 = CustomBookMeta.getGeneration(itemStack2); + + if (generation1 == null) CustomBookMeta.setGeneration(itemStack1, CustomBookMeta.Generation.ORIGINAL); + if (generation2 == null) CustomBookMeta.setGeneration(itemStack2, CustomBookMeta.Generation.ORIGINAL); + } else { + if (bookMeta1.getGeneration() == null) bookMeta1.setGeneration(BookMeta.Generation.ORIGINAL); + if (bookMeta2.getGeneration() == null) bookMeta2.setGeneration(BookMeta.Generation.ORIGINAL); + } + + itemStack1.setItemMeta(bookMeta1); + itemStack2.setItemMeta(bookMeta2); + + itemStack1 = decode(encode(itemStack1)); + itemStack2 = decode(encode(itemStack2)); + } + + return itemStack1.isSimilar(itemStack2); + } + + /** + * Gets the amount of items in an inventory + * + * @param inventory The inventory, in which the items are counted + * @param itemStack The items to count + * @return Amount of given items in the given inventory + */ + public static int getAmount(Inventory inventory, ItemStack itemStack) { + int amount = 0; + + ArrayList inventoryItems = new ArrayList<>(); + + if (inventory instanceof PlayerInventory) { + for (int i = 0; i < 37; i++) { + if (i == 36) { + if (getMajorVersion() < 9) { + break; + } + i = 40; + } + inventoryItems.add(inventory.getItem(i)); + } + } else { + for (int i = 0; i < inventory.getSize(); i++) { + inventoryItems.add(inventory.getItem(i)); + } + } + + for (ItemStack item : inventoryItems) { + if (isItemSimilar(item, itemStack)) { + amount += item.getAmount(); + } + } + + return amount; + } + + /** + * Get the amount of the given item, that fits in the given inventory + * + * @param inventory Inventory, where to search for free space + * @param itemStack Item, of which the amount that fits in the inventory should be returned + * @return Amount of the given item, that fits in the given inventory + */ + public static int getFreeSpaceForItem(Inventory inventory, ItemStack itemStack) { + HashMap slotFree = new HashMap<>(); + + if (inventory instanceof PlayerInventory) { + for (int i = 0; i < 37; i++) { + if (i == 36) { + if (getMajorVersion() < 9) { + break; + } + i = 40; + } + + ItemStack item = inventory.getItem(i); + if (item == null || item.getType() == Material.AIR) { + slotFree.put(i, itemStack.getMaxStackSize()); + } else { + if (isItemSimilar(item, itemStack)) { + int amountInSlot = item.getAmount(); + int amountToFullStack = itemStack.getMaxStackSize() - amountInSlot; + slotFree.put(i, amountToFullStack); + } + } + } + } else { + for (int i = 0; i < inventory.getSize(); i++) { + ItemStack item = inventory.getItem(i); + if (item == null || item.getType() == Material.AIR) { + slotFree.put(i, itemStack.getMaxStackSize()); + } else { + if (isItemSimilar(item, itemStack)) { + int amountInSlot = item.getAmount(); + int amountToFullStack = itemStack.getMaxStackSize() - amountInSlot; + slotFree.put(i, amountToFullStack); + } + } + } + } + + int freeAmount = 0; + for (int value : slotFree.values()) { + freeAmount += value; + } + + return freeAmount; + } + + /** + * @param p Player whose item in his main hand should be returned + * @return {@link ItemStack} in his main hand, or {@code null} if he doesn't hold one + */ + public static ItemStack getItemInMainHand(Player p) { + if (getMajorVersion() < 9) { + if (p.getItemInHand().getType() == Material.AIR) + return null; + else + return p.getItemInHand(); + } + + if (p.getInventory().getItemInMainHand().getType() == Material.AIR) + return null; + else + return p.getInventory().getItemInMainHand(); + } + + /** + * @param p Player whose item in his off hand should be returned + * @return {@link ItemStack} in his off hand, or {@code null} if he doesn't hold one or the server version is below 1.9 + */ + public static ItemStack getItemInOffHand(Player p) { + if (getMajorVersion() < 9) + return null; + else if (p.getInventory().getItemInOffHand().getType() == Material.AIR) + return null; + else + return p.getInventory().getItemInOffHand(); + } + + /** + * @param p Player whose item in his hand should be returned + * @return Item in his main hand, or the item in his off if he doesn't have one in this main hand, or {@code null} + * if he doesn't have one in both hands + */ + public static ItemStack getPreferredItemInHand(Player p) { + if (getMajorVersion() < 9) + return getItemInMainHand(p); + else if (getItemInMainHand(p) != null) + return getItemInMainHand(p); + else + return getItemInOffHand(p); + } + + /** + * @param p Player to check if he has an axe in one of his hands + * @return Whether a player has an axe in one of his hands + */ + public static boolean hasAxeInHand(Player p) { + List axes; + if (Utils.getMajorVersion() < 13) + axes = Arrays.asList("WOOD_AXE", "STONE_AXE", "IRON_AXE", "GOLD_AXE", "DIAMOND_AXE"); + else + axes = Arrays.asList("WOODEN_AXE", "STONE_AXE", "IRON_AXE", "GOLDEN_AXE", "DIAMOND_AXE"); + + ItemStack item = getItemInMainHand(p); + if (item == null || !axes.contains(item.getType().toString())) { + item = getItemInOffHand(p); + } + + return item != null && axes.contains(item.getType().toString()); + } + + /** + *

Check if a player is allowed to create a shop that sells or buys the given item.

+ * @param player Player to check + * @param item Item to be sold or bought + * @param buy Whether buying should be enabled + * @param sell Whether selling should be enabled + * @return Whether the player is allowed + */ + public static boolean hasPermissionToCreateShop(Player player, ItemStack item, boolean buy, boolean sell) { + if (hasPermissionToCreateShop(player, item, Permissions.CREATE)) { + return true; + } else if (!sell && buy && hasPermissionToCreateShop(player, item,Permissions.CREATE_BUY)) { + return true; + } else if (!buy && sell && hasPermissionToCreateShop(player, item, Permissions.CREATE_SELL)) { + return true; + } else if (buy && sell && hasPermissionToCreateShop(player, item, Permissions.CREATE_BUY, Permissions.CREATE_SELL)) { + return true; + } + + return false; + } + + private static boolean hasPermissionToCreateShop(Player player, ItemStack item, String... permissions) { + for (String permission : permissions) { + boolean b1 = false; + boolean b2 = false; + boolean b3 = false; + + if (player.hasPermission(permission)) { + b1 = true; + } + + if (item != null) { + if (item.getDurability() == 0) { + String perm1 = permission + "." + item.getType().toString(); + String perm2 = permission + "." + item.getType().toString() + ".0"; + + if (player.hasPermission(perm1) || player.hasPermission(perm2)) { + b2 = true; + } + } + + if (player.hasPermission(permission + "." + item.getType().toString() + "." + item.getDurability())) { + b3 = true; + } + } + + if (!(b1 || b2 || b3)) { + return false; + } + } + + return true; + } + + /** + * Get a set for the location(s) of the shop's chest(s) + * @param shop The shop + * @return A set of 1 or 2 locations + */ + public static Set getChestLocations(Shop shop) { + Set chestLocations = new HashSet<>(); + InventoryHolder ih = shop.getInventoryHolder(); + if (ih instanceof DoubleChest) { + DoubleChest dc = (DoubleChest) ih; + chestLocations.add(((Chest) dc.getLeftSide()).getLocation()); + chestLocations.add(((Chest) dc.getRightSide()).getLocation()); + } else { + chestLocations.add(shop.getLocation()); + } + return chestLocations; + } + + /** + * Send a clickable update notification to the given player. + * @param plugin An instance of the {@link ShopChest} plugin + * @param p The player to receive the notification + */ + public static void sendUpdateMessage(ShopChest plugin, Player p) { + JsonBuilder jb = new JsonBuilder(plugin); + Map hoverEvent = new HashMap<>(); + hoverEvent.put("action", new JsonBuilder.Part("show_text")); + hoverEvent.put("value", new JsonBuilder.Part(LanguageUtils.getMessage(Message.UPDATE_CLICK_TO_DOWNLOAD))); + + Map clickEvent = new HashMap<>(); + clickEvent.put("action", new JsonBuilder.Part("open_url")); + clickEvent.put("value", new JsonBuilder.Part(plugin.getDownloadLink())); + + JsonBuilder.PartMap rootPart = JsonBuilder.parse(LanguageUtils.getMessage(Message.UPDATE_AVAILABLE, + new Replacement(Placeholder.VERSION, plugin.getLatestVersion()))).toMap(); + + rootPart.setValue("hoverEvent", new JsonBuilder.PartMap(hoverEvent)); + rootPart.setValue("clickEvent", new JsonBuilder.PartMap(clickEvent)); + + jb.setRootPart(rootPart); + jb.sendJson(p); + } + + /** + * Create a NMS data watcher object to send via a {@code PacketPlayOutEntityMetadata} packet. + * Gravity will be disabled and the custom name will be displayed if available. + * @param customName Custom Name of the entity or {@code null} + * @param nmsItemStack NMS ItemStack or {@code null} if armor stand + */ + public static Object createDataWatcher(String customName, Object nmsItemStack) { + String version = getServerVersion(); + int majorVersion = getMajorVersion(); + + try { + byte entityFlags = nmsItemStack == null ? (byte) 0b100000 : 0; // invisible if armor stand + byte armorStandFlags = nmsItemStack == null ? (byte) 0b10000 : 0; // marker (since 1.8_R2) + + Object dataWatcher = dataWatcherClass.getConstructor(entityClass).newInstance((Object) null); + if (majorVersion < 9) { + if (getRevision() == 1) armorStandFlags = 0; // Marker not supported on 1.8_R1 + + Method a = dataWatcherClass.getMethod("a", int.class, Object.class); + a.invoke(dataWatcher, 0, entityFlags); // flags + a.invoke(dataWatcher, 1, (short) 300); // air ticks (?) + a.invoke(dataWatcher, 3, (byte) (customName != null ? 1 : 0)); // custom name visible + a.invoke(dataWatcher, 2, customName != null ? customName : ""); // custom name + a.invoke(dataWatcher, 4, (byte) 1); // silent + a.invoke(dataWatcher, 10, nmsItemStack == null ? armorStandFlags : nmsItemStack); // item / armor stand flags + } else { + Method register = dataWatcherClass.getMethod("register", dataWatcherObjectClass, Object.class); + String[] dataWatcherObjectFieldNames; + + if ("v1_9_R1".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"ax", "ay", "aA", "az", "aB", null, "c", "a"}; + } else if ("v1_9_R2".equals(version)){ + dataWatcherObjectFieldNames = new String[] {"ay", "az", "aB", "aA", "aC", null, "c", "a"}; + } else if ("v1_10_R1".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"aa", "az", "aB", "aA", "aC", "aD", "c", "a"}; + } else if ("v1_11_R1".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"Z", "az", "aB", "aA", "aC", "aD", "c", "a"}; + } else if ("v1_12_R1".equals(version) || "v1_12_R2".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"Z", "aA", "aC", "aB", "aD", "aE", "c", "a"}; + } else if ("v1_13_R1".equals(version) || "v1_13_R2".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"ac", "aD", "aF", "aE", "aG", "aH", "b", "a"}; + } else if ("v1_14_R1".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"W", "AIR_TICKS", "aA", "az", "aB", "aC", "ITEM", "b"}; + } else if ("v1_15_R1".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"T", "AIR_TICKS", "aA", "az", "aB", "aC", "ITEM", "b"}; + } else if ("v1_16_R1".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"T", "AIR_TICKS", "ay", "ax", "az", "aA", "ITEM", "b"}; + } else if ("v1_16_R2".equals(version) || "v1_16_R3".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"S", "AIR_TICKS", "ar", "aq", "as", "at", "ITEM", "b"}; + } else if ("v1_17_R1".equals(version)) { + dataWatcherObjectFieldNames = new String[] {"Z", "aI", "aK", "aJ", "aL", "aM", "c", "bG"}; + } else { + return null; + } + + Field fEntityFlags = entityClass.getDeclaredField(dataWatcherObjectFieldNames[0]); + Field fAirTicks = entityClass.getDeclaredField(dataWatcherObjectFieldNames[1]); + Field fNameVisible = entityClass.getDeclaredField(dataWatcherObjectFieldNames[2]); + Field fCustomName = entityClass.getDeclaredField(dataWatcherObjectFieldNames[3]); + Field fSilent = entityClass.getDeclaredField(dataWatcherObjectFieldNames[4]); + Field fNoGravity = majorVersion >= 10 ? entityClass.getDeclaredField(dataWatcherObjectFieldNames[5]) : null; + Field fItem = entityItemClass.getDeclaredField(dataWatcherObjectFieldNames[6]); + Field fArmorStandFlags = entityArmorStandClass.getDeclaredField(dataWatcherObjectFieldNames[7]); + + fEntityFlags.setAccessible(true); + fAirTicks.setAccessible(true); + fNameVisible.setAccessible(true); + fCustomName.setAccessible(true); + fSilent.setAccessible(true); + if (majorVersion >= 10) fNoGravity.setAccessible(true); + fItem.setAccessible(true); + fArmorStandFlags.setAccessible(true); + + register.invoke(dataWatcher, fEntityFlags.get(null), entityFlags); + register.invoke(dataWatcher, fAirTicks.get(null), 300); + register.invoke(dataWatcher, fNameVisible.get(null), customName != null); + register.invoke(dataWatcher, fSilent.get(null), true); + if (majorVersion < 13) register.invoke(dataWatcher, fCustomName.get(null), customName != null ? customName : ""); + + if (nmsItemStack != null) { + register.invoke(dataWatcher, fItem.get(null), majorVersion < 11 ? com.google.common.base.Optional.of(nmsItemStack) : nmsItemStack); + } else { + register.invoke(dataWatcher, fArmorStandFlags.get(null), armorStandFlags); + } + + if (majorVersion >= 10) { + register.invoke(dataWatcher, fNoGravity.get(null), true); + if (majorVersion >= 13) { + if (customName != null) { + Object iChatBaseComponent = chatSerializerClass.getMethod("a", String.class).invoke(null, JsonBuilder.parse(customName).toString()); + register.invoke(dataWatcher, fCustomName.get(null), Optional.of(iChatBaseComponent)); + } else { + register.invoke(dataWatcher, fCustomName.get(null), Optional.empty()); + } + } + } + } + return dataWatcher; + } catch (InstantiationException | InvocationTargetException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) { + ShopChest.getInstance().getLogger().severe("Failed to create data watcher!"); + ShopChest.getInstance().debug("Failed to create data watcher"); + ShopChest.getInstance().debug(e); + } + return null; + } + + /** + * Get a free entity ID for use in {@link #createPacketSpawnEntity(ShopChest, int, UUID, Location, Vector, EntityType)} + * + * @return The id or {@code -1} if a free entity ID could not be retrieved. + */ + public static int getFreeEntityId() { + try { + Field entityCountField = new FieldResolver(entityClass).resolve("entityCount", "b"); + entityCountField.setAccessible(true); + if (entityCountField.getType() == int.class) { + int id = entityCountField.getInt(null); + entityCountField.setInt(null, id+1); + return id; + } else if (entityCountField.getType() == AtomicInteger.class) { + return ((AtomicInteger) entityCountField.get(null)).incrementAndGet(); + } + + return -1; + } catch (Exception e) { + return -1; + } + } + + /** + * Create a {@code PacketPlayOutSpawnEntity} object. + * Only {@link EntityType#ARMOR_STAND} and {@link EntityType#DROPPED_ITEM} are supported! + */ + public static Object createPacketSpawnEntity(ShopChest plugin, int id, UUID uuid, Location loc, EntityType type) { + try { + Class packetPlayOutSpawnEntityClass = nmsClassResolver.resolveSilent("network.protocol.game.PacketPlayOutSpawnEntity"); + Class entityTypesClass = nmsClassResolver.resolveSilent("world.entity.EntityTypes"); + Class vec3dClass = nmsClassResolver.resolveSilent("world.phys.Vec3D"); + + boolean isPre9 = getMajorVersion() < 9; + boolean isPre14 = getMajorVersion() < 14; + + double y = loc.getY(); + if (type == EntityType.ARMOR_STAND && !getServerVersion().equals("v1_8_R1")) { + // Marker armor stand => lift by normal armor stand height + y += 1.975; + } + + if (getMajorVersion() >= 17) { + // Empty packet constructor does not exist anymore in 1.17+ + Constructor c = packetPlayOutSpawnEntityClass.getConstructor(int.class, UUID.class, double.class, double.class, double.class, + float.class, float.class, entityTypesClass, int.class, vec3dClass); + + Object vec3d = vec3dClass.getField("a").get(null); + Object entityType = entityTypesClass.getField(type == EntityType.ARMOR_STAND ? "c" : "Q").get(null); + + return c.newInstance(id, uuid, loc.getX(), y, loc.getZ(), 0f, 0f, entityType, 0, vec3d); + } + + Object packet = packetPlayOutSpawnEntityClass.getConstructor().newInstance(); + + Field[] fields = new Field[12]; + fields[0] = packetPlayOutSpawnEntityClass.getDeclaredField("a"); // ID + fields[1] = packetPlayOutSpawnEntityClass.getDeclaredField("b"); // UUID (Only 1.9+) + fields[2] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "b" : "c"); // Loc X + fields[3] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "c" : "d"); // Loc Y + fields[4] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "d" : "e"); // Loc Z + fields[5] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "e" : "f"); // Mot X + fields[6] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "f" : "g"); // Mot Y + fields[7] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "g" : "h"); // Mot Z + fields[8] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "h" : "i"); // Pitch + fields[9] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "i" : "j"); // Yaw + fields[10] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "j" : "k"); // Type + fields[11] = packetPlayOutSpawnEntityClass.getDeclaredField(isPre9 ? "k" : "l"); // Data + + for (Field field : fields) { + field.setAccessible(true); + } + + Object entityType = null; + if (!isPre14) { + entityType = entityTypesClass.getField(type == EntityType.ARMOR_STAND ? "ARMOR_STAND" : "ITEM").get(null); + } + + fields[0].set(packet, id); + if (!isPre9) fields[1].set(packet, uuid); + if (isPre9) { + fields[2].set(packet, (int)(loc.getX() * 32)); + fields[3].set(packet, (int)(y * 32)); + fields[4].set(packet, (int)(loc.getZ() * 32)); + } else { + fields[2].set(packet, loc.getX()); + fields[3].set(packet, y); + fields[4].set(packet, loc.getZ()); + } + fields[5].set(packet, 0); + fields[6].set(packet, 0); + fields[7].set(packet, 0); + fields[8].set(packet, 0); + fields[9].set(packet, 0); + if (isPre14) fields[10].set(packet, type == EntityType.ARMOR_STAND ? 78 : 2); + else fields[10].set(packet, entityType); + fields[11].set(packet, 0); + + return packet; + } catch (NoSuchMethodException | NoSuchFieldException | IllegalAccessException | InvocationTargetException | InstantiationException e) { + plugin.getLogger().severe("Failed to create packet to spawn entity!"); + plugin.debug("Failed to create packet to spawn entity!"); + plugin.debug(e); + return null; + } + } + + /** + * Send a packet to a player + * @param plugin An instance of the {@link ShopChest} plugin + * @param packet Packet to send + * @param player Player to which the packet should be sent + * @return {@code true} if the packet was sent, or {@code false} if an exception was thrown + */ + public static boolean sendPacket(ShopChest plugin, Object packet, Player player) { + try { + if (packet == null) { + plugin.debug("Failed to send packet: Packet is null"); + return false; + } + + Class packetClass = nmsClassResolver.resolveSilent("network.protocol.Packet"); + if (packetClass == null) { + plugin.debug("Failed to send packet: Could not find Packet class"); + return false; + } + + Object nmsPlayer = player.getClass().getMethod("getHandle").invoke(player); + Field fConnection = (new FieldResolver(nmsPlayer.getClass())).resolve("playerConnection", "b"); + Object playerConnection = fConnection.get(nmsPlayer); + + playerConnection.getClass().getMethod("sendPacket", packetClass).invoke(playerConnection, packet); + + return true; + } catch (NoSuchMethodException | NoSuchFieldException | IllegalAccessException | InvocationTargetException e) { + plugin.getLogger().severe("Failed to send packet " + packet.getClass().getName()); + plugin.debug("Failed to send packet " + packet.getClass().getName()); + plugin.debug(e); + return false; + } + } + + /** + * @return The current server version with revision number (e.g. v1_9_R2, v1_10_R1) + */ + public static String getServerVersion() { + String packageName = Bukkit.getServer().getClass().getPackage().getName(); + + return packageName.substring(packageName.lastIndexOf('.') + 1); + } + + /** + * @return The revision of the current server version (e.g. 2 for v1_9_R2, 1 for v1_10_R1) + */ + public static int getRevision() { + return Integer.parseInt(getServerVersion().substring(getServerVersion().length() - 1)); + } + + /** + * @return The major version of the server (e.g. 9 for 1.9.2, 10 for 1.10) + */ + public static int getMajorVersion() { + return Integer.parseInt(getServerVersion().split("_")[1]); + } + + /** + * Encodes an {@link ItemStack} in a Base64 String + * @param itemStack {@link ItemStack} to encode + * @return Base64 encoded String + */ + public static String encode(ItemStack itemStack) { + YamlConfiguration config = new YamlConfiguration(); + config.set("i", itemStack); + return Base64.getEncoder().encodeToString(config.saveToString().getBytes(StandardCharsets.UTF_8)); + } + + /** + * Decodes an {@link ItemStack} from a Base64 String + * @param string Base64 encoded String to decode + * @return Decoded {@link ItemStack} + */ + public static ItemStack decode(String string) { + YamlConfiguration config = new YamlConfiguration(); + try { + config.loadFromString(new String(Base64.getDecoder().decode(string), StandardCharsets.UTF_8)); + } catch (IllegalArgumentException | InvalidConfigurationException e) { + e.printStackTrace(); + return null; + } + return config.getItemStack("i", null); + } + + +} diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml new file mode 100644 index 0000000..f00e5d5 --- /dev/null +++ b/plugin/src/main/resources/config.yml @@ -0,0 +1,224 @@ +# =============================================== +# ====== Configuration File of 'ShopChest' ====== +# =============================================== +# +# Lines starting with '#' are comments and are ignored by the server. +# +# You can find item names in the 'item_names.txt' file. + +# Set the main command you have to enter to manage the shops. +# (default: "/shop ...") +main-command-name: "shop" + +# Set the language file for all translatable messages or names. +# The value must equal to the name of one of a file in the 'lang' folder +# (without the '.lang' extension). +language-file: "en_US" + +# Set the item with which a player can click a shop to retrieve information. +# You can set this to an empty string ("") to disable this feature. +shop-info-item: "STICK" + +# Set whether buys or sells need to be confirmed by the player +# in order to prevent accidents. +confirm-shopping: false + +# Set whether players should be able to select the shop item from the +# creative inventory if they don't hold an item in their hand. +creative-select-item: true + +# Set whether the (current) shop creation price should be refunded +# when the shop is removed by its creator. +refund-shop-creation: false + +# Set whether the plugin will check for updates on server start +# and notify permitted players on join. +# The command is not affected by this setting and will continue to +# check for updates. +enable-update-checker: true + +# Set whether buys and sells should be logged in the database. +enable-economy-log: false + +# Set the maximum age for economy log entries in days. +# All log entries older than this will be deleted on server start. +# Set this to 0 to disable this feature. +cleanup-economy-log-days: 30 + +# Set whether a debug log file should be created. +# The file may get large! Please enable this setting when reporting issues. +enable-debug-log: false + +# Set whether various protection plugins should be hooked into (if installed) +# in order to allow or deny shop creation in certain locations. +enable-worldguard-integration: true +enable-towny-integration: true +enable-authme-integration: true +enable-plotsquared-integration: true +enable-uskyblock-integration: true +enable-askyblock-integration: true +enable-bentobox-integration: true +enable-islandworld-integration: true +enable-griefprevention-integration: true +enable-areashop-integration: true + +# Set whether the vendor of a shop should get messages when players buy +# or sell something from/to his shop or when his shop is out of stock. +enable-vendor-messages: true + +# Set whether the vendor of a shop should get messages on all servers when players +# buy or sell something from/to his shop or when his shop is out of stock. +enable-vendor-bungee-messages: false + +# Set whether only the shop a player is pointing at should be shown. +# If set to false, every shop near the player (with the specified +# distance) will be shown to him. +only-show-shops-in-sight: true + +# Set whether the hologram's location should be fixed at the bottom, +# so when it gets more lines, it won't interfere with the item or chest, +# but goes higher. +hologram-fixed-bottom: true + +# Set the amount (may be negative) a hologram should be lifted in the y-axis. +# A value of '1' equals to one block, and a value of '0.25' is equal to the +# height of one line. +hologram-lift: 0 + +# Set whether players should be allowed to buy or sell less items +# than the vendor has specified, in case the player does not have enough +# money or items, or if the chest does not have enough items or space, +# or if the vendor does not have enough money. +# The price will be calculated correspondingly. +auto-calculate-item-amount: false + +# Set whether prices may contain decimals (prices of existing shops will stay). +allow-decimals-in-price: true + +# Set whether players should be allowed to sell/buy broken items. +allow-broken-items: false + +# Set whether the level of a potion or tipped arrow (if upgraded) should be +# appended to the item name. If set to true, the level ("II") will be +# displayed after the item name, but only if the item does not have a +# custom name. +append-potion-level-to-item-name: false + +# Set whether shops should automatically be removed from the database if +# an error occurred while loading. +# (e.g. no chest, no space above chest, or unknown world) +remove-shop-on-error: false + +# Set whether the mouse buttons should be inverted. +# Default: +# Right-Click -> Buy +# Left-Click -> Sell +invert-mouse-buttons: false + +# Set the maximal distance (in blocks) to the shop where the +# player can see the hologram. +maximal-distance: 2 + +# Set the maximal distance (in blocks) to the shop where the +# player can see the floating shop item. +maximal-item-distance: 40 + +# Set whether the buy price must be greater than or equal to the sell price. +buy-greater-or-equal-sell: true + +# Set the minimum and maximum prices for each individual item. +minimum-prices: +# "DIAMOND": 0.5 + +maximum-prices: +# "STONE": 2 + +# Set the items of which a player can't create a shop. +blacklist: +# - "DIORITE" + +# Set the price a player has to pay in order to create... +# You can set this to 0 to disable costs. +shop-creation-price: + + # ...a normal shop + normal: 5 + + # ...an admin shop + admin: 0 + +# Shop limits are handled with permissions. +# A player with permission "shopchest.limit.X" has a limit of X shops, +# a player with permission "shopchest.limit.*" does not have a shop limit. +# Admin shops are excluded from the shop limit. +shop-limits: + + # Set the amount of shops that anyone who doesn't have a + # specific permission may have. + # If you don't want the players to have a limit by default + # set the value to -1. + default: 5 + +# Set the events of AreaShop when shops on that region should be removed. +# Valid values are: DELETE, UNRENT, RESELL, SELL +areashop-remove-shops: + - "DELETE" + - "UNRENT" + - "RESELL" + - "SELL" + +# Set whether the custom WorldGuard flags should be allowed by default. +worldguard-default-flag-values: + + create-shop: false + use-shop: false + use-admin-shop: false + +# Set the types of Towny plots where shop creation should be allowed. +# Valid values are: +# RESIDENTIAL, COMMERCIAL, ARENA, EMBASSY, WILDS, SPLEEF, INN, JAIL, FARM +towny-shop-plots: + + residents: + - "COMMERCIAL" + + mayor: + - "COMMERCIAL" + + king: + - "COMMERCIAL" + +# Configuration of the database, where everything is stored. +# Shops are found in the table 'shopchest_shops', and logged economy +# transactions are found in the table 'shopchest_economy_logs' +database: + + # Select the type of database which should be used + # Either use 'SQLite' or 'MySQL'. Otherwise you will break the plugin! + type: "SQLite" + + # Set the prefix of all table names related to this plugin. + table-prefix: "shopchest_" + + # If the specified type is 'MySQL', here you configure the... + mysql: + + # ...interval in seconds, when the database should be pinged, + # to keep the connection alive + # You can set this to '0' to disable the ping interval + ping-interval: 3600 + + # ...hostname where the database is accessible + hostname: "" + + # ...port where the database is accessible (default: 3306) + port: 3306 + + # ...database you want to use + database: "" + + # ...username you are going to login with + username: "" + + # ...password you are going to login with + password: "" \ No newline at end of file diff --git a/plugin/src/main/resources/hologram-format.yml b/plugin/src/main/resources/hologram-format.yml new file mode 100644 index 0000000..c241500 --- /dev/null +++ b/plugin/src/main/resources/hologram-format.yml @@ -0,0 +1,78 @@ +# =============================================== +# === ShopChest's hologram configuration file === +# =============================================== +# +# Valid requirements are: +# VENDOR, AMOUNT, ITEM_TYPE, ITEM_NAME, HAS_ENCHANTMENT, BUY_PRICE, +# SELL_PRICE, HAS_POTION_EFFECT, IS_MUSIC_DISC, IS_POTION_EXTENDED, +# IS_WRITTEN_BOOK, IS_BANNER_PATTERN, ADMIN_SHOP, NORMAL_SHOP, +# IN_STOCK, MAX_STACK, CHEST_SPACE, DURABILITY +# +# You can also use the requirements for conditions. +# ITEM_TYPE will return the type of the item (-> item_names.txt), +# ITEM_NAME can be compared against a custom named item's name (may be null). +# +# Examples: +# - IN_STOCK > 0 +# - VENDOR == "EpicEric" +# - BUY_PRICE <= SELL_PRICE +# - ITEM_TYPE == "STONE:2" +# - ITEM_TYPE != "IRON_INGOT" +# - ITEM_NAME == "The Mighty Sword" +# - (AMOUNT > 10) && (AMOUNT <= 20) +# - (IN_STOCK > 0) || ADMIN_SHOP +# +# Valid placeholders are: +# %VENDOR%, %AMOUNT%, %ITEMNAME%, %ENCHANTMENT%, %BUY-PRICE%, +# %SELL-PRICE%, %POTION-EFFECT%, %MUSIC-TITLE%, %BANNER-PATTERN-NAME%, +# %GENERATION%, %STOCK%, %MAX-STACK%, %CHEST-SPACE%, %DURABILITY% +# +# In the format, placeholders can also be used for scripts. +# Examples: +# - "In Stock: {%STOCK% / 64} Stk." +# - "In Stock: {(%STOCK% - (%STOCK% % 64)) / 64} Stk. {%STOCK% % 64}" +# +# Other information: +# - Options can be called however you want. +# - Color codes can be used in the format. +# - Options are checked from top to bottom; the first to +# fulfill the requirements will be taken. +# - All scripts have to be in JavaScript syntax. +# - Lines start with 0. + +lines: + 0: + options: + normal-shop: + format: "%VENDOR%" + requirements: + - NORMAL_SHOP + + admin-shop: + format: "&cAdmin Shop" + requirements: + - ADMIN_SHOP + + 1: + options: + default: + format: "%AMOUNT% x %ITEMNAME%" + requirements: + + 2: + options: + buy-and-sell: + format: "Buy %BUY-PRICE% | %SELL-PRICE% Sell" + requirements: + - BUY_PRICE > 0 + - SELL_PRICE > 0 + + only-buy: + format: "Buy %BUY-PRICE%" + requirements: + - BUY_PRICE > 0 + + only-sell: + format: "Sell %SELL-PRICE%" + requirements: + - SELL_PRICE > 0 \ No newline at end of file diff --git a/plugin/src/main/resources/item_names.txt b/plugin/src/main/resources/item_names.txt new file mode 100644 index 0000000..3b64c9f --- /dev/null +++ b/plugin/src/main/resources/item_names.txt @@ -0,0 +1,1230 @@ +Item names for Spigot 1.16.1 +(Source: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/Material.html) + +ACACIA_BOAT +ACACIA_BUTTON +ACACIA_DOOR +ACACIA_FENCE +ACACIA_FENCE_GATE +ACACIA_LEAVES +ACACIA_LOG +ACACIA_PLANKS +ACACIA_PRESSURE_PLATE +ACACIA_SAPLING +ACACIA_SIGN +ACACIA_SLAB +ACACIA_STAIRS +ACACIA_TRAPDOOR +ACACIA_WALL_SIGN +ACACIA_WOOD +ACTIVATOR_RAIL +AIR +ALLIUM +AMETHYST_BLOCK +AMETHYST_CLUSTER +AMETHYST_SHARD +ANCIENT_DEBRIS +ANDESITE +ANDESITE_SLAB +ANDESITE_STAIRS +ANDESITE_WALL +ANVIL +APPLE +ARMOR_STAND +ARROW +ATTACHED_MELON_STEM +ATTACHED_PUMPKIN_STEM +AXOLOTL_BUCKET +AXOLOTL_SPAWN_EGG +AZALEA +AZALEA_LEAVES +AZURE_BLUET +BAKED_POTATO +BAMBOO +BAMBOO_SAPLING +BARREL +BARRIER +BASALT +BAT_SPAWN_EGG +BEACON +BEDROCK +BEEF +BEEHIVE +BEETROOT +BEETROOTS +BEETROOT_SEEDS +BEETROOT_SOUP +BEE_NEST +BEE_SPAWN_EGG +BELL +BIG_DRIPLEAF +BIG_DRIPLEAF_STEM +BIRCH_BOAT +BIRCH_BUTTON +BIRCH_DOOR +BIRCH_FENCE +BIRCH_FENCE_GATE +BIRCH_LEAVES +BIRCH_LOG +BIRCH_PLANKS +BIRCH_PRESSURE_PLATE +BIRCH_SAPLING +BIRCH_SIGN +BIRCH_SLAB +BIRCH_STAIRS +BIRCH_TRAPDOOR +BIRCH_WALL_SIGN +BIRCH_WOOD +BLACKSTONE +BLACKSTONE_SLAB +BLACKSTONE_STAIRS +BLACKSTONE_WALL +BLACK_BANNER +BLACK_BED +BLACK_CANDLE +BLACK_CANDLE_CAKE +BLACK_CARPET +BLACK_CONCRETE +BLACK_CONCRETE_POWDER +BLACK_DYE +BLACK_GLAZED_TERRACOTTA +BLACK_SHULKER_BOX +BLACK_STAINED_GLASS +BLACK_STAINED_GLASS_PANE +BLACK_TERRACOTTA +BLACK_WALL_BANNER +BLACK_WOOL +BLAST_FURNACE +BLAZE_POWDER +BLAZE_ROD +BLAZE_SPAWN_EGG +BLUE_BANNER +BLUE_BED +BLUE_CANDLE +BLUE_CANDLE_CAKE +BLUE_CARPET +BLUE_CONCRETE +BLUE_CONCRETE_POWDER +BLUE_DYE +BLUE_GLAZED_TERRACOTTA +BLUE_ICE +BLUE_ORCHID +BLUE_SHULKER_BOX +BLUE_STAINED_GLASS +BLUE_STAINED_GLASS_PANE +BLUE_TERRACOTTA +BLUE_WALL_BANNER +BLUE_WOOL +BONE +BONE_BLOCK +BONE_MEAL +BOOK +BOOKSHELF +BOW +BOWL +BRAIN_CORAL +BRAIN_CORAL_BLOCK +BRAIN_CORAL_FAN +BRAIN_CORAL_WALL_FAN +BREAD +BREWING_STAND +BRICK +BRICKS +BRICK_SLAB +BRICK_STAIRS +BRICK_WALL +BROWN_BANNER +BROWN_BED +BROWN_CANDLE +BROWN_CANDLE_CAKE +BROWN_CARPET +BROWN_CONCRETE +BROWN_CONCRETE_POWDER +BROWN_DYE +BROWN_GLAZED_TERRACOTTA +BROWN_MUSHROOM +BROWN_MUSHROOM_BLOCK +BROWN_SHULKER_BOX +BROWN_STAINED_GLASS +BROWN_STAINED_GLASS_PANE +BROWN_TERRACOTTA +BROWN_WALL_BANNER +BROWN_WOOL +BUBBLE_COLUMN +BUBBLE_CORAL +BUBBLE_CORAL_BLOCK +BUBBLE_CORAL_FAN +BUBBLE_CORAL_WALL_FAN +BUCKET +BUDDING_AMETHYST +BUNDLE +CACTUS +CAKE +CALCITE +CAMPFIRE +CANDLE +CANDLE_CAKE +CARROT +CARROTS +CARROT_ON_A_STICK +CARTOGRAPHY_TABLE +CARVED_PUMPKIN +CAT_SPAWN_EGG +CAULDRON +CAVE_AIR +CAVE_SPIDER_SPAWN_EGG +CAVE_VINES +CAVE_VINES_PLANT +CHAIN +CHAINMAIL_BOOTS +CHAINMAIL_CHESTPLATE +CHAINMAIL_HELMET +CHAINMAIL_LEGGINGS +CHAIN_COMMAND_BLOCK +CHARCOAL +CHEST +CHEST_MINECART +CHICKEN +CHICKEN_SPAWN_EGG +CHIPPED_ANVIL +CHISELED_DEEPSLATE +CHISELED_NETHER_BRICKS +CHISELED_POLISHED_BLACKSTONE +CHISELED_QUARTZ_BLOCK +CHISELED_RED_SANDSTONE +CHISELED_SANDSTONE +CHISELED_STONE_BRICKS +CHORUS_FLOWER +CHORUS_FRUIT +CHORUS_PLANT +CLAY +CLAY_BALL +CLOCK +COAL +COAL_BLOCK +COAL_ORE +COARSE_DIRT +COBBLED_DEEPSLATE +COBBLED_DEEPSLATE_SLAB +COBBLED_DEEPSLATE_STAIRS +COBBLED_DEEPSLATE_WALL +COBBLESTONE +COBBLESTONE_SLAB +COBBLESTONE_STAIRS +COBBLESTONE_WALL +COBWEB +COCOA +COCOA_BEANS +COD +COD_BUCKET +COD_SPAWN_EGG +COMMAND_BLOCK +COMMAND_BLOCK_MINECART +COMPARATOR +COMPASS +COMPOSTER +CONDUIT +COOKED_BEEF +COOKED_CHICKEN +COOKED_COD +COOKED_MUTTON +COOKED_PORKCHOP +COOKED_RABBIT +COOKED_SALMON +COOKIE +COPPER_BLOCK +COPPER_INGOT +COPPER_ORE +CORNFLOWER +COW_SPAWN_EGG +CRACKED_DEEPSLATE_BRICKS +CRACKED_DEEPSLATE_TILES +CRACKED_NETHER_BRICKS +CRACKED_POLISHED_BLACKSTONE_BRICKS +CRACKED_STONE_BRICKS +CRAFTING_TABLE +CREEPER_BANNER_PATTERN +CREEPER_HEAD +CREEPER_SPAWN_EGG +CREEPER_WALL_HEAD +CRIMSON_BUTTON +CRIMSON_DOOR +CRIMSON_FENCE +CRIMSON_FENCE_GATE +CRIMSON_FUNGUS +CRIMSON_HYPHAE +CRIMSON_NYLIUM +CRIMSON_PLANKS +CRIMSON_PRESSURE_PLATE +CRIMSON_ROOTS +CRIMSON_SIGN +CRIMSON_SLAB +CRIMSON_STAIRS +CRIMSON_STEM +CRIMSON_TRAPDOOR +CRIMSON_WALL_SIGN +CROSSBOW +CRYING_OBSIDIAN +CUT_COPPER +CUT_COPPER_SLAB +CUT_COPPER_STAIRS +CUT_RED_SANDSTONE +CUT_RED_SANDSTONE_SLAB +CUT_SANDSTONE +CUT_SANDSTONE_SLAB +CYAN_BANNER +CYAN_BED +CYAN_CANDLE +CYAN_CANDLE_CAKE +CYAN_CARPET +CYAN_CONCRETE +CYAN_CONCRETE_POWDER +CYAN_DYE +CYAN_GLAZED_TERRACOTTA +CYAN_SHULKER_BOX +CYAN_STAINED_GLASS +CYAN_STAINED_GLASS_PANE +CYAN_TERRACOTTA +CYAN_WALL_BANNER +CYAN_WOOL +DAMAGED_ANVIL +DANDELION +DARK_OAK_BOAT +DARK_OAK_BUTTON +DARK_OAK_DOOR +DARK_OAK_FENCE +DARK_OAK_FENCE_GATE +DARK_OAK_LEAVES +DARK_OAK_LOG +DARK_OAK_PLANKS +DARK_OAK_PRESSURE_PLATE +DARK_OAK_SAPLING +DARK_OAK_SIGN +DARK_OAK_SLAB +DARK_OAK_STAIRS +DARK_OAK_TRAPDOOR +DARK_OAK_WALL_SIGN +DARK_OAK_WOOD +DARK_PRISMARINE +DARK_PRISMARINE_SLAB +DARK_PRISMARINE_STAIRS +DAYLIGHT_DETECTOR +DEAD_BRAIN_CORAL +DEAD_BRAIN_CORAL_BLOCK +DEAD_BRAIN_CORAL_FAN +DEAD_BRAIN_CORAL_WALL_FAN +DEAD_BUBBLE_CORAL +DEAD_BUBBLE_CORAL_BLOCK +DEAD_BUBBLE_CORAL_FAN +DEAD_BUBBLE_CORAL_WALL_FAN +DEAD_BUSH +DEAD_FIRE_CORAL +DEAD_FIRE_CORAL_BLOCK +DEAD_FIRE_CORAL_FAN +DEAD_FIRE_CORAL_WALL_FAN +DEAD_HORN_CORAL +DEAD_HORN_CORAL_BLOCK +DEAD_HORN_CORAL_FAN +DEAD_HORN_CORAL_WALL_FAN +DEAD_TUBE_CORAL +DEAD_TUBE_CORAL_BLOCK +DEAD_TUBE_CORAL_FAN +DEAD_TUBE_CORAL_WALL_FAN +DEBUG_STICK +DEEPSLATE +DEEPSLATE_BRICKS +DEEPSLATE_BRICK_SLAB +DEEPSLATE_BRICK_STAIRS +DEEPSLATE_BRICK_WALL +DEEPSLATE_COAL_ORE +DEEPSLATE_COPPER_ORE +DEEPSLATE_DIAMOND_ORE +DEEPSLATE_EMERALD_ORE +DEEPSLATE_GOLD_ORE +DEEPSLATE_IRON_ORE +DEEPSLATE_LAPIS_ORE +DEEPSLATE_REDSTONE_ORE +DEEPSLATE_TILES +DEEPSLATE_TILE_SLAB +DEEPSLATE_TILE_STAIRS +DEEPSLATE_TILE_WALL +DETECTOR_RAIL +DIAMOND +DIAMOND_AXE +DIAMOND_BLOCK +DIAMOND_BOOTS +DIAMOND_CHESTPLATE +DIAMOND_HELMET +DIAMOND_HOE +DIAMOND_HORSE_ARMOR +DIAMOND_LEGGINGS +DIAMOND_ORE +DIAMOND_PICKAXE +DIAMOND_SHOVEL +DIAMOND_SWORD +DIORITE +DIORITE_SLAB +DIORITE_STAIRS +DIORITE_WALL +DIRT +DIRT_PATH +DISPENSER +DOLPHIN_SPAWN_EGG +DONKEY_SPAWN_EGG +DRAGON_BREATH +DRAGON_EGG +DRAGON_HEAD +DRAGON_WALL_HEAD +DRIED_KELP +DRIED_KELP_BLOCK +DRIPSTONE_BLOCK +DROPPER +DROWNED_SPAWN_EGG +EGG +ELDER_GUARDIAN_SPAWN_EGG +ELYTRA +EMERALD +EMERALD_BLOCK +EMERALD_ORE +ENCHANTED_BOOK +ENCHANTED_GOLDEN_APPLE +ENCHANTING_TABLE +ENDERMAN_SPAWN_EGG +ENDERMITE_SPAWN_EGG +ENDER_CHEST +ENDER_EYE +ENDER_PEARL +END_CRYSTAL +END_GATEWAY +END_PORTAL +END_PORTAL_FRAME +END_ROD +END_STONE +END_STONE_BRICKS +END_STONE_BRICK_SLAB +END_STONE_BRICK_STAIRS +END_STONE_BRICK_WALL +EVOKER_SPAWN_EGG +EXPERIENCE_BOTTLE +EXPOSED_COPPER +EXPOSED_CUT_COPPER +EXPOSED_CUT_COPPER_SLAB +EXPOSED_CUT_COPPER_STAIRS +FARMLAND +FEATHER +FERMENTED_SPIDER_EYE +FERN +FILLED_MAP +FIRE +FIREWORK_ROCKET +FIREWORK_STAR +FIRE_CHARGE +FIRE_CORAL +FIRE_CORAL_BLOCK +FIRE_CORAL_FAN +FIRE_CORAL_WALL_FAN +FISHING_ROD +FLETCHING_TABLE +FLINT +FLINT_AND_STEEL +FLOWERING_AZALEA +FLOWERING_AZALEA_LEAVES +FLOWER_BANNER_PATTERN +FLOWER_POT +FOX_SPAWN_EGG +FROSTED_ICE +FURNACE +FURNACE_MINECART +GHAST_SPAWN_EGG +GHAST_TEAR +GILDED_BLACKSTONE +GLASS +GLASS_BOTTLE +GLASS_PANE +GLISTERING_MELON_SLICE +GLOBE_BANNER_PATTERN +GLOWSTONE +GLOWSTONE_DUST +GLOW_BERRIES +GLOW_INK_SAC +GLOW_ITEM_FRAME +GLOW_LICHEN +GLOW_SQUID_SPAWN_EGG +GOAT_SPAWN_EGG +GOLDEN_APPLE +GOLDEN_AXE +GOLDEN_BOOTS +GOLDEN_CARROT +GOLDEN_CHESTPLATE +GOLDEN_HELMET +GOLDEN_HOE +GOLDEN_HORSE_ARMOR +GOLDEN_LEGGINGS +GOLDEN_PICKAXE +GOLDEN_SHOVEL +GOLDEN_SWORD +GOLD_BLOCK +GOLD_INGOT +GOLD_NUGGET +GOLD_ORE +GRANITE +GRANITE_SLAB +GRANITE_STAIRS +GRANITE_WALL +GRASS +GRASS_BLOCK +GRAVEL +GRAY_BANNER +GRAY_BED +GRAY_CANDLE +GRAY_CANDLE_CAKE +GRAY_CARPET +GRAY_CONCRETE +GRAY_CONCRETE_POWDER +GRAY_DYE +GRAY_GLAZED_TERRACOTTA +GRAY_SHULKER_BOX +GRAY_STAINED_GLASS +GRAY_STAINED_GLASS_PANE +GRAY_TERRACOTTA +GRAY_WALL_BANNER +GRAY_WOOL +GREEN_BANNER +GREEN_BED +GREEN_CANDLE +GREEN_CANDLE_CAKE +GREEN_CARPET +GREEN_CONCRETE +GREEN_CONCRETE_POWDER +GREEN_DYE +GREEN_GLAZED_TERRACOTTA +GREEN_SHULKER_BOX +GREEN_STAINED_GLASS +GREEN_STAINED_GLASS_PANE +GREEN_TERRACOTTA +GREEN_WALL_BANNER +GREEN_WOOL +GRINDSTONE +GUARDIAN_SPAWN_EGG +GUNPOWDER +HANGING_ROOTS +HAY_BLOCK +HEART_OF_THE_SEA +HEAVY_WEIGHTED_PRESSURE_PLATE +HOGLIN_SPAWN_EGG +HONEYCOMB +HONEYCOMB_BLOCK +HONEY_BLOCK +HONEY_BOTTLE +HOPPER +HOPPER_MINECART +HORN_CORAL +HORN_CORAL_BLOCK +HORN_CORAL_FAN +HORN_CORAL_WALL_FAN +HORSE_SPAWN_EGG +HUSK_SPAWN_EGG +ICE +INFESTED_CHISELED_STONE_BRICKS +INFESTED_COBBLESTONE +INFESTED_CRACKED_STONE_BRICKS +INFESTED_DEEPSLATE +INFESTED_MOSSY_STONE_BRICKS +INFESTED_STONE +INFESTED_STONE_BRICKS +INK_SAC +IRON_AXE +IRON_BARS +IRON_BLOCK +IRON_BOOTS +IRON_CHESTPLATE +IRON_DOOR +IRON_HELMET +IRON_HOE +IRON_HORSE_ARMOR +IRON_INGOT +IRON_LEGGINGS +IRON_NUGGET +IRON_ORE +IRON_PICKAXE +IRON_SHOVEL +IRON_SWORD +IRON_TRAPDOOR +ITEM_FRAME +JACK_O_LANTERN +JIGSAW +JUKEBOX +JUNGLE_BOAT +JUNGLE_BUTTON +JUNGLE_DOOR +JUNGLE_FENCE +JUNGLE_FENCE_GATE +JUNGLE_LEAVES +JUNGLE_LOG +JUNGLE_PLANKS +JUNGLE_PRESSURE_PLATE +JUNGLE_SAPLING +JUNGLE_SIGN +JUNGLE_SLAB +JUNGLE_STAIRS +JUNGLE_TRAPDOOR +JUNGLE_WALL_SIGN +JUNGLE_WOOD +KELP +KELP_PLANT +KNOWLEDGE_BOOK +LADDER +LANTERN +LAPIS_BLOCK +LAPIS_LAZULI +LAPIS_ORE +LARGE_AMETHYST_BUD +LARGE_FERN +LAVA +LAVA_BUCKET +LAVA_CAULDRON +LEAD +LEATHER +LEATHER_BOOTS +LEATHER_CHESTPLATE +LEATHER_HELMET +LEATHER_HORSE_ARMOR +LEATHER_LEGGINGS +LECTERN +LEVER +LIGHT +LIGHTNING_ROD +LIGHT_BLUE_BANNER +LIGHT_BLUE_BED +LIGHT_BLUE_CANDLE +LIGHT_BLUE_CANDLE_CAKE +LIGHT_BLUE_CARPET +LIGHT_BLUE_CONCRETE +LIGHT_BLUE_CONCRETE_POWDER +LIGHT_BLUE_DYE +LIGHT_BLUE_GLAZED_TERRACOTTA +LIGHT_BLUE_SHULKER_BOX +LIGHT_BLUE_STAINED_GLASS +LIGHT_BLUE_STAINED_GLASS_PANE +LIGHT_BLUE_TERRACOTTA +LIGHT_BLUE_WALL_BANNER +LIGHT_BLUE_WOOL +LIGHT_GRAY_BANNER +LIGHT_GRAY_BED +LIGHT_GRAY_CANDLE +LIGHT_GRAY_CANDLE_CAKE +LIGHT_GRAY_CARPET +LIGHT_GRAY_CONCRETE +LIGHT_GRAY_CONCRETE_POWDER +LIGHT_GRAY_DYE +LIGHT_GRAY_GLAZED_TERRACOTTA +LIGHT_GRAY_SHULKER_BOX +LIGHT_GRAY_STAINED_GLASS +LIGHT_GRAY_STAINED_GLASS_PANE +LIGHT_GRAY_TERRACOTTA +LIGHT_GRAY_WALL_BANNER +LIGHT_GRAY_WOOL +LIGHT_WEIGHTED_PRESSURE_PLATE +LILAC +LILY_OF_THE_VALLEY +LILY_PAD +LIME_BANNER +LIME_BED +LIME_CANDLE +LIME_CANDLE_CAKE +LIME_CARPET +LIME_CONCRETE +LIME_CONCRETE_POWDER +LIME_DYE +LIME_GLAZED_TERRACOTTA +LIME_SHULKER_BOX +LIME_STAINED_GLASS +LIME_STAINED_GLASS_PANE +LIME_TERRACOTTA +LIME_WALL_BANNER +LIME_WOOL +LINGERING_POTION +LLAMA_SPAWN_EGG +LODESTONE +LOOM +MAGENTA_BANNER +MAGENTA_BED +MAGENTA_CANDLE +MAGENTA_CANDLE_CAKE +MAGENTA_CARPET +MAGENTA_CONCRETE +MAGENTA_CONCRETE_POWDER +MAGENTA_DYE +MAGENTA_GLAZED_TERRACOTTA +MAGENTA_SHULKER_BOX +MAGENTA_STAINED_GLASS +MAGENTA_STAINED_GLASS_PANE +MAGENTA_TERRACOTTA +MAGENTA_WALL_BANNER +MAGENTA_WOOL +MAGMA_BLOCK +MAGMA_CREAM +MAGMA_CUBE_SPAWN_EGG +MAP +MEDIUM_AMETHYST_BUD +MELON +MELON_SEEDS +MELON_SLICE +MELON_STEM +MILK_BUCKET +MINECART +MOJANG_BANNER_PATTERN +MOOSHROOM_SPAWN_EGG +MOSSY_COBBLESTONE +MOSSY_COBBLESTONE_SLAB +MOSSY_COBBLESTONE_STAIRS +MOSSY_COBBLESTONE_WALL +MOSSY_STONE_BRICKS +MOSSY_STONE_BRICK_SLAB +MOSSY_STONE_BRICK_STAIRS +MOSSY_STONE_BRICK_WALL +MOSS_BLOCK +MOSS_CARPET +MOVING_PISTON +MULE_SPAWN_EGG +MUSHROOM_STEM +MUSHROOM_STEW +MUSIC_DISC_11 +MUSIC_DISC_13 +MUSIC_DISC_BLOCKS +MUSIC_DISC_CAT +MUSIC_DISC_CHIRP +MUSIC_DISC_FAR +MUSIC_DISC_MALL +MUSIC_DISC_MELLOHI +MUSIC_DISC_PIGSTEP +MUSIC_DISC_STAL +MUSIC_DISC_STRAD +MUSIC_DISC_WAIT +MUSIC_DISC_WARD +MUTTON +MYCELIUM +NAME_TAG +NAUTILUS_SHELL +NETHERITE_AXE +NETHERITE_BLOCK +NETHERITE_BOOTS +NETHERITE_CHESTPLATE +NETHERITE_HELMET +NETHERITE_HOE +NETHERITE_INGOT +NETHERITE_LEGGINGS +NETHERITE_PICKAXE +NETHERITE_SCRAP +NETHERITE_SHOVEL +NETHERITE_SWORD +NETHERRACK +NETHER_BRICK +NETHER_BRICKS +NETHER_BRICK_FENCE +NETHER_BRICK_SLAB +NETHER_BRICK_STAIRS +NETHER_BRICK_WALL +NETHER_GOLD_ORE +NETHER_PORTAL +NETHER_QUARTZ_ORE +NETHER_SPROUTS +NETHER_STAR +NETHER_WART +NETHER_WART_BLOCK +NOTE_BLOCK +OAK_BOAT +OAK_BUTTON +OAK_DOOR +OAK_FENCE +OAK_FENCE_GATE +OAK_LEAVES +OAK_LOG +OAK_PLANKS +OAK_PRESSURE_PLATE +OAK_SAPLING +OAK_SIGN +OAK_SLAB +OAK_STAIRS +OAK_TRAPDOOR +OAK_WALL_SIGN +OAK_WOOD +OBSERVER +OBSIDIAN +OCELOT_SPAWN_EGG +ORANGE_BANNER +ORANGE_BED +ORANGE_CANDLE +ORANGE_CANDLE_CAKE +ORANGE_CARPET +ORANGE_CONCRETE +ORANGE_CONCRETE_POWDER +ORANGE_DYE +ORANGE_GLAZED_TERRACOTTA +ORANGE_SHULKER_BOX +ORANGE_STAINED_GLASS +ORANGE_STAINED_GLASS_PANE +ORANGE_TERRACOTTA +ORANGE_TULIP +ORANGE_WALL_BANNER +ORANGE_WOOL +OXEYE_DAISY +OXIDIZED_COPPER +OXIDIZED_CUT_COPPER +OXIDIZED_CUT_COPPER_SLAB +OXIDIZED_CUT_COPPER_STAIRS +PACKED_ICE +PAINTING +PANDA_SPAWN_EGG +PAPER +PARROT_SPAWN_EGG +PEONY +PETRIFIED_OAK_SLAB +PHANTOM_MEMBRANE +PHANTOM_SPAWN_EGG +PIGLIN_BANNER_PATTERN +PIGLIN_BRUTE_SPAWN_EGG +PIGLIN_SPAWN_EGG +PIG_SPAWN_EGG +PILLAGER_SPAWN_EGG +PINK_BANNER +PINK_BED +PINK_CANDLE +PINK_CANDLE_CAKE +PINK_CARPET +PINK_CONCRETE +PINK_CONCRETE_POWDER +PINK_DYE +PINK_GLAZED_TERRACOTTA +PINK_SHULKER_BOX +PINK_STAINED_GLASS +PINK_STAINED_GLASS_PANE +PINK_TERRACOTTA +PINK_TULIP +PINK_WALL_BANNER +PINK_WOOL +PISTON +PISTON_HEAD +PLAYER_HEAD +PLAYER_WALL_HEAD +PODZOL +POINTED_DRIPSTONE +POISONOUS_POTATO +POLAR_BEAR_SPAWN_EGG +POLISHED_ANDESITE +POLISHED_ANDESITE_SLAB +POLISHED_ANDESITE_STAIRS +POLISHED_BASALT +POLISHED_BLACKSTONE +POLISHED_BLACKSTONE_BRICKS +POLISHED_BLACKSTONE_BRICK_SLAB +POLISHED_BLACKSTONE_BRICK_STAIRS +POLISHED_BLACKSTONE_BRICK_WALL +POLISHED_BLACKSTONE_BUTTON +POLISHED_BLACKSTONE_PRESSURE_PLATE +POLISHED_BLACKSTONE_SLAB +POLISHED_BLACKSTONE_STAIRS +POLISHED_BLACKSTONE_WALL +POLISHED_DEEPSLATE +POLISHED_DEEPSLATE_SLAB +POLISHED_DEEPSLATE_STAIRS +POLISHED_DEEPSLATE_WALL +POLISHED_DIORITE +POLISHED_DIORITE_SLAB +POLISHED_DIORITE_STAIRS +POLISHED_GRANITE +POLISHED_GRANITE_SLAB +POLISHED_GRANITE_STAIRS +POPPED_CHORUS_FRUIT +POPPY +PORKCHOP +POTATO +POTATOES +POTION +POTTED_ACACIA_SAPLING +POTTED_ALLIUM +POTTED_AZALEA_BUSH +POTTED_AZURE_BLUET +POTTED_BAMBOO +POTTED_BIRCH_SAPLING +POTTED_BLUE_ORCHID +POTTED_BROWN_MUSHROOM +POTTED_CACTUS +POTTED_CORNFLOWER +POTTED_CRIMSON_FUNGUS +POTTED_CRIMSON_ROOTS +POTTED_DANDELION +POTTED_DARK_OAK_SAPLING +POTTED_DEAD_BUSH +POTTED_FERN +POTTED_FLOWERING_AZALEA_BUSH +POTTED_JUNGLE_SAPLING +POTTED_LILY_OF_THE_VALLEY +POTTED_OAK_SAPLING +POTTED_ORANGE_TULIP +POTTED_OXEYE_DAISY +POTTED_PINK_TULIP +POTTED_POPPY +POTTED_RED_MUSHROOM +POTTED_RED_TULIP +POTTED_SPRUCE_SAPLING +POTTED_WARPED_FUNGUS +POTTED_WARPED_ROOTS +POTTED_WHITE_TULIP +POTTED_WITHER_ROSE +POWDER_SNOW +POWDER_SNOW_BUCKET +POWDER_SNOW_CAULDRON +POWERED_RAIL +PRISMARINE +PRISMARINE_BRICKS +PRISMARINE_BRICK_SLAB +PRISMARINE_BRICK_STAIRS +PRISMARINE_CRYSTALS +PRISMARINE_SHARD +PRISMARINE_SLAB +PRISMARINE_STAIRS +PRISMARINE_WALL +PUFFERFISH +PUFFERFISH_BUCKET +PUFFERFISH_SPAWN_EGG +PUMPKIN +PUMPKIN_PIE +PUMPKIN_SEEDS +PUMPKIN_STEM +PURPLE_BANNER +PURPLE_BED +PURPLE_CANDLE +PURPLE_CANDLE_CAKE +PURPLE_CARPET +PURPLE_CONCRETE +PURPLE_CONCRETE_POWDER +PURPLE_DYE +PURPLE_GLAZED_TERRACOTTA +PURPLE_SHULKER_BOX +PURPLE_STAINED_GLASS +PURPLE_STAINED_GLASS_PANE +PURPLE_TERRACOTTA +PURPLE_WALL_BANNER +PURPLE_WOOL +PURPUR_BLOCK +PURPUR_PILLAR +PURPUR_SLAB +PURPUR_STAIRS +QUARTZ +QUARTZ_BLOCK +QUARTZ_BRICKS +QUARTZ_PILLAR +QUARTZ_SLAB +QUARTZ_STAIRS +RABBIT +RABBIT_FOOT +RABBIT_HIDE +RABBIT_SPAWN_EGG +RABBIT_STEW +RAIL +RAVAGER_SPAWN_EGG +RAW_COPPER +RAW_COPPER_BLOCK +RAW_GOLD +RAW_GOLD_BLOCK +RAW_IRON +RAW_IRON_BLOCK +REDSTONE +REDSTONE_BLOCK +REDSTONE_LAMP +REDSTONE_ORE +REDSTONE_TORCH +REDSTONE_WALL_TORCH +REDSTONE_WIRE +RED_BANNER +RED_BED +RED_CANDLE +RED_CANDLE_CAKE +RED_CARPET +RED_CONCRETE +RED_CONCRETE_POWDER +RED_DYE +RED_GLAZED_TERRACOTTA +RED_MUSHROOM +RED_MUSHROOM_BLOCK +RED_NETHER_BRICKS +RED_NETHER_BRICK_SLAB +RED_NETHER_BRICK_STAIRS +RED_NETHER_BRICK_WALL +RED_SAND +RED_SANDSTONE +RED_SANDSTONE_SLAB +RED_SANDSTONE_STAIRS +RED_SANDSTONE_WALL +RED_SHULKER_BOX +RED_STAINED_GLASS +RED_STAINED_GLASS_PANE +RED_TERRACOTTA +RED_TULIP +RED_WALL_BANNER +RED_WOOL +REPEATER +REPEATING_COMMAND_BLOCK +RESPAWN_ANCHOR +ROOTED_DIRT +ROSE_BUSH +ROTTEN_FLESH +SADDLE +SALMON +SALMON_BUCKET +SALMON_SPAWN_EGG +SAND +SANDSTONE +SANDSTONE_SLAB +SANDSTONE_STAIRS +SANDSTONE_WALL +SCAFFOLDING +SCULK_SENSOR +SCUTE +SEAGRASS +SEA_LANTERN +SEA_PICKLE +SHEARS +SHEEP_SPAWN_EGG +SHIELD +SHROOMLIGHT +SHULKER_BOX +SHULKER_SHELL +SHULKER_SPAWN_EGG +SILVERFISH_SPAWN_EGG +SKELETON_HORSE_SPAWN_EGG +SKELETON_SKULL +SKELETON_SPAWN_EGG +SKELETON_WALL_SKULL +SKULL_BANNER_PATTERN +SLIME_BALL +SLIME_BLOCK +SLIME_SPAWN_EGG +SMALL_AMETHYST_BUD +SMALL_DRIPLEAF +SMITHING_TABLE +SMOKER +SMOOTH_BASALT +SMOOTH_QUARTZ +SMOOTH_QUARTZ_SLAB +SMOOTH_QUARTZ_STAIRS +SMOOTH_RED_SANDSTONE +SMOOTH_RED_SANDSTONE_SLAB +SMOOTH_RED_SANDSTONE_STAIRS +SMOOTH_SANDSTONE +SMOOTH_SANDSTONE_SLAB +SMOOTH_SANDSTONE_STAIRS +SMOOTH_STONE +SMOOTH_STONE_SLAB +SNOW +SNOWBALL +SNOW_BLOCK +SOUL_CAMPFIRE +SOUL_FIRE +SOUL_LANTERN +SOUL_SAND +SOUL_SOIL +SOUL_TORCH +SOUL_WALL_TORCH +SPAWNER +SPECTRAL_ARROW +SPIDER_EYE +SPIDER_SPAWN_EGG +SPLASH_POTION +SPONGE +SPORE_BLOSSOM +SPRUCE_BOAT +SPRUCE_BUTTON +SPRUCE_DOOR +SPRUCE_FENCE +SPRUCE_FENCE_GATE +SPRUCE_LEAVES +SPRUCE_LOG +SPRUCE_PLANKS +SPRUCE_PRESSURE_PLATE +SPRUCE_SAPLING +SPRUCE_SIGN +SPRUCE_SLAB +SPRUCE_STAIRS +SPRUCE_TRAPDOOR +SPRUCE_WALL_SIGN +SPRUCE_WOOD +SPYGLASS +SQUID_SPAWN_EGG +STICK +STICKY_PISTON +STONE +STONECUTTER +STONE_AXE +STONE_BRICKS +STONE_BRICK_SLAB +STONE_BRICK_STAIRS +STONE_BRICK_WALL +STONE_BUTTON +STONE_HOE +STONE_PICKAXE +STONE_PRESSURE_PLATE +STONE_SHOVEL +STONE_SLAB +STONE_STAIRS +STONE_SWORD +STRAY_SPAWN_EGG +STRIDER_SPAWN_EGG +STRING +STRIPPED_ACACIA_LOG +STRIPPED_ACACIA_WOOD +STRIPPED_BIRCH_LOG +STRIPPED_BIRCH_WOOD +STRIPPED_CRIMSON_HYPHAE +STRIPPED_CRIMSON_STEM +STRIPPED_DARK_OAK_LOG +STRIPPED_DARK_OAK_WOOD +STRIPPED_JUNGLE_LOG +STRIPPED_JUNGLE_WOOD +STRIPPED_OAK_LOG +STRIPPED_OAK_WOOD +STRIPPED_SPRUCE_LOG +STRIPPED_SPRUCE_WOOD +STRIPPED_WARPED_HYPHAE +STRIPPED_WARPED_STEM +STRUCTURE_BLOCK +STRUCTURE_VOID +SUGAR +SUGAR_CANE +SUNFLOWER +SUSPICIOUS_STEW +SWEET_BERRIES +SWEET_BERRY_BUSH +TALL_GRASS +TALL_SEAGRASS +TARGET +TERRACOTTA +TINTED_GLASS +TIPPED_ARROW +TNT +TNT_MINECART +TORCH +TOTEM_OF_UNDYING +TRADER_LLAMA_SPAWN_EGG +TRAPPED_CHEST +TRIDENT +TRIPWIRE +TRIPWIRE_HOOK +TROPICAL_FISH +TROPICAL_FISH_BUCKET +TROPICAL_FISH_SPAWN_EGG +TUBE_CORAL +TUBE_CORAL_BLOCK +TUBE_CORAL_FAN +TUBE_CORAL_WALL_FAN +TUFF +TURTLE_EGG +TURTLE_HELMET +TURTLE_SPAWN_EGG +TWISTING_VINES +TWISTING_VINES_PLANT +VEX_SPAWN_EGG +VILLAGER_SPAWN_EGG +VINDICATOR_SPAWN_EGG +VINE +VOID_AIR +WALL_TORCH +WANDERING_TRADER_SPAWN_EGG +WARPED_BUTTON +WARPED_DOOR +WARPED_FENCE +WARPED_FENCE_GATE +WARPED_FUNGUS +WARPED_FUNGUS_ON_A_STICK +WARPED_HYPHAE +WARPED_NYLIUM +WARPED_PLANKS +WARPED_PRESSURE_PLATE +WARPED_ROOTS +WARPED_SIGN +WARPED_SLAB +WARPED_STAIRS +WARPED_STEM +WARPED_TRAPDOOR +WARPED_WALL_SIGN +WARPED_WART_BLOCK +WATER +WATER_BUCKET +WATER_CAULDRON +WAXED_COPPER_BLOCK +WAXED_CUT_COPPER +WAXED_CUT_COPPER_SLAB +WAXED_CUT_COPPER_STAIRS +WAXED_EXPOSED_COPPER +WAXED_EXPOSED_CUT_COPPER +WAXED_EXPOSED_CUT_COPPER_SLAB +WAXED_EXPOSED_CUT_COPPER_STAIRS +WAXED_OXIDIZED_COPPER +WAXED_OXIDIZED_CUT_COPPER +WAXED_OXIDIZED_CUT_COPPER_SLAB +WAXED_OXIDIZED_CUT_COPPER_STAIRS +WAXED_WEATHERED_COPPER +WAXED_WEATHERED_CUT_COPPER +WAXED_WEATHERED_CUT_COPPER_SLAB +WAXED_WEATHERED_CUT_COPPER_STAIRS +WEATHERED_COPPER +WEATHERED_CUT_COPPER +WEATHERED_CUT_COPPER_SLAB +WEATHERED_CUT_COPPER_STAIRS +WEEPING_VINES +WEEPING_VINES_PLANT +WET_SPONGE +WHEAT +WHEAT_SEEDS +WHITE_BANNER +WHITE_BED +WHITE_CANDLE +WHITE_CANDLE_CAKE +WHITE_CARPET +WHITE_CONCRETE +WHITE_CONCRETE_POWDER +WHITE_DYE +WHITE_GLAZED_TERRACOTTA +WHITE_SHULKER_BOX +WHITE_STAINED_GLASS +WHITE_STAINED_GLASS_PANE +WHITE_TERRACOTTA +WHITE_TULIP +WHITE_WALL_BANNER +WHITE_WOOL +WITCH_SPAWN_EGG +WITHER_ROSE +WITHER_SKELETON_SKULL +WITHER_SKELETON_SPAWN_EGG +WITHER_SKELETON_WALL_SKULL +WOLF_SPAWN_EGG +WOODEN_AXE +WOODEN_HOE +WOODEN_PICKAXE +WOODEN_SHOVEL +WOODEN_SWORD +WRITABLE_BOOK +WRITTEN_BOOK +YELLOW_BANNER +YELLOW_BED +YELLOW_CANDLE +YELLOW_CANDLE_CAKE +YELLOW_CARPET +YELLOW_CONCRETE +YELLOW_CONCRETE_POWDER +YELLOW_DYE +YELLOW_GLAZED_TERRACOTTA +YELLOW_SHULKER_BOX +YELLOW_STAINED_GLASS +YELLOW_STAINED_GLASS_PANE +YELLOW_TERRACOTTA +YELLOW_WALL_BANNER +YELLOW_WOOL +ZOGLIN_SPAWN_EGG +ZOMBIE_HEAD +ZOMBIE_HORSE_SPAWN_EGG +ZOMBIE_SPAWN_EGG +ZOMBIE_VILLAGER_SPAWN_EGG +ZOMBIE_WALL_HEAD +ZOMBIFIED_PIGLIN_SPAWN_EGG \ No newline at end of file diff --git a/plugin/src/main/resources/lang/de_DE-legacy.lang b/plugin/src/main/resources/lang/de_DE-legacy.lang new file mode 100644 index 0000000..b739c4b --- /dev/null +++ b/plugin/src/main/resources/lang/de_DE-legacy.lang @@ -0,0 +1,919 @@ +message.shop-created=&6Dir wurden &c%CREATION-PRICE% &6abgenommen, um diesen Shop zu erstellen. +message.admin-shop-created=&6Dir wurden &c%CREATION-PRICE% &6abgenommen, um diesen Admin Shop zu erstellen. +message.chest-already-shop=&cTruhe ist bereits ein Shop. +message.chest-blocked=&cÜber der Truhe ist kein Platz. +message.double-chest-blocked=&cÜber der Truhe ist kein Platz. +message.shop-removed=&6Shop entfernt. +message.shop-removed-refund=&6Shop entfernt. Dir wurden &c%CREATION-PRICE%&6 erstattet. +message.all-shops-removed=&6Alle (&c%AMOUNT%&6) Shops von &c%VENDOR%&6 wurden entfernt. +message.chest-no-shop=&cTruhe ist kein Shop. +message.shop-create-not-enough-money=&cNicht genug Geld. Du brauchst &6%CREATION-PRICE% &cum einen Shop zu erstellen. +message.shopInfo.vendor=&6Verkäufer: &e%VENDOR% +message.shopInfo.product=&6Produkt: &e%AMOUNT% x %ITEMNAME% +message.shopInfo.stock=&6Auf Lager: &e%STOCK% +message.shopInfo.chest-space=&6Platz in Truhe: &e%CHEST-SPACE% +message.shopInfo.price=&6Preis: Kauf: &e%BUY-PRICE%&6 Verkauf: &e%SELL-PRICE% +message.shopInfo.disabled=&7Deaktiviert +message.shopInfo.is-normal=&6Typ: &eNormal +message.shopInfo.is-admin=&6Typ: &eAdmin +message.buy-and-sell-disabled=&cDu kannst keinen Shop ohne Kauf- und Verkaufspreis erstellen. +message.buy-success=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%BUY-PRICE%&a von &6%VENDOR% &agekauft. +message.buy-success-admin=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%BUY-PRICE% &agekauft. +message.sell-success=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE%&a an &6%VENDOR% &averkauft. +message.sell-success-admin=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE% &averkauft. +message.someone-bought=&6%PLAYER% &ahat &6%AMOUNT% x %ITEMNAME%&a für &6%BUY-PRICE%&a von deinem Shop gekauft. +message.someone-sold=&6%PLAYER% &ahat &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE%&a an deinen Shop verkauft. +message.revenue-while-offline=&6Während du offline warst, haben deine Shops einen Umsatz von &c%REVENUE%&6 gemacht. +message.not-enough-inventory-space=&cNicht genug Platz im Inventar. +message.chest-not-enough-inventory-space=&cShop ist voll. +message.not-enough-money=&cNicht genug Geld. +message.not-enough-items=&cNicht genug Items. +message.vendor-not-enough-money=&cVerkäufer hat nicht genug Geld. +message.out-of-stock=&cShop ausverkauft. +message.vendor-out-of-stock=&cDein Shop, der &6%AMOUNT% x %ITEMNAME% &cverkauft, ist ausverkauft. +message.error-occurred=&cEin Fehler ist aufgetreten: %ERROR% +message.amount-and-price-not-number=&cAnzahl und Preise müssen Zahlen sein. +message.amount-is-zero=&cAnzahl muss größer als 0 sein. +message.prices-contain-decimals=&cPreise dürfen keine Dezimalen enthalten. +message.no-item-in-hand=&cKein Item in der Hand. +message.click-chest-to-create-shop=&aKlicke innerhalb von 15 Sekunden auf eine Truhe, um einen Shop zu erstellen. +message.click-chest-to-remove-shop=&aKlicke innerhalb von 15 Sekunden auf einen Shop, um ihn zu entfernen. +message.click-chest-for-info=&aKlicke innerhalb von 15 Sekunden auf einen Shop, um Informationen über ihn zu bekommen. +message.click-chest-to-open-shop=&Klicke innerhalb von 15 Sekunden auf einen Shop, um ihn zu öffnen. +message.click-to-confirm=&aKlicke noch einmal zum Bestätigen. +message.opened-shop=&aDu hast &6%VENDOR%&as Shop geöffnet. +message.cannot-break-shop=&cDu kannst einen Shop nicht zerstören. +message.cannot-sell-broken-item=&cDu kannst kein kaputtes Artikel verkaufen. +message.buy-price-too-low=&cDer Kaufpreis muss höher sein als %MIN-PRICE%. +message.sell-price-too-low=&cDer Verkaufspreis muss höher sein als %MIN-PRICE%. +message.buy-price-too-high=&cDer Kaufpreis muss geringer sein als %MAX-PRICE%. +message.sell-price-too-high=&cDer Verkaufspreis muss geringer sein als %MAX-PRICE%. +message.buying-disabled=&cKaufen ist an diesem Shop nicht möglich. +message.selling-disabled=&cVerkaufen ist an diesem Shop nicht möglich. +message.reloaded-shops=&a%AMOUNT% Shop/s wurden erfolgreich neu geladen. +message.shop-limit-reached=&cDu hast dein Limit von &6%LIMIT% &cShop/s erreicht. +message.occupied-shop-slots=&6Du hast &c%AMOUNT%/%LIMIT% &6Shop Slot/s benutzt. +message.cannot-sell-item=&cDu kannst für diesen Artikel keinen Shop erstellen. +message.use-in-creative=&cDu kannst im Kreativ-Modus keine Shops benutzen. +message.select-item=&aÖffne dein Inventar und lass ein Item fallen, um es auszuwählen. +message.item-selected=&aItem wurde ausgewählt: &6%ITEMNAME% +message.creation-cancelled=&cShoperstellung wurde abgebrochen. +message.update.update-available=&6&lVersion &c&l%VERSION% &6&lvon &c&lShopChest &6&list verfügbar. +message.update.click-to-download=Klicke hier zum Herunterladen +message.update.no-update=&6&lKeine neue Aktualisierung verfügbar. +message.update.checking=&6&lSuche nach Aktualisierungen... +message.update.error=&c&lFehler beim Suchen nach Aktualisierungen. +message.noPermission.create=&cDu hast keine Berechtigung einen Shop zu erstellen. +message.noPermission.create-admin=&cDu hast keine Berechtigung einen Admin-Shop zu erstellen. +message.noPermission.create-protected=&cDu hast keine Berechtigung hier einen Shop zu erstellen. +message.noPermission.open-others=&cDu hast keine Berechtigung diesen Shop zu öffnen. +message.noPermission.buy=&cDu hast keine Berechtigung etwas zu kaufen. +message.noPermission.sell=&cDu hast keine Berechtigung etwas zu verkaufen. +message.noPermission.buy-here=&cDu hast keine Berechtigung hier etwas zu kaufen. +message.noPermission.sell-here=&cDu hast keine Berechtigung hier etwas zu verkaufen. +message.noPermission.remove-others=&cDu hast keine Berechtigung diesen Shop zu entfernen. +message.noPermission.remove-admin=&cDu hast keine Berechtigung einen Admin Shop zu entfernen. +message.noPermission.reload=&cDu hast keine Berechtigung die Shops neu zu laden. +message.noPermission.update=&cDu hast keine Berechtigung nach Aktualisierungen zu suchen. +message.noPermission.config=&cDu hast keine Berechtigung Konfigurationswerte zu verändern. +message.noPermission.extend-others=&cDu hast keine Berechtigung diesen Shop zu erweitern. +message.noPermission.extend-protected=&cDu hast keine Berechtigung diesen Shop nach hier zu erweitern. +message.commandDescription.header=&6==== &c/%COMMAND% &6Hilfe +message.commandDescription.footer=&6==== Ende +message.commandDescription.create=&a/%COMMAND% create - Erstelle einen Shop. +message.commandDescription.create-admin=&a/%COMMAND% create [admin] - Erstelle einen Shop. +message.commandDescription.remove=&a/%COMMAND% remove - Entferne einen Shop. +message.commandDescription.info=&a/%COMMAND% info - Rufe Informationen über den Shop ab. +message.commandDescription.removeall=&a/%COMMAND% removeall - Entferne alle Shops eines Spielers. +message.commandDescription.reload=&a/%COMMAND% reload - Lade die Shops neu. +message.commandDescription.update=&a/%COMMAND% update - Suche nach Aktualisierungen. +message.commandDescription.limits=&a/%COMMAND% limits - Betrachte die Shop Limits. +message.commandDescription.open=&a/%COMMAND% open - Öffne einen Shop. +message.commandDescription.config=&a/%COMMAND% config - Verändere Konfigurationswerte. +message.config.set=&6Eigenschaft &a%PROPERTY% &6wurde auf &a%VALUE% &6gesetzt. +message.config.added=&6Wert &a%VALUE% &6wurde zu &a%PROPERTY% &6hinzugefügt. +message.config.removed=&6Wert &a%VALUE% &6wurde aus &a%PROPERTY% &6entfernt. + +book.generation.0=Original +book.generation.1=Kopie des Originals +book.generation.2=Kopie einer Kopie +book.generation.3=Zerrissen +effect.damageBoost=Stärke +effect.fireResistance=Feuerschutz +effect.harm=Direktschaden +effect.heal=Direktheilung +effect.invisibility=Unsichtbarkeit +effect.jump=Sprungkraft +effect.luck=Glück +effect.moveSlowdown=Langsamkeit +effect.moveSpeed=Schnelligkeit +effect.nightVision=Nachtsicht +effect.poison=Vergiftung +effect.regeneration=Regeneration +effect.waterBreathing=Unterwasseratem +effect.weakness=Schwäche +enchantment.arrowDamage=Stärke +enchantment.arrowFire=Flamme +enchantment.arrowInfinite=Unendlich +enchantment.arrowKnockback=Schlag +enchantment.binding_curse=Fluch der Bindung +enchantment.damage.all=Schärfe +enchantment.damage.arthropods=Nemesis der Gliederfüßer +enchantment.damage.undead=Bann +enchantment.digging=Effizienz +enchantment.durability=Haltbarkeit +enchantment.fire=Verbrennung +enchantment.fishingSpeed=Köder +enchantment.frostWalker=Eisläufer +enchantment.knockback=Rückstoß +enchantment.level.1=I +enchantment.level.10=X +enchantment.level.2=II +enchantment.level.3=III +enchantment.level.4=IV +enchantment.level.5=V +enchantment.level.6=VI +enchantment.level.7=VII +enchantment.level.8=VIII +enchantment.level.9=IX +enchantment.lootBonus=Plünderung +enchantment.lootBonusDigger=Glück +enchantment.lootBonusFishing=Glück des Meeres +enchantment.mending=Reparatur +enchantment.oxygen=Atmung +enchantment.protect.all=Schutz +enchantment.protect.explosion=Explosionsschutz +enchantment.protect.fall=Federfall +enchantment.protect.fire=Feuerschutz +enchantment.protect.projectile=Schusssicher +enchantment.sweeping=Schwungkraft +enchantment.thorns=Dornen +enchantment.untouching=Behutsamkeit +enchantment.vanishing_curse=Fluch des Verschwindens +enchantment.waterWalker=Wasserläufer +enchantment.waterWorker=Wasseraffinität +entity.Bat.name=Fledermaus +entity.Blaze.name=Lohe +entity.CaveSpider.name=Höhlenspinne +entity.Chicken.name=Huhn +entity.Cow.name=Kuh +entity.Creeper.name=Creeper +entity.Donkey.name=Esel +entity.ElderGuardian.name=Großer Wächter +entity.Enderman.name=Enderman +entity.Endermite.name=Endermite +entity.EntityHorse.name=Pferd +entity.EvocationIllager.name=Magier +entity.Ghast.name=Ghast +entity.Guardian.name=Wächter +entity.Horse.name=Pferd +entity.Husk.name=Wüstenzombie +entity.IllusionIllager.name=Illusionist +entity.LavaSlime.name=Magmawürfel +entity.Llama.name=Lama +entity.Mule.name=Maultier +entity.MushroomCow.name=Mooshroom +entity.Ozelot.name=Ozelot +entity.Parrot.name=Papagei +entity.Pig.name=Schwein +entity.PigZombie.name=Schweinezombie +entity.PolarBear.name=Eisbär +entity.Rabbit.name=Kaninchen +entity.Sheep.name=Schaf +entity.Shulker.name=Shulker +entity.Silverfish.name=Silberfischchen +entity.Skeleton.name=Skelett +entity.SkeletonHorse.name=Skelettpferd +entity.Slime.name=Schleim +entity.Spider.name=Spinne +entity.Squid.name=Tintenfisch +entity.Stray.name=Eiswanderer +entity.Vex.name=Plagegeist +entity.Villager.name=Dorfbewohner +entity.VindicationIllager.name=Diener +entity.Witch.name=Hexe +entity.WitherSkeleton.name=Witherskelett +entity.Wolf.name=Wolf +entity.Zombie.name=Zombie +entity.ZombieHorse.name=Zombiepferd +entity.ZombieVillager.name=Dorfbewohnerzombie +item.apple.name=Apfel +item.appleGold.name=Goldener Apfel +item.armorStand.name=Rüstungsständer +item.arrow.name=Pfeil +item.banner.black.name=Schwarzes Banner +item.banner.blue.name=Blaues Banner +item.banner.brown.name=Braunes Banner +item.banner.cyan.name=Türkises Banner +item.banner.gray.name=Graues Banner +item.banner.green.name=Grünes Banner +item.banner.lightBlue.name=Hellblaues Banner +item.banner.lime.name=Hellgrünes Banner +item.banner.magenta.name=Magenta Banner +item.banner.orange.name=Oranges Banner +item.banner.pink.name=Rosa Banner +item.banner.purple.name=Violettes Banner +item.banner.red.name=Rotes Banner +item.banner.silver.name=Hellgraues Banner +item.banner.white.name=Weißes Banner +item.banner.yellow.name=Gelbes Banner +item.bed.black.name=Schwarzes Bett +item.bed.blue.name=Blaues Bett +item.bed.brown.name=Braunes Bett +item.bed.cyan.name=Türkises Bett +item.bed.gray.name=Graues Bett +item.bed.green.name=Grünes Bett +item.bed.lightBlue.name=Hellblaues Bett +item.bed.lime.name=Hellgrünes Bett +item.bed.magenta.name=Magenta Bett +item.bed.name=Bett +item.bed.orange.name=Oranges Bett +item.bed.pink.name=Rosa Bett +item.bed.purple.name=Violettes Bett +item.bed.red.name=Rotes Bett +item.bed.silver.name=Hellgraues Bett +item.bed.white.name=Weißes Bett +item.bed.yellow.name=Gelbes Bett +item.beefCooked.name=Steak +item.beefRaw.name=Rohes Rindfleisch +item.beetroot.name=Rote Bete +item.beetroot_seeds.name=Rote-Bete-Samen +item.beetroot_soup.name=Borschtsch +item.blazePowder.name=Lohenstaub +item.blazeRod.name=Lohenrute +item.boat.acacia.name=Akazienholzboot +item.boat.birch.name=Birkenholzboot +item.boat.dark_oak.name=Schwarzeichenholzboot +item.boat.jungle.name=Tropenholzboot +item.boat.oak.name=Eichenholzboot +item.boat.spruce.name=Fichtenholzboot +item.bone.name=Knochen +item.book.name=Buch +item.bootsChain.name=Kettenstiefel +item.bootsCloth.name=Lederstiefel +item.bootsDiamond.name=Diamantstiefel +item.bootsGold.name=Goldstiefel +item.bootsIron.name=Eisenstiefel +item.bow.name=Bogen +item.bowl.name=Schüssel +item.bread.name=Brot +item.brewingStand.name=Braustand +item.brick.name=Ziegel +item.bucket.name=Eimer +item.bucketLava.name=Lavaeimer +item.bucketWater.name=Wassereimer +item.cake.name=Kuchen +item.carrotGolden.name=Goldene Karotte +item.carrotOnAStick.name=Karottenrute +item.carrots.name=Karotte +item.cauldron.name=Kessel +item.charcoal.name=Holzkohle +item.chestplateChain.name=Kettenhemd +item.chestplateCloth.name=Lederjacke +item.chestplateDiamond.name=Diamantharnisch +item.chestplateGold.name=Goldharnisch +item.chestplateIron.name=Eisenharnisch +item.chickenCooked.name=Gebratenes Hühnchen +item.chickenRaw.name=Rohes Hühnchen +item.chorusFruit.name=Chorusfrucht +item.chorusFruitPopped.name=Geplatzte Chorusfrucht +item.clay.name=Tonklumpen +item.clock.name=Uhr +item.coal.name=Kohle +item.comparator.name=Redstone-Komparator +item.compass.name=Kompass +item.cookie.name=Keks +item.diamond.name=Diamant +item.diode.name=Redstone-Verstärker +item.doorAcacia.name=Akazienholztür +item.doorBirch.name=Birkenholztür +item.doorDarkOak.name=Schwarzeichenholztür +item.doorIron.name=Eisentür +item.doorJungle.name=Tropenholztür +item.doorOak.name=Eichenholztür +item.doorSpruce.name=Fichtenholztür +item.dragon_breath.name=Drachenatem +item.dyePowder.black.name=Tintenbeutel +item.dyePowder.blue.name=Lapislazuli +item.dyePowder.brown.name=Kakaobohnen +item.dyePowder.cyan.name=Türkiser Farbstoff +item.dyePowder.gray.name=Grauer Farbstoff +item.dyePowder.green.name=Kaktusgrün +item.dyePowder.lightBlue.name=Hellblauer Farbstoff +item.dyePowder.lime.name=Hellgrüner Farbstoff +item.dyePowder.magenta.name=Magenta Farbstoff +item.dyePowder.orange.name=Oranger Farbstoff +item.dyePowder.pink.name=Rosa Farbstoff +item.dyePowder.purple.name=Violetter Farbstoff +item.dyePowder.red.name=Roter Farbstoff +item.dyePowder.silver.name=Hellgrauer Farbstoff +item.dyePowder.white.name=Knochenmehl +item.dyePowder.yellow.name=Gelber Farbstoff +item.egg.name=Ei +item.elytra.name=Elytren +item.emerald.name=Smaragd +item.emptyMap.name=Leere Karte +item.enchantedBook.name=Verzaubertes Buch +item.end_crystal.name=Enderkristall +item.enderPearl.name=Enderperle +item.expBottle.name=Erfahrungsfläschchen +item.eyeOfEnder.name=Enderauge +item.feather.name=Feder +item.fermentedSpiderEye.name=Fermentiertes Spinnenauge +item.fireball.name=Feuerkugel +item.fireworks.name=Feuerwerksrakete +item.fireworksCharge.name=Feuerwerksstern +item.fish.clownfish.raw.name=Clownfisch +item.fish.cod.cooked.name=Gebratener Kabeljau +item.fish.cod.raw.name=Roher Kabeljau +item.fish.pufferfish.raw.name=Kugelfisch +item.fish.salmon.cooked.name=Gebratener Lachs +item.fish.salmon.raw.name=Roher Lachs +item.fishingRod.name=Angel +item.flint.name=Feuerstein +item.flintAndSteel.name=Feuerzeug +item.flowerPot.name=Blumentopf +item.frame.name=Rahmen +item.ghastTear.name=Ghastträne +item.glassBottle.name=Glasflasche +item.goldNugget.name=Goldklumpen +item.hatchetDiamond.name=Diamantaxt +item.hatchetGold.name=Goldaxt +item.hatchetIron.name=Eisenaxt +item.hatchetStone.name=Steinaxt +item.hatchetWood.name=Holzaxt +item.helmetChain.name=Kettenhaube +item.helmetCloth.name=Lederkappe +item.helmetDiamond.name=Diamanthelm +item.helmetGold.name=Goldhelm +item.helmetIron.name=Eisenhelm +item.hoeDiamond.name=Diamanthacke +item.hoeGold.name=Goldhacke +item.hoeIron.name=Eisenhacke +item.hoeStone.name=Steinhacke +item.hoeWood.name=Holzhacke +item.horsearmordiamond.name=Diamantene Pferderüstung +item.horsearmorgold.name=Goldene Pferderüstung +item.horsearmormetal.name=Eiserne Pferderüstung +item.ingotGold.name=Goldbarren +item.ingotIron.name=Eisenbarren +item.ironNugget.name=Eisenklumpen +item.knowledgeBook.name=Buch des Wissens +item.leash.name=Leine +item.leather.name=Leder +item.leggingsChain.name=Kettenhose +item.leggingsCloth.name=Lederhose +item.leggingsDiamond.name=Diamantbeinschutz +item.leggingsGold.name=Goldbeinschutz +item.leggingsIron.name=Eisenbeinschutz +item.magmaCream.name=Magmacreme +item.map.name=Karte +item.melon.name=Melonenscheibe +item.milk.name=Milch +item.minecart.name=Lore +item.minecartChest.name=Güterlore +item.minecartCommandBlock.name=Befehlsblocklore +item.minecartFurnace.name=Antriebslore +item.minecartHopper.name=Trichterlore +item.minecartTnt.name=TNT-Lore +item.monsterPlacer.name=Erschaffe +item.mushroomStew.name=Pilzsuppe +item.muttonCooked.name=Gebratenes Hammelfleisch +item.muttonRaw.name=Rohes Hammelfleisch +item.nameTag.name=Namensschild +item.netherStalkSeeds.name=Netherwarze +item.netherStar.name=Netherstern +item.netherbrick.name=Netherziegel +item.netherquartz.name=Netherquarz +item.painting.name=Gemälde +item.paper.name=Papier +item.pickaxeDiamond.name=Diamantspitzhacke +item.pickaxeGold.name=Goldspitzhacke +item.pickaxeIron.name=Eisenspitzhacke +item.pickaxeStone.name=Steinspitzhacke +item.pickaxeWood.name=Holzspitzhacke +item.porkchopCooked.name=Gebratenes Schweinefleisch +item.porkchopRaw.name=Rohes Schweinefleisch +item.potato.name=Kartoffel +item.potatoBaked.name=Ofenkartoffel +item.potatoPoisonous.name=Giftige Kartoffel +item.potion.name=Trank +item.prismarineCrystals.name=Prismarinkristalle +item.prismarineShard.name=Prismarinscherbe +item.pumpkinPie.name=Kürbiskuchen +item.rabbitCooked.name=Gebratenes Kaninchen +item.rabbitFoot.name=Hasenpfote +item.rabbitHide.name=Kaninchenfell +item.rabbitRaw.name=Rohes Kaninchen +item.rabbitStew.name=Kaninchenragout +item.record.11.desc=C418 - 11 +item.record.13.desc=C418 - 13 +item.record.blocks.desc=C418 - Blocks +item.record.cat.desc=C418 - Cat +item.record.chirp.desc=C418 - Chirp +item.record.far.desc=C418 - Far +item.record.mall.desc=C418 - Mall +item.record.mellohi.desc=C418 - Mellohi +item.record.name=Schallplatte +item.record.stal.desc=C418 - Stal +item.record.strad.desc=C418 - Strad +item.record.wait.desc=C418 - Wait +item.record.ward.desc=C418 - Ward +item.redstone.name=Redstone +item.reeds.name=Zuckerrohr +item.rottenFlesh.name=Verrottetes Fleisch +item.saddle.name=Sattel +item.seeds.name=Weizenkörner +item.seeds_melon.name=Melonenkerne +item.seeds_pumpkin.name=Kürbiskerne +item.shears.name=Schere +item.shield.name=Schild +item.shovelDiamond.name=Diamantschaufel +item.shovelGold.name=Goldschaufel +item.shovelIron.name=Eisenschaufel +item.shovelStone.name=Steinschaufel +item.shovelWood.name=Holzschaufel +item.shulkerShell.name=Shulkerschale +item.sign.name=Schild +item.skull.char.name=Kopf +item.skull.creeper.name=Creeperkopf +item.skull.dragon.name=Drachenkopf +item.skull.skeleton.name=Skelettschädel +item.skull.wither.name=Witherskelettschädel +item.skull.zombie.name=Zombiekopf +item.slimeball.name=Schleimball +item.snowball.name=Schneeball +item.speckledMelon.name=Glitzernde Melonenscheibe +item.spectral_arrow.name=Spektralpfeil +item.spiderEye.name=Spinnenauge +item.stick.name=Stock +item.string.name=Faden +item.sugar.name=Zucker +item.sulphur.name=Schwarzpulver +item.swordDiamond.name=Diamantschwert +item.swordGold.name=Goldschwert +item.swordIron.name=Eisenschwert +item.swordStone.name=Steinschwert +item.swordWood.name=Holzschwert +item.tipped_arrow.name=Getränkter Pfeil +item.totem.name=Totem der Unsterblichkeit +item.wheat.name=Weizen +item.writingBook.name=Buch und Feder +item.writtenBook.name=Beschriebenes Buch +item.yellowDust.name=Glowstonestaub +lingering_potion.effect.awkward=Seltsamer Verweiltrank +lingering_potion.effect.empty=Nicht braubarer Verweiltrank +lingering_potion.effect.fire_resistance=Verweiltrank der Feuerresistenz +lingering_potion.effect.harming=Verweiltrank des Schadens +lingering_potion.effect.healing=Verweiltrank der Heilung +lingering_potion.effect.invisibility=Verweiltrank der Unsichtbarkeit +lingering_potion.effect.leaping=Verweiltrank der Sprungkraft +lingering_potion.effect.luck=Verweiltrank des Glücks +lingering_potion.effect.mundane=Gewöhnlicher Verweiltrank +lingering_potion.effect.night_vision=Verweiltrank der Nachtsicht +lingering_potion.effect.poison=Verweiltrank der Vergiftung +lingering_potion.effect.regeneration=Verweiltrank der Regeneration +lingering_potion.effect.slowness=Verweiltrank der Langsamkeit +lingering_potion.effect.strength=Verweiltrank der Stärke +lingering_potion.effect.swiftness=Verweiltrank der Schnelligkeit +lingering_potion.effect.thick=Dickflüssiger Verweiltrank +lingering_potion.effect.water=Verweilende Wasserflasche +lingering_potion.effect.water_breathing=Verweiltrank der Unterwasseratmung +lingering_potion.effect.weakness=Verweiltrank der Schwäche +potion.effect.awkward=Seltsamer Trank +potion.effect.empty=Nicht braubarer Trank +potion.effect.fire_resistance=Trank der Feuerresistenz +potion.effect.harming=Trank des Schadens +potion.effect.healing=Trank der Heilung +potion.effect.invisibility=Trank der Unsichtbarkeit +potion.effect.leaping=Trank der Sprungkraft +potion.effect.luck=Trank des Glücks +potion.effect.mundane=Gewöhnlicher Trank +potion.effect.night_vision=Trank der Nachtsicht +potion.effect.poison=Trank der Vergiftung +potion.effect.regeneration=Trank der Regeneration +potion.effect.slowness=Trank der Langsamkeit +potion.effect.strength=Trank der Stärke +potion.effect.swiftness=Trank der Schnelligkeit +potion.effect.thick=Dickflüssiger Trank +potion.effect.water=Wasserflasche +potion.effect.water_breathing=Trank der Unterwasseratmung +potion.effect.weakness=Trank der Schwäche +splash_potion.effect.awkward=Seltsamer Wurftrank +splash_potion.effect.empty=Nicht braubarer Wurftrank +splash_potion.effect.fire_resistance=Wurftrank der Feuerresistenz +splash_potion.effect.harming=Wurftrank des Schadens +splash_potion.effect.healing=Wurftrank der Heilung +splash_potion.effect.invisibility=Wurftrank der Unsichtbarkeit +splash_potion.effect.leaping=Wurftrank der Sprungkraft +splash_potion.effect.luck=Wurftrank des Glücks +splash_potion.effect.mundane=Gewöhnlicher Wurftrank +splash_potion.effect.night_vision=Wurftrank der Nachtsicht +splash_potion.effect.poison=Wurftrank der Vergiftung +splash_potion.effect.regeneration=Wurftrank der Regeneration +splash_potion.effect.slowness=Wurftrank der Langsamkeit +splash_potion.effect.strength=Wurftrank der Stärke +splash_potion.effect.swiftness=Wurftrank der Schnelligkeit +splash_potion.effect.thick=Dickflüssiger Wurftrank +splash_potion.effect.water=Werfbare Wasserflasche +splash_potion.effect.water_breathing=Wurftrank der Unterwasseratmung +splash_potion.effect.weakness=Wurftrank der Schwäche +tile.acaciaFence.name=Akazienholzzaun +tile.acaciaFenceGate.name=Akazienholzzauntor +tile.activatorRail.name=Aktivierungsschiene +tile.anvil.intact.name=Amboss +tile.anvil.slightlyDamaged.name=Leicht beschädigter Amboss +tile.anvil.veryDamaged.name=Stark beschädigter Amboss +tile.barrier.name=Barriere +tile.beacon.name=Leuchtfeuer +tile.bedrock.name=Grundgestein +tile.birchFence.name=Birkenholzzaun +tile.birchFenceGate.name=Birkenholzzauntor +tile.blockCoal.name=Kohleblock +tile.blockDiamond.name=Diamantblock +tile.blockEmerald.name=Smaragdblock +tile.blockGold.name=Goldblock +tile.blockIron.name=Eisenblock +tile.blockLapis.name=Lapislazuliblock +tile.blockRedstone.name=Redstone-Block +tile.boneBlock.name=Knochenblock +tile.bookshelf.name=Bücherregal +tile.brick.name=Ziegelsteine +tile.button.name=Knopf +tile.cactus.name=Kaktus +tile.chainCommandBlock.name=Ketten-Befehlsblock +tile.chest.name=Truhe +tile.chestTrap.name=Redstone-Truhe +tile.chorusFlower.name=Chorusblüte +tile.chorusPlant.name=Choruspflanze +tile.clay.name=Ton +tile.clayHardened.name=Keramik +tile.clayHardenedStained.black.name=Schwarze Keramik +tile.clayHardenedStained.blue.name=Blaue Keramik +tile.clayHardenedStained.brown.name=Braune Keramik +tile.clayHardenedStained.cyan.name=Türkise Keramik +tile.clayHardenedStained.gray.name=Graue Keramik +tile.clayHardenedStained.green.name=Grüne Keramik +tile.clayHardenedStained.lightBlue.name=Hellblaue Keramik +tile.clayHardenedStained.lime.name=Hellgrüne Keramik +tile.clayHardenedStained.magenta.name=Magenta Keramik +tile.clayHardenedStained.orange.name=Orange Keramik +tile.clayHardenedStained.pink.name=Rosa Keramik +tile.clayHardenedStained.purple.name=Violette Keramik +tile.clayHardenedStained.red.name=Rote Keramik +tile.clayHardenedStained.silver.name=Hellgraue Keramik +tile.clayHardenedStained.white.name=Weiße Keramik +tile.clayHardenedStained.yellow.name=Gelbe Keramik +tile.cloth.black.name=Schwarze Wolle +tile.cloth.blue.name=Blaue Wolle +tile.cloth.brown.name=Braune Wolle +tile.cloth.cyan.name=Türkise Wolle +tile.cloth.gray.name=Graue Wolle +tile.cloth.green.name=Grüne Wolle +tile.cloth.lightBlue.name=Hellblaue Wolle +tile.cloth.lime.name=Hellgrüne Wolle +tile.cloth.magenta.name=Magenta Wolle +tile.cloth.orange.name=Orange Wolle +tile.cloth.pink.name=Rosa Wolle +tile.cloth.purple.name=Violette Wolle +tile.cloth.red.name=Rote Wolle +tile.cloth.silver.name=Hellgraue Wolle +tile.cloth.white.name=Weiße Wolle +tile.cloth.yellow.name=Gelbe Wolle +tile.cobbleWall.mossy.name=Bemooste Bruchsteinmauer +tile.cobbleWall.normal.name=Bruchsteinmauer +tile.commandBlock.name=Befehlsblock +tile.concrete.black.name=Schwarzer Beton +tile.concrete.blue.name=Blauer Beton +tile.concrete.brown.name=Brauner Beton +tile.concrete.cyan.name=Türkiser Beton +tile.concrete.gray.name=Grauer Beton +tile.concrete.green.name=Grüner Beton +tile.concrete.lightBlue.name=Hellblauer Beton +tile.concrete.lime.name=Hellgrüner Beton +tile.concrete.magenta.name=Magenta Beton +tile.concrete.orange.name=Oranger Beton +tile.concrete.pink.name=Rosa Beton +tile.concrete.purple.name=Violetter Beton +tile.concrete.red.name=Roter Beton +tile.concrete.silver.name=Hellgrauer Beton +tile.concrete.white.name=Weißer Beton +tile.concrete.yellow.name=Gelber Beton +tile.concretePowder.black.name=Schwarzer Trockenbeton +tile.concretePowder.blue.name=Blauer Trockenbeton +tile.concretePowder.brown.name=Brauner Trockenbeton +tile.concretePowder.cyan.name=Türkiser Trockenbeton +tile.concretePowder.gray.name=Grauer Trockenbeton +tile.concretePowder.green.name=Grüner Trockenbeton +tile.concretePowder.lightBlue.name=Hellblauer Trockenbeton +tile.concretePowder.lime.name=Hellgrüner Trockenbeton +tile.concretePowder.magenta.name=Magenta Trockenbeton +tile.concretePowder.orange.name=Oranger Trockenbeton +tile.concretePowder.pink.name=Rosa Trockenbeton +tile.concretePowder.purple.name=Violetter Trockenbeton +tile.concretePowder.red.name=Roter Trockenbeton +tile.concretePowder.silver.name=Hellgrauer Trockenbeton +tile.concretePowder.white.name=Weißer Trockenbeton +tile.concretePowder.yellow.name=Gelber Trockenbeton +tile.darkOakFence.name=Schwarzeichenholzzaun +tile.darkOakFenceGate.name=Schwarzeichenholzzauntor +tile.daylightDetector.name=Tageslichtsensor +tile.deadbush.name=Toter Busch +tile.detectorRail.name=Sensorschiene +tile.dirt.coarse.name=Grobe Erde +tile.dirt.default.name=Erde +tile.dirt.podzol.name=Podsol +tile.dispenser.name=Werfer +tile.doublePlant.fern.name=Großer Farn +tile.doublePlant.grass.name=Hohes Gras +tile.doublePlant.paeonia.name=Pfingstrose +tile.doublePlant.rose.name=Rosenstrauch +tile.doublePlant.sunflower.name=Sonnenblume +tile.doublePlant.syringa.name=Flieder +tile.dragonEgg.name=Drachenei +tile.dropper.name=Spender +tile.enchantmentTable.name=Zaubertisch +tile.endBricks.name=Endsteinziegel +tile.endPortalFrame.name=Endportalrahmen +tile.endRod.name=Endstab +tile.enderChest.name=Endertruhe +tile.farmland.name=Ackerboden +tile.fence.name=Eichenholzzaun +tile.fenceGate.name=Eichenholzzauntor +tile.fenceIron.name=Eisengitter +tile.fire.name=Feuer +tile.flower1.dandelion.name=Löwenzahn +tile.flower2.allium.name=Sternlauch +tile.flower2.blueOrchid.name=Blaue Orchidee +tile.flower2.houstonia.name=Porzellansternchen +tile.flower2.oxeyeDaisy.name=Margerite +tile.flower2.poppy.name=Mohn +tile.flower2.tulipOrange.name=Orange Tulpe +tile.flower2.tulipPink.name=Rosa Tulpe +tile.flower2.tulipRed.name=Rote Tulpe +tile.flower2.tulipWhite.name=Weiße Tulpe +tile.furnace.name=Ofen +tile.glass.name=Glas +tile.glazedTerracottaBlack.name=Schwarze glasierte Keramik +tile.glazedTerracottaBlue.name=Blaue glasierte Keramik +tile.glazedTerracottaBrown.name=Braune glasierte Keramik +tile.glazedTerracottaCyan.name=Türkise glasierte Keramik +tile.glazedTerracottaGray.name=Graue glasierte Keramik +tile.glazedTerracottaGreen.name=Grüne glasierte Keramik +tile.glazedTerracottaLightBlue.name=Hellblaue glasierte Keramik +tile.glazedTerracottaLime.name=Hellgrüne glasierte Keramik +tile.glazedTerracottaMagenta.name=Magenta glasierte Keramik +tile.glazedTerracottaOrange.name=Orange glasierte Keramik +tile.glazedTerracottaPink.name=Rosa glasierte Keramik +tile.glazedTerracottaPurple.name=Violette glasierte Keramik +tile.glazedTerracottaRed.name=Rote glasierte Keramik +tile.glazedTerracottaSilver.name=Hellgraue glasierte Keramik +tile.glazedTerracottaWhite.name=Weiße glasierte Keramik +tile.glazedTerracottaYellow.name=Gelbe glasierte Keramik +tile.goldenRail.name=Antriebsschiene +tile.grass.name=Grasblock +tile.grassPath.name=Trampelpfad +tile.gravel.name=Kies +tile.hayBlock.name=Strohballen +tile.hellrock.name=Netherrack +tile.hellsand.name=Seelensand +tile.hopper.name=Trichter +tile.ice.name=Eis +tile.icePacked.name=Packeis +tile.ironTrapdoor.name=Eisenfalltür +tile.jukebox.name=Plattenspieler +tile.jungleFence.name=Tropenholzzaun +tile.jungleFenceGate.name=Tropenholzzauntor +tile.ladder.name=Leiter +tile.lava.name=Lava +tile.leaves.acacia.name=Akazienlaub +tile.leaves.big_oak.name=Schwarzeichenlaub +tile.leaves.birch.name=Birkenlaub +tile.leaves.jungle.name=Tropenbaumlaub +tile.leaves.oak.name=Eichenlaub +tile.leaves.spruce.name=Fichtennadeln +tile.lever.name=Hebel +tile.lightgem.name=Glowstone +tile.litpumpkin.name=Kürbislaterne +tile.log.acacia.name=Akazienholz +tile.log.big_oak.name=Schwarzeichenholz +tile.log.birch.name=Birkenholz +tile.log.jungle.name=Tropenholz +tile.log.oak.name=Eichenholz +tile.log.spruce.name=Fichtenholz +tile.magma.name=Magmablock +tile.melon.name=Melone +tile.mobSpawner.name=Monsterspawner +tile.monsterStoneEgg.brick.name=Steinziegel (Silberfischchen) +tile.monsterStoneEgg.chiseledbrick.name=Gemeißelte Steinziegel (Silberfischchen) +tile.monsterStoneEgg.cobble.name=Bruchstein (Silberfischchen) +tile.monsterStoneEgg.crackedbrick.name=Rissige Steinziegel (Silberfischchen) +tile.monsterStoneEgg.mossybrick.name=Bemooste Steinziegel (Silberfischchen) +tile.monsterStoneEgg.stone.name=Stein (Silberfischchen) +tile.mushroom.name=Pilz +tile.musicBlock.name=Notenblock +tile.mycel.name=Myzel +tile.netherBrick.name=Netherziegel +tile.netherFence.name=Netherziegelzaun +tile.netherStalk.name=Netherwarze +tile.netherWartBlock.name=Netherwarzenblock +tile.netherquartz.name=Netherquarzerz +tile.notGate.name=Redstone-Fackel +tile.observer.name=Beobachter +tile.obsidian.name=Obsidian +tile.oreCoal.name=Steinkohle +tile.oreDiamond.name=Diamanterz +tile.oreEmerald.name=Smaragderz +tile.oreGold.name=Golderz +tile.oreIron.name=Eisenerz +tile.oreLapis.name=Lapislazulierz +tile.oreRedstone.name=Redstone-Erz +tile.pistonBase.name=Kolben +tile.pistonStickyBase.name=Klebriger Kolben +tile.portal.name=Portal +tile.pressurePlateStone.name=Steindruckplatte +tile.pressurePlateWood.name=Holzdruckplatte +tile.prismarine.bricks.name=Prismarinziegel +tile.prismarine.dark.name=Dunkler Prismarin +tile.prismarine.rough.name=Prismarin +tile.pumpkin.name=Kürbis +tile.purpurBlock.name=Purpurblock +tile.purpurPillar.name=Purpursäule +tile.purpurSlab.name=Purpurstufe +tile.quartzBlock.chiseled.name=Gemeißelter Quarzblock +tile.quartzBlock.default.name=Quarzblock +tile.quartzBlock.lines.name=Quarzsäule +tile.rail.name=Schiene +tile.redNetherBrick.name=Rote Netherziegel +tile.redSandStone.chiseled.name=Gemeißelter roter Sandstein +tile.redSandStone.default.name=Roter Sandstein +tile.redSandStone.smooth.name=Glatter roter Sandstein +tile.redstoneLight.name=Redstone-Lampe +tile.repeatingCommandBlock.name=Wiederhol-Befehlsblock +tile.sand.default.name=Sand +tile.sand.red.name=Roter Sand +tile.sandStone.chiseled.name=Gemeißelter Sandstein +tile.sandStone.default.name=Sandstein +tile.sandStone.smooth.name=Glatter Sandstein +tile.sapling.acacia.name=Akaziensetzling +tile.sapling.big_oak.name=Schwarzeichensetzling +tile.sapling.birch.name=Birkensetzling +tile.sapling.jungle.name=Tropenbaumsetzling +tile.sapling.oak.name=Eichensetzling +tile.sapling.spruce.name=Fichtensetzling +tile.seaLantern.name=Seelaterne +tile.shulkerBoxBlack.name=Schwarze Shulkerkiste +tile.shulkerBoxBlue.name=Blaue Shulkerkiste +tile.shulkerBoxBrown.name=Braune Shulkerkiste +tile.shulkerBoxCyan.name=Türkise Shulkerkiste +tile.shulkerBoxGray.name=Graue Shulkerkiste +tile.shulkerBoxGreen.name=Grüne Shulkerkiste +tile.shulkerBoxLightBlue.name=Hellblaue Shulkerkiste +tile.shulkerBoxLime.name=Hellgrüne Shulkerkiste +tile.shulkerBoxMagenta.name=Magenta Shulkerkiste +tile.shulkerBoxOrange.name=Orange Shulkerkiste +tile.shulkerBoxPink.name=Rosa Shulkerkiste +tile.shulkerBoxPurple.name=Violette Shulkerkiste +tile.shulkerBoxRed.name=Rote Shulkerkiste +tile.shulkerBoxSilver.name=Hellgraue Shulkerkiste +tile.shulkerBoxWhite.name=Weiße Shulkerkiste +tile.shulkerBoxYellow.name=Gelbe Shulkerkiste +tile.slime.name=Schleimblock +tile.snow.name=Schnee +tile.sponge.dry.name=Schwamm +tile.sponge.wet.name=Nasser Schwamm +tile.spruceFence.name=Fichtenholzzaun +tile.spruceFenceGate.name=Fichtenholzzauntor +tile.stainedGlass.black.name=Schwarzes Glas +tile.stainedGlass.blue.name=Blaues Glas +tile.stainedGlass.brown.name=Braunes Glas +tile.stainedGlass.cyan.name=Türkises Glas +tile.stainedGlass.gray.name=Graues Glas +tile.stainedGlass.green.name=Grünes Glas +tile.stainedGlass.lightBlue.name=Hellblaues Glas +tile.stainedGlass.lime.name=Hellgrünes Glas +tile.stainedGlass.magenta.name=Magenta Glas +tile.stainedGlass.orange.name=Oranges Glas +tile.stainedGlass.pink.name=Rosa Glas +tile.stainedGlass.purple.name=Violettes Glas +tile.stainedGlass.red.name=Rotes Glas +tile.stainedGlass.silver.name=Hellgraues Glas +tile.stainedGlass.white.name=Weißes Glas +tile.stainedGlass.yellow.name=Gelbes Glas +tile.stairsBrick.name=Ziegeltreppe +tile.stairsNetherBrick.name=Netherziegeltreppe +tile.stairsPurpur.name=Purpurtreppe +tile.stairsQuartz.name=Quarztreppe +tile.stairsRedSandStone.name=Rote Sandsteintreppe +tile.stairsSandStone.name=Sandsteintreppe +tile.stairsStone.name=Bruchsteintreppe +tile.stairsStoneBrickSmooth.name=Steinziegeltreppe +tile.stairsWood.name=Eichenholztreppe +tile.stairsWoodAcacia.name=Akazienholztreppe +tile.stairsWoodBirch.name=Birkenholztreppe +tile.stairsWoodDarkOak.name=Schwarzeichenholztreppe +tile.stairsWoodJungle.name=Tropenholztreppe +tile.stairsWoodSpruce.name=Fichtenholztreppe +tile.stone.andesite.name=Andesit +tile.stone.andesiteSmooth.name=Polierter Andesit +tile.stone.diorite.name=Diorit +tile.stone.dioriteSmooth.name=Polierter Diorit +tile.stone.granite.name=Granit +tile.stone.graniteSmooth.name=Polierter Granit +tile.stone.stone.name=Stein +tile.stoneMoss.name=Bemooster Bruchstein +tile.stoneSlab.brick.name=Ziegelstufe +tile.stoneSlab.cobble.name=Bruchsteinstufe +tile.stoneSlab.netherBrick.name=Netherziegelstufe +tile.stoneSlab.quartz.name=Quarzstufe +tile.stoneSlab.sand.name=Sandsteinstufe +tile.stoneSlab.smoothStoneBrick.name=Steinziegelstufe +tile.stoneSlab.stone.name=Steinstufe +tile.stoneSlab.wood.name=Holzstufe +tile.stoneSlab2.red_sandstone.name=Rote Sandsteinstufe +tile.stonebrick.name=Bruchstein +tile.stonebricksmooth.chiseled.name=Gemeißelte Steinziegel +tile.stonebricksmooth.cracked.name=Rissige Steinziegel +tile.stonebricksmooth.default.name=Steinziegel +tile.stonebricksmooth.mossy.name=Bemooste Steinziegel +tile.structureBlock.name=Konstruktionsblock +tile.structureVoid.name=Konstruktionsleere +tile.tallgrass.fern.name=Farn +tile.tallgrass.grass.name=Gras +tile.tallgrass.shrub.name=Busch +tile.thinGlass.name=Glasscheibe +tile.thinStainedGlass.black.name=Schwarze Glasscheibe +tile.thinStainedGlass.blue.name=Blaue Glasscheibe +tile.thinStainedGlass.brown.name=Braune Glasscheibe +tile.thinStainedGlass.cyan.name=Türkise Glasscheibe +tile.thinStainedGlass.gray.name=Graue Glasscheibe +tile.thinStainedGlass.green.name=Grüne Glasscheibe +tile.thinStainedGlass.lightBlue.name=Hellblaue Glasscheibe +tile.thinStainedGlass.lime.name=Hellgrüne Glasscheibe +tile.thinStainedGlass.magenta.name=Magenta Glasscheibe +tile.thinStainedGlass.orange.name=Orange Glasscheibe +tile.thinStainedGlass.pink.name=Rosa Glasscheibe +tile.thinStainedGlass.purple.name=Violette Glasscheibe +tile.thinStainedGlass.red.name=Rote Glasscheibe +tile.thinStainedGlass.silver.name=Hellgraue Glasscheibe +tile.thinStainedGlass.white.name=Weiße Glasscheibe +tile.thinStainedGlass.yellow.name=Gelbe Glasscheibe +tile.tnt.name=TNT +tile.torch.name=Fackel +tile.trapdoor.name=Holzfalltür +tile.tripWireSource.name=Haken +tile.vine.name=Ranken +tile.water.name=Wasser +tile.waterlily.name=Seerosenblatt +tile.web.name=Spinnennetz +tile.weightedPlate_heavy.name=Wägeplatte (hohe Gewichte) +tile.weightedPlate_light.name=Wägeplatte (niedrige Gewichte) +tile.whiteStone.name=Endstein +tile.wood.acacia.name=Akazienholzbretter +tile.wood.big_oak.name=Schwarzeichenholzbretter +tile.wood.birch.name=Birkenholzbretter +tile.wood.jungle.name=Tropenholzbretter +tile.wood.oak.name=Eichenholzbretter +tile.wood.spruce.name=Fichtenholzbretter +tile.woodSlab.acacia.name=Akazienholzstufe +tile.woodSlab.big_oak.name=Schwarzeichenholzstufe +tile.woodSlab.birch.name=Birkenholzstufe +tile.woodSlab.jungle.name=Tropenholzstufe +tile.woodSlab.oak.name=Eichenholzstufe +tile.woodSlab.spruce.name=Fichtenholzstufe +tile.woolCarpet.black.name=Schwarzer Teppich +tile.woolCarpet.blue.name=Blauer Teppich +tile.woolCarpet.brown.name=Brauner Teppich +tile.woolCarpet.cyan.name=Türkiser Teppich +tile.woolCarpet.gray.name=Grauer Teppich +tile.woolCarpet.green.name=Grüner Teppich +tile.woolCarpet.lightBlue.name=Hellblauer Teppich +tile.woolCarpet.lime.name=Hellgrüner Teppich +tile.woolCarpet.magenta.name=Magenta Teppich +tile.woolCarpet.orange.name=Oranger Teppich +tile.woolCarpet.pink.name=Rosa Teppich +tile.woolCarpet.purple.name=Violetter Teppich +tile.woolCarpet.red.name=Roter Teppich +tile.woolCarpet.silver.name=Hellgrauer Teppich +tile.woolCarpet.white.name=Weißer Teppich +tile.woolCarpet.yellow.name=Gelber Teppich +tile.workbench.name=Werkbank +tipped_arrow.effect.awkward=Getränkter Pfeil +tipped_arrow.effect.empty=Nicht herstellbarer getränkter Pfeil +tipped_arrow.effect.fire_resistance=Pfeil der Feuerresistenz +tipped_arrow.effect.harming=Pfeil des Schadens +tipped_arrow.effect.healing=Pfeil der Heilung +tipped_arrow.effect.invisibility=Pfeil der Unsichtbarkeit +tipped_arrow.effect.leaping=Pfeil der Sprungkraft +tipped_arrow.effect.luck=Pfeil des Glücks +tipped_arrow.effect.mundane=Getränkter Pfeil +tipped_arrow.effect.night_vision=Pfeil der Nachtsicht +tipped_arrow.effect.poison=Pfeil der Vergiftung +tipped_arrow.effect.regeneration=Pfeil der Regeneration +tipped_arrow.effect.slowness=Pfeil der Langsamkeit +tipped_arrow.effect.strength=Pfeil der Stärke +tipped_arrow.effect.swiftness=Pfeil der Schnelligkeit +tipped_arrow.effect.thick=Getränkter Pfeil +tipped_arrow.effect.water=Nasser Pfeil +tipped_arrow.effect.water_breathing=Pfeil der Unterwasseratmung +tipped_arrow.effect.weakness=Pfeil der Schwäche \ No newline at end of file diff --git a/plugin/src/main/resources/lang/de_DE.lang b/plugin/src/main/resources/lang/de_DE.lang new file mode 100644 index 0000000..9d18498 --- /dev/null +++ b/plugin/src/main/resources/lang/de_DE.lang @@ -0,0 +1,1518 @@ +message.shop-created=&6Dir wurden &c%CREATION-PRICE% &6abgenommen, um diesen Shop zu erstellen. +message.admin-shop-created=&6Dir wurden &c%CREATION-PRICE% &6abgenommen, um diesen Admin Shop zu erstellen. +message.chest-already-shop=&cTruhe ist bereits ein Shop. +message.chest-blocked=&cÜber der Truhe ist kein Platz. +message.double-chest-blocked=&cÜber der Truhe ist kein Platz. +message.shop-removed=&6Shop entfernt. +message.shop-removed-refund=&6Shop entfernt. Dir wurden &c%CREATION-PRICE%&6 erstattet. +message.all-shops-removed=&6Alle (&c%AMOUNT%&6) Shops von &c%VENDOR%&6 wurden entfernt. +message.chest-no-shop=&cTruhe ist kein Shop. +message.shop-create-not-enough-money=&cNicht genug Geld. Du brauchst &6%CREATION-PRICE% &cum einen Shop zu erstellen. +message.shopInfo.vendor=&6Verkäufer: &e%VENDOR% +message.shopInfo.product=&6Produkt: &e%AMOUNT% x %ITEMNAME% +message.shopInfo.stock=&6Auf Lager: &e%STOCK% +message.shopInfo.chest-space=&6Platz in Truhe: &e%CHEST-SPACE% +message.shopInfo.price=&6Preis: Kauf: &e%BUY-PRICE%&6 Verkauf: &e%SELL-PRICE% +message.shopInfo.disabled=&7Deaktiviert +message.shopInfo.is-normal=&6Typ: &eNormal +message.shopInfo.is-admin=&6Typ: &eAdmin +message.buy-and-sell-disabled=&cDu kannst keinen Shop ohne Kauf- und Verkaufspreis erstellen. +message.buy-success=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%BUY-PRICE%&a von &6%VENDOR% &agekauft. +message.buy-success-admin=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%BUY-PRICE% &agekauft. +message.sell-success=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE%&a an &6%VENDOR% &averkauft. +message.sell-success-admin=&aDu hast &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE% &averkauft. +message.someone-bought=&6%PLAYER% &ahat &6%AMOUNT% x %ITEMNAME%&a für &6%BUY-PRICE%&a von deinem Shop gekauft. +message.someone-sold=&6%PLAYER% &ahat &6%AMOUNT% x %ITEMNAME%&a für &6%SELL-PRICE%&a an deinen Shop verkauft. +message.revenue-while-offline=&6Während du offline warst, haben deine Shops einen Umsatz von &c%REVENUE%&6 gemacht. +message.not-enough-inventory-space=&cNicht genug Platz im Inventar. +message.chest-not-enough-inventory-space=&cShop ist voll. +message.not-enough-money=&cNicht genug Geld. +message.not-enough-items=&cNicht genug Items. +message.vendor-not-enough-money=&cVerkäufer hat nicht genug Geld. +message.out-of-stock=&cShop ausverkauft. +message.vendor-out-of-stock=&cDein Shop, der &6%AMOUNT% x %ITEMNAME% &cverkauft, ist ausverkauft. +message.error-occurred=&cEin Fehler ist aufgetreten: %ERROR% +message.amount-and-price-not-number=&cAnzahl und Preise müssen Zahlen sein. +message.amount-is-zero=&cAnzahl muss größer als 0 sein. +message.prices-contain-decimals=&cPreise dürfen keine Dezimalen enthalten. +message.no-item-in-hand=&cKein Item in der Hand. +message.click-chest-to-create-shop=&aKlicke innerhalb von 15 Sekunden auf eine Truhe, um einen Shop zu erstellen. +message.click-chest-to-remove-shop=&aKlicke innerhalb von 15 Sekunden auf einen Shop, um ihn zu entfernen. +message.click-chest-for-info=&aKlicke innerhalb von 15 Sekunden auf einen Shop, um Informationen über ihn zu bekommen. +message.click-chest-to-open-shop=&Klicke innerhalb von 15 Sekunden auf einen Shop, um ihn zu öffnen. +message.click-to-confirm=&aKlicke noch einmal zum Bestätigen. +message.opened-shop=&aDu hast &6%VENDOR%&as Shop geöffnet. +message.cannot-break-shop=&cDu kannst einen Shop nicht zerstören. +message.cannot-sell-broken-item=&cDu kannst kein kaputtes Artikel verkaufen. +message.buy-price-too-low=&cDer Kaufpreis muss höher sein als %MIN-PRICE%. +message.sell-price-too-low=&cDer Verkaufspreis muss höher sein als %MIN-PRICE%. +message.buy-price-too-high=&cDer Kaufpreis muss geringer sein als %MAX-PRICE%. +message.sell-price-too-high=&cDer Verkaufspreis muss geringer sein als %MAX-PRICE%. +message.buying-disabled=&cKaufen ist an diesem Shop nicht möglich. +message.selling-disabled=&cVerkaufen ist an diesem Shop nicht möglich. +message.reloaded-shops=&a%AMOUNT% Shop/s wurden erfolgreich neu geladen. +message.shop-limit-reached=&cDu hast dein Limit von &6%LIMIT% &cShop/s erreicht. +message.occupied-shop-slots=&6Du hast &c%AMOUNT%/%LIMIT% &6Shop Slot/s benutzt. +message.cannot-sell-item=&cDu kannst für diesen Artikel keinen Shop erstellen. +message.use-in-creative=&cDu kannst im Kreativ-Modus keine Shops benutzen. +message.select-item=&aÖffne dein Inventar und lass ein Item fallen, um es auszuwählen. +message.item-selected=&aItem wurde ausgewählt: &6%ITEMNAME% +message.creation-cancelled=&cShoperstellung wurde abgebrochen. +message.update.update-available=&6&lVersion &c&l%VERSION% &6&lvon &c&lShopChest &6&list verfügbar. +message.update.click-to-download=Klicke hier zum Herunterladen +message.update.no-update=&6&lKeine neue Aktualisierung verfügbar. +message.update.checking=&6&lSuche nach Aktualisierungen... +message.update.error=&c&lFehler beim Suchen nach Aktualisierungen. +message.noPermission.create=&cDu hast keine Berechtigung einen Shop zu erstellen. +message.noPermission.create-admin=&cDu hast keine Berechtigung einen Admin-Shop zu erstellen. +message.noPermission.create-protected=&cDu hast keine Berechtigung hier einen Shop zu erstellen. +message.noPermission.open-others=&cDu hast keine Berechtigung diesen Shop zu öffnen. +message.noPermission.buy=&cDu hast keine Berechtigung etwas zu kaufen. +message.noPermission.sell=&cDu hast keine Berechtigung etwas zu verkaufen. +message.noPermission.buy-here=&cDu hast keine Berechtigung hier etwas zu kaufen. +message.noPermission.sell-here=&cDu hast keine Berechtigung hier etwas zu verkaufen. +message.noPermission.remove-others=&cDu hast keine Berechtigung diesen Shop zu entfernen. +message.noPermission.remove-admin=&cDu hast keine Berechtigung einen Admin Shop zu entfernen. +message.noPermission.reload=&cDu hast keine Berechtigung die Shops neu zu laden. +message.noPermission.update=&cDu hast keine Berechtigung nach Aktualisierungen zu suchen. +message.noPermission.config=&cDu hast keine Berechtigung Konfigurationswerte zu verändern. +message.noPermission.extend-others=&cDu hast keine Berechtigung diesen Shop zu erweitern. +message.noPermission.extend-protected=&cDu hast keine Berechtigung diesen Shop nach hier zu erweitern. +message.commandDescription.header=&6==== &c/%COMMAND% &6Hilfe +message.commandDescription.footer=&6==== Ende +message.commandDescription.create=&a/%COMMAND% create - Erstelle einen Shop. +message.commandDescription.create-admin=&a/%COMMAND% create [admin] - Erstelle einen Shop. +message.commandDescription.remove=&a/%COMMAND% remove - Entferne einen Shop. +message.commandDescription.info=&a/%COMMAND% info - Rufe Informationen über den Shop ab. +message.commandDescription.removeall=&a/%COMMAND% removeall - Entferne alle Shops eines Spielers. +message.commandDescription.reload=&a/%COMMAND% reload - Lade die Shops neu. +message.commandDescription.update=&a/%COMMAND% update - Suche nach Aktualisierungen. +message.commandDescription.limits=&a/%COMMAND% limits - Betrachte die Shop Limits. +message.commandDescription.open=&a/%COMMAND% open - Öffne einen Shop. +message.commandDescription.config=&a/%COMMAND% config - Verändere Konfigurationswerte. +message.config.set=&6Eigenschaft &a%PROPERTY% &6wurde auf &a%VALUE% &6gesetzt. +message.config.added=&6Wert &a%VALUE% &6wurde zu &a%PROPERTY% &6hinzugefügt. +message.config.removed=&6Wert &a%VALUE% &6wurde aus &a%PROPERTY% &6entfernt. + +block.minecraft.acacia_button=Akazienholzknopf +block.minecraft.acacia_door=Akazienholztür +block.minecraft.acacia_fence=Akazienholzzaun +block.minecraft.acacia_fence_gate=Akazienholzzauntor +block.minecraft.acacia_leaves=Akazienlaub +block.minecraft.acacia_log=Akazienstamm +block.minecraft.acacia_planks=Akazienholzbretter +block.minecraft.acacia_pressure_plate=Akazienholzdruckplatte +block.minecraft.acacia_sapling=Akaziensetzling +block.minecraft.acacia_sign=Akazienholzschild +block.minecraft.acacia_slab=Akazienholzstufe +block.minecraft.acacia_stairs=Akazienholztreppe +block.minecraft.acacia_trapdoor=Akazienholzfalltür +block.minecraft.acacia_wall_sign=Akazienholzwandschild +block.minecraft.acacia_wood=Akazienholz +block.minecraft.activator_rail=Aktivierungsschiene +block.minecraft.air=Luft +block.minecraft.allium=Sternlauch +block.minecraft.amethyst_block=Amethystblock +block.minecraft.amethyst_cluster=Amethysthaufen +block.minecraft.ancient_debris=Antiker Schrott +block.minecraft.andesite=Andesit +block.minecraft.andesite_slab=Andesitstufe +block.minecraft.andesite_stairs=Andesittreppe +block.minecraft.andesite_wall=Andesitmauer +block.minecraft.anvil=Amboss +block.minecraft.attached_melon_stem=Melonenranke +block.minecraft.attached_pumpkin_stem=Kürbisranke +block.minecraft.azalea=Azalee +block.minecraft.azalea_leaves=Azaleenlaub +block.minecraft.azure_bluet=Porzellansternchen +block.minecraft.bamboo=Bambus +block.minecraft.bamboo_sapling=Bambussprössling +block.minecraft.barrel=Fass +block.minecraft.barrier=Barriere +block.minecraft.basalt=Basalt +block.minecraft.beacon=Leuchtfeuer +block.minecraft.bedrock=Grundgestein +block.minecraft.bee_nest=Bienennest +block.minecraft.beehive=Bienenstock +block.minecraft.beetroots=Rote Bete +block.minecraft.bell=Glocke +block.minecraft.big_dripleaf=Großes Tropfblatt +block.minecraft.big_dripleaf_stem=Großer Tropfblattstiel +block.minecraft.birch_button=Birkenholzknopf +block.minecraft.birch_door=Birkenholztür +block.minecraft.birch_fence=Birkenholzzaun +block.minecraft.birch_fence_gate=Birkenholzzauntor +block.minecraft.birch_leaves=Birkenlaub +block.minecraft.birch_log=Birkenstamm +block.minecraft.birch_planks=Birkenholzbretter +block.minecraft.birch_pressure_plate=Birkenholzdruckplatte +block.minecraft.birch_sapling=Birkensetzling +block.minecraft.birch_sign=Birkenholzschild +block.minecraft.birch_slab=Birkenholzstufe +block.minecraft.birch_stairs=Birkenholztreppe +block.minecraft.birch_trapdoor=Birkenholzfalltür +block.minecraft.birch_wall_sign=Birkenholzwandschild +block.minecraft.birch_wood=Birkenholz +block.minecraft.black_banner=Schwarzes Banner +block.minecraft.black_bed=Schwarzes Bett +block.minecraft.black_candle=Schwarze Kerze +block.minecraft.black_candle_cake=Kuchen mit schwarzer Kerze +block.minecraft.black_carpet=Schwarzer Teppich +block.minecraft.black_concrete=Schwarzer Beton +block.minecraft.black_concrete_powder=Schwarzer Trockenbeton +block.minecraft.black_glazed_terracotta=Schwarze glasierte Keramik +block.minecraft.black_shulker_box=Schwarze Shulkerkiste +block.minecraft.black_stained_glass=Schwarzes Glas +block.minecraft.black_stained_glass_pane=Schwarze Glasscheibe +block.minecraft.black_terracotta=Schwarze Keramik +block.minecraft.black_wool=Schwarze Wolle +block.minecraft.blackstone=Schwarzstein +block.minecraft.blackstone_slab=Schwarzsteinstufe +block.minecraft.blackstone_stairs=Schwarzsteintreppe +block.minecraft.blackstone_wall=Schwarzsteinmauer +block.minecraft.blast_furnace=Schmelzofen +block.minecraft.blue_banner=Blaues Banner +block.minecraft.blue_bed=Blaues Bett +block.minecraft.blue_candle=Blaue Kerze +block.minecraft.blue_candle_cake=Kuchen mit blauer Kerze +block.minecraft.blue_carpet=Blauer Teppich +block.minecraft.blue_concrete=Blauer Beton +block.minecraft.blue_concrete_powder=Blauer Trockenbeton +block.minecraft.blue_glazed_terracotta=Blaue glasierte Keramik +block.minecraft.blue_ice=Blaueis +block.minecraft.blue_orchid=Blaue Orchidee +block.minecraft.blue_shulker_box=Blaue Shulkerkiste +block.minecraft.blue_stained_glass=Blaues Glas +block.minecraft.blue_stained_glass_pane=Blaue Glasscheibe +block.minecraft.blue_terracotta=Blaue Keramik +block.minecraft.blue_wool=Blaue Wolle +block.minecraft.bone_block=Knochenblock +block.minecraft.bookshelf=Bücherregal +block.minecraft.brain_coral=Hirnkoralle +block.minecraft.brain_coral_block=Hirnkorallenblock +block.minecraft.brain_coral_fan=Hirnkorallenfächer +block.minecraft.brain_coral_wall_fan=Hirnkorallenwandfächer +block.minecraft.brewing_stand=Braustand +block.minecraft.brick_slab=Ziegelstufe +block.minecraft.brick_stairs=Ziegeltreppe +block.minecraft.brick_wall=Ziegelsteinmauer +block.minecraft.bricks=Ziegelsteine +block.minecraft.brown_banner=Braunes Banner +block.minecraft.brown_bed=Braunes Bett +block.minecraft.brown_candle=Braune Kerze +block.minecraft.brown_candle_cake=Kuchen mit brauner Kerze +block.minecraft.brown_carpet=Brauner Teppich +block.minecraft.brown_concrete=Brauner Beton +block.minecraft.brown_concrete_powder=Brauner Trockenbeton +block.minecraft.brown_glazed_terracotta=Braune glasierte Keramik +block.minecraft.brown_mushroom=Brauner Pilz +block.minecraft.brown_mushroom_block=Brauner Pilzblock +block.minecraft.brown_shulker_box=Braune Shulkerkiste +block.minecraft.brown_stained_glass=Braunes Glas +block.minecraft.brown_stained_glass_pane=Braune Glasscheibe +block.minecraft.brown_terracotta=Braune Keramik +block.minecraft.brown_wool=Braune Wolle +block.minecraft.bubble_column=Blasensäule +block.minecraft.bubble_coral=Blasenkoralle +block.minecraft.bubble_coral_block=Blasenkorallenblock +block.minecraft.bubble_coral_fan=Blasenkorallenfächer +block.minecraft.bubble_coral_wall_fan=Blasenkorallenwandfächer +block.minecraft.budding_amethyst=Amethystknospenblock +block.minecraft.cactus=Kaktus +block.minecraft.cake=Kuchen +block.minecraft.calcite=Kalzit +block.minecraft.campfire=Lagerfeuer +block.minecraft.candle=Kerze +block.minecraft.candle_cake=Kuchen mit Kerze +block.minecraft.carrots=Karotten +block.minecraft.cartography_table=Kartentisch +block.minecraft.carved_pumpkin=Geschnitzter Kürbis +block.minecraft.cauldron=Kessel +block.minecraft.cave_air=Höhlenluft +block.minecraft.cave_vines=Höhlenranken +block.minecraft.cave_vines_plant=Höhlenrankenpflanze +block.minecraft.chain=Kette +block.minecraft.chain_command_block=Ketten-Befehlsblock +block.minecraft.chest=Truhe +block.minecraft.chipped_anvil=Angeschlagener Amboss +block.minecraft.chiseled_deepslate=Gemeißelter Tiefenschiefer +block.minecraft.chiseled_nether_bricks=Gemeißelte Netherziegel +block.minecraft.chiseled_polished_blackstone=Gemeißelter polierter Schwarzstein +block.minecraft.chiseled_quartz_block=Gemeißelter Quarzblock +block.minecraft.chiseled_red_sandstone=Gemeißelter roter Sandstein +block.minecraft.chiseled_sandstone=Gemeißelter Sandstein +block.minecraft.chiseled_stone_bricks=Gemeißelte Steinziegel +block.minecraft.chorus_flower=Chorusblüte +block.minecraft.chorus_plant=Choruspflanze +block.minecraft.clay=Ton +block.minecraft.coal_block=Kohleblock +block.minecraft.coal_ore=Steinkohle +block.minecraft.coarse_dirt=Grobe Erde +block.minecraft.cobbled_deepslate=Bruchtiefenschiefer +block.minecraft.cobbled_deepslate_slab=Bruchtiefenschieferstufe +block.minecraft.cobbled_deepslate_stairs=Bruchtiefenschiefertreppe +block.minecraft.cobbled_deepslate_wall=Bruchtiefenschiefermauer +block.minecraft.cobblestone=Bruchstein +block.minecraft.cobblestone_slab=Bruchsteinstufe +block.minecraft.cobblestone_stairs=Bruchsteintreppe +block.minecraft.cobblestone_wall=Bruchsteinmauer +block.minecraft.cobweb=Spinnennetz +block.minecraft.cocoa=Kakao +block.minecraft.command_block=Befehlsblock +block.minecraft.comparator=Redstone-Komparator +block.minecraft.composter=Komposter +block.minecraft.conduit=Aquisator +block.minecraft.copper_block=Kupferblock +block.minecraft.copper_ore=Kupfererz +block.minecraft.cornflower=Kornblume +block.minecraft.cracked_deepslate_bricks=Rissige Tiefenschieferziegel +block.minecraft.cracked_deepslate_tiles=Rissige Tiefenschieferfliesen +block.minecraft.cracked_nether_bricks=Rissige Netherziegel +block.minecraft.cracked_polished_blackstone_bricks=Rissige polierte Schwarzsteinziegel +block.minecraft.cracked_stone_bricks=Rissige Steinziegel +block.minecraft.crafting_table=Werkbank +block.minecraft.creeper_head=Creeperkopf +block.minecraft.creeper_wall_head=Creeper-Wandkopf +block.minecraft.crimson_button=Karmesinknopf +block.minecraft.crimson_door=Karmesintür +block.minecraft.crimson_fence=Karmesinzaun +block.minecraft.crimson_fence_gate=Karmesinzauntor +block.minecraft.crimson_fungus=Karmesinpilz +block.minecraft.crimson_hyphae=Karmesinhyphen +block.minecraft.crimson_nylium=Karmesin-Nezel +block.minecraft.crimson_planks=Karmesinbretter +block.minecraft.crimson_pressure_plate=Karmesindruckplatte +block.minecraft.crimson_roots=Karmesinwurzeln +block.minecraft.crimson_sign=Karmesinschild +block.minecraft.crimson_slab=Karmesinstufe +block.minecraft.crimson_stairs=Karmesintreppe +block.minecraft.crimson_stem=Karmesinstiel +block.minecraft.crimson_trapdoor=Karmesinfalltür +block.minecraft.crimson_wall_sign=Karmesinwandschild +block.minecraft.crying_obsidian=Weinender Obsidian +block.minecraft.cut_copper=Geschnittener Kupferblock +block.minecraft.cut_copper_slab=Geschnittene Kupferstufe +block.minecraft.cut_copper_stairs=Geschnittene Kupfertreppe +block.minecraft.cut_red_sandstone=Geschnittener roter Sandstein +block.minecraft.cut_red_sandstone_slab=Geschnittene rote Sandsteinstufe +block.minecraft.cut_sandstone=Geschnittener Sandstein +block.minecraft.cut_sandstone_slab=Geschnittene Sandsteinstufe +block.minecraft.cyan_banner=Türkises Banner +block.minecraft.cyan_bed=Türkises Bett +block.minecraft.cyan_candle=Türkise Kerze +block.minecraft.cyan_candle_cake=Kuchen mit türkiser Kerze +block.minecraft.cyan_carpet=Türkiser Teppich +block.minecraft.cyan_concrete=Türkiser Beton +block.minecraft.cyan_concrete_powder=Türkiser Trockenbeton +block.minecraft.cyan_glazed_terracotta=Türkise glasierte Keramik +block.minecraft.cyan_shulker_box=Türkise Shulkerkiste +block.minecraft.cyan_stained_glass=Türkises Glas +block.minecraft.cyan_stained_glass_pane=Türkise Glasscheibe +block.minecraft.cyan_terracotta=Türkise Keramik +block.minecraft.cyan_wool=Türkise Wolle +block.minecraft.damaged_anvil=Beschädigter Amboss +block.minecraft.dandelion=Löwenzahn +block.minecraft.dark_oak_button=Schwarzeichenholzknopf +block.minecraft.dark_oak_door=Schwarzeichenholztür +block.minecraft.dark_oak_fence=Schwarzeichenholzzaun +block.minecraft.dark_oak_fence_gate=Schwarzeichenholzzauntor +block.minecraft.dark_oak_leaves=Schwarzeichenlaub +block.minecraft.dark_oak_log=Schwarzeichenstamm +block.minecraft.dark_oak_planks=Schwarzeichenholzbretter +block.minecraft.dark_oak_pressure_plate=Schwarzeichenholzdruckplatte +block.minecraft.dark_oak_sapling=Schwarzeichensetzling +block.minecraft.dark_oak_sign=Schwarzeichenholzschild +block.minecraft.dark_oak_slab=Schwarzeichenholzstufe +block.minecraft.dark_oak_stairs=Schwarzeichenholztreppe +block.minecraft.dark_oak_trapdoor=Schwarzeichenholzfalltür +block.minecraft.dark_oak_wall_sign=Schwarzeichenholzwandschild +block.minecraft.dark_oak_wood=Schwarzeichenholz +block.minecraft.dark_prismarine=Dunkler Prismarin +block.minecraft.dark_prismarine_slab=Dunkle Prismarinstufe +block.minecraft.dark_prismarine_stairs=Dunkle Prismarintreppe +block.minecraft.daylight_detector=Tageslichtsensor +block.minecraft.dead_brain_coral=Abgestorbene Hirnkoralle +block.minecraft.dead_brain_coral_block=Abgestorbener Hirnkorallenblock +block.minecraft.dead_brain_coral_fan=Abgestorbener Hirnkorallenfächer +block.minecraft.dead_brain_coral_wall_fan=Abgestorbener Hirnkorallenwandfächer +block.minecraft.dead_bubble_coral=Abgestorbene Blasenkoralle +block.minecraft.dead_bubble_coral_block=Abgestorbener Blasenkorallenblock +block.minecraft.dead_bubble_coral_fan=Abgestorbener Blasenkorallenfächer +block.minecraft.dead_bubble_coral_wall_fan=Abgestorbener Blasenkorallenwandfächer +block.minecraft.dead_bush=Toter Busch +block.minecraft.dead_fire_coral=Abgestorbene Feuerkoralle +block.minecraft.dead_fire_coral_block=Abgestorbener Feuerkorallenblock +block.minecraft.dead_fire_coral_fan=Abgestorbener Feuerkorallenfächer +block.minecraft.dead_fire_coral_wall_fan=Abgestorbener Feuerkorallenwandfächer +block.minecraft.dead_horn_coral=Abgestorbene Geweihkoralle +block.minecraft.dead_horn_coral_block=Abgestorbener Geweihkorallenblock +block.minecraft.dead_horn_coral_fan=Abgestorbener Geweihkorallenfächer +block.minecraft.dead_horn_coral_wall_fan=Abgestorbener Geweihkorallenwandfächer +block.minecraft.dead_tube_coral=Abgestorbene Orgelkoralle +block.minecraft.dead_tube_coral_block=Abgestorbener Orgelkorallenblock +block.minecraft.dead_tube_coral_fan=Abgestorbener Orgelkorallenfächer +block.minecraft.dead_tube_coral_wall_fan=Abgestorbener Orgelkorallenwandfächer +block.minecraft.deepslate=Tiefenschiefer +block.minecraft.deepslate_brick_slab=Tiefenschieferziegelstufe +block.minecraft.deepslate_brick_stairs=Tiefenschieferziegeltreppe +block.minecraft.deepslate_brick_wall=Tiefenschieferziegelmauer +block.minecraft.deepslate_bricks=Tiefenschieferziegel +block.minecraft.deepslate_coal_ore=Tiefenschiefer-Steinkohle +block.minecraft.deepslate_copper_ore=Tiefenschiefer-Kupfererz +block.minecraft.deepslate_diamond_ore=Tiefenschiefer-Diamanterz +block.minecraft.deepslate_emerald_ore=Tiefenschiefer-Smaragderz +block.minecraft.deepslate_gold_ore=Tiefenschiefer-Golderz +block.minecraft.deepslate_iron_ore=Tiefenschiefer-Eisenerz +block.minecraft.deepslate_lapis_ore=Tiefenschiefer-Lapislazulierz +block.minecraft.deepslate_redstone_ore=Tiefenschiefer-Redstone-Erz +block.minecraft.deepslate_tile_slab=Tiefenschieferfliesenstufe +block.minecraft.deepslate_tile_stairs=Tiefenschieferfliesentreppe +block.minecraft.deepslate_tile_wall=Tiefenschieferfliesenmauer +block.minecraft.deepslate_tiles=Tiefenschieferfliesen +block.minecraft.detector_rail=Sensorschiene +block.minecraft.diamond_block=Diamantblock +block.minecraft.diamond_ore=Diamanterz +block.minecraft.diorite=Diorit +block.minecraft.diorite_slab=Dioritstufe +block.minecraft.diorite_stairs=Diorittreppe +block.minecraft.diorite_wall=Dioritmauer +block.minecraft.dirt=Erde +block.minecraft.dirt_path=Trampelpfad +block.minecraft.dispenser=Werfer +block.minecraft.dragon_egg=Drachenei +block.minecraft.dragon_head=Drachenkopf +block.minecraft.dragon_wall_head=Drachen-Wandkopf +block.minecraft.dried_kelp_block=Getrockneter Seetangblock +block.minecraft.dripstone_block=Tropfsteinblock +block.minecraft.dropper=Spender +block.minecraft.emerald_block=Smaragdblock +block.minecraft.emerald_ore=Smaragderz +block.minecraft.enchanting_table=Zaubertisch +block.minecraft.end_gateway=Endtransitportal +block.minecraft.end_portal=Endportal +block.minecraft.end_portal_frame=Endportalrahmen +block.minecraft.end_rod=Endstab +block.minecraft.end_stone=Endstein +block.minecraft.end_stone_brick_slab=Endsteinziegelstufe +block.minecraft.end_stone_brick_stairs=Endsteinziegeltreppe +block.minecraft.end_stone_brick_wall=Endsteinziegelmauer +block.minecraft.end_stone_bricks=Endsteinziegel +block.minecraft.ender_chest=Endertruhe +block.minecraft.exposed_copper=Angelaufener Kupferblock +block.minecraft.exposed_cut_copper=Angelaufener geschnittener Kupferblock +block.minecraft.exposed_cut_copper_slab=Angelaufene geschnittene Kupferstufe +block.minecraft.exposed_cut_copper_stairs=Angelaufene geschnittene Kupfertreppe +block.minecraft.farmland=Ackerboden +block.minecraft.fern=Farn +block.minecraft.fire=Feuer +block.minecraft.fire_coral=Feuerkoralle +block.minecraft.fire_coral_block=Feuerkorallenblock +block.minecraft.fire_coral_fan=Feuerkorallenfächer +block.minecraft.fire_coral_wall_fan=Feuerkorallenwandfächer +block.minecraft.fletching_table=Bognertisch +block.minecraft.flower_pot=Blumentopf +block.minecraft.flowering_azalea=Blühende Azalee +block.minecraft.flowering_azalea_leaves=Blühendes Azaleenlaub +block.minecraft.frosted_ice=Brüchiges Eis +block.minecraft.furnace=Ofen +block.minecraft.gilded_blackstone=Golddurchzogener Schwarzstein +block.minecraft.glass=Glas +block.minecraft.glass_pane=Glasscheibe +block.minecraft.glow_lichen=Leuchtflechte +block.minecraft.glowstone=Glowstone +block.minecraft.gold_block=Goldblock +block.minecraft.gold_ore=Golderz +block.minecraft.granite=Granit +block.minecraft.granite_slab=Granitstufe +block.minecraft.granite_stairs=Granittreppe +block.minecraft.granite_wall=Granitmauer +block.minecraft.grass=Gras +block.minecraft.grass_block=Grasblock +block.minecraft.grass_path=Trampelpfad +block.minecraft.gravel=Kies +block.minecraft.gray_banner=Graues Banner +block.minecraft.gray_bed=Graues Bett +block.minecraft.gray_candle=Graue Kerze +block.minecraft.gray_candle_cake=Kuchen mit grauer Kerze +block.minecraft.gray_carpet=Grauer Teppich +block.minecraft.gray_concrete=Grauer Beton +block.minecraft.gray_concrete_powder=Grauer Trockenbeton +block.minecraft.gray_glazed_terracotta=Graue glasierte Keramik +block.minecraft.gray_shulker_box=Graue Shulkerkiste +block.minecraft.gray_stained_glass=Graues Glas +block.minecraft.gray_stained_glass_pane=Graue Glasscheibe +block.minecraft.gray_terracotta=Graue Keramik +block.minecraft.gray_wool=Graue Wolle +block.minecraft.green_banner=Grünes Banner +block.minecraft.green_bed=Grünes Bett +block.minecraft.green_candle=Grüne Kerze +block.minecraft.green_candle_cake=Kuchen mit grüner Kerze +block.minecraft.green_carpet=Grüner Teppich +block.minecraft.green_concrete=Grüner Beton +block.minecraft.green_concrete_powder=Grüner Trockenbeton +block.minecraft.green_glazed_terracotta=Grüne glasierte Keramik +block.minecraft.green_shulker_box=Grüne Shulkerkiste +block.minecraft.green_stained_glass=Grünes Glas +block.minecraft.green_stained_glass_pane=Grüne Glasscheibe +block.minecraft.green_terracotta=Grüne Keramik +block.minecraft.green_wool=Grüne Wolle +block.minecraft.grindstone=Schleifstein +block.minecraft.hanging_roots=Hängende Wurzeln +block.minecraft.hay_block=Strohballen +block.minecraft.heavy_weighted_pressure_plate=Grobwägeplatte +block.minecraft.honey_block=Honigblock +block.minecraft.honeycomb_block=Honigwabenblock +block.minecraft.hopper=Trichter +block.minecraft.horn_coral=Geweihkoralle +block.minecraft.horn_coral_block=Geweihkorallenblock +block.minecraft.horn_coral_fan=Geweihkorallenfächer +block.minecraft.horn_coral_wall_fan=Geweihkorallenwandfächer +block.minecraft.ice=Eis +block.minecraft.infested_chiseled_stone_bricks=Befallene gemeißelte Steinziegel +block.minecraft.infested_cobblestone=Befallener Bruchstein +block.minecraft.infested_cracked_stone_bricks=Befallene rissige Steinziegel +block.minecraft.infested_deepslate=Befallener Tiefenschiefer +block.minecraft.infested_mossy_stone_bricks=Befallene bemooste Steinziegel +block.minecraft.infested_stone=Befallener Stein +block.minecraft.infested_stone_bricks=Befallene Steinziegel +block.minecraft.iron_bars=Eisengitter +block.minecraft.iron_block=Eisenblock +block.minecraft.iron_door=Eisentür +block.minecraft.iron_ore=Eisenerz +block.minecraft.iron_trapdoor=Eisenfalltür +block.minecraft.jack_o_lantern=Kürbislaterne +block.minecraft.jigsaw=Verbundblock +block.minecraft.jukebox=Plattenspieler +block.minecraft.jungle_button=Tropenholzknopf +block.minecraft.jungle_door=Tropenholztür +block.minecraft.jungle_fence=Tropenholzzaun +block.minecraft.jungle_fence_gate=Tropenholzzauntor +block.minecraft.jungle_leaves=Tropenbaumlaub +block.minecraft.jungle_log=Tropenbaumstamm +block.minecraft.jungle_planks=Tropenholzbretter +block.minecraft.jungle_pressure_plate=Tropenholzdruckplatte +block.minecraft.jungle_sapling=Tropenbaumsetzling +block.minecraft.jungle_sign=Tropenholzschild +block.minecraft.jungle_slab=Tropenholzstufe +block.minecraft.jungle_stairs=Tropenholztreppe +block.minecraft.jungle_trapdoor=Tropenholzfalltür +block.minecraft.jungle_wall_sign=Tropenholzwandschild +block.minecraft.jungle_wood=Tropenholz +block.minecraft.kelp=Seetang +block.minecraft.kelp_plant=Seetangstängel +block.minecraft.ladder=Leiter +block.minecraft.lantern=Laterne +block.minecraft.lapis_block=Lapislazuliblock +block.minecraft.lapis_ore=Lapislazulierz +block.minecraft.large_amethyst_bud=Große Amethystknospe +block.minecraft.large_fern=Großer Farn +block.minecraft.lava=Lava +block.minecraft.lava_cauldron=Lavakessel +block.minecraft.lectern=Lesepult +block.minecraft.lever=Hebel +block.minecraft.light=Lichtblock +block.minecraft.light_blue_banner=Hellblaues Banner +block.minecraft.light_blue_bed=Hellblaues Bett +block.minecraft.light_blue_candle=Hellblaue Kerze +block.minecraft.light_blue_candle_cake=Kuchen mit hellblauer Kerze +block.minecraft.light_blue_carpet=Hellblauer Teppich +block.minecraft.light_blue_concrete=Hellblauer Beton +block.minecraft.light_blue_concrete_powder=Hellblauer Trockenbeton +block.minecraft.light_blue_glazed_terracotta=Hellblaue glasierte Keramik +block.minecraft.light_blue_shulker_box=Hellblaue Shulkerkiste +block.minecraft.light_blue_stained_glass=Hellblaues Glas +block.minecraft.light_blue_stained_glass_pane=Hellblaue Glasscheibe +block.minecraft.light_blue_terracotta=Hellblaue Keramik +block.minecraft.light_blue_wool=Hellblaue Wolle +block.minecraft.light_gray_banner=Hellgraues Banner +block.minecraft.light_gray_bed=Hellgraues Bett +block.minecraft.light_gray_candle=Hellgraue Kerze +block.minecraft.light_gray_candle_cake=Kuchen mit hellgrauer Kerze +block.minecraft.light_gray_carpet=Hellgrauer Teppich +block.minecraft.light_gray_concrete=Hellgrauer Beton +block.minecraft.light_gray_concrete_powder=Hellgrauer Trockenbeton +block.minecraft.light_gray_glazed_terracotta=Hellgraue glasierte Keramik +block.minecraft.light_gray_shulker_box=Hellgraue Shulkerkiste +block.minecraft.light_gray_stained_glass=Hellgraues Glas +block.minecraft.light_gray_stained_glass_pane=Hellgraue Glasscheibe +block.minecraft.light_gray_terracotta=Hellgraue Keramik +block.minecraft.light_gray_wool=Hellgraue Wolle +block.minecraft.light_weighted_pressure_plate=Feinwägeplatte +block.minecraft.lightning_rod=Blitzableiter +block.minecraft.lilac=Flieder +block.minecraft.lily_of_the_valley=Maiglöckchen +block.minecraft.lily_pad=Seerosenblatt +block.minecraft.lime_banner=Hellgrünes Banner +block.minecraft.lime_bed=Hellgrünes Bett +block.minecraft.lime_candle=Hellgrüne Kerze +block.minecraft.lime_candle_cake=Kuchen mit hellgrüner Kerze +block.minecraft.lime_carpet=Hellgrüner Teppich +block.minecraft.lime_concrete=Hellgrüner Beton +block.minecraft.lime_concrete_powder=Hellgrüner Trockenbeton +block.minecraft.lime_glazed_terracotta=Hellgrüne glasierte Keramik +block.minecraft.lime_shulker_box=Hellgrüne Shulkerkiste +block.minecraft.lime_stained_glass=Hellgrünes Glas +block.minecraft.lime_stained_glass_pane=Hellgrüne Glasscheibe +block.minecraft.lime_terracotta=Hellgrüne Keramik +block.minecraft.lime_wool=Hellgrüne Wolle +block.minecraft.lodestone=Leitstein +block.minecraft.loom=Webstuhl +block.minecraft.magenta_banner=Magenta Banner +block.minecraft.magenta_bed=Magenta Bett +block.minecraft.magenta_candle=Magenta Kerze +block.minecraft.magenta_candle_cake=Kuchen mit magenta Kerze +block.minecraft.magenta_carpet=Magenta Teppich +block.minecraft.magenta_concrete=Magenta Beton +block.minecraft.magenta_concrete_powder=Magenta Trockenbeton +block.minecraft.magenta_glazed_terracotta=Magenta glasierte Keramik +block.minecraft.magenta_shulker_box=Magenta Shulkerkiste +block.minecraft.magenta_stained_glass=Magenta Glas +block.minecraft.magenta_stained_glass_pane=Magenta Glasscheibe +block.minecraft.magenta_terracotta=Magenta Keramik +block.minecraft.magenta_wool=Magenta Wolle +block.minecraft.magma_block=Magmablock +block.minecraft.medium_amethyst_bud=Mittlere Amethystknospe +block.minecraft.melon=Melone +block.minecraft.melon_stem=Melonenpflanze +block.minecraft.moss_block=Moosblock +block.minecraft.moss_carpet=Moosteppich +block.minecraft.mossy_cobblestone=Bemooster Bruchstein +block.minecraft.mossy_cobblestone_slab=Bemooste Bruchsteinstufe +block.minecraft.mossy_cobblestone_stairs=Bemooste Bruchsteintreppe +block.minecraft.mossy_cobblestone_wall=Bemooste Bruchsteinmauer +block.minecraft.mossy_stone_brick_slab=Bemooste Steinziegelstufe +block.minecraft.mossy_stone_brick_stairs=Bemooste Steinziegeltreppe +block.minecraft.mossy_stone_brick_wall=Bemooste Steinziegelmauer +block.minecraft.mossy_stone_bricks=Bemooste Steinziegel +block.minecraft.moving_piston=Bewegter Block +block.minecraft.mushroom_stem=Pilzstiel +block.minecraft.mycelium=Myzel +block.minecraft.nether_brick_fence=Netherziegelzaun +block.minecraft.nether_brick_slab=Netherziegelstufe +block.minecraft.nether_brick_stairs=Netherziegeltreppe +block.minecraft.nether_brick_wall=Netherziegelmauer +block.minecraft.nether_bricks=Netherziegel +block.minecraft.nether_gold_ore=Nethergolderz +block.minecraft.nether_portal=Netherportal +block.minecraft.nether_quartz_ore=Netherquarzerz +block.minecraft.nether_sprouts=Nethersprossen +block.minecraft.nether_wart=Netherwarzen +block.minecraft.nether_wart_block=Netherwarzenblock +block.minecraft.netherite_block=Netheritblock +block.minecraft.netherrack=Netherrack +block.minecraft.note_block=Notenblock +block.minecraft.oak_button=Eichenholzknopf +block.minecraft.oak_door=Eichenholztür +block.minecraft.oak_fence=Eichenholzzaun +block.minecraft.oak_fence_gate=Eichenholzzauntor +block.minecraft.oak_leaves=Eichenlaub +block.minecraft.oak_log=Eichenstamm +block.minecraft.oak_planks=Eichenholzbretter +block.minecraft.oak_pressure_plate=Eichenholzdruckplatte +block.minecraft.oak_sapling=Eichensetzling +block.minecraft.oak_sign=Eichenholzschild +block.minecraft.oak_slab=Eichenholzstufe +block.minecraft.oak_stairs=Eichenholztreppe +block.minecraft.oak_trapdoor=Eichenholzfalltür +block.minecraft.oak_wall_sign=Eichenholzwandschild +block.minecraft.oak_wood=Eichenholz +block.minecraft.observer=Beobachter +block.minecraft.obsidian=Obsidian +block.minecraft.ominous_banner=Unheilvolles Banner +block.minecraft.orange_banner=Oranges Banner +block.minecraft.orange_bed=Oranges Bett +block.minecraft.orange_candle=Orange Kerze +block.minecraft.orange_candle_cake=Kuchen mit oranger Kerze +block.minecraft.orange_carpet=Oranger Teppich +block.minecraft.orange_concrete=Oranger Beton +block.minecraft.orange_concrete_powder=Oranger Trockenbeton +block.minecraft.orange_glazed_terracotta=Orange glasierte Keramik +block.minecraft.orange_shulker_box=Orange Shulkerkiste +block.minecraft.orange_stained_glass=Oranges Glas +block.minecraft.orange_stained_glass_pane=Orange Glasscheibe +block.minecraft.orange_terracotta=Orange Keramik +block.minecraft.orange_tulip=Orange Tulpe +block.minecraft.orange_wool=Orange Wolle +block.minecraft.oxeye_daisy=Margerite +block.minecraft.oxidized_copper=Oxidierter Kupferblock +block.minecraft.oxidized_cut_copper=Oxidierter geschnittener Kupferblock +block.minecraft.oxidized_cut_copper_slab=Oxidierte geschnittene Kupferstufe +block.minecraft.oxidized_cut_copper_stairs=Oxidierte geschnittene Kupfertreppe +block.minecraft.packed_ice=Packeis +block.minecraft.peony=Pfingstrose +block.minecraft.petrified_oak_slab=Versteinerte Eichenholzstufe +block.minecraft.pink_banner=Rosa Banner +block.minecraft.pink_bed=Rosa Bett +block.minecraft.pink_candle=Rosa Kerze +block.minecraft.pink_candle_cake=Kuchen mit rosa Kerze +block.minecraft.pink_carpet=Rosa Teppich +block.minecraft.pink_concrete=Rosa Beton +block.minecraft.pink_concrete_powder=Rosa Trockenbeton +block.minecraft.pink_glazed_terracotta=Rosa glasierte Keramik +block.minecraft.pink_shulker_box=Rosa Shulkerkiste +block.minecraft.pink_stained_glass=Rosa Glas +block.minecraft.pink_stained_glass_pane=Rosa Glasscheibe +block.minecraft.pink_terracotta=Rosa Keramik +block.minecraft.pink_tulip=Rosa Tulpe +block.minecraft.pink_wool=Rosa Wolle +block.minecraft.piston=Kolben +block.minecraft.piston_head=Kolbenkopf +block.minecraft.player_head=Spielerkopf +block.minecraft.player_wall_head=Spieler-Wandkopf +block.minecraft.podzol=Podsol +block.minecraft.pointed_dripstone=Spitzer Tropfstein +block.minecraft.polished_andesite=Polierter Andesit +block.minecraft.polished_andesite_slab=Polierte Andesitstufe +block.minecraft.polished_andesite_stairs=Polierte Andesittreppe +block.minecraft.polished_basalt=Polierter Basalt +block.minecraft.polished_blackstone=Polierter Schwarzstein +block.minecraft.polished_blackstone_brick_slab=Polierte Schwarzsteinziegelstufe +block.minecraft.polished_blackstone_brick_stairs=Polierte Schwarzsteinziegeltreppe +block.minecraft.polished_blackstone_brick_wall=Polierte Schwarzsteinziegelmauer +block.minecraft.polished_blackstone_bricks=Polierte Schwarzsteinziegel +block.minecraft.polished_blackstone_button=Polierter Schwarzsteinknopf +block.minecraft.polished_blackstone_pressure_plate=Polierte Schwarzsteindruckplatte +block.minecraft.polished_blackstone_slab=Polierte Schwarzsteinstufe +block.minecraft.polished_blackstone_stairs=Polierte Schwarzsteintreppe +block.minecraft.polished_blackstone_wall=Polierte Schwarzsteinmauer +block.minecraft.polished_deepslate=Polierter Tiefenschiefer +block.minecraft.polished_deepslate_slab=Polierte Tiefenschieferstufe +block.minecraft.polished_deepslate_stairs=Polierte Tiefenschiefertreppe +block.minecraft.polished_deepslate_wall=Polierte Tiefenschiefermauer +block.minecraft.polished_diorite=Polierter Diorit +block.minecraft.polished_diorite_slab=Polierte Dioritstufe +block.minecraft.polished_diorite_stairs=Polierte Diorittreppe +block.minecraft.polished_granite=Polierter Granit +block.minecraft.polished_granite_slab=Polierte Granitstufe +block.minecraft.polished_granite_stairs=Polierte Granittreppe +block.minecraft.poppy=Mohn +block.minecraft.potatoes=Kartoffeln +block.minecraft.potted_acacia_sapling=Eingetopfter Akaziensetzling +block.minecraft.potted_allium=Eingetopfter Sternlauch +block.minecraft.potted_azalea_bush=Eingetopfte Azalee +block.minecraft.potted_azure_bluet=Eingetopftes Porzellansternchen +block.minecraft.potted_bamboo=Eingetopfter Bambus +block.minecraft.potted_birch_sapling=Eingetopfter Birkensetzling +block.minecraft.potted_blue_orchid=Eingetopfte blaue Orchidee +block.minecraft.potted_brown_mushroom=Eingetopfter brauner Pilz +block.minecraft.potted_cactus=Eingetopfter Kaktus +block.minecraft.potted_cornflower=Eingetopfte Kornblume +block.minecraft.potted_crimson_fungus=Eingetopfter Karmesinpilz +block.minecraft.potted_crimson_roots=Eingetopfte Karmesinwurzeln +block.minecraft.potted_dandelion=Eingetopfter Löwenzahn +block.minecraft.potted_dark_oak_sapling=Eingetopfter Schwarzeichensetzling +block.minecraft.potted_dead_bush=Eingetopfter toter Busch +block.minecraft.potted_fern=Eingetopfter Farn +block.minecraft.potted_flowering_azalea_bush=Eingetopfte blühende Azalee +block.minecraft.potted_jungle_sapling=Eingetopfter Tropenbaumsetzling +block.minecraft.potted_lily_of_the_valley=Eingetopftes Maiglöckchen +block.minecraft.potted_oak_sapling=Eingetopfter Eichensetzling +block.minecraft.potted_orange_tulip=Eingetopfte orange Tulpe +block.minecraft.potted_oxeye_daisy=Eingetopfte Margerite +block.minecraft.potted_pink_tulip=Eingetopfte rosa Tulpe +block.minecraft.potted_poppy=Eingetopfter Mohn +block.minecraft.potted_red_mushroom=Eingetopfter roter Pilz +block.minecraft.potted_red_tulip=Eingetopfte rote Tulpe +block.minecraft.potted_spruce_sapling=Eingetopfter Fichtensetzling +block.minecraft.potted_warped_fungus=Eingetopfter Wirrpilz +block.minecraft.potted_warped_roots=Eingetopfte Wirrwurzeln +block.minecraft.potted_white_tulip=Eingetopfte weiße Tulpe +block.minecraft.potted_wither_rose=Eingetopfte Witherrose +block.minecraft.powder_snow=Pulverschnee +block.minecraft.powder_snow_cauldron=Pulverschneekessel +block.minecraft.powered_rail=Antriebsschiene +block.minecraft.prismarine=Prismarin +block.minecraft.prismarine_brick_slab=Prismarinziegelstufe +block.minecraft.prismarine_brick_stairs=Prismarinziegeltreppe +block.minecraft.prismarine_bricks=Prismarinziegel +block.minecraft.prismarine_slab=Prismarinstufe +block.minecraft.prismarine_stairs=Prismarintreppe +block.minecraft.prismarine_wall=Prismarinmauer +block.minecraft.pumpkin=Kürbis +block.minecraft.pumpkin_stem=Kürbispflanze +block.minecraft.purple_banner=Violettes Banner +block.minecraft.purple_bed=Violettes Bett +block.minecraft.purple_candle=Violette Kerze +block.minecraft.purple_candle_cake=Kuchen mit violetter Kerze +block.minecraft.purple_carpet=Violetter Teppich +block.minecraft.purple_concrete=Violetter Beton +block.minecraft.purple_concrete_powder=Violetter Trockenbeton +block.minecraft.purple_glazed_terracotta=Violette glasierte Keramik +block.minecraft.purple_shulker_box=Violette Shulkerkiste +block.minecraft.purple_stained_glass=Violettes Glas +block.minecraft.purple_stained_glass_pane=Violette Glasscheibe +block.minecraft.purple_terracotta=Violette Keramik +block.minecraft.purple_wool=Violette Wolle +block.minecraft.purpur_block=Purpurblock +block.minecraft.purpur_pillar=Purpursäule +block.minecraft.purpur_slab=Purpurstufe +block.minecraft.purpur_stairs=Purpurtreppe +block.minecraft.quartz_block=Quarzblock +block.minecraft.quartz_bricks=Quarzziegel +block.minecraft.quartz_pillar=Quarzsäule +block.minecraft.quartz_slab=Quarzstufe +block.minecraft.quartz_stairs=Quarztreppe +block.minecraft.rail=Schiene +block.minecraft.raw_copper_block=Rohkupferblock +block.minecraft.raw_gold_block=Rohgoldblock +block.minecraft.raw_iron_block=Roheisenblock +block.minecraft.red_banner=Rotes Banner +block.minecraft.red_bed=Rotes Bett +block.minecraft.red_candle=Rote Kerze +block.minecraft.red_candle_cake=Kuchen mit roter Kerze +block.minecraft.red_carpet=Roter Teppich +block.minecraft.red_concrete=Roter Beton +block.minecraft.red_concrete_powder=Roter Trockenbeton +block.minecraft.red_glazed_terracotta=Rote glasierte Keramik +block.minecraft.red_mushroom=Roter Pilz +block.minecraft.red_mushroom_block=Roter Pilzblock +block.minecraft.red_nether_brick_slab=Rote Netherziegelstufe +block.minecraft.red_nether_brick_stairs=Rote Netherziegeltreppe +block.minecraft.red_nether_brick_wall=Rote Netherziegelmauer +block.minecraft.red_nether_bricks=Rote Netherziegel +block.minecraft.red_sand=Roter Sand +block.minecraft.red_sandstone=Roter Sandstein +block.minecraft.red_sandstone_slab=Rote Sandsteinstufe +block.minecraft.red_sandstone_stairs=Rote Sandsteintreppe +block.minecraft.red_sandstone_wall=Rote Sandsteinmauer +block.minecraft.red_shulker_box=Rote Shulkerkiste +block.minecraft.red_stained_glass=Rotes Glas +block.minecraft.red_stained_glass_pane=Rote Glasscheibe +block.minecraft.red_terracotta=Rote Keramik +block.minecraft.red_tulip=Rote Tulpe +block.minecraft.red_wool=Rote Wolle +block.minecraft.redstone_block=Redstone-Block +block.minecraft.redstone_lamp=Redstone-Lampe +block.minecraft.redstone_ore=Redstone-Erz +block.minecraft.redstone_torch=Redstone-Fackel +block.minecraft.redstone_wall_torch=Redstone-Wandfackel +block.minecraft.redstone_wire=Redstone-Leitung +block.minecraft.repeater=Redstone-Verstärker +block.minecraft.repeating_command_block=Wiederhol-Befehlsblock +block.minecraft.respawn_anchor=Seelenanker +block.minecraft.rooted_dirt=Wurzelerde +block.minecraft.rose_bush=Rosenstrauch +block.minecraft.sand=Sand +block.minecraft.sandstone=Sandstein +block.minecraft.sandstone_slab=Sandsteinstufe +block.minecraft.sandstone_stairs=Sandsteintreppe +block.minecraft.sandstone_wall=Sandsteinmauer +block.minecraft.scaffolding=Gerüst +block.minecraft.sculk_sensor=Sculk-Sensor +block.minecraft.sea_lantern=Seelaterne +block.minecraft.sea_pickle=Meeresgurke +block.minecraft.seagrass=Seegras +block.minecraft.shroomlight=Pilzlicht +block.minecraft.shulker_box=Shulkerkiste +block.minecraft.skeleton_skull=Skelettschädel +block.minecraft.skeleton_wall_skull=Skelett-Wandschädel +block.minecraft.slime_block=Schleimblock +block.minecraft.small_amethyst_bud=Kleine Amethystknospe +block.minecraft.small_dripleaf=Kleines Tropfblatt +block.minecraft.smithing_table=Schmiedetisch +block.minecraft.smoker=Räucherofen +block.minecraft.smooth_basalt=Glatter Basalt +block.minecraft.smooth_quartz=Glatter Quarzblock +block.minecraft.smooth_quartz_slab=Glatte Quarzstufe +block.minecraft.smooth_quartz_stairs=Glatte Quarztreppe +block.minecraft.smooth_red_sandstone=Glatter roter Sandstein +block.minecraft.smooth_red_sandstone_slab=Glatte rote Sandsteinstufe +block.minecraft.smooth_red_sandstone_stairs=Glatte rote Sandsteintreppe +block.minecraft.smooth_sandstone=Glatter Sandstein +block.minecraft.smooth_sandstone_slab=Glatte Sandsteinstufe +block.minecraft.smooth_sandstone_stairs=Glatte Sandsteintreppe +block.minecraft.smooth_stone=Glatter Stein +block.minecraft.smooth_stone_slab=Glatte Steinstufe +block.minecraft.snow=Schnee +block.minecraft.snow_block=Schneeblock +block.minecraft.soul_campfire=Seelenlagerfeuer +block.minecraft.soul_fire=Seelenfeuer +block.minecraft.soul_lantern=Seelenlaterne +block.minecraft.soul_sand=Seelensand +block.minecraft.soul_soil=Seelenerde +block.minecraft.soul_torch=Seelenfackel +block.minecraft.soul_wall_torch=Seelenwandfackel +block.minecraft.spawner=Spawner +block.minecraft.sponge=Schwamm +block.minecraft.spore_blossom=Sporenblüte +block.minecraft.spruce_button=Fichtenholzknopf +block.minecraft.spruce_door=Fichtenholztür +block.minecraft.spruce_fence=Fichtenholzzaun +block.minecraft.spruce_fence_gate=Fichtenholzzauntor +block.minecraft.spruce_leaves=Fichtennadeln +block.minecraft.spruce_log=Fichtenstamm +block.minecraft.spruce_planks=Fichtenholzbretter +block.minecraft.spruce_pressure_plate=Fichtenholzdruckplatte +block.minecraft.spruce_sapling=Fichtensetzling +block.minecraft.spruce_sign=Fichtenholzschild +block.minecraft.spruce_slab=Fichtenholzstufe +block.minecraft.spruce_stairs=Fichtenholztreppe +block.minecraft.spruce_trapdoor=Fichtenholzfalltür +block.minecraft.spruce_wall_sign=Fichtenholzwandschild +block.minecraft.spruce_wood=Fichtenholz +block.minecraft.sticky_piston=Klebriger Kolben +block.minecraft.stone=Stein +block.minecraft.stone_brick_slab=Steinziegelstufe +block.minecraft.stone_brick_stairs=Steinziegeltreppe +block.minecraft.stone_brick_wall=Steinziegelmauer +block.minecraft.stone_bricks=Steinziegel +block.minecraft.stone_button=Steinknopf +block.minecraft.stone_pressure_plate=Steindruckplatte +block.minecraft.stone_slab=Steinstufe +block.minecraft.stone_stairs=Steintreppe +block.minecraft.stonecutter=Steinsäge +block.minecraft.stripped_acacia_log=Entrindeter Akazienstamm +block.minecraft.stripped_acacia_wood=Entrindetes Akazienholz +block.minecraft.stripped_birch_log=Entrindeter Birkenstamm +block.minecraft.stripped_birch_wood=Entrindetes Birkenholz +block.minecraft.stripped_crimson_hyphae=Geschälte Karmesinhyphen +block.minecraft.stripped_crimson_stem=Geschälter Karmesinstiel +block.minecraft.stripped_dark_oak_log=Entrindeter Schwarzeichenstamm +block.minecraft.stripped_dark_oak_wood=Entrindetes Schwarzeichenholz +block.minecraft.stripped_jungle_log=Entrindeter Tropenbaumstamm +block.minecraft.stripped_jungle_wood=Entrindetes Tropenholz +block.minecraft.stripped_oak_log=Entrindeter Eichenstamm +block.minecraft.stripped_oak_wood=Entrindetes Eichenholz +block.minecraft.stripped_spruce_log=Entrindeter Fichtenstamm +block.minecraft.stripped_spruce_wood=Entrindetes Fichtenholz +block.minecraft.stripped_warped_hyphae=Geschälte Wirrhyphen +block.minecraft.stripped_warped_stem=Geschälter Wirrstiel +block.minecraft.structure_block=Konstruktionsblock +block.minecraft.structure_void=Konstruktionsleere +block.minecraft.sugar_cane=Zuckerrohr +block.minecraft.sunflower=Sonnenblume +block.minecraft.sweet_berry_bush=Süßbeerstrauch +block.minecraft.tall_grass=Hohes Gras +block.minecraft.tall_seagrass=Hohes Seegras +block.minecraft.target=Zielblock +block.minecraft.terracotta=Keramik +block.minecraft.tinted_glass=Getöntes Glas +block.minecraft.tnt=TNT +block.minecraft.torch=Fackel +block.minecraft.trapped_chest=Redstone-Truhe +block.minecraft.tripwire=Stolperdraht +block.minecraft.tripwire_hook=Haken +block.minecraft.tube_coral=Orgelkoralle +block.minecraft.tube_coral_block=Orgelkorallenblock +block.minecraft.tube_coral_fan=Orgelkorallenfächer +block.minecraft.tube_coral_wall_fan=Orgelkorallenwandfächer +block.minecraft.tuff=Tuffstein +block.minecraft.turtle_egg=Schildkrötenei +block.minecraft.twisting_vines=Zwirbelranken +block.minecraft.twisting_vines_plant=Zwirbelrankenpflanze +block.minecraft.vine=Ranken +block.minecraft.void_air=Leerenluft +block.minecraft.wall_sign=Wandschild +block.minecraft.wall_torch=Wandfackel +block.minecraft.warped_button=Wirrknopf +block.minecraft.warped_door=Wirrtür +block.minecraft.warped_fence=Wirrzaun +block.minecraft.warped_fence_gate=Wirrzauntor +block.minecraft.warped_fungus=Wirrpilz +block.minecraft.warped_hyphae=Wirrhyphen +block.minecraft.warped_nylium=Wirr-Nezel +block.minecraft.warped_planks=Wirrbretter +block.minecraft.warped_pressure_plate=Wirrdruckplatte +block.minecraft.warped_roots=Wirrwurzeln +block.minecraft.warped_sign=Wirrschild +block.minecraft.warped_slab=Wirrstufe +block.minecraft.warped_stairs=Wirrtreppe +block.minecraft.warped_stem=Wirrstiel +block.minecraft.warped_trapdoor=Wirrfalltür +block.minecraft.warped_wall_sign=Wirrwandschild +block.minecraft.warped_wart_block=Wirrwarzenblock +block.minecraft.water=Wasser +block.minecraft.water_cauldron=Wasserkessel +block.minecraft.waxed_copper_block=Gewachster Kupferblock +block.minecraft.waxed_cut_copper=Gewachster geschnittener Kupferblock +block.minecraft.waxed_cut_copper_slab=Gewachste geschnittene Kupferstufe +block.minecraft.waxed_cut_copper_stairs=Gewachste geschnittene Kupfertreppe +block.minecraft.waxed_exposed_copper=Gewachster angelaufener Kupferblock +block.minecraft.waxed_exposed_cut_copper=Gewachster angelaufener geschnittener Kupferblock +block.minecraft.waxed_exposed_cut_copper_slab=Gewachste angelaufene geschnittene Kupferstufe +block.minecraft.waxed_exposed_cut_copper_stairs=Gewachste angelaufene geschnittene Kupfertreppe +block.minecraft.waxed_oxidized_copper=Gewachster oxidierter Kupferblock +block.minecraft.waxed_oxidized_cut_copper=Gewachster oxidierter geschnittener Kupferblock +block.minecraft.waxed_oxidized_cut_copper_slab=Gewachste oxidierte geschnittene Kupferstufe +block.minecraft.waxed_oxidized_cut_copper_stairs=Gewachste oxidierte geschnittene Kupfertreppe +block.minecraft.waxed_weathered_copper=Gewachster verwitterter Kupferblock +block.minecraft.waxed_weathered_cut_copper=Gewachster verwitterter geschnittener Kupferblock +block.minecraft.waxed_weathered_cut_copper_slab=Gewachste verwitterte geschnittene Kupferstufe +block.minecraft.waxed_weathered_cut_copper_stairs=Gewachste verwitterte geschnittene Kupfertreppe +block.minecraft.weathered_copper=Verwitterter Kupferblock +block.minecraft.weathered_cut_copper=Verwitterter geschnittener Kupferblock +block.minecraft.weathered_cut_copper_slab=Verwitterte geschnittene Kupferstufe +block.minecraft.weathered_cut_copper_stairs=Verwitterte geschnittene Kupfertreppe +block.minecraft.weeping_vines=Trauerranken +block.minecraft.weeping_vines_plant=Trauerrankenpflanze +block.minecraft.wet_sponge=Nasser Schwamm +block.minecraft.wheat=Weizenpflanze +block.minecraft.white_banner=Weißes Banner +block.minecraft.white_bed=Weißes Bett +block.minecraft.white_candle=Weiße Kerze +block.minecraft.white_candle_cake=Kuchen mit weißer Kerze +block.minecraft.white_carpet=Weißer Teppich +block.minecraft.white_concrete=Weißer Beton +block.minecraft.white_concrete_powder=Weißer Trockenbeton +block.minecraft.white_glazed_terracotta=Weiße glasierte Keramik +block.minecraft.white_shulker_box=Weiße Shulkerkiste +block.minecraft.white_stained_glass=Weißes Glas +block.minecraft.white_stained_glass_pane=Weiße Glasscheibe +block.minecraft.white_terracotta=Weiße Keramik +block.minecraft.white_tulip=Weiße Tulpe +block.minecraft.white_wool=Weiße Wolle +block.minecraft.wither_rose=Witherrose +block.minecraft.wither_skeleton_skull=Witherskelettschädel +block.minecraft.wither_skeleton_wall_skull=Witherskelett-Wandschädel +block.minecraft.yellow_banner=Gelbes Banner +block.minecraft.yellow_bed=Gelbes Bett +block.minecraft.yellow_candle=Gelbe Kerze +block.minecraft.yellow_candle_cake=Kuchen mit gelber Kerze +block.minecraft.yellow_carpet=Gelber Teppich +block.minecraft.yellow_concrete=Gelber Beton +block.minecraft.yellow_concrete_powder=Gelber Trockenbeton +block.minecraft.yellow_glazed_terracotta=Gelbe glasierte Keramik +block.minecraft.yellow_shulker_box=Gelbe Shulkerkiste +block.minecraft.yellow_stained_glass=Gelbes Glas +block.minecraft.yellow_stained_glass_pane=Gelbe Glasscheibe +block.minecraft.yellow_terracotta=Gelbe Keramik +block.minecraft.yellow_wool=Gelbe Wolle +block.minecraft.zombie_head=Zombiekopf +block.minecraft.zombie_wall_head=Zombie-Wandkopf +book.generation.0=Original +book.generation.1=Kopie des Originals +book.generation.2=Kopie einer Kopie +book.generation.3=Zerrissen +effect.minecraft.absorption=Absorption +effect.minecraft.bad_omen=Böses Omen +effect.minecraft.blindness=Blindheit +effect.minecraft.conduit_power=Meereskraft +effect.minecraft.dolphins_grace=Gunst des Delfins +effect.minecraft.fire_resistance=Feuerschutz +effect.minecraft.glowing=Leuchten +effect.minecraft.haste=Eile +effect.minecraft.health_boost=Extraenergie +effect.minecraft.hero_of_the_village=Held des Dorfes +effect.minecraft.hunger=Hunger +effect.minecraft.instant_damage=Direktschaden +effect.minecraft.instant_health=Direktheilung +effect.minecraft.invisibility=Unsichtbarkeit +effect.minecraft.jump_boost=Sprungkraft +effect.minecraft.levitation=Schwebekraft +effect.minecraft.luck=Glück +effect.minecraft.mining_fatigue=Abbaulähmung +effect.minecraft.nausea=Übelkeit +effect.minecraft.night_vision=Nachtsicht +effect.minecraft.poison=Vergiftung +effect.minecraft.regeneration=Regeneration +effect.minecraft.resistance=Resistenz +effect.minecraft.saturation=Sättigung +effect.minecraft.slow_falling=Sanfter Fall +effect.minecraft.slowness=Langsamkeit +effect.minecraft.speed=Schnelligkeit +effect.minecraft.strength=Stärke +effect.minecraft.unluck=Pech +effect.minecraft.water_breathing=Unterwasseratmung +effect.minecraft.weakness=Schwäche +effect.minecraft.wither=Ausdörrung +enchantment.level.1=I +enchantment.level.10=X +enchantment.level.2=II +enchantment.level.3=III +enchantment.level.4=IV +enchantment.level.5=V +enchantment.level.6=VI +enchantment.level.7=VII +enchantment.level.8=VIII +enchantment.level.9=IX +enchantment.minecraft.aqua_affinity=Wasseraffinität +enchantment.minecraft.bane_of_arthropods=Nemesis der Gliederfüßer +enchantment.minecraft.binding_curse=Fluch der Bindung +enchantment.minecraft.blast_protection=Explosionsschutz +enchantment.minecraft.channeling=Entladung +enchantment.minecraft.depth_strider=Wasserläufer +enchantment.minecraft.efficiency=Effizienz +enchantment.minecraft.feather_falling=Federfall +enchantment.minecraft.fire_aspect=Verbrennung +enchantment.minecraft.fire_protection=Feuerschutz +enchantment.minecraft.flame=Flamme +enchantment.minecraft.fortune=Glück +enchantment.minecraft.frost_walker=Eisläufer +enchantment.minecraft.impaling=Harpune +enchantment.minecraft.infinity=Unendlichkeit +enchantment.minecraft.knockback=Rückstoß +enchantment.minecraft.looting=Plünderung +enchantment.minecraft.loyalty=Treue +enchantment.minecraft.luck_of_the_sea=Glück des Meeres +enchantment.minecraft.lure=Köder +enchantment.minecraft.mending=Reparatur +enchantment.minecraft.multishot=Mehrfachschuss +enchantment.minecraft.piercing=Durchschuss +enchantment.minecraft.power=Stärke +enchantment.minecraft.projectile_protection=Schusssicher +enchantment.minecraft.protection=Schutz +enchantment.minecraft.punch=Schlag +enchantment.minecraft.quick_charge=Schnellladen +enchantment.minecraft.respiration=Atmung +enchantment.minecraft.riptide=Sog +enchantment.minecraft.sharpness=Schärfe +enchantment.minecraft.silk_touch=Behutsamkeit +enchantment.minecraft.smite=Bann +enchantment.minecraft.soul_speed=Seelenläufer +enchantment.minecraft.sweeping=Schwungkraft +enchantment.minecraft.thorns=Dornen +enchantment.minecraft.unbreaking=Haltbarkeit +enchantment.minecraft.vanishing_curse=Fluch des Verschwindens +item.minecraft.acacia_boat=Akazienholzboot +item.minecraft.amethyst_shard=Amethystscherbe +item.minecraft.apple=Apfel +item.minecraft.armor_stand=Rüstungsständer +item.minecraft.arrow=Pfeil +item.minecraft.axolotl_bucket=Axolotleimer +item.minecraft.axolotl_spawn_egg=Axolotl-Spawn-Ei +item.minecraft.baked_potato=Ofenkartoffel +item.minecraft.bat_spawn_egg=Fledermaus-Spawn-Ei +item.minecraft.bee_spawn_egg=Bienen-Spawn-Ei +item.minecraft.beef=Rohes Rindfleisch +item.minecraft.beetroot=Rote Bete +item.minecraft.beetroot_seeds=Rote-Bete-Samen +item.minecraft.beetroot_soup=Borschtsch +item.minecraft.birch_boat=Birkenholzboot +item.minecraft.black_dye=Schwarzer Farbstoff +item.minecraft.blaze_powder=Lohenstaub +item.minecraft.blaze_rod=Lohenrute +item.minecraft.blaze_spawn_egg=Lohen-Spawn-Ei +item.minecraft.blue_dye=Blauer Farbstoff +item.minecraft.bone=Knochen +item.minecraft.bone_meal=Knochenmehl +item.minecraft.book=Buch +item.minecraft.bow=Bogen +item.minecraft.bowl=Schüssel +item.minecraft.bread=Brot +item.minecraft.brewing_stand=Braustand +item.minecraft.brick=Ziegel +item.minecraft.brown_dye=Brauner Farbstoff +item.minecraft.bucket=Eimer +item.minecraft.bundle=Bündel +item.minecraft.cactus_green=Kaktusgrün +item.minecraft.carrot=Karotte +item.minecraft.carrot_on_a_stick=Karottenrute +item.minecraft.cat_spawn_egg=Katzen-Spawn-Ei +item.minecraft.cauldron=Kessel +item.minecraft.cave_spider_spawn_egg=Höhlenspinnen-Spawn-Ei +item.minecraft.chainmail_boots=Kettenstiefel +item.minecraft.chainmail_chestplate=Kettenhemd +item.minecraft.chainmail_helmet=Kettenhaube +item.minecraft.chainmail_leggings=Kettenhose +item.minecraft.charcoal=Holzkohle +item.minecraft.chest_minecart=Güterlore +item.minecraft.chicken=Rohes Hühnchen +item.minecraft.chicken_spawn_egg=Huhn-Spawn-Ei +item.minecraft.chorus_fruit=Chorusfrucht +item.minecraft.clay_ball=Tonklumpen +item.minecraft.clock=Uhr +item.minecraft.coal=Kohle +item.minecraft.cocoa_beans=Kakaobohnen +item.minecraft.cod=Roher Kabeljau +item.minecraft.cod_bucket=Kabeljaueimer +item.minecraft.cod_spawn_egg=Kabeljau-Spawn-Ei +item.minecraft.command_block_minecart=Befehlsblocklore +item.minecraft.compass=Kompass +item.minecraft.cooked_beef=Steak +item.minecraft.cooked_chicken=Gebratenes Hühnchen +item.minecraft.cooked_cod=Gebratener Kabeljau +item.minecraft.cooked_mutton=Gebratenes Hammelfleisch +item.minecraft.cooked_porkchop=Gebratenes Schweinefleisch +item.minecraft.cooked_rabbit=Gebratenes Kaninchen +item.minecraft.cooked_salmon=Gebratener Lachs +item.minecraft.cookie=Keks +item.minecraft.copper_ingot=Kupferbarren +item.minecraft.cow_spawn_egg=Kuh-Spawn-Ei +item.minecraft.creeper_banner_pattern=Bannervorlage +item.minecraft.creeper_banner_pattern.desc=Creeper +item.minecraft.creeper_head=Creeperkopf +item.minecraft.creeper_spawn_egg=Creeper-Spawn-Ei +item.minecraft.crossbow=Armbrust +item.minecraft.crossbow.projectile=Geschoss: +item.minecraft.cyan_dye=Türkiser Farbstoff +item.minecraft.dandelion_yellow=Löwenzahngelb +item.minecraft.dark_oak_boat=Schwarzeichenholzboot +item.minecraft.debug_stick=Debug-Stab +item.minecraft.diamond=Diamant +item.minecraft.diamond_axe=Diamantaxt +item.minecraft.diamond_boots=Diamantstiefel +item.minecraft.diamond_chestplate=Diamantharnisch +item.minecraft.diamond_helmet=Diamanthelm +item.minecraft.diamond_hoe=Diamanthacke +item.minecraft.diamond_horse_armor=Diamantener Rossharnisch +item.minecraft.diamond_leggings=Diamantbeinschutz +item.minecraft.diamond_pickaxe=Diamantspitzhacke +item.minecraft.diamond_shovel=Diamantschaufel +item.minecraft.diamond_sword=Diamantschwert +item.minecraft.dolphin_spawn_egg=Delfin-Spawn-Ei +item.minecraft.donkey_spawn_egg=Esel-Spawn-Ei +item.minecraft.dragon_breath=Drachenatem +item.minecraft.dragon_head=Drachenkopf +item.minecraft.dried_kelp=Getrockneter Seetang +item.minecraft.drowned_spawn_egg=Ertrunkenen-Spawn-Ei +item.minecraft.egg=Ei +item.minecraft.elder_guardian_spawn_egg=Großer-Wächter-Spawn-Ei +item.minecraft.elytra=Elytren +item.minecraft.emerald=Smaragd +item.minecraft.enchanted_book=Verzaubertes Buch +item.minecraft.enchanted_golden_apple=Verzauberter goldener Apfel +item.minecraft.end_crystal=Enderkristall +item.minecraft.ender_eye=Enderauge +item.minecraft.ender_pearl=Enderperle +item.minecraft.enderman_spawn_egg=Enderman-Spawn-Ei +item.minecraft.endermite_spawn_egg=Endermiten-Spawn-Ei +item.minecraft.evoker_spawn_egg=Magier-Spawn-Ei +item.minecraft.experience_bottle=Erfahrungsfläschchen +item.minecraft.feather=Feder +item.minecraft.fermented_spider_eye=Fermentiertes Spinnenauge +item.minecraft.filled_map=Karte +item.minecraft.fire_charge=Feuerkugel +item.minecraft.firework_rocket=Feuerwerksrakete +item.minecraft.firework_star=Feuerwerksstern +item.minecraft.fishing_rod=Angel +item.minecraft.flint=Feuerstein +item.minecraft.flint_and_steel=Feuerzeug +item.minecraft.flower_banner_pattern=Bannervorlage +item.minecraft.flower_banner_pattern.desc=Blume +item.minecraft.flower_pot=Blumentopf +item.minecraft.fox_spawn_egg=Fuchs-Spawn-Ei +item.minecraft.furnace_minecart=Ofenlore +item.minecraft.ghast_spawn_egg=Ghast-Spawn-Ei +item.minecraft.ghast_tear=Ghastträne +item.minecraft.glass_bottle=Glasflasche +item.minecraft.glistering_melon_slice=Glitzernde Melonenscheibe +item.minecraft.globe_banner_pattern=Bannervorlage +item.minecraft.globe_banner_pattern.desc=Globus +item.minecraft.glow_berries=Leuchtbeeren +item.minecraft.glow_ink_sac=Leuchttintenbeutel +item.minecraft.glow_item_frame=Leuchtrahmen +item.minecraft.glow_squid_spawn_egg=Leuchttintenfisch-Spawn-Ei +item.minecraft.glowstone_dust=Glowstonestaub +item.minecraft.goat_spawn_egg=Ziegen-Spawn-Ei +item.minecraft.gold_ingot=Goldbarren +item.minecraft.gold_nugget=Goldklumpen +item.minecraft.golden_apple=Goldener Apfel +item.minecraft.golden_axe=Goldaxt +item.minecraft.golden_boots=Goldstiefel +item.minecraft.golden_carrot=Goldene Karotte +item.minecraft.golden_chestplate=Goldharnisch +item.minecraft.golden_helmet=Goldhelm +item.minecraft.golden_hoe=Goldhacke +item.minecraft.golden_horse_armor=Goldener Rossharnisch +item.minecraft.golden_leggings=Goldbeinschutz +item.minecraft.golden_pickaxe=Goldspitzhacke +item.minecraft.golden_shovel=Goldschaufel +item.minecraft.golden_sword=Goldschwert +item.minecraft.gray_dye=Grauer Farbstoff +item.minecraft.green_dye=Grüner Farbstoff +item.minecraft.guardian_spawn_egg=Wächter-Spawn-Ei +item.minecraft.gunpowder=Schwarzpulver +item.minecraft.heart_of_the_sea=Herz des Meeres +item.minecraft.hoglin_spawn_egg=Hoglin-Spawn-Ei +item.minecraft.honey_bottle=Honigflasche +item.minecraft.honeycomb=Honigwabe +item.minecraft.hopper_minecart=Trichterlore +item.minecraft.horse_spawn_egg=Pferde-Spawn-Ei +item.minecraft.husk_spawn_egg=Wüstenzombie-Spawn-Ei +item.minecraft.ink_sac=Tintenbeutel +item.minecraft.iron_axe=Eisenaxt +item.minecraft.iron_boots=Eisenstiefel +item.minecraft.iron_chestplate=Eisenharnisch +item.minecraft.iron_helmet=Eisenhelm +item.minecraft.iron_hoe=Eisenhacke +item.minecraft.iron_horse_armor=Eiserner Rossharnisch +item.minecraft.iron_ingot=Eisenbarren +item.minecraft.iron_leggings=Eisenbeinschutz +item.minecraft.iron_nugget=Eisenklumpen +item.minecraft.iron_pickaxe=Eisenspitzhacke +item.minecraft.iron_shovel=Eisenschaufel +item.minecraft.iron_sword=Eisenschwert +item.minecraft.item_frame=Rahmen +item.minecraft.jungle_boat=Tropenholzboot +item.minecraft.knowledge_book=Buch des Wissens +item.minecraft.lapis_lazuli=Lapislazuli +item.minecraft.lava_bucket=Lavaeimer +item.minecraft.lead=Leine +item.minecraft.leather=Leder +item.minecraft.leather_boots=Lederstiefel +item.minecraft.leather_chestplate=Lederjacke +item.minecraft.leather_helmet=Lederkappe +item.minecraft.leather_horse_armor=Lederner Rossharnisch +item.minecraft.leather_leggings=Lederhose +item.minecraft.light_blue_dye=Hellblauer Farbstoff +item.minecraft.light_gray_dye=Hellgrauer Farbstoff +item.minecraft.lime_dye=Hellgrüner Farbstoff +item.minecraft.lingering_potion=Verweiltrank +item.minecraft.lingering_potion.effect.awkward=Seltsamer Verweiltrank +item.minecraft.lingering_potion.effect.empty=Nicht braubarer Verweiltrank +item.minecraft.lingering_potion.effect.fire_resistance=Verweiltrank der Feuerresistenz +item.minecraft.lingering_potion.effect.harming=Verweiltrank des Schadens +item.minecraft.lingering_potion.effect.healing=Verweiltrank der Heilung +item.minecraft.lingering_potion.effect.invisibility=Verweiltrank der Unsichtbarkeit +item.minecraft.lingering_potion.effect.leaping=Verweiltrank der Sprungkraft +item.minecraft.lingering_potion.effect.levitation=Verweiltrank der Schwebekraft +item.minecraft.lingering_potion.effect.luck=Verweiltrank des Glücks +item.minecraft.lingering_potion.effect.mundane=Gewöhnlicher Verweiltrank +item.minecraft.lingering_potion.effect.night_vision=Verweiltrank der Nachtsicht +item.minecraft.lingering_potion.effect.poison=Verweiltrank der Vergiftung +item.minecraft.lingering_potion.effect.regeneration=Verweiltrank der Regeneration +item.minecraft.lingering_potion.effect.slow_falling=Verweiltrank des sanften Falls +item.minecraft.lingering_potion.effect.slowness=Verweiltrank der Langsamkeit +item.minecraft.lingering_potion.effect.strength=Verweiltrank der Stärke +item.minecraft.lingering_potion.effect.swiftness=Verweiltrank der Schnelligkeit +item.minecraft.lingering_potion.effect.thick=Dickflüssiger Verweiltrank +item.minecraft.lingering_potion.effect.turtle_master=Verweiltrank des Schildkrötenmeisters +item.minecraft.lingering_potion.effect.water=Verweilende Wasserflasche +item.minecraft.lingering_potion.effect.water_breathing=Verweiltrank der Unterwasseratmung +item.minecraft.lingering_potion.effect.weakness=Verweiltrank der Schwäche +item.minecraft.llama_spawn_egg=Lama-Spawn-Ei +item.minecraft.lodestone_compass=Leitstein-Kompass +item.minecraft.magenta_dye=Magenta Farbstoff +item.minecraft.magma_cream=Magmacreme +item.minecraft.magma_cube_spawn_egg=Magmawürfel-Spawn-Ei +item.minecraft.map=Leere Karte +item.minecraft.melon_seeds=Melonenkerne +item.minecraft.melon_slice=Melonenscheibe +item.minecraft.milk_bucket=Milcheimer +item.minecraft.minecart=Lore +item.minecraft.mojang_banner_pattern=Bannervorlage +item.minecraft.mojang_banner_pattern.desc=Mojang-Logo +item.minecraft.mooshroom_spawn_egg=Mooshroom-Spawn-Ei +item.minecraft.mule_spawn_egg=Maultier-Spawn-Ei +item.minecraft.mushroom_stew=Pilzsuppe +item.minecraft.music_disc_11=Schallplatte +item.minecraft.music_disc_11.desc=C418 - 11 +item.minecraft.music_disc_13=Schallplatte +item.minecraft.music_disc_13.desc=C418 - 13 +item.minecraft.music_disc_blocks=Schallplatte +item.minecraft.music_disc_blocks.desc=C418 - Blocks +item.minecraft.music_disc_cat=Schallplatte +item.minecraft.music_disc_cat.desc=C418 - Cat +item.minecraft.music_disc_chirp=Schallplatte +item.minecraft.music_disc_chirp.desc=C418 - Chirp +item.minecraft.music_disc_far=Schallplatte +item.minecraft.music_disc_far.desc=C418 - Far +item.minecraft.music_disc_mall=Schallplatte +item.minecraft.music_disc_mall.desc=C418 - Mall +item.minecraft.music_disc_mellohi=Schallplatte +item.minecraft.music_disc_mellohi.desc=C418 - Mellohi +item.minecraft.music_disc_pigstep=Schallplatte +item.minecraft.music_disc_pigstep.desc=Lena Raine - Pigstep +item.minecraft.music_disc_stal=Schallplatte +item.minecraft.music_disc_stal.desc=C418 - Stal +item.minecraft.music_disc_strad=Schallplatte +item.minecraft.music_disc_strad.desc=C418 - Strad +item.minecraft.music_disc_wait=Schallplatte +item.minecraft.music_disc_wait.desc=C418 - Wait +item.minecraft.music_disc_ward=Schallplatte +item.minecraft.music_disc_ward.desc=C418 - Ward +item.minecraft.mutton=Rohes Hammelfleisch +item.minecraft.name_tag=Namensschild +item.minecraft.nautilus_shell=Nautilusschale +item.minecraft.nether_brick=Netherziegel +item.minecraft.nether_star=Netherstern +item.minecraft.nether_wart=Netherwarze +item.minecraft.netherite_axe=Netheritaxt +item.minecraft.netherite_boots=Netheritstiefel +item.minecraft.netherite_chestplate=Netheritharnisch +item.minecraft.netherite_helmet=Netherithelm +item.minecraft.netherite_hoe=Netherithacke +item.minecraft.netherite_ingot=Netheritbarren +item.minecraft.netherite_leggings=Netheritbeinschutz +item.minecraft.netherite_pickaxe=Netheritspitzhacke +item.minecraft.netherite_scrap=Netheritplatten +item.minecraft.netherite_shovel=Netheritschaufel +item.minecraft.netherite_sword=Netheritschwert +item.minecraft.oak_boat=Eichenholzboot +item.minecraft.ocelot_spawn_egg=Ozelot-Spawn-Ei +item.minecraft.orange_dye=Oranger Farbstoff +item.minecraft.painting=Gemälde +item.minecraft.panda_spawn_egg=Panda-Spawn-Ei +item.minecraft.paper=Papier +item.minecraft.parrot_spawn_egg=Papageien-Spawn-Ei +item.minecraft.phantom_membrane=Phantomhaut +item.minecraft.phantom_spawn_egg=Phantom-Spawn-Ei +item.minecraft.pig_spawn_egg=Schweine-Spawn-Ei +item.minecraft.piglin_banner_pattern=Bannervorlage +item.minecraft.piglin_banner_pattern.desc=Schnauze +item.minecraft.piglin_brute_spawn_egg=Piglin-Barbaren-Spawn-Ei +item.minecraft.piglin_spawn_egg=Piglin-Spawn-Ei +item.minecraft.pillager_spawn_egg=Plünderer-Spawn-Ei +item.minecraft.pink_dye=Rosa Farbstoff +item.minecraft.poisonous_potato=Giftige Kartoffel +item.minecraft.polar_bear_spawn_egg=Eisbären-Spawn-Ei +item.minecraft.popped_chorus_fruit=Geplatzte Chorusfrucht +item.minecraft.porkchop=Rohes Schweinefleisch +item.minecraft.potato=Kartoffel +item.minecraft.potion=Trank +item.minecraft.potion.effect.awkward=Seltsamer Trank +item.minecraft.potion.effect.empty=Nicht braubarer Trank +item.minecraft.potion.effect.fire_resistance=Trank der Feuerresistenz +item.minecraft.potion.effect.harming=Trank des Schadens +item.minecraft.potion.effect.healing=Trank der Heilung +item.minecraft.potion.effect.invisibility=Trank der Unsichtbarkeit +item.minecraft.potion.effect.leaping=Trank der Sprungkraft +item.minecraft.potion.effect.levitation=Trank der Schwebekraft +item.minecraft.potion.effect.luck=Trank des Glücks +item.minecraft.potion.effect.mundane=Gewöhnlicher Trank +item.minecraft.potion.effect.night_vision=Trank der Nachtsicht +item.minecraft.potion.effect.poison=Trank der Vergiftung +item.minecraft.potion.effect.regeneration=Trank der Regeneration +item.minecraft.potion.effect.slow_falling=Trank des sanften Falls +item.minecraft.potion.effect.slowness=Trank der Langsamkeit +item.minecraft.potion.effect.strength=Trank der Stärke +item.minecraft.potion.effect.swiftness=Trank der Schnelligkeit +item.minecraft.potion.effect.thick=Dickflüssiger Trank +item.minecraft.potion.effect.turtle_master=Trank des Schildkrötenmeisters +item.minecraft.potion.effect.water=Wasserflasche +item.minecraft.potion.effect.water_breathing=Trank der Unterwasseratmung +item.minecraft.potion.effect.weakness=Trank der Schwäche +item.minecraft.powder_snow_bucket=Pulverschneeeimer +item.minecraft.prismarine_crystals=Prismarinkristalle +item.minecraft.prismarine_shard=Prismarinscherbe +item.minecraft.pufferfish=Kugelfisch +item.minecraft.pufferfish_bucket=Kugelfischeimer +item.minecraft.pufferfish_spawn_egg=Kugelfisch-Spawn-Ei +item.minecraft.pumpkin_pie=Kürbiskuchen +item.minecraft.pumpkin_seeds=Kürbiskerne +item.minecraft.purple_dye=Violetter Farbstoff +item.minecraft.quartz=Netherquarz +item.minecraft.rabbit=Rohes Kaninchen +item.minecraft.rabbit_foot=Hasenpfote +item.minecraft.rabbit_hide=Kaninchenfell +item.minecraft.rabbit_spawn_egg=Kaninchen-Spawn-Ei +item.minecraft.rabbit_stew=Kaninchenragout +item.minecraft.ravager_spawn_egg=Verwüster-Spawn-Ei +item.minecraft.raw_copper=Rohkupfer +item.minecraft.raw_gold=Rohgold +item.minecraft.raw_iron=Roheisen +item.minecraft.red_dye=Roter Farbstoff +item.minecraft.redstone=Redstone-Staub +item.minecraft.rose_red=Rosenrot +item.minecraft.rotten_flesh=Verrottetes Fleisch +item.minecraft.saddle=Sattel +item.minecraft.salmon=Roher Lachs +item.minecraft.salmon_bucket=Lachseimer +item.minecraft.salmon_spawn_egg=Lachs-Spawn-Ei +item.minecraft.scute=Hornschild +item.minecraft.shears=Schere +item.minecraft.sheep_spawn_egg=Schafs-Spawn-Ei +item.minecraft.shield=Schild +item.minecraft.shulker_shell=Shulkerschale +item.minecraft.shulker_spawn_egg=Shulker-Spawn-Ei +item.minecraft.sign=Schild +item.minecraft.silverfish_spawn_egg=Silberfischchen-Spawn-Ei +item.minecraft.skeleton_horse_spawn_egg=Skelettpferde-Spawn-Ei +item.minecraft.skeleton_skull=Skelettschädel +item.minecraft.skeleton_spawn_egg=Skelett-Spawn-Ei +item.minecraft.skull_banner_pattern=Bannervorlage +item.minecraft.skull_banner_pattern.desc=Schädel +item.minecraft.slime_ball=Schleimball +item.minecraft.slime_spawn_egg=Schleim-Spawn-Ei +item.minecraft.snowball=Schneeball +item.minecraft.spectral_arrow=Spektralpfeil +item.minecraft.spider_eye=Spinnenauge +item.minecraft.spider_spawn_egg=Spinnen-Spawn-Ei +item.minecraft.splash_potion=Wurftrank +item.minecraft.splash_potion.effect.awkward=Seltsamer Wurftrank +item.minecraft.splash_potion.effect.empty=Nicht braubarer Wurftrank +item.minecraft.splash_potion.effect.fire_resistance=Wurftrank der Feuerresistenz +item.minecraft.splash_potion.effect.harming=Wurftrank des Schadens +item.minecraft.splash_potion.effect.healing=Wurftrank der Heilung +item.minecraft.splash_potion.effect.invisibility=Wurftrank der Unsichtbarkeit +item.minecraft.splash_potion.effect.leaping=Wurftrank der Sprungkraft +item.minecraft.splash_potion.effect.levitation=Wurftrank der Schwebekraft +item.minecraft.splash_potion.effect.luck=Wurftrank des Glücks +item.minecraft.splash_potion.effect.mundane=Gewöhnlicher Wurftrank +item.minecraft.splash_potion.effect.night_vision=Wurftrank der Nachtsicht +item.minecraft.splash_potion.effect.poison=Wurftrank der Vergiftung +item.minecraft.splash_potion.effect.regeneration=Wurftrank der Regeneration +item.minecraft.splash_potion.effect.slow_falling=Wurftrank des sanften Falls +item.minecraft.splash_potion.effect.slowness=Wurftrank der Langsamkeit +item.minecraft.splash_potion.effect.strength=Wurftrank der Stärke +item.minecraft.splash_potion.effect.swiftness=Wurftrank der Schnelligkeit +item.minecraft.splash_potion.effect.thick=Dickflüssiger Wurftrank +item.minecraft.splash_potion.effect.turtle_master=Wurftrank des Schildkrötenmeisters +item.minecraft.splash_potion.effect.water=Werfbare Wasserflasche +item.minecraft.splash_potion.effect.water_breathing=Wurftrank der Unterwasseratmung +item.minecraft.splash_potion.effect.weakness=Wurftrank der Schwäche +item.minecraft.spruce_boat=Fichtenholzboot +item.minecraft.spyglass=Fernrohr +item.minecraft.squid_spawn_egg=Tintenfisch-Spawn-Ei +item.minecraft.stick=Stock +item.minecraft.stone_axe=Steinaxt +item.minecraft.stone_hoe=Steinhacke +item.minecraft.stone_pickaxe=Steinspitzhacke +item.minecraft.stone_shovel=Steinschaufel +item.minecraft.stone_sword=Steinschwert +item.minecraft.stray_spawn_egg=Eiswanderer-Spawn-Ei +item.minecraft.strider_spawn_egg=Schreiter-Spawn-Ei +item.minecraft.string=Faden +item.minecraft.sugar=Zucker +item.minecraft.suspicious_stew=Seltsame Suppe +item.minecraft.sweet_berries=Süßbeeren +item.minecraft.tipped_arrow=Getränkter Pfeil +item.minecraft.tipped_arrow.effect.awkward=Getränkter Pfeil +item.minecraft.tipped_arrow.effect.empty=Nicht herstellbarer getränkter Pfeil +item.minecraft.tipped_arrow.effect.fire_resistance=Pfeil der Feuerresistenz +item.minecraft.tipped_arrow.effect.harming=Pfeil des Schadens +item.minecraft.tipped_arrow.effect.healing=Pfeil der Heilung +item.minecraft.tipped_arrow.effect.invisibility=Pfeil der Unsichtbarkeit +item.minecraft.tipped_arrow.effect.leaping=Pfeil der Sprungkraft +item.minecraft.tipped_arrow.effect.levitation=Pfeil der Schwebekraft +item.minecraft.tipped_arrow.effect.luck=Pfeil des Glücks +item.minecraft.tipped_arrow.effect.mundane=Getränkter Pfeil +item.minecraft.tipped_arrow.effect.night_vision=Pfeil der Nachtsicht +item.minecraft.tipped_arrow.effect.poison=Pfeil der Vergiftung +item.minecraft.tipped_arrow.effect.regeneration=Pfeil der Regeneration +item.minecraft.tipped_arrow.effect.slow_falling=Pfeil des sanften Falls +item.minecraft.tipped_arrow.effect.slowness=Pfeil der Langsamkeit +item.minecraft.tipped_arrow.effect.strength=Pfeil der Stärke +item.minecraft.tipped_arrow.effect.swiftness=Pfeil der Schnelligkeit +item.minecraft.tipped_arrow.effect.thick=Getränkter Pfeil +item.minecraft.tipped_arrow.effect.turtle_master=Pfeil des Schildkrötenmeisters +item.minecraft.tipped_arrow.effect.water=Nasser Pfeil +item.minecraft.tipped_arrow.effect.water_breathing=Pfeil der Unterwasseratmung +item.minecraft.tipped_arrow.effect.weakness=Pfeil der Schwäche +item.minecraft.tnt_minecart=TNT-Lore +item.minecraft.totem_of_undying=Totem der Unsterblichkeit +item.minecraft.trader_llama_spawn_egg=Händlerlama-Spawn-Ei +item.minecraft.trident=Dreizack +item.minecraft.tropical_fish=Tropenfisch +item.minecraft.tropical_fish_bucket=Tropenfischeimer +item.minecraft.tropical_fish_spawn_egg=Tropenfisch-Spawn-Ei +item.minecraft.turtle_helmet=Schildkrötenpanzer +item.minecraft.turtle_spawn_egg=Schildkröten-Spawn-Ei +item.minecraft.vex_spawn_egg=Plagegeister-Spawn-Ei +item.minecraft.villager_spawn_egg=Dorfbewohner-Spawn-Ei +item.minecraft.vindicator_spawn_egg=Diener-Spawn-Ei +item.minecraft.wandering_trader_spawn_egg=Fahrender-Händler-Spawn-Ei +item.minecraft.warped_fungus_on_a_stick=Wirrpilzrute +item.minecraft.water_bucket=Wassereimer +item.minecraft.wheat=Weizen +item.minecraft.wheat_seeds=Weizenkörner +item.minecraft.white_dye=Weißer Farbstoff +item.minecraft.witch_spawn_egg=Hexen-Spawn-Ei +item.minecraft.wither_skeleton_skull=Witherskelettschädel +item.minecraft.wither_skeleton_spawn_egg=Witherskelett-Spawn-Ei +item.minecraft.wolf_spawn_egg=Wolfs-Spawn-Ei +item.minecraft.wooden_axe=Holzaxt +item.minecraft.wooden_hoe=Holzhacke +item.minecraft.wooden_pickaxe=Holzspitzhacke +item.minecraft.wooden_shovel=Holzschaufel +item.minecraft.wooden_sword=Holzschwert +item.minecraft.writable_book=Buch und Feder +item.minecraft.written_book=Beschriebenes Buch +item.minecraft.yellow_dye=Gelber Farbstoff +item.minecraft.zombie_head=Zombiekopf +item.minecraft.zoglin_spawn_egg=Zoglin-Spawn-Ei +item.minecraft.zombie_horse_spawn_egg=Zombiepferde-Spawn-Ei +item.minecraft.zombie_pigman_spawn_egg=Schweinezombie-Spawn-Ei +item.minecraft.zombie_spawn_egg=Zombie-Spawn-Ei +item.minecraft.zombie_villager_spawn_egg=Zombiedorfbewohner-Spawn-Ei +item.minecraft.zombified_piglin_spawn_egg=Zombifizierter-Piglin-Spawn-Ei \ No newline at end of file diff --git a/plugin/src/main/resources/lang/en_US-legacy.lang b/plugin/src/main/resources/lang/en_US-legacy.lang new file mode 100644 index 0000000..946cea0 --- /dev/null +++ b/plugin/src/main/resources/lang/en_US-legacy.lang @@ -0,0 +1,1163 @@ +# ============================================================================= +# = THIS LANGAUGE FILE IS ONLY FOR MINECRAFT VERSIONS BELOW 1.13! = +# = IF YOU TRANSLATE THIS, YOU HAVE TO APPEND "-legacy" TO THE FILE NAME = +# = OR IT WILL THROW A LOT OF ERRORS! = +# ============================================================================= + + +# Set the message when a shop is created at the clicked chest. +# Usable Placeholders: %CREATION-PRICE% +message.shop-created=&6You were withdrawn &c%CREATION-PRICE% &6to create this shop. + +# Set the message when an admin shop is created at the clicked chest. +# Usable Placeholders: %CREATION-PRICE% +message.admin-shop-created=&6You were withdrawn &c%CREATION-PRICE% &6to create this admin shop. + +# Set the message when the clicked chest already is a shop. +message.chest-already-shop=&cChest already is shop. + +# Set the message when there is a block above the clicked chest. +message.chest-blocked=&cThere must not be a block above the chest. + +# Set the message when a player tries to place a chest next to a shop's chest +# to create a double chest shop, but there is a block above the placed chest. +message.double-chest-blocked=&cThere must not be a block above the chest. + +# Set the message when the clicked shop is removed but no refund was given. +message.shop-removed=&6Shop removed. + +# Set the message when the clicked shop is removed and the player is refunded +# the creation price. +# Usable Placeholders: %CREATION-PRICE% +message.shop-removed-refund=&6Shop removed. You were refunded &c%CREATION-PRICE%&6. + +# Set the message when all shops of a player were removed. +# Usable Placeholders: %AMOUNT%, %VENDOR% +message.all-shops-removed=&6Removed all (&c%AMOUNT%&6) shops of &c%VENDOR%&6. + +# Set the message when the clicked chest is not a shop. +message.chest-no-shop=&cChest is not a shop. + +# Set the message when the player doesn't have enough money to create a shop +# Usable Placeholders: %CREATION-PRICE% +message.shop-create-not-enough-money=&cNot enough money. You need &6%CREATION-PRICE% &cto create a shop. + +# Set the vendor message the player gets after entering '/shop info'. +# Usable Placeholders: %VENDOR% +message.shopInfo.vendor=&6Vendor: &e%VENDOR% + +# Set the product message the player gets after entering '/shop info'. +# Usable Placeholders: %AMOUNT%, %ITEMNAME% +message.shopInfo.product=&6Product: &e%AMOUNT% x %ITEMNAME% + +# Set the in-stock message the player after entering '/shop info'. +# Usable Placeholders=%STOCK% +message.shopInfo.stock=&6In Stock: &e%STOCK% + +# Set the chest-space message the player after entering '/shop info'. +# Usable Placeholders=%CHEST-SPACE% +message.shopInfo.chest-space=&6Space in chest: &e%CHEST-SPACE% + +# Set the price message the player gets after entering '/shop info'. +# Usable Placeholders: %BUY-PRICE%, %SELL-PRICE% +message.shopInfo.price=&6Price: Buy: &e%BUY-PRICE%&6 Sell: &e%SELL-PRICE% + +# If the sell price or buy price is disabled, this message will be displayed instead of the price in the message above. +message.shopInfo.disabled=&7Disabled + +# Set the type message the player gets after entering '/shop info' ... +# ... when the shop is normal. +message.shopInfo.is-normal=&6Type: &eNormal + +# ... when the shop is an admin shop. +message.shopInfo.is-admin=&6Type: &eAdmin + +# Set the message when the player tries to create a shop with sell price and buy price set to 0 +message.buy-and-sell-disabled=&cYou can't create a shop with buying and selling disabled. + +# Set the message when the player successfully bought something. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %BUY-PRICE%, %VENDOR% +message.buy-success=&aYou bought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a from &6%VENDOR%&a. + +# Set the message when the player successfully bought something from an admin shop. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %BUY-PRICE% +message.buy-success-admin=&aYou bought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a. + +# Set the message when the player successfully sold something. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %SELL-PRICE%, %VENDOR% +message.sell-success=&aYou sold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to &6%VENDOR%&a. + +# Set the message when the player successfully sold something to an admin shop. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %SELL-PRICE% +message.sell-success-admin=&aYou sold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a. + +# Set the message when a player bought something from the player's shop. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %BUY-PRICE%, %PLAYER% +message.someone-bought=&6%PLAYER% &abought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a from your shop. + +# Set the message when a player sold something to the player's shop. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %SELL-PRICE%, %PLAYER% +message.someone-sold=&6%PLAYER% &asold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to your shop. + +# Set the message when a player joins and made a revenue while he was offline. +# Usable Placeholders: %REVENUE% +message.revenue-while-offline=&6While you were offline, your shops have made a revenue of &c%REVENUE%&6. + +# Set the message when the inventory is full when the player is buying something. +message.not-enough-inventory-space=&cNot enough space in inventory. + +# Set the message when the shop's inventory is full when the player is selling something. +message.chest-not-enough-inventory-space=&cShop is full. + +# Set the message when the player doesn't have enough money to buy something. +message.not-enough-money=&cNot enough money. + +# Set the message when the player doesn't have enough items to sell. +message.not-enough-items=&cNot enough items. + +# Set the message when the vendor doesn't have enough money to buy something from the player +message.vendor-not-enough-money=&cVendor has not enough money. + +# Set the message when the shop is out of stock. +message.out-of-stock=&cShop out of stock. + +# Set the message the vendor gets when his shop is out of stock +# Usable Placeholders: %AMOUNT%, %ITEMNAME% +message.vendor-out-of-stock=&cYour shop that sells &6%AMOUNT% x %ITEMNAME% &cis out of stock. + +# Set the message when an error occurred. +# Usable Placeholders: %ERROR% +message.error-occurred=&cAn error occurred: %ERROR% + +# Set the message when the arguments , and/or of '/shop create' are not a number. +message.amount-and-price-not-number=&cAmount and prices must be numbers. + +# Set the message when the argument is zero +message.amount-is-zero=&cAmount must be greater than 0. + +# Set the message when the config value "allow-decimals-in-prices" is set to false +# and a player enters a price with decimals +message.prices-contain-decimals=&cPrices must not contain decimals. + +# Set the message when the player doesn't hold an item in the hand. +message.no-item-in-hand=&cNo item in hand + +# Set the message when the player must click a chest to create a shop. +message.click-chest-to-create-shop=&aClick a chest within 15 seconds to create a shop. + +# Set the message when the player must click a shop to remove it. +message.click-chest-to-remove-shop=&aClick a shop within 15 seconds to remove it. + +# Set the message when the player must click a shop to retrieve information. +message.click-chest-for-info=&aClick a shop within 15 seconds to retrieve information. + +# Set the message when the player must click a shop to open it. +message.click-chest-to-open-shop=&aClick a shop within 15 seconds to open it. + +# Set the message when the player must click the shop again to confirm the buy/sell. +message.click-to-confirm=&aClick again to confirm. + +# Set the message when the player opened a shop. +# Usable Placeholders: %VENDOR% +message.opened-shop=&aYou opened %VENDOR%'s shop. + +# Set the message when the player tries to break a shop. +message.cannot-break-shop=&cYou can't break a shop. + +# Set the message when the player tries to sell a broken item. +message.cannot-sell-broken-item=&cYou can't sell a broken item. + +# Set the message when the entered buy price is below the minimum price. +# Usable Placeholders: %MIN-PRICE% +message.buy-price-too-low=&cThe buy price must be higher than %MIN-PRICE%. + +# Set the message when the entered sell price is below the minimum price. +# Usable Placeholders: %MIN-PRICE% +message.sell-price-too-low=&cThe sell price must be higher than %MIN-PRICE%. + +# Set the message when the entered buy price is below the maximum price. +# Usable Placeholders: %MAX-PRICE% +message.buy-price-too-high=&cThe buy price must be lower than %MAX-PRICE%. + +# Set the message when the entered sell price is below the maximum price. +# Usable Placeholders: %MAX-PRICE% +message.sell-price-too-high=&cThe sell price must be lower than %MAX-PRICE%. + +# Set the message when buying is disabled at the shop. +message.buying-disabled=&cBuying is disabled at this shop. + +# Set the message when selling is disabled at the shop. +message.selling-disabled=&cSelling is disabled at this shop. + +# Set the message when reloading is done. +# Usable Placeholders: %AMOUNT% (Amount of shops) +message.reloaded-shops=&aSuccessfully reloaded %AMOUNT% shop/s. + +# Set the message when the player's shop limit is reached. +# Usable Placeholders: %LIMIT% +message.shop-limit-reached=&cYou reached your limit of &6%LIMIT% &cshop/s. + +# Set the message that shows the player how many shop slots of his shop limit he has occupied. +# Usable Placeholders: %LIMIT%, %AMOUNT% (Amount of shops) +message.occupied-shop-slots=&6You have &c%AMOUNT%/%LIMIT% &6shop slot/s occupied. + +# Set the message when the player tries to create a shop with an item which is listed in the blacklist. +message.cannot-sell-item=&cYou cannot create a shop with this item. + +# Set the message when the player tries to use a shop in creative mode. +message.use-in-creative=&cYou cannot use a shop in creative mode. + +# Set the message when the player has to select an item from the creative menu. +message.select-item=&aOpen your inventory, and drop an item to select it. + +# Set the message when the player has selected an item from the creative menu. +# Usable Placeholders: %ITEMNAME% +message.item-selected=&aItem has been selected: &6%ITEMNAME% + +# Set the message when the player closes the creative menu to select an item. +message.creation-cancelled=&cShop creation has been cancelled. + +# Set the message when an update is available. +# Usable Placeholders: %VERSION% +message.update.update-available=&6&lVersion &c&l%VERSION% &6&lof &c&lShopChest &6&lis available &c&lhere. + +# Set the message you get when hovering over the available message. +message.update.click-to-download=Click to download + +# Set the message when no update is available. +message.update.no-update=&6&lNo new update available. + +# Set the message when the update checker is started. +message.update.checking=&6&lChecking for updates... + +# Set the message when an error occurs while checking for updates. +message.update.error=&c&lError while checking for updates. + +# Set the message when a not permitted player tries to create a shop. +message.noPermission.create=&cYou don't have permission to create a shop. + +# Set the message when a not permitted player tries to create an admin shop. +message.noPermission.create-admin=&cYou don't have permission to create an admin shop. + +# Set the message when a not permitted player tries to create a shop on a protected chest. +message.noPermission.create-protected=&cYou don't have permission to create a shop here. + +# Set the message when a not permitted player tries to open another player's shop. +message.noPermission.open-others=&cYou don't have permission to open this chest. + +# Set the message when a not permitted player tries to buy something. +message.noPermission.buy=&cYou don't have permission to buy something. + +# Set the message when a not permitted player tries to sell something. +message.noPermission.sell=&cYou don't have permission to sell something. + +# Set the message when a player tries to buy something in a region/plot that denied shop use. +message.noPermission.buy-here=&cYou don't have permission to buy something here. + +# Set the message when a player tries to sell something in a region/plot region that denied shop use. +message.noPermission.sell-here=&cYou don't have permission to sell something here. + +# Set the message when a not permitted player tries to remove another player's shop. +message.noPermission.remove-others=&cYou don't have permission to remove this shop. + +# Set the message when a not permitted player tries to remove an admin shop. +message.noPermission.remove-admin=&cYou don't have permission to remove an admin shop. + +# Set the message when a not permitted player tries to reload the shops. +message.noPermission.reload=&cYou don't have permission to reload the shops. + +# Set the message when a not permitted player tries to check for updates. +message.noPermission.update=&cYou don't have permission to check for updates. + +# Set the message when a not permitted player tries to change configuration values. +message.noPermission.config=&cYou don't have permission to change configuration values. + +# Set the message when a not permitted player tries to extend another player's shop's chest. +message.noPermission.extend-others=&cYou don't have permission to extend this chest. + +# Set the message when a not permitted player tries to extend a chest into a protected region/plot (e.g. WorldGuard/Towny). +message.noPermission.extend-protected=&cYou don't have permission to extend this chest to here. + +# Set the header of the help message the player gets after entering '/shop' or an invalid command. +# Usable Placeholders: %COMMAND% +message.commandDescription.header=&6==== &c/%COMMAND% &6Help + +# Set the footer of the help message the player gets after entering '/shop' or an invalid command. +# Usable Placeholders: %COMMAND% +message.commandDescription.footer=&6==== End + +# Set the command description message for '/shop create' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.create=&a/%COMMAND% create - Create a shop. + +# Set the command description message for '/shop create' when you type '/shop' and have permission "shopchest.create.admin" +# Usable Placeholders: %COMMAND% +message.commandDescription.create-admin=&a/%COMMAND% create [admin] - Create a shop. + +# Set the command description message for '/shop remove' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.remove=&a/%COMMAND% remove - Remove a shop. + +# Set the command description message for '/shop info' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.info=&a/%COMMAND% info - Retrieve shop information. + +# Set the command description message for '/shop removeall' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.removeall=&a/%COMMAND% removeall - Remove all shops of a player. + +# Set the command description message for '/shop reload' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.reload=&a/%COMMAND% reload - Reload shops. + +# Set the command description message for '/shop update' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.update=&a/%COMMAND% update - Check for Updates. + +# Set the command description message for '/shop limits' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.limits=&a/%COMMAND% limits - View shop limits. + +# Set the command description message for '/shop open' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.open=&a/%COMMAND% open - Open a shop. + +# Set the command description message for '/shop config' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.config=&a/%COMMAND% config - Change configuration values. + +# Set the message a player gets after setting a configuration value per command +# Usable Placeholders: %PROPERTY%, %VALUE% +message.config.set=&6Changed &a%PROPERTY% &6to &a%VALUE%&6. + +# Set the message a player gets after adding a value to a list in the configuration per command +# Usable Placeholders: %PROPERTY%, %VALUE% +message.config.added=&6Added &a%VALUE% &6to &a%PROPERTY%&6. + +# Set the message a player gets after removing a value from a list in the configuration per command +# Usable Placeholders: %PROPERTY%, %VALUE% +message.config.removed=&6Removed &a%VALUE% &6from &a%PROPERTY%&6. + +book.generation.0=Original +book.generation.1=Copy of original +book.generation.2=Copy of a copy +book.generation.3=Tattered +tile.barrier.name=Barrier +tile.stone.stone.name=Stone +tile.stone.granite.name=Granite +tile.stone.graniteSmooth.name=Polished Granite +tile.stone.diorite.name=Diorite +tile.stone.dioriteSmooth.name=Polished Diorite +tile.stone.andesite.name=Andesite +tile.stone.andesiteSmooth.name=Polished Andesite +tile.hayBlock.name=Hay Bale +tile.grass.name=Grass Block +tile.dirt.default.name=Dirt +tile.dirt.coarse.name=Coarse Dirt +tile.dirt.podzol.name=Podzol +tile.stonebrick.name=Cobblestone +tile.wood.oak.name=Oak Wood Planks +tile.wood.spruce.name=Spruce Wood Planks +tile.wood.birch.name=Birch Wood Planks +tile.wood.jungle.name=Jungle Wood Planks +tile.wood.acacia.name=Acacia Wood Planks +tile.wood.big_oak.name=Dark Oak Wood Planks +tile.sapling.oak.name=Oak Sapling +tile.sapling.spruce.name=Spruce Sapling +tile.sapling.birch.name=Birch Sapling +tile.sapling.jungle.name=Jungle Sapling +tile.sapling.acacia.name=Acacia Sapling +tile.sapling.big_oak.name=Dark Oak Sapling +tile.deadbush.name=Dead Bush +tile.bedrock.name=Bedrock +tile.water.name=Water +tile.lava.name=Lava +tile.sand.default.name=Sand +tile.sand.red.name=Red Sand +tile.sandStone.default.name=Sandstone +tile.sandStone.chiseled.name=Chiseled Sandstone +tile.sandStone.smooth.name=Smooth Sandstone +tile.redSandStone.default.name=Red Sandstone +tile.redSandStone.chiseled.name=Chiseled Red Sandstone +tile.redSandStone.smooth.name=Smooth Red Sandstone +tile.gravel.name=Gravel +tile.oreGold.name=Gold Ore +tile.oreIron.name=Iron Ore +tile.oreCoal.name=Coal Ore +tile.log.oak.name=Oak Wood +tile.log.spruce.name=Spruce Wood +tile.log.birch.name=Birch Wood +tile.log.jungle.name=Jungle Wood +tile.log.acacia.name=Acacia Wood +tile.log.big_oak.name=Dark Oak Wood +tile.leaves.oak.name=Oak Leaves +tile.leaves.spruce.name=Spruce Leaves +tile.leaves.birch.name=Birch Leaves +tile.leaves.jungle.name=Jungle Leaves +tile.leaves.acacia.name=Acacia Leaves +tile.leaves.big_oak.name=Dark Oak Leaves +tile.tallgrass.shrub.name=Shrub +tile.tallgrass.grass.name=Grass +tile.tallgrass.fern.name=Fern +tile.sponge.dry.name=Sponge +tile.sponge.wet.name=Wet Sponge +tile.glass.name=Glass +tile.stainedGlass.black.name=Black Stained Glass +tile.stainedGlass.red.name=Red Stained Glass +tile.stainedGlass.green.name=Green Stained Glass +tile.stainedGlass.brown.name=Brown Stained Glass +tile.stainedGlass.blue.name=Blue Stained Glass +tile.stainedGlass.purple.name=Purple Stained Glass +tile.stainedGlass.cyan.name=Cyan Stained Glass +tile.stainedGlass.silver.name=Light Gray Stained Glass +tile.stainedGlass.gray.name=Gray Stained Glass +tile.stainedGlass.pink.name=Pink Stained Glass +tile.stainedGlass.lime.name=Lime Stained Glass +tile.stainedGlass.yellow.name=Yellow Stained Glass +tile.stainedGlass.lightBlue.name=Light Blue Stained Glass +tile.stainedGlass.magenta.name=Magenta Stained Glass +tile.stainedGlass.orange.name=Orange Stained Glass +tile.stainedGlass.white.name=White Stained Glass +tile.thinStainedGlass.black.name=Black Stained Glass Pane +tile.thinStainedGlass.red.name=Red Stained Glass Pane +tile.thinStainedGlass.green.name=Green Stained Glass Pane +tile.thinStainedGlass.brown.name=Brown Stained Glass Pane +tile.thinStainedGlass.blue.name=Blue Stained Glass Pane +tile.thinStainedGlass.purple.name=Purple Stained Glass Pane +tile.thinStainedGlass.cyan.name=Cyan Stained Glass Pane +tile.thinStainedGlass.silver.name=Light Gray Stained Glass Pane +tile.thinStainedGlass.gray.name=Gray Stained Glass Pane +tile.thinStainedGlass.pink.name=Pink Stained Glass Pane +tile.thinStainedGlass.lime.name=Lime Stained Glass Pane +tile.thinStainedGlass.yellow.name=Yellow Stained Glass Pane +tile.thinStainedGlass.lightBlue.name=Light Blue Stained Glass Pane +tile.thinStainedGlass.magenta.name=Magenta Stained Glass Pane +tile.thinStainedGlass.orange.name=Orange Stained Glass Pane +tile.thinStainedGlass.white.name=White Stained Glass Pane +tile.thinGlass.name=Glass Pane +tile.flower1.dandelion.name=Dandelion +tile.flower2.poppy.name=Poppy +tile.flower2.blueOrchid.name=Blue Orchid +tile.flower2.allium.name=Allium +tile.flower2.houstonia.name=Azure Bluet +tile.flower2.tulipRed.name=Red Tulip +tile.flower2.tulipOrange.name=Orange Tulip +tile.flower2.tulipWhite.name=White Tulip +tile.flower2.tulipPink.name=Pink Tulip +tile.flower2.oxeyeDaisy.name=Oxeye Daisy +tile.doublePlant.sunflower.name=Sunflower +tile.doublePlant.syringa.name=Lilac +tile.doublePlant.grass.name=Double Tallgrass +tile.doublePlant.fern.name=Large Fern +tile.doublePlant.rose.name=Rose Bush +tile.doublePlant.paeonia.name=Peony +tile.mushroom.name=Mushroom +tile.blockGold.name=Block of Gold +tile.blockIron.name=Block of Iron +tile.stoneSlab.stone.name=Stone Slab +tile.stoneSlab.sand.name=Sandstone Slab +tile.stoneSlab.wood.name=Wooden Slab +tile.stoneSlab.cobble.name=Cobblestone Slab +tile.stoneSlab.brick.name=Bricks Slab +tile.stoneSlab.smoothStoneBrick.name=Stone Bricks Slab +tile.stoneSlab.netherBrick.name=Nether Brick Slab +tile.stoneSlab.quartz.name=Quartz Slab +tile.stoneSlab2.red_sandstone.name=Red Sandstone Slab +tile.woodSlab.oak.name=Oak Wood Slab +tile.woodSlab.spruce.name=Spruce Wood Slab +tile.woodSlab.birch.name=Birch Wood Slab +tile.woodSlab.jungle.name=Jungle Wood Slab +tile.woodSlab.acacia.name=Acacia Wood Slab +tile.woodSlab.big_oak.name=Dark Oak Wood Slab +tile.brick.name=Bricks +tile.tnt.name=TNT +tile.bookshelf.name=Bookshelf +tile.stoneMoss.name=Moss Stone +tile.obsidian.name=Obsidian +tile.torch.name=Torch +tile.fire.name=Fire +tile.mobSpawner.name=Monster Spawner +tile.stairsWood.name=Oak Wood Stairs +tile.stairsWoodSpruce.name=Spruce Wood Stairs +tile.stairsWoodBirch.name=Birch Wood Stairs +tile.stairsWoodJungle.name=Jungle Wood Stairs +tile.stairsWoodAcacia.name=Acacia Wood Stairs +tile.stairsWoodDarkOak.name=Dark Oak Wood Stairs +tile.chest.name=Chest +tile.chestTrap.name=Trapped Chest +tile.oreDiamond.name=Diamond Ore +tile.blockCoal.name=Block of Coal +tile.blockDiamond.name=Block of Diamond +tile.workbench.name=Crafting Table +tile.farmland.name=Farmland +tile.furnace.name=Furnace +tile.ladder.name=Ladder +tile.rail.name=Rail +tile.goldenRail.name=Powered Rail +tile.activatorRail.name=Activator Rail +tile.detectorRail.name=Detector Rail +tile.stairsStone.name=Cobblestone Stairs +tile.stairsSandStone.name=Sandstone Stairs +tile.stairsRedSandStone.name=Red Sandstone Stairs +tile.lever.name=Lever +tile.pressurePlateStone.name=Stone Pressure Plate +tile.pressurePlateWood.name=Wooden Pressure Plate +tile.weightedPlate_light.name=Weighted Pressure Plate (Light) +tile.weightedPlate_heavy.name=Weighted Pressure Plate (Heavy) +tile.oreRedstone.name=Redstone Ore +tile.notGate.name=Redstone Torch +tile.button.name=Button +tile.snow.name=Snow +tile.woolCarpet.black.name=Black Carpet +tile.woolCarpet.red.name=Red Carpet +tile.woolCarpet.green.name=Green Carpet +tile.woolCarpet.brown.name=Brown Carpet +tile.woolCarpet.blue.name=Blue Carpet +tile.woolCarpet.purple.name=Purple Carpet +tile.woolCarpet.cyan.name=Cyan Carpet +tile.woolCarpet.silver.name=Light Gray Carpet +tile.woolCarpet.gray.name=Gray Carpet +tile.woolCarpet.pink.name=Pink Carpet +tile.woolCarpet.lime.name=Lime Carpet +tile.woolCarpet.yellow.name=Yellow Carpet +tile.woolCarpet.lightBlue.name=Light Blue Carpet +tile.woolCarpet.magenta.name=Magenta Carpet +tile.woolCarpet.orange.name=Orange Carpet +tile.woolCarpet.white.name=White Carpet +tile.ice.name=Ice +tile.icePacked.name=Packed Ice +tile.cactus.name=Cactus +tile.clay.name=Clay +tile.clayHardenedStained.black.name=Black Terracotta +tile.clayHardenedStained.red.name=Red Terracotta +tile.clayHardenedStained.green.name=Green Terracotta +tile.clayHardenedStained.brown.name=Brown Terracotta +tile.clayHardenedStained.blue.name=Blue Terracotta +tile.clayHardenedStained.purple.name=Purple Terracotta +tile.clayHardenedStained.cyan.name=Cyan Terracotta +tile.clayHardenedStained.silver.name=Light Gray Terracotta +tile.clayHardenedStained.gray.name=Gray Terracotta +tile.clayHardenedStained.pink.name=Pink Terracotta +tile.clayHardenedStained.lime.name=Lime Terracotta +tile.clayHardenedStained.yellow.name=Yellow Terracotta +tile.clayHardenedStained.lightBlue.name=Light Blue Terracotta +tile.clayHardenedStained.magenta.name=Magenta Terracotta +tile.clayHardenedStained.orange.name=Orange Terracotta +tile.clayHardenedStained.white.name=White Terracotta +tile.clayHardened.name=Terracotta +tile.jukebox.name=Jukebox +tile.fence.name=Oak Fence +tile.spruceFence.name=Spruce Fence +tile.birchFence.name=Birch Fence +tile.jungleFence.name=Jungle Fence +tile.darkOakFence.name=Dark Oak Fence +tile.acaciaFence.name=Acacia Fence +tile.fenceGate.name=Oak Fence Gate +tile.spruceFenceGate.name=Spruce Fence Gate +tile.birchFenceGate.name=Birch Fence Gate +tile.jungleFenceGate.name=Jungle Fence Gate +tile.darkOakFenceGate.name=Dark Oak Fence Gate +tile.acaciaFenceGate.name=Acacia Fence Gate +tile.pumpkin.name=Pumpkin +tile.litpumpkin.name=Jack o'Lantern +tile.hellrock.name=Netherrack +tile.hellsand.name=Soul Sand +tile.lightgem.name=Glowstone +tile.portal.name=Portal +tile.cloth.black.name=Black Wool +tile.cloth.red.name=Red Wool +tile.cloth.green.name=Green Wool +tile.cloth.brown.name=Brown Wool +tile.cloth.blue.name=Blue Wool +tile.cloth.purple.name=Purple Wool +tile.cloth.cyan.name=Cyan Wool +tile.cloth.silver.name=Light Gray Wool +tile.cloth.gray.name=Gray Wool +tile.cloth.pink.name=Pink Wool +tile.cloth.lime.name=Lime Wool +tile.cloth.yellow.name=Yellow Wool +tile.cloth.lightBlue.name=Light Blue Wool +tile.cloth.magenta.name=Magenta Wool +tile.cloth.orange.name=Orange Wool +tile.cloth.white.name=White Wool +tile.oreLapis.name=Lapis Lazuli Ore +tile.blockLapis.name=Lapis Lazuli Block +tile.dispenser.name=Dispenser +tile.dropper.name=Dropper +tile.musicBlock.name=Note Block +tile.trapdoor.name=Wooden Trapdoor +tile.ironTrapdoor.name=Iron Trapdoor +tile.web.name=Cobweb +tile.stonebricksmooth.default.name=Stone Bricks +tile.stonebricksmooth.mossy.name=Mossy Stone Bricks +tile.stonebricksmooth.cracked.name=Cracked Stone Bricks +tile.stonebricksmooth.chiseled.name=Chiseled Stone Bricks +tile.monsterStoneEgg.stone.name=Stone Monster Egg +tile.monsterStoneEgg.cobble.name=Cobblestone Monster Egg +tile.monsterStoneEgg.brick.name=Stone Brick Monster Egg +tile.monsterStoneEgg.mossybrick.name=Mossy Stone Brick Monster Egg +tile.monsterStoneEgg.crackedbrick.name=Cracked Stone Brick Monster Egg +tile.monsterStoneEgg.chiseledbrick.name=Chiseled Stone Brick Monster Egg +tile.pistonBase.name=Piston +tile.pistonStickyBase.name=Sticky Piston +tile.fenceIron.name=Iron Bars +tile.melon.name=Melon +tile.stairsBrick.name=Brick Stairs +tile.stairsStoneBrickSmooth.name=Stone Brick Stairs +tile.vine.name=Vines +tile.netherBrick.name=Nether Brick +tile.netherFence.name=Nether Brick Fence +tile.stairsNetherBrick.name=Nether Brick Stairs +tile.netherStalk.name=Nether Wart +tile.enchantmentTable.name=Enchantment Table +tile.anvil.intact.name=Anvil +tile.anvil.slightlyDamaged.name=Slightly Damaged Anvil +tile.anvil.veryDamaged.name=Very Damaged Anvil +tile.whiteStone.name=End Stone +tile.endPortalFrame.name=End Portal +tile.mycel.name=Mycelium +tile.waterlily.name=Lily Pad +tile.dragonEgg.name=Dragon Egg +tile.redstoneLight.name=Redstone Lamp +tile.enderChest.name=Ender Chest +tile.oreEmerald.name=Emerald Ore +tile.blockEmerald.name=Block of Emerald +tile.blockRedstone.name=Block of Redstone +tile.tripWireSource.name=Tripwire Hook +tile.commandBlock.name=Command Block +tile.repeatingCommandBlock.name=Repeating Command Block +tile.chainCommandBlock.name=Chain Command Block +tile.beacon.name=Beacon +tile.cobbleWall.normal.name=Cobblestone Wall +tile.cobbleWall.mossy.name=Mossy Cobblestone Wall +tile.daylightDetector.name=Daylight Sensor +tile.netherquartz.name=Nether Quartz Ore +tile.hopper.name=Hopper +tile.quartzBlock.default.name=Block of Quartz +tile.quartzBlock.chiseled.name=Chiseled Quartz Block +tile.quartzBlock.lines.name=Pillar Quartz Block +tile.stairsQuartz.name=Quartz Stairs +tile.slime.name=Slime Block +tile.prismarine.rough.name=Prismarine +tile.prismarine.bricks.name=Prismarine Bricks +tile.prismarine.dark.name=Dark Prismarine +tile.seaLantern.name=Sea Lantern +tile.endRod.name=End Rod +tile.chorusPlant.name=Chorus Plant +tile.chorusFlower.name=Chorus Flower +tile.purpurBlock.name=Purpur Block +tile.purpurPillar.name=Purpur Pillar +tile.stairsPurpur.name=Purpur Stairs +tile.purpurSlab.name=Purpur Slab +tile.endBricks.name=End Stone Bricks +tile.grassPath.name=Grass Path +tile.magma.name=Magma Block +tile.netherWartBlock.name=Nether Wart Block +tile.redNetherBrick.name=Red Nether Brick +tile.boneBlock.name=Bone Block +tile.observer.name=Observer +tile.shulkerBoxWhite.name=White Shulker Box +tile.shulkerBoxOrange.name=Orange Shulker Box +tile.shulkerBoxMagenta.name=Magenta Shulker Box +tile.shulkerBoxLightBlue.name=Light Blue Shulker Box +tile.shulkerBoxYellow.name=Yellow Shulker Box +tile.shulkerBoxLime.name=Lime Shulker Box +tile.shulkerBoxPink.name=Pink Shulker Box +tile.shulkerBoxGray.name=Gray Shulker Box +tile.shulkerBoxSilver.name=Light Gray Shulker Box +tile.shulkerBoxCyan.name=Cyan Shulker Box +tile.shulkerBoxPurple.name=Purple Shulker Box +tile.shulkerBoxBlue.name=Blue Shulker Box +tile.shulkerBoxBrown.name=Brown Shulker Box +tile.shulkerBoxGreen.name=Green Shulker Box +tile.shulkerBoxRed.name=Red Shulker Box +tile.shulkerBoxBlack.name=Black Shulker Box +tile.glazedTerracottaWhite.name=White Glazed Terracotta +tile.glazedTerracottaOrange.name=Orange Glazed Terracotta +tile.glazedTerracottaMagenta.name=Magenta Glazed Terracotta +tile.glazedTerracottaLightBlue.name=Light Blue Glazed Terracotta +tile.glazedTerracottaYellow.name=Yellow Glazed Terracotta +tile.glazedTerracottaLime.name=Lime Glazed Terracotta +tile.glazedTerracottaPink.name=Pink Glazed Terracotta +tile.glazedTerracottaGray.name=Gray Glazed Terracotta +tile.glazedTerracottaSilver.name=Light Gray Glazed Terracotta +tile.glazedTerracottaCyan.name=Cyan Glazed Terracotta +tile.glazedTerracottaPurple.name=Purple Glazed Terracotta +tile.glazedTerracottaBlue.name=Blue Glazed Terracotta +tile.glazedTerracottaBrown.name=Brown Glazed Terracotta +tile.glazedTerracottaGreen.name=Green Glazed Terracotta +tile.glazedTerracottaRed.name=Red Glazed Terracotta +tile.glazedTerracottaBlack.name=Black Glazed Terracotta +tile.concrete.black.name=Black Concrete +tile.concrete.red.name=Red Concrete +tile.concrete.green.name=Green Concrete +tile.concrete.brown.name=Brown Concrete +tile.concrete.blue.name=Blue Concrete +tile.concrete.purple.name=Purple Concrete +tile.concrete.cyan.name=Cyan Concrete +tile.concrete.silver.name=Light Gray Concrete +tile.concrete.gray.name=Gray Concrete +tile.concrete.pink.name=Pink Concrete +tile.concrete.lime.name=Lime Concrete +tile.concrete.yellow.name=Yellow Concrete +tile.concrete.lightBlue.name=Light Blue Concrete +tile.concrete.magenta.name=Magenta Concrete +tile.concrete.orange.name=Orange Concrete +tile.concrete.white.name=White Concrete +tile.concretePowder.black.name=Black Concrete Powder +tile.concretePowder.red.name=Red Concrete Powder +tile.concretePowder.green.name=Green Concrete Powder +tile.concretePowder.brown.name=Brown Concrete Powder +tile.concretePowder.blue.name=Blue Concrete Powder +tile.concretePowder.purple.name=Purple Concrete Powder +tile.concretePowder.cyan.name=Cyan Concrete Powder +tile.concretePowder.silver.name=Light Gray Concrete Powder +tile.concretePowder.gray.name=Gray Concrete Powder +tile.concretePowder.pink.name=Pink Concrete Powder +tile.concretePowder.lime.name=Lime Concrete Powder +tile.concretePowder.yellow.name=Yellow Concrete Powder +tile.concretePowder.lightBlue.name=Light Blue Concrete Powder +tile.concretePowder.magenta.name=Magenta Concrete Powder +tile.concretePowder.orange.name=Orange Concrete Powder +tile.concretePowder.white.name=White Concrete Powder +tile.structureVoid.name=Structure Void +tile.structureBlock.name=Structure Block +item.nameTag.name=Name Tag +item.leash.name=Lead +item.shovelIron.name=Iron Shovel +item.pickaxeIron.name=Iron Pickaxe +item.hatchetIron.name=Iron Axe +item.flintAndSteel.name=Flint and Steel +item.apple.name=Apple +item.cookie.name=Cookie +item.bow.name=Bow +item.arrow.name=Arrow +item.spectral_arrow.name=Spectral Arrow +item.tipped_arrow.name=Tipped Arrow +item.coal.name=Coal +item.charcoal.name=Charcoal +item.diamond.name=Diamond +item.emerald.name=Emerald +item.ingotIron.name=Iron Ingot +item.ingotGold.name=Gold Ingot +item.swordIron.name=Iron Sword +item.swordWood.name=Wooden Sword +item.shovelWood.name=Wooden Shovel +item.pickaxeWood.name=Wooden Pickaxe +item.hatchetWood.name=Wooden Axe +item.swordStone.name=Stone Sword +item.shovelStone.name=Stone Shovel +item.pickaxeStone.name=Stone Pickaxe +item.hatchetStone.name=Stone Axe +item.swordDiamond.name=Diamond Sword +item.shovelDiamond.name=Diamond Shovel +item.pickaxeDiamond.name=Diamond Pickaxe +item.hatchetDiamond.name=Diamond Axe +item.stick.name=Stick +item.bowl.name=Bowl +item.mushroomStew.name=Mushroom Stew +item.swordGold.name=Golden Sword +item.shovelGold.name=Golden Shovel +item.pickaxeGold.name=Golden Pickaxe +item.hatchetGold.name=Golden Axe +item.string.name=String +item.feather.name=Feather +item.sulphur.name=Gunpowder +item.hoeWood.name=Wooden Hoe +item.hoeStone.name=Stone Hoe +item.hoeIron.name=Iron Hoe +item.hoeDiamond.name=Diamond Hoe +item.hoeGold.name=Golden Hoe +item.seeds.name=Seeds +item.seeds_pumpkin.name=Pumpkin Seeds +item.seeds_melon.name=Melon Seeds +item.melon.name=Melon +item.wheat.name=Wheat +item.bread.name=Bread +item.helmetCloth.name=Leather Cap +item.chestplateCloth.name=Leather Tunic +item.leggingsCloth.name=Leather Pants +item.bootsCloth.name=Leather Boots +item.helmetChain.name=Chain Helmet +item.chestplateChain.name=Chain Chestplate +item.leggingsChain.name=Chain Leggings +item.bootsChain.name=Chain Boots +item.helmetIron.name=Iron Helmet +item.chestplateIron.name=Iron Chestplate +item.leggingsIron.name=Iron Leggings +item.bootsIron.name=Iron Boots +item.helmetDiamond.name=Diamond Helmet +item.chestplateDiamond.name=Diamond Chestplate +item.leggingsDiamond.name=Diamond Leggings +item.bootsDiamond.name=Diamond Boots +item.helmetGold.name=Golden Helmet +item.chestplateGold.name=Golden Chestplate +item.leggingsGold.name=Golden Leggings +item.bootsGold.name=Golden Boots +item.flint.name=Flint +item.porkchopRaw.name=Raw Porkchop +item.porkchopCooked.name=Cooked Porkchop +item.chickenRaw.name=Raw Chicken +item.chickenCooked.name=Cooked Chicken +item.muttonRaw.name=Raw Mutton +item.muttonCooked.name=Cooked Mutton +item.rabbitRaw.name=Raw Rabbit +item.rabbitCooked.name=Cooked Rabbit +item.rabbitStew.name=Rabbit Stew +item.rabbitFoot.name=Rabbit's Foot +item.rabbitHide.name=Rabbit Hide +item.beefRaw.name=Raw Beef +item.beefCooked.name=Steak +item.painting.name=Painting +item.frame.name=Item Frame +item.appleGold.name=Golden Apple +item.sign.name=Sign +item.doorOak.name=Oak Door +item.doorSpruce.name=Spruce Door +item.doorBirch.name=Birch Door +item.doorJungle.name=Jungle Door +item.doorAcacia.name=Acacia Door +item.doorDarkOak.name=Dark Oak Door +item.bucket.name=Bucket +item.bucketWater.name=Water Bucket +item.bucketLava.name=Lava Bucket +item.minecart.name=Minecart +item.saddle.name=Saddle +item.doorIron.name=Iron Door +item.redstone.name=Redstone +item.snowball.name=Snowball +item.boat.oak.name=Oak Boat +item.boat.spruce.name=Spruce Boat +item.boat.birch.name=Birch Boat +item.boat.jungle.name=Jungle Boat +item.boat.acacia.name=Acacia Boat +item.boat.dark_oak.name=Dark Oak Boat +item.leather.name=Leather +item.milk.name=Milk +item.brick.name=Brick +item.clay.name=Clay +item.reeds.name=Sugar Canes +item.paper.name=Paper +item.book.name=Book +item.slimeball.name=Slimeball +item.minecartChest.name=Minecart with Chest +item.minecartFurnace.name=Minecart with Furnace +item.minecartTnt.name=Minecart with TNT +item.minecartHopper.name=Minecart with Hopper +item.minecartCommandBlock.name=Minecart with Command Block +item.egg.name=Egg +item.compass.name=Compass +item.fishingRod.name=Fishing Rod +item.clock.name=Clock +item.yellowDust.name=Glowstone Dust +item.fish.cod.raw.name=Raw Fish +item.fish.salmon.raw.name=Raw Salmon +item.fish.pufferfish.raw.name=Pufferfish +item.fish.clownfish.raw.name=Clownfish +item.fish.cod.cooked.name=Cooked Fish +item.fish.salmon.cooked.name=Cooked Salmon +item.record.name=Music Disc +item.record.13.desc=C418 - 13 +item.record.cat.desc=C418 - cat +item.record.blocks.desc=C418 - blocks +item.record.chirp.desc=C418 - chirp +item.record.far.desc=C418 - far +item.record.mall.desc=C418 - mall +item.record.mellohi.desc=C418 - mellohi +item.record.stal.desc=C418 - stal +item.record.strad.desc=C418 - strad +item.record.ward.desc=C418 - ward +item.record.11.desc=C418 - 11 +item.record.wait.desc=C418 - wait +item.bone.name=Bone +item.dyePowder.black.name=Ink Sac +item.dyePowder.red.name=Rose Red +item.dyePowder.green.name=Cactus Green +item.dyePowder.brown.name=Cocoa Beans +item.dyePowder.blue.name=Lapis Lazuli +item.dyePowder.purple.name=Purple Dye +item.dyePowder.cyan.name=Cyan Dye +item.dyePowder.silver.name=Light Gray Dye +item.dyePowder.gray.name=Gray Dye +item.dyePowder.pink.name=Pink Dye +item.dyePowder.lime.name=Lime Dye +item.dyePowder.yellow.name=Dandelion Yellow +item.dyePowder.lightBlue.name=Light Blue Dye +item.dyePowder.magenta.name=Magenta Dye +item.dyePowder.orange.name=Orange Dye +item.dyePowder.white.name=Bone Meal +item.sugar.name=Sugar +item.cake.name=Cake +item.bed.name=Bed +item.bed.black.name=Black Bed +item.bed.red.name=Red Bed +item.bed.green.name=Green Bed +item.bed.brown.name=Brown Bed +item.bed.blue.name=Blue Bed +item.bed.purple.name=Purple Bed +item.bed.cyan.name=Cyan Bed +item.bed.silver.name=Light Gray Bed +item.bed.gray.name=Gray Bed +item.bed.pink.name=Pink Bed +item.bed.lime.name=Lime Bed +item.bed.yellow.name=Yellow Bed +item.bed.lightBlue.name=Light Blue Bed +item.bed.magenta.name=Magenta Bed +item.bed.orange.name=Orange Bed +item.bed.white.name=White Bed +item.diode.name=Redstone Repeater +item.comparator.name=Redstone Comparator +item.map.name=Map +item.shears.name=Shears +item.rottenFlesh.name=Rotten Flesh +item.enderPearl.name=Ender Pearl +item.blazeRod.name=Blaze Rod +item.ghastTear.name=Ghast Tear +item.netherStalkSeeds.name=Nether Wart +item.potion.name=Potion +item.end_crystal.name=End Crystal +item.goldNugget.name=Gold Nugget +item.glassBottle.name=Glass Bottle +item.spiderEye.name=Spider Eye +item.fermentedSpiderEye.name=Fermented Spider Eye +item.blazePowder.name=Blaze Powder +item.magmaCream.name=Magma Cream +item.cauldron.name=Cauldron +item.brewingStand.name=Brewing Stand +item.eyeOfEnder.name=Eye of Ender +item.speckledMelon.name=Glistering Melon +item.monsterPlacer.name=Spawn +item.expBottle.name=Bottle o' Enchanting +item.fireball.name=Fire Charge +item.writingBook.name=Book and Quill +item.writtenBook.name=Written Book +item.flowerPot.name=Flower Pot +item.emptyMap.name=Empty Map +item.carrots.name=Carrot +item.carrotGolden.name=Golden Carrot +item.potato.name=Potato +item.potatoBaked.name=Baked Potato +item.potatoPoisonous.name=Poisonous Potato +item.skull.skeleton.name=Skeleton Skull +item.skull.wither.name=Wither Skeleton Skull +item.skull.zombie.name=Zombie Head +item.skull.char.name=Head +item.skull.creeper.name=Creeper Head +item.skull.dragon.name=Dragon Head +item.carrotOnAStick.name=Carrot on a Stick +item.netherStar.name=Nether Star +item.pumpkinPie.name=Pumpkin Pie +item.enchantedBook.name=Enchanted Book +item.fireworks.name=Firework Rocket +item.fireworksCharge.name=Firework Star +item.netherbrick.name=Nether Brick +item.netherquartz.name=Nether Quartz +item.armorStand.name=Armor Stand +item.horsearmormetal.name=Iron Horse Armor +item.horsearmorgold.name=Gold Horse Armor +item.horsearmordiamond.name=Diamond Horse Armor +item.prismarineShard.name=Prismarine Shard +item.prismarineCrystals.name=Prismarine Crystals +item.chorusFruit.name=Chorus Fruit +item.chorusFruitPopped.name=Popped Chorus Fruit +item.beetroot.name=Beetroot +item.beetroot_seeds.name=Beetroot Seeds +item.beetroot_soup.name=Beetroot Soup +item.dragon_breath.name=Dragon's Breath +item.elytra.name=Elytra +item.totem.name=Totem of Undying +item.shulkerShell.name=Shulker Shell +item.ironNugget.name=Iron Nugget +item.knowledgeBook.name=Knowledge Book +entity.Creeper.name=Creeper +entity.Skeleton.name=Skeleton +entity.WitherSkeleton.name=Wither Skeleton +entity.Stray.name=Stray +entity.Spider.name=Spider +entity.Zombie.name=Zombie +entity.Husk.name=Husk +entity.Slime.name=Slime +entity.Ghast.name=Ghast +entity.PigZombie.name=Zombie Pigman +entity.Enderman.name=Enderman +entity.Endermite.name=Endermite +entity.EntityHorse.name=Horse +entity.Silverfish.name=Silverfish +entity.CaveSpider.name=Cave Spider +entity.Blaze.name=Blaze +entity.LavaSlime.name=Magma Cube +entity.MushroomCow.name=Mooshroom +entity.Villager.name=Villager +entity.ZombieVillager.name=Zombie Villager +entity.Witch.name=Witch +entity.Guardian.name=Guardian +entity.ElderGuardian.name=Elder Guardian +entity.Shulker.name=Shulker +entity.PolarBear.name=Polar Bear +entity.EvocationIllager.name=Evoker +entity.Vex.name=Vex +entity.VindicationIllager.name=Vindicator +entity.Parrot.name=Parrot +entity.IllusionIllager.name=Illusioner +entity.Pig.name=Pig +entity.Sheep.name=Sheep +entity.Cow.name=Cow +entity.Chicken.name=Chicken +entity.Squid.name=Squid +entity.Wolf.name=Wolf +entity.Ozelot.name=Ocelot +entity.Bat.name=Bat +entity.Horse.name=Horse +entity.Donkey.name=Donkey +entity.Mule.name=Mule +entity.SkeletonHorse.name=Skeleton Horse +entity.ZombieHorse.name=Zombie Horse +entity.Rabbit.name=Rabbit +entity.Llama.name=Llama +effect.moveSpeed=Speed +effect.moveSlowdown=Slowness +effect.damageBoost=Strength +effect.heal=Instant Health +effect.harm=Instant Damage +effect.jump=Jump Boost +effect.regeneration=Regeneration +effect.fireResistance=Fire Resistance +effect.waterBreathing=Water Breathing +effect.invisibility=Invisibility +effect.nightVision=Night Vision +effect.weakness=Weakness +effect.poison=Poison +effect.luck=Luck +tipped_arrow.effect.empty=Uncraftable Tipped Arrow +tipped_arrow.effect.water=Tipped Arrow +tipped_arrow.effect.mundane=Tipped Arrow +tipped_arrow.effect.thick=Tipped Arrow +tipped_arrow.effect.awkward=Tipped Arrow +tipped_arrow.effect.night_vision=Arrow of Night Vision +tipped_arrow.effect.invisibility=Arrow of Invisibility +tipped_arrow.effect.leaping=Arrow of Leaping +tipped_arrow.effect.fire_resistance=Arrow of Fire Resistance +tipped_arrow.effect.swiftness=Arrow of Swiftness +tipped_arrow.effect.slowness=Arrow of Slowness +tipped_arrow.effect.water_breathing=Arrow of Water Breathing +tipped_arrow.effect.healing=Arrow of Healing +tipped_arrow.effect.harming=Arrow of Harming +tipped_arrow.effect.poison=Arrow of Poison +tipped_arrow.effect.regeneration=Arrow of Regeneration +tipped_arrow.effect.strength=Arrow of Strength +tipped_arrow.effect.weakness=Arrow of Weakness +tipped_arrow.effect.luck=Arrow of Luck +potion.effect.empty=Uncraftable Potion +potion.effect.water=Water Bottle +potion.effect.mundane=Mundane Potion +potion.effect.thick=Thick Potion +potion.effect.awkward=Awkward Potion +potion.effect.night_vision=Potion of Night Vision +potion.effect.invisibility=Potion of Invisibility +potion.effect.leaping=Potion of Leaping +potion.effect.fire_resistance=Potion of Fire Resistance +potion.effect.swiftness=Potion of Swiftness +potion.effect.slowness=Potion of Slowness +potion.effect.water_breathing=Potion of Water Breathing +potion.effect.healing=Potion of Healing +potion.effect.harming=Potion of Harming +potion.effect.poison=Potion of Poison +potion.effect.regeneration=Potion of Regeneration +potion.effect.strength=Potion of Strength +potion.effect.weakness=Potion of Weakness +potion.effect.luck=Potion of Luck +splash_potion.effect.empty=Splash Uncraftable Potion +splash_potion.effect.water=Splash Water Bottle +splash_potion.effect.mundane=Mundane Splash Potion +splash_potion.effect.thick=Thick Splash Potion +splash_potion.effect.awkward=Awkward Splash Potion +splash_potion.effect.night_vision=Splash Potion of Night Vision +splash_potion.effect.invisibility=Splash Potion of Invisibility +splash_potion.effect.leaping=Splash Potion of Leaping +splash_potion.effect.fire_resistance=Splash Potion of Fire Resistance +splash_potion.effect.swiftness=Splash Potion of Swiftness +splash_potion.effect.slowness=Splash Potion of Slowness +splash_potion.effect.water_breathing=Splash Potion of Water Breathing +splash_potion.effect.healing=Splash Potion of Healing +splash_potion.effect.harming=Splash Potion of Harming +splash_potion.effect.poison=Splash Potion of Poison +splash_potion.effect.regeneration=Splash Potion of Regeneration +splash_potion.effect.strength=Splash Potion of Strength +splash_potion.effect.weakness=Splash Potion of Weakness +splash_potion.effect.luck=Splash Potion of Luck +lingering_potion.effect.empty=Lingering Uncraftable Potion +lingering_potion.effect.water=Lingering Water Bottle +lingering_potion.effect.mundane=Mundane Lingering Potion +lingering_potion.effect.thick=Thick Lingering Potion +lingering_potion.effect.awkward=Awkward Lingering Potion +lingering_potion.effect.night_vision=Lingering Potion of Night Vision +lingering_potion.effect.invisibility=Lingering Potion of Invisibility +lingering_potion.effect.leaping=Lingering Potion of Leaping +lingering_potion.effect.fire_resistance=Lingering Potion of Fire Resistance +lingering_potion.effect.swiftness=Lingering Potion of Swiftness +lingering_potion.effect.slowness=Lingering Potion of Slowness +lingering_potion.effect.water_breathing=Lingering Potion of Water Breathing +lingering_potion.effect.healing=Lingering Potion of Healing +lingering_potion.effect.harming=Lingering Potion of Harming +lingering_potion.effect.poison=Lingering Potion of Poison +lingering_potion.effect.regeneration=Lingering Potion of Regeneration +lingering_potion.effect.strength=Lingering Potion of Strength +lingering_potion.effect.weakness=Lingering Potion of Weakness +lingering_potion.effect.luck=Lingering Potion of Luck +enchantment.damage.all=Sharpness +enchantment.damage.undead=Smite +enchantment.damage.arthropods=Bane of Arthropods +enchantment.knockback=Knockback +enchantment.fire=Fire Aspect +enchantment.sweeping=Sweeping Edge +enchantment.protect.all=Protection +enchantment.protect.fire=Fire Protection +enchantment.protect.fall=Feather Falling +enchantment.protect.explosion=Blast Protection +enchantment.protect.projectile=Projectile Protection +enchantment.oxygen=Respiration +enchantment.waterWorker=Aqua Affinity +enchantment.waterWalker=Depth Strider +enchantment.frostWalker=Frost Walker +enchantment.digging=Efficiency +enchantment.untouching=Silk Touch +enchantment.durability=Unbreaking +enchantment.lootBonus=Looting +enchantment.lootBonusDigger=Fortune +enchantment.lootBonusFishing=Luck of the Sea +enchantment.fishingSpeed=Lure +enchantment.arrowDamage=Power +enchantment.arrowFire=Flame +enchantment.arrowKnockback=Punch +enchantment.arrowInfinite=Infinity +enchantment.thorns=Thorns +enchantment.mending=Mending +enchantment.binding_curse=Curse of Binding +enchantment.vanishing_curse=Curse of Vanishing +enchantment.level.1=I +enchantment.level.2=II +enchantment.level.3=III +enchantment.level.4=IV +enchantment.level.5=V +enchantment.level.6=VI +enchantment.level.7=VII +enchantment.level.8=VIII +enchantment.level.9=IX +enchantment.level.10=X +item.banner.black.name=Black Banner +item.banner.red.name=Red Banner +item.banner.green.name=Green Banner +item.banner.brown.name=Brown Banner +item.banner.blue.name=Blue Banner +item.banner.purple.name=Purple Banner +item.banner.cyan.name=Cyan Banner +item.banner.silver.name=Light Gray Banner +item.banner.gray.name=Gray Banner +item.banner.pink.name=Pink Banner +item.banner.lime.name=Lime Banner +item.banner.yellow.name=Yellow Banner +item.banner.lightBlue.name=Light Blue Banner +item.banner.magenta.name=Magenta Banner +item.banner.orange.name=Orange Banner +item.banner.white.name=White Banner +item.shield.name=Shield \ No newline at end of file diff --git a/plugin/src/main/resources/lang/en_US.lang b/plugin/src/main/resources/lang/en_US.lang new file mode 100644 index 0000000..d403ea8 --- /dev/null +++ b/plugin/src/main/resources/lang/en_US.lang @@ -0,0 +1,1754 @@ +# Set the message when a shop is created at the clicked chest. +# Usable Placeholders: %CREATION-PRICE% +message.shop-created=&6You were withdrawn &c%CREATION-PRICE% &6to create this shop. + +# Set the message when an admin shop is created at the clicked chest. +# Usable Placeholders: %CREATION-PRICE% +message.admin-shop-created=&6You were withdrawn &c%CREATION-PRICE% &6to create this admin shop. + +# Set the message when the clicked chest already is a shop. +message.chest-already-shop=&cChest already is shop. + +# Set the message when there is a block above the clicked chest. +message.chest-blocked=&cThere must not be a block above the chest. + +# Set the message when a player tries to place a chest next to a shop's chest +# to create a double chest shop, but there is a block above the placed chest. +message.double-chest-blocked=&cThere must not be a block above the chest. + +# Set the message when the clicked shop is removed but no refund was given. +message.shop-removed=&6Shop removed. + +# Set the message when the clicked shop is removed and the player is refunded +# the creation price. +# Usable Placeholders: %CREATION-PRICE% +message.shop-removed-refund=&6Shop removed. You were refunded &c%CREATION-PRICE%&6. + +# Set the message when all shops of a player were removed. +# Usable Placeholders: %AMOUNT%, %VENDOR% +message.all-shops-removed=&6Removed all (&c%AMOUNT%&6) shops of &c%VENDOR%&6. + +# Set the message when the clicked chest is not a shop. +message.chest-no-shop=&cChest is not a shop. + +# Set the message when the player doesn't have enough money to create a shop +# Usable Placeholders: %CREATION-PRICE% +message.shop-create-not-enough-money=&cNot enough money. You need &6%CREATION-PRICE% &cto create a shop. + +# Set the vendor message the player gets after entering '/shop info'. +# Usable Placeholders: %VENDOR% +message.shopInfo.vendor=&6Vendor: &e%VENDOR% + +# Set the product message the player gets after entering '/shop info'. +# Usable Placeholders: %AMOUNT%, %ITEMNAME% +message.shopInfo.product=&6Product: &e%AMOUNT% x %ITEMNAME% + +# Set the in-stock message the player after entering '/shop info'. +# Usable Placeholders=%STOCK% +message.shopInfo.stock=&6In Stock: &e%STOCK% + +# Set the chest-space message the player after entering '/shop info'. +# Usable Placeholders=%CHEST-SPACE% +message.shopInfo.chest-space=&6Space in chest: &e%CHEST-SPACE% + +# Set the price message the player gets after entering '/shop info'. +# Usable Placeholders: %BUY-PRICE%, %SELL-PRICE% +message.shopInfo.price=&6Price: Buy: &e%BUY-PRICE%&6 Sell: &e%SELL-PRICE% + +# If the sell price or buy price is disabled, this message will be displayed instead of the price in the message above. +message.shopInfo.disabled=&7Disabled + +# Set the type message the player gets after entering '/shop info' ... +# ... when the shop is normal. +message.shopInfo.is-normal=&6Type: &eNormal + +# ... when the shop is an admin shop. +message.shopInfo.is-admin=&6Type: &eAdmin + +# Set the message when the player tries to create a shop with sell price and buy price set to 0 +message.buy-and-sell-disabled=&cYou can't create a shop with buying and selling disabled. + +# Set the message when the player successfully bought something. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %BUY-PRICE%, %VENDOR% +message.buy-success=&aYou bought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a from &6%VENDOR%&a. + +# Set the message when the player successfully bought something from an admin shop. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %BUY-PRICE% +message.buy-success-admin=&aYou bought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a. + +# Set the message when the player successfully sold something. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %SELL-PRICE%, %VENDOR% +message.sell-success=&aYou sold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to &6%VENDOR%&a. + +# Set the message when the player successfully sold something to an admin shop. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %SELL-PRICE% +message.sell-success-admin=&aYou sold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a. + +# Set the message when a player bought something from the player's shop. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %BUY-PRICE%, %PLAYER% +message.someone-bought=&6%PLAYER% &abought &6%AMOUNT% x %ITEMNAME%&a for &6%BUY-PRICE%&a from your shop. + +# Set the message when a player sold something to the player's shop. +# Usable Placeholders: %AMOUNT%, %ITEMNAME%, %SELL-PRICE%, %PLAYER% +message.someone-sold=&6%PLAYER% &asold &6%AMOUNT% x %ITEMNAME%&a for &6%SELL-PRICE%&a to your shop. + +# Set the message when a player joins and made a revenue while he was offline. +# Usable Placeholders: %REVENUE% +message.revenue-while-offline=&6While you were offline, your shops have made a revenue of &c%REVENUE%&6. + +# Set the message when the inventory is full when the player is buying something. +message.not-enough-inventory-space=&cNot enough space in inventory. + +# Set the message when the shop's inventory is full when the player is selling something. +message.chest-not-enough-inventory-space=&cShop is full. + +# Set the message when the player doesn't have enough money to buy something. +message.not-enough-money=&cNot enough money. + +# Set the message when the player doesn't have enough items to sell. +message.not-enough-items=&cNot enough items. + +# Set the message when the vendor doesn't have enough money to buy something from the player +message.vendor-not-enough-money=&cVendor has not enough money. + +# Set the message when the shop is out of stock. +message.out-of-stock=&cShop out of stock. + +# Set the message the vendor gets when his shop is out of stock +# Usable Placeholders: %AMOUNT%, %ITEMNAME% +message.vendor-out-of-stock=&cYour shop that sells &6%AMOUNT% x %ITEMNAME% &cis out of stock. + +# Set the message when an error occurred. +# Usable Placeholders: %ERROR% +message.error-occurred=&cAn error occurred: %ERROR% + +# Set the message when the arguments , and/or of '/shop create' are not a number. +message.amount-and-price-not-number=&cAmount and prices must be numbers. + +# Set the message when the argument is zero +message.amount-is-zero=&cAmount must be greater than 0. + +# Set the message when the config value "allow-decimals-in-prices" is set to false +# and a player enters a price with decimals +message.prices-contain-decimals=&cPrices must not contain decimals. + +# Set the message when the player doesn't hold an item in the hand. +message.no-item-in-hand=&cNo item in hand + +# Set the message when the player must click a chest to create a shop. +message.click-chest-to-create-shop=&aClick a chest within 15 seconds to create a shop. + +# Set the message when the player must click a shop to remove it. +message.click-chest-to-remove-shop=&aClick a shop within 15 seconds to remove it. + +# Set the message when the player must click a shop to retrieve information. +message.click-chest-for-info=&aClick a shop within 15 seconds to retrieve information. + +# Set the message when the player must click a shop to open it. +message.click-chest-to-open-shop=&aClick a shop within 15 seconds to open it. + +# Set the message when the player must click the shop again to confirm the buy/sell. +message.click-to-confirm=&aClick again to confirm. + +# Set the message when the player opened a shop. +# Usable Placeholders: %VENDOR% +message.opened-shop=&aYou opened %VENDOR%'s shop. + +# Set the message when the player tries to break a shop. +message.cannot-break-shop=&cYou can't break a shop. + +# Set the message when the player tries to sell a broken item. +message.cannot-sell-broken-item=&cYou can't sell a broken item. + +# Set the message when the entered buy price is below the minimum price. +# Usable Placeholders: %MIN-PRICE% +message.buy-price-too-low=&cThe buy price must be higher than %MIN-PRICE%. + +# Set the message when the entered sell price is below the minimum price. +# Usable Placeholders: %MIN-PRICE% +message.sell-price-too-low=&cThe sell price must be higher than %MIN-PRICE%. + +# Set the message when the entered buy price is below the maximum price. +# Usable Placeholders: %MAX-PRICE% +message.buy-price-too-high=&cThe buy price must be lower than %MAX-PRICE%. + +# Set the message when the entered sell price is below the maximum price. +# Usable Placeholders: %MAX-PRICE% +message.sell-price-too-high=&cThe sell price must be lower than %MAX-PRICE%. + +# Set the message when buying is disabled at the shop. +message.buying-disabled=&cBuying is disabled at this shop. + +# Set the message when selling is disabled at the shop. +message.selling-disabled=&cSelling is disabled at this shop. + +# Set the message when reloading is done. +# Usable Placeholders: %AMOUNT% (Amount of shops) +message.reloaded-shops=&aSuccessfully reloaded %AMOUNT% shop/s. + +# Set the message when the player's shop limit is reached. +# Usable Placeholders: %LIMIT% +message.shop-limit-reached=&cYou reached your limit of &6%LIMIT% &cshop/s. + +# Set the message that shows the player how many shop slots of his shop limit he has occupied. +# Usable Placeholders: %LIMIT%, %AMOUNT% (Amount of shops) +message.occupied-shop-slots=&6You have &c%AMOUNT%/%LIMIT% &6shop slot/s occupied. + +# Set the message when the player tries to create a shop with an item which is listed in the blacklist. +message.cannot-sell-item=&cYou cannot create a shop with this item. + +# Set the message when the player tries to use a shop in creative mode. +message.use-in-creative=&cYou cannot use a shop in creative mode. + +# Set the message when the player has to select an item from the creative menu. +message.select-item=&aOpen your inventory, and drop an item to select it. + +# Set the message when the player has selected an item from the creative menu. +# Usable Placeholders: %ITEMNAME% +message.item-selected=&aItem has been selected: &6%ITEMNAME% + +# Set the message when the player closes the creative menu to select an item. +message.creation-cancelled=&cShop creation has been cancelled. + +# Set the message when an update is available. +# Usable Placeholders: %VERSION% +message.update.update-available=&6&lVersion &c&l%VERSION% &6&lof &c&lShopChest &6&lis available &c&lhere. + +# Set the message you get when hovering over the available message. +message.update.click-to-download=Click to download + +# Set the message when no update is available. +message.update.no-update=&6&lNo new update available. + +# Set the message when the update checker is started. +message.update.checking=&6&lChecking for updates... + +# Set the message when an error occurs while checking for updates. +message.update.error=&c&lError while checking for updates. + +# Set the message when a not permitted player tries to create a shop. +message.noPermission.create=&cYou don't have permission to create a shop. + +# Set the message when a not permitted player tries to create an admin shop. +message.noPermission.create-admin=&cYou don't have permission to create an admin shop. + +# Set the message when a not permitted player tries to create a shop on a protected chest. +message.noPermission.create-protected=&cYou don't have permission to create a shop here. + +# Set the message when a not permitted player tries to open another player's shop. +message.noPermission.open-others=&cYou don't have permission to open this chest. + +# Set the message when a not permitted player tries to buy something. +message.noPermission.buy=&cYou don't have permission to buy something. + +# Set the message when a not permitted player tries to sell something. +message.noPermission.sell=&cYou don't have permission to sell something. + +# Set the message when a player tries to buy something in a region/plot that denied shop use. +message.noPermission.buy-here=&cYou don't have permission to buy something here. + +# Set the message when a player tries to sell something in a region/plot region that denied shop use. +message.noPermission.sell-here=&cYou don't have permission to sell something here. + +# Set the message when a not permitted player tries to remove another player's shop. +message.noPermission.remove-others=&cYou don't have permission to remove this shop. + +# Set the message when a not permitted player tries to remove an admin shop. +message.noPermission.remove-admin=&cYou don't have permission to remove an admin shop. + +# Set the message when a not permitted player tries to reload the shops. +message.noPermission.reload=&cYou don't have permission to reload the shops. + +# Set the message when a not permitted player tries to check for updates. +message.noPermission.update=&cYou don't have permission to check for updates. + +# Set the message when a not permitted player tries to change configuration values. +message.noPermission.config=&cYou don't have permission to change configuration values. + +# Set the message when a not permitted player tries to extend another player's shop's chest. +message.noPermission.extend-others=&cYou don't have permission to extend this chest. + +# Set the message when a not permitted player tries to extend a chest into a protected region/plot (e.g. WorldGuard/Towny). +message.noPermission.extend-protected=&cYou don't have permission to extend this chest to here. + +# Set the header of the help message the player gets after entering '/shop' or an invalid command. +# Usable Placeholders: %COMMAND% +message.commandDescription.header=&6==== &c/%COMMAND% &6Help + +# Set the footer of the help message the player gets after entering '/shop' or an invalid command. +# Usable Placeholders: %COMMAND% +message.commandDescription.footer=&6==== End + +# Set the command description message for '/shop create' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.create=&a/%COMMAND% create - Create a shop. + +# Set the command description message for '/shop create' when you type '/shop' and have permission "shopchest.create.admin" +# Usable Placeholders: %COMMAND% +message.commandDescription.create-admin=&a/%COMMAND% create [admin] - Create a shop. + +# Set the command description message for '/shop remove' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.remove=&a/%COMMAND% remove - Remove a shop. + +# Set the command description message for '/shop info' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.info=&a/%COMMAND% info - Retrieve shop information. + +# Set the command description message for '/shop removeall' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.removeall=&a/%COMMAND% removeall - Remove all shops of a player. + +# Set the command description message for '/shop reload' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.reload=&a/%COMMAND% reload - Reload shops. + +# Set the command description message for '/shop update' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.update=&a/%COMMAND% update - Check for Updates. + +# Set the command description message for '/shop limits' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.limits=&a/%COMMAND% limits - View shop limits. + +# Set the command description message for '/shop open' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.open=&a/%COMMAND% open - Open a shop. + +# Set the command description message for '/shop config' when you type '/shop'. +# Usable Placeholders: %COMMAND% +message.commandDescription.config=&a/%COMMAND% config - Change configuration values. + +# Set the message a player gets after setting a configuration value per command +# Usable Placeholders: %PROPERTY%, %VALUE% +message.config.set=&6Changed &a%PROPERTY% &6to &a%VALUE%&6. + +# Set the message a player gets after adding a value to a list in the configuration per command +# Usable Placeholders: %PROPERTY%, %VALUE% +message.config.added=&6Added &a%VALUE% &6to &a%PROPERTY%&6. + +# Set the message a player gets after removing a value from a list in the configuration per command +# Usable Placeholders: %PROPERTY%, %VALUE% +message.config.removed=&6Removed &a%VALUE% &6from &a%PROPERTY%&6. + +book.generation.0=Original +book.generation.1=Copy of original +book.generation.2=Copy of a copy +book.generation.3=Tattered +block.minecraft.air=Air +block.minecraft.barrier=Barrier +block.minecraft.light=Light +block.minecraft.stone=Stone +block.minecraft.granite=Granite +block.minecraft.polished_granite=Polished Granite +block.minecraft.diorite=Diorite +block.minecraft.polished_diorite=Polished Diorite +block.minecraft.andesite=Andesite +block.minecraft.polished_andesite=Polished Andesite +block.minecraft.hay_block=Hay Bale +block.minecraft.grass_block=Grass Block +block.minecraft.dirt=Dirt +block.minecraft.coarse_dirt=Coarse Dirt +block.minecraft.podzol=Podzol +block.minecraft.cobblestone=Cobblestone +block.minecraft.oak_planks=Oak Planks +block.minecraft.spruce_planks=Spruce Planks +block.minecraft.birch_planks=Birch Planks +block.minecraft.jungle_planks=Jungle Planks +block.minecraft.acacia_planks=Acacia Planks +block.minecraft.dark_oak_planks=Dark Oak Planks +block.minecraft.oak_sapling=Oak Sapling +block.minecraft.spruce_sapling=Spruce Sapling +block.minecraft.birch_sapling=Birch Sapling +block.minecraft.jungle_sapling=Jungle Sapling +block.minecraft.acacia_sapling=Acacia Sapling +block.minecraft.dark_oak_sapling=Dark Oak Sapling +block.minecraft.oak_door=Oak Door +block.minecraft.spruce_door=Spruce Door +block.minecraft.birch_door=Birch Door +block.minecraft.jungle_door=Jungle Door +block.minecraft.acacia_door=Acacia Door +block.minecraft.dark_oak_door=Dark Oak Door +block.minecraft.bedrock=Bedrock +block.minecraft.water=Water +block.minecraft.lava=Lava +block.minecraft.sand=Sand +block.minecraft.red_sand=Red Sand +block.minecraft.sandstone=Sandstone +block.minecraft.chiseled_sandstone=Chiseled Sandstone +block.minecraft.cut_sandstone=Cut Sandstone +block.minecraft.red_sandstone=Red Sandstone +block.minecraft.chiseled_red_sandstone=Chiseled Red Sandstone +block.minecraft.cut_red_sandstone=Cut Red Sandstone +block.minecraft.gravel=Gravel +block.minecraft.gold_ore=Gold Ore +block.minecraft.deepslate_gold_ore=Deepslate Gold Ore +block.minecraft.nether_gold_ore=Nether Gold Ore +block.minecraft.iron_ore=Iron Ore +block.minecraft.deepslate_iron_ore=Deepslate Iron Ore +block.minecraft.coal_ore=Coal Ore +block.minecraft.deepslate_coal_ore=Deepslate Coal Ore +block.minecraft.oak_wood=Oak Wood +block.minecraft.spruce_wood=Spruce Wood +block.minecraft.birch_wood=Birch Wood +block.minecraft.jungle_wood=Jungle Wood +block.minecraft.acacia_wood=Acacia Wood +block.minecraft.dark_oak_wood=Dark Oak Wood +block.minecraft.oak_log=Oak Log +block.minecraft.spruce_log=Spruce Log +block.minecraft.birch_log=Birch Log +block.minecraft.jungle_log=Jungle Log +block.minecraft.acacia_log=Acacia Log +block.minecraft.dark_oak_log=Dark Oak Log +block.minecraft.stripped_oak_log=Stripped Oak Log +block.minecraft.stripped_spruce_log=Stripped Spruce Log +block.minecraft.stripped_birch_log=Stripped Birch Log +block.minecraft.stripped_jungle_log=Stripped Jungle Log +block.minecraft.stripped_acacia_log=Stripped Acacia Log +block.minecraft.stripped_dark_oak_log=Stripped Dark Oak Log +block.minecraft.stripped_oak_wood=Stripped Oak Wood +block.minecraft.stripped_spruce_wood=Stripped Spruce Wood +block.minecraft.stripped_birch_wood=Stripped Birch Wood +block.minecraft.stripped_jungle_wood=Stripped Jungle Wood +block.minecraft.stripped_acacia_wood=Stripped Acacia Wood +block.minecraft.stripped_dark_oak_wood=Stripped Dark Oak Wood +block.minecraft.oak_leaves=Oak Leaves +block.minecraft.spruce_leaves=Spruce Leaves +block.minecraft.birch_leaves=Birch Leaves +block.minecraft.jungle_leaves=Jungle Leaves +block.minecraft.acacia_leaves=Acacia Leaves +block.minecraft.dark_oak_leaves=Dark Oak Leaves +block.minecraft.dead_bush=Dead Bush +block.minecraft.grass=Grass +block.minecraft.fern=Fern +block.minecraft.sponge=Sponge +block.minecraft.wet_sponge=Wet Sponge +block.minecraft.glass=Glass +block.minecraft.kelp_plant=Kelp Plant +block.minecraft.kelp=Kelp +block.minecraft.dried_kelp_block=Dried Kelp Block +block.minecraft.white_stained_glass=White Stained Glass +block.minecraft.orange_stained_glass=Orange Stained Glass +block.minecraft.magenta_stained_glass=Magenta Stained Glass +block.minecraft.light_blue_stained_glass=Light Blue Stained Glass +block.minecraft.yellow_stained_glass=Yellow Stained Glass +block.minecraft.lime_stained_glass=Lime Stained Glass +block.minecraft.pink_stained_glass=Pink Stained Glass +block.minecraft.gray_stained_glass=Gray Stained Glass +block.minecraft.light_gray_stained_glass=Light Gray Stained Glass +block.minecraft.cyan_stained_glass=Cyan Stained Glass +block.minecraft.purple_stained_glass=Purple Stained Glass +block.minecraft.blue_stained_glass=Blue Stained Glass +block.minecraft.brown_stained_glass=Brown Stained Glass +block.minecraft.green_stained_glass=Green Stained Glass +block.minecraft.red_stained_glass=Red Stained Glass +block.minecraft.black_stained_glass=Black Stained Glass +block.minecraft.white_stained_glass_pane=White Stained Glass Pane +block.minecraft.orange_stained_glass_pane=Orange Stained Glass Pane +block.minecraft.magenta_stained_glass_pane=Magenta Stained Glass Pane +block.minecraft.light_blue_stained_glass_pane=Light Blue Stained Glass Pane +block.minecraft.yellow_stained_glass_pane=Yellow Stained Glass Pane +block.minecraft.lime_stained_glass_pane=Lime Stained Glass Pane +block.minecraft.pink_stained_glass_pane=Pink Stained Glass Pane +block.minecraft.gray_stained_glass_pane=Gray Stained Glass Pane +block.minecraft.light_gray_stained_glass_pane=Light Gray Stained Glass Pane +block.minecraft.cyan_stained_glass_pane=Cyan Stained Glass Pane +block.minecraft.purple_stained_glass_pane=Purple Stained Glass Pane +block.minecraft.blue_stained_glass_pane=Blue Stained Glass Pane +block.minecraft.brown_stained_glass_pane=Brown Stained Glass Pane +block.minecraft.green_stained_glass_pane=Green Stained Glass Pane +block.minecraft.red_stained_glass_pane=Red Stained Glass Pane +block.minecraft.black_stained_glass_pane=Black Stained Glass Pane +block.minecraft.glass_pane=Glass Pane +block.minecraft.dandelion=Dandelion +block.minecraft.poppy=Poppy +block.minecraft.blue_orchid=Blue Orchid +block.minecraft.allium=Allium +block.minecraft.azure_bluet=Azure Bluet +block.minecraft.red_tulip=Red Tulip +block.minecraft.orange_tulip=Orange Tulip +block.minecraft.white_tulip=White Tulip +block.minecraft.pink_tulip=Pink Tulip +block.minecraft.oxeye_daisy=Oxeye Daisy +block.minecraft.cornflower=Cornflower +block.minecraft.lily_of_the_valley=Lily of the Valley +block.minecraft.wither_rose=Wither Rose +block.minecraft.sunflower=Sunflower +block.minecraft.lilac=Lilac +block.minecraft.tall_grass=Tall Grass +block.minecraft.tall_seagrass=Tall Seagrass +block.minecraft.large_fern=Large Fern +block.minecraft.rose_bush=Rose Bush +block.minecraft.peony=Peony +block.minecraft.seagrass=Seagrass +block.minecraft.sea_pickle=Sea Pickle +block.minecraft.brown_mushroom=Brown Mushroom +block.minecraft.red_mushroom_block=Red Mushroom Block +block.minecraft.brown_mushroom_block=Brown Mushroom Block +block.minecraft.mushroom_stem=Mushroom Stem +block.minecraft.gold_block=Block of Gold +block.minecraft.iron_block=Block of Iron +block.minecraft.smooth_stone=Smooth Stone +block.minecraft.smooth_sandstone=Smooth Sandstone +block.minecraft.smooth_red_sandstone=Smooth Red Sandstone +block.minecraft.smooth_quartz=Smooth Quartz Block +block.minecraft.stone_slab=Stone Slab +block.minecraft.smooth_stone_slab=Smooth Stone Slab +block.minecraft.sandstone_slab=Sandstone Slab +block.minecraft.red_sandstone_slab=Red Sandstone Slab +block.minecraft.cut_sandstone_slab=Cut Sandstone Slab +block.minecraft.cut_red_sandstone_slab=Cut Red Sandstone Slab +block.minecraft.petrified_oak_slab=Petrified Oak Slab +block.minecraft.cobblestone_slab=Cobblestone Slab +block.minecraft.brick_slab=Brick Slab +block.minecraft.stone_brick_slab=Stone Brick Slab +block.minecraft.nether_brick_slab=Nether Brick Slab +block.minecraft.quartz_slab=Quartz Slab +block.minecraft.oak_slab=Oak Slab +block.minecraft.spruce_slab=Spruce Slab +block.minecraft.birch_slab=Birch Slab +block.minecraft.jungle_slab=Jungle Slab +block.minecraft.acacia_slab=Acacia Slab +block.minecraft.dark_oak_slab=Dark Oak Slab +block.minecraft.dark_prismarine_slab=Dark Prismarine Slab +block.minecraft.prismarine_slab=Prismarine Slab +block.minecraft.prismarine_brick_slab=Prismarine Brick Slab +block.minecraft.bricks=Bricks +block.minecraft.tnt=TNT +block.minecraft.bookshelf=Bookshelf +block.minecraft.mossy_cobblestone=Mossy Cobblestone +block.minecraft.obsidian=Obsidian +block.minecraft.torch=Torch +block.minecraft.wall_torch=Wall Torch +block.minecraft.soul_torch=Soul Torch +block.minecraft.soul_wall_torch=Soul Wall Torch +block.minecraft.fire=Fire +block.minecraft.spawner=Spawner +block.minecraft.respawn_anchor=Respawn Anchor +block.minecraft.oak_stairs=Oak Stairs +block.minecraft.spruce_stairs=Spruce Stairs +block.minecraft.birch_stairs=Birch Stairs +block.minecraft.jungle_stairs=Jungle Stairs +block.minecraft.acacia_stairs=Acacia Stairs +block.minecraft.dark_oak_stairs=Dark Oak Stairs +block.minecraft.dark_prismarine_stairs=Dark Prismarine Stairs +block.minecraft.prismarine_stairs=Prismarine Stairs +block.minecraft.prismarine_brick_stairs=Prismarine Brick Stairs +block.minecraft.chest=Chest +block.minecraft.trapped_chest=Trapped Chest +block.minecraft.redstone_wire=Redstone Wire +block.minecraft.diamond_ore=Diamond Ore +block.minecraft.deepslate_diamond_ore=Deepslate Diamond Ore +block.minecraft.coal_block=Block of Coal +block.minecraft.diamond_block=Block of Diamond +block.minecraft.crafting_table=Crafting Table +block.minecraft.wheat=Wheat Crops +block.minecraft.farmland=Farmland +block.minecraft.furnace=Furnace +block.minecraft.wall_sign=Wall Sign +block.minecraft.oak_sign=Oak Sign +block.minecraft.spruce_sign=Spruce Sign +block.minecraft.birch_sign=Birch Sign +block.minecraft.acacia_sign=Acacia Sign +block.minecraft.jungle_sign=Jungle Sign +block.minecraft.dark_oak_sign=Dark Oak Sign +block.minecraft.oak_wall_sign=Oak Wall Sign +block.minecraft.spruce_wall_sign=Spruce Wall Sign +block.minecraft.birch_wall_sign=Birch Wall Sign +block.minecraft.acacia_wall_sign=Acacia Wall Sign +block.minecraft.jungle_wall_sign=Jungle Wall Sign +block.minecraft.dark_oak_wall_sign=Dark Oak Wall Sign +block.minecraft.ladder=Ladder +block.minecraft.scaffolding=Scaffolding +block.minecraft.rail=Rail +block.minecraft.powered_rail=Powered Rail +block.minecraft.activator_rail=Activator Rail +block.minecraft.detector_rail=Detector Rail +block.minecraft.cobblestone_stairs=Cobblestone Stairs +block.minecraft.sandstone_stairs=Sandstone Stairs +block.minecraft.red_sandstone_stairs=Red Sandstone Stairs +block.minecraft.lever=Lever +block.minecraft.stone_pressure_plate=Stone Pressure Plate +block.minecraft.oak_pressure_plate=Oak Pressure Plate +block.minecraft.spruce_pressure_plate=Spruce Pressure Plate +block.minecraft.birch_pressure_plate=Birch Pressure Plate +block.minecraft.jungle_pressure_plate=Jungle Pressure Plate +block.minecraft.acacia_pressure_plate=Acacia Pressure Plate +block.minecraft.dark_oak_pressure_plate=Dark Oak Pressure Plate +block.minecraft.light_weighted_pressure_plate=Light Weighted Pressure Plate +block.minecraft.heavy_weighted_pressure_plate=Heavy Weighted Pressure Plate +block.minecraft.iron_door=Iron Door +block.minecraft.redstone_ore=Redstone Ore +block.minecraft.deepslate_redstone_ore=Deepslate Redstone Ore +block.minecraft.redstone_torch=Redstone Torch +block.minecraft.redstone_wall_torch=Redstone Wall Torch +block.minecraft.stone_button=Stone Button +block.minecraft.oak_button=Oak Button +block.minecraft.spruce_button=Spruce Button +block.minecraft.birch_button=Birch Button +block.minecraft.jungle_button=Jungle Button +block.minecraft.acacia_button=Acacia Button +block.minecraft.dark_oak_button=Dark Oak Button +block.minecraft.snow=Snow +block.minecraft.white_carpet=White Carpet +block.minecraft.orange_carpet=Orange Carpet +block.minecraft.magenta_carpet=Magenta Carpet +block.minecraft.light_blue_carpet=Light Blue Carpet +block.minecraft.yellow_carpet=Yellow Carpet +block.minecraft.lime_carpet=Lime Carpet +block.minecraft.pink_carpet=Pink Carpet +block.minecraft.gray_carpet=Gray Carpet +block.minecraft.light_gray_carpet=Light Gray Carpet +block.minecraft.cyan_carpet=Cyan Carpet +block.minecraft.purple_carpet=Purple Carpet +block.minecraft.blue_carpet=Blue Carpet +block.minecraft.brown_carpet=Brown Carpet +block.minecraft.green_carpet=Green Carpet +block.minecraft.red_carpet=Red Carpet +block.minecraft.black_carpet=Black Carpet +block.minecraft.ice=Ice +block.minecraft.frosted_ice=Frosted Ice +block.minecraft.packed_ice=Packed Ice +block.minecraft.blue_ice=Blue Ice +block.minecraft.cactus=Cactus +block.minecraft.clay=Clay +block.minecraft.white_terracotta=White Terracotta +block.minecraft.orange_terracotta=Orange Terracotta +block.minecraft.magenta_terracotta=Magenta Terracotta +block.minecraft.light_blue_terracotta=Light Blue Terracotta +block.minecraft.yellow_terracotta=Yellow Terracotta +block.minecraft.lime_terracotta=Lime Terracotta +block.minecraft.pink_terracotta=Pink Terracotta +block.minecraft.gray_terracotta=Gray Terracotta +block.minecraft.light_gray_terracotta=Light Gray Terracotta +block.minecraft.cyan_terracotta=Cyan Terracotta +block.minecraft.purple_terracotta=Purple Terracotta +block.minecraft.blue_terracotta=Blue Terracotta +block.minecraft.brown_terracotta=Brown Terracotta +block.minecraft.green_terracotta=Green Terracotta +block.minecraft.red_terracotta=Red Terracotta +block.minecraft.black_terracotta=Black Terracotta +block.minecraft.terracotta=Terracotta +block.minecraft.sugar_cane=Sugar Cane +block.minecraft.jukebox=Jukebox +block.minecraft.oak_fence=Oak Fence +block.minecraft.spruce_fence=Spruce Fence +block.minecraft.birch_fence=Birch Fence +block.minecraft.jungle_fence=Jungle Fence +block.minecraft.dark_oak_fence=Dark Oak Fence +block.minecraft.acacia_fence=Acacia Fence +block.minecraft.oak_fence_gate=Oak Fence Gate +block.minecraft.spruce_fence_gate=Spruce Fence Gate +block.minecraft.birch_fence_gate=Birch Fence Gate +block.minecraft.jungle_fence_gate=Jungle Fence Gate +block.minecraft.dark_oak_fence_gate=Dark Oak Fence Gate +block.minecraft.acacia_fence_gate=Acacia Fence Gate +block.minecraft.pumpkin_stem=Pumpkin Stem +block.minecraft.attached_pumpkin_stem=Attached Pumpkin Stem +block.minecraft.pumpkin=Pumpkin +block.minecraft.carved_pumpkin=Carved Pumpkin +block.minecraft.jack_o_lantern=Jack o'Lantern +block.minecraft.netherrack=Netherrack +block.minecraft.soul_sand=Soul Sand +block.minecraft.glowstone=Glowstone +block.minecraft.nether_portal=Nether Portal +block.minecraft.white_wool=White Wool +block.minecraft.orange_wool=Orange Wool +block.minecraft.magenta_wool=Magenta Wool +block.minecraft.light_blue_wool=Light Blue Wool +block.minecraft.yellow_wool=Yellow Wool +block.minecraft.lime_wool=Lime Wool +block.minecraft.pink_wool=Pink Wool +block.minecraft.gray_wool=Gray Wool +block.minecraft.light_gray_wool=Light Gray Wool +block.minecraft.cyan_wool=Cyan Wool +block.minecraft.purple_wool=Purple Wool +block.minecraft.blue_wool=Blue Wool +block.minecraft.brown_wool=Brown Wool +block.minecraft.green_wool=Green Wool +block.minecraft.red_wool=Red Wool +block.minecraft.black_wool=Black Wool +block.minecraft.lapis_ore=Lapis Lazuli Ore +block.minecraft.deepslate_lapis_ore=Deepslate Lapis Lazuli Ore +block.minecraft.lapis_block=Block of Lapis Lazuli +block.minecraft.dispenser=Dispenser +block.minecraft.dropper=Dropper +block.minecraft.note_block=Note Block +block.minecraft.cake=Cake +block.minecraft.oak_trapdoor=Oak Trapdoor +block.minecraft.spruce_trapdoor=Spruce Trapdoor +block.minecraft.birch_trapdoor=Birch Trapdoor +block.minecraft.jungle_trapdoor=Jungle Trapdoor +block.minecraft.acacia_trapdoor=Acacia Trapdoor +block.minecraft.dark_oak_trapdoor=Dark Oak Trapdoor +block.minecraft.iron_trapdoor=Iron Trapdoor +block.minecraft.cobweb=Cobweb +block.minecraft.stone_bricks=Stone Bricks +block.minecraft.mossy_stone_bricks=Mossy Stone Bricks +block.minecraft.cracked_stone_bricks=Cracked Stone Bricks +block.minecraft.chiseled_stone_bricks=Chiseled Stone Bricks +block.minecraft.infested_stone=Infested Stone +block.minecraft.infested_cobblestone=Infested Cobblestone +block.minecraft.infested_stone_bricks=Infested Stone Bricks +block.minecraft.infested_mossy_stone_bricks=Infested Mossy Stone Bricks +block.minecraft.infested_cracked_stone_bricks=Infested Cracked Stone Bricks +block.minecraft.infested_chiseled_stone_bricks=Infested Chiseled Stone Bricks +block.minecraft.piston=Piston +block.minecraft.sticky_piston=Sticky Piston +block.minecraft.iron_bars=Iron Bars +block.minecraft.melon=Melon +block.minecraft.brick_stairs=Brick Stairs +block.minecraft.stone_brick_stairs=Stone Brick Stairs +block.minecraft.vine=Vines +block.minecraft.nether_bricks=Nether Bricks +block.minecraft.nether_brick_fence=Nether Brick Fence +block.minecraft.nether_brick_stairs=Nether Brick Stairs +block.minecraft.nether_wart=Nether Wart +block.minecraft.warped_wart_block=Warped Wart Block +block.minecraft.warped_stem=Warped Stem +block.minecraft.stripped_warped_stem=Stripped Warped Stem +block.minecraft.warped_hyphae=Warped Hyphae +block.minecraft.stripped_warped_hyphae=Stripped Warped Hyphae +block.minecraft.crimson_stem=Crimson Stem +block.minecraft.stripped_crimson_stem=Stripped Crimson Stem +block.minecraft.crimson_hyphae=Crimson Hyphae +block.minecraft.stripped_crimson_hyphae=Stripped Crimson Hyphae +block.minecraft.warped_nylium=Warped Nylium +block.minecraft.crimson_nylium=Crimson Nylium +block.minecraft.warped_fungus=Warped Fungus +block.minecraft.crimson_fungus=Crimson Fungus +block.minecraft.crimson_roots=Crimson Roots +block.minecraft.warped_roots=Warped Roots +block.minecraft.nether_sprouts=Nether Sprouts +block.minecraft.shroomlight=Shroomlight +block.minecraft.weeping_vines=Weeping Vines +block.minecraft.weeping_vines_plant=Weeping Vines Plant +block.minecraft.twisting_vines=Twisting Vines +block.minecraft.twisting_vines_plant=Twisting Vines Plant +block.minecraft.soul_soil=Soul Soil +block.minecraft.basalt=Basalt +block.minecraft.polished_basalt=Polished Basalt +block.minecraft.warped_planks=Warped Planks +block.minecraft.warped_slab=Warped Slab +block.minecraft.warped_pressure_plate=Warped Pressure Plate +block.minecraft.warped_fence=Warped Fence +block.minecraft.warped_trapdoor=Warped Trapdoor +block.minecraft.warped_fence_gate=Warped Fence Gate +block.minecraft.warped_stairs=Warped Stairs +block.minecraft.warped_button=Warped Button +block.minecraft.warped_door=Warped Door +block.minecraft.warped_sign=Warped Sign +block.minecraft.warped_wall_sign=Warped Wall Sign +block.minecraft.crimson_planks=Crimson Planks +block.minecraft.crimson_slab=Crimson Slab +block.minecraft.crimson_pressure_plate=Crimson Pressure Plate +block.minecraft.crimson_fence=Crimson Fence +block.minecraft.crimson_trapdoor=Crimson Trapdoor +block.minecraft.crimson_fence_gate=Crimson Fence Gate +block.minecraft.crimson_stairs=Crimson Stairs +block.minecraft.crimson_button=Crimson Button +block.minecraft.crimson_door=Crimson Door +block.minecraft.crimson_sign=Crimson Sign +block.minecraft.crimson_wall_sign=Crimson Wall Sign +block.minecraft.soul_fire=Soul Fire +block.minecraft.cauldron=Cauldron +block.minecraft.water_cauldron=Water Cauldron +block.minecraft.lava_cauldron=Lava Cauldron +block.minecraft.powder_snow_cauldron=Powder Snow Cauldron +block.minecraft.enchanting_table=Enchanting Table +block.minecraft.anvil=Anvil +block.minecraft.chipped_anvil=Chipped Anvil +block.minecraft.damaged_anvil=Damaged Anvil +block.minecraft.end_stone=End Stone +block.minecraft.end_portal_frame=End Portal Frame +block.minecraft.mycelium=Mycelium +block.minecraft.lily_pad=Lily Pad +block.minecraft.dragon_egg=Dragon Egg +block.minecraft.redstone_lamp=Redstone Lamp +block.minecraft.cocoa=Cocoa +block.minecraft.ender_chest=Ender Chest +block.minecraft.emerald_ore=Emerald Ore +block.minecraft.deepslate_emerald_ore=Deepslate Emerald Ore +block.minecraft.emerald_block=Block of Emerald +block.minecraft.redstone_block=Block of Redstone +block.minecraft.tripwire=Tripwire +block.minecraft.tripwire_hook=Tripwire Hook +block.minecraft.command_block=Command Block +block.minecraft.repeating_command_block=Repeating Command Block +block.minecraft.chain_command_block=Chain Command Block +block.minecraft.beacon=Beacon +block.minecraft.cobblestone_wall=Cobblestone Wall +block.minecraft.mossy_cobblestone_wall=Mossy Cobblestone Wall +block.minecraft.carrots=Carrots +block.minecraft.potatoes=Potatoes +block.minecraft.daylight_detector=Daylight Detector +block.minecraft.nether_quartz_ore=Nether Quartz Ore +block.minecraft.hopper=Hopper +block.minecraft.quartz_block=Block of Quartz +block.minecraft.chiseled_quartz_block=Chiseled Quartz Block +block.minecraft.quartz_pillar=Quartz Pillar +block.minecraft.quartz_stairs=Quartz Stairs +block.minecraft.slime_block=Slime Block +block.minecraft.prismarine=Prismarine +block.minecraft.prismarine_bricks=Prismarine Bricks +block.minecraft.dark_prismarine=Dark Prismarine +block.minecraft.sea_lantern=Sea Lantern +block.minecraft.end_rod=End Rod +block.minecraft.chorus_plant=Chorus Plant +block.minecraft.chorus_flower=Chorus Flower +block.minecraft.purpur_block=Purpur Block +block.minecraft.purpur_pillar=Purpur Pillar +block.minecraft.purpur_stairs=Purpur Stairs +block.minecraft.purpur_slab=Purpur Slab +block.minecraft.end_stone_bricks=End Stone Bricks +block.minecraft.beetroots=Beetroots +block.minecraft.dirt_path=Dirt Path +block.minecraft.grass_path=Grass Path +block.minecraft.magma_block=Magma Block +block.minecraft.nether_wart_block=Nether Wart Block +block.minecraft.red_nether_bricks=Red Nether Bricks +block.minecraft.bone_block=Bone Block +block.minecraft.observer=Observer +block.minecraft.shulker_box=Shulker Box +block.minecraft.white_shulker_box=White Shulker Box +block.minecraft.orange_shulker_box=Orange Shulker Box +block.minecraft.magenta_shulker_box=Magenta Shulker Box +block.minecraft.light_blue_shulker_box=Light Blue Shulker Box +block.minecraft.yellow_shulker_box=Yellow Shulker Box +block.minecraft.lime_shulker_box=Lime Shulker Box +block.minecraft.pink_shulker_box=Pink Shulker Box +block.minecraft.gray_shulker_box=Gray Shulker Box +block.minecraft.light_gray_shulker_box=Light Gray Shulker Box +block.minecraft.cyan_shulker_box=Cyan Shulker Box +block.minecraft.purple_shulker_box=Purple Shulker Box +block.minecraft.blue_shulker_box=Blue Shulker Box +block.minecraft.brown_shulker_box=Brown Shulker Box +block.minecraft.green_shulker_box=Green Shulker Box +block.minecraft.red_shulker_box=Red Shulker Box +block.minecraft.black_shulker_box=Black Shulker Box +block.minecraft.white_glazed_terracotta=White Glazed Terracotta +block.minecraft.orange_glazed_terracotta=Orange Glazed Terracotta +block.minecraft.magenta_glazed_terracotta=Magenta Glazed Terracotta +block.minecraft.light_blue_glazed_terracotta=Light Blue Glazed Terracotta +block.minecraft.yellow_glazed_terracotta=Yellow Glazed Terracotta +block.minecraft.lime_glazed_terracotta=Lime Glazed Terracotta +block.minecraft.pink_glazed_terracotta=Pink Glazed Terracotta +block.minecraft.gray_glazed_terracotta=Gray Glazed Terracotta +block.minecraft.light_gray_glazed_terracotta=Light Gray Glazed Terracotta +block.minecraft.cyan_glazed_terracotta=Cyan Glazed Terracotta +block.minecraft.purple_glazed_terracotta=Purple Glazed Terracotta +block.minecraft.blue_glazed_terracotta=Blue Glazed Terracotta +block.minecraft.brown_glazed_terracotta=Brown Glazed Terracotta +block.minecraft.green_glazed_terracotta=Green Glazed Terracotta +block.minecraft.red_glazed_terracotta=Red Glazed Terracotta +block.minecraft.black_glazed_terracotta=Black Glazed Terracotta +block.minecraft.black_concrete=Black Concrete +block.minecraft.red_concrete=Red Concrete +block.minecraft.green_concrete=Green Concrete +block.minecraft.brown_concrete=Brown Concrete +block.minecraft.blue_concrete=Blue Concrete +block.minecraft.purple_concrete=Purple Concrete +block.minecraft.cyan_concrete=Cyan Concrete +block.minecraft.light_gray_concrete=Light Gray Concrete +block.minecraft.gray_concrete=Gray Concrete +block.minecraft.pink_concrete=Pink Concrete +block.minecraft.lime_concrete=Lime Concrete +block.minecraft.yellow_concrete=Yellow Concrete +block.minecraft.light_blue_concrete=Light Blue Concrete +block.minecraft.magenta_concrete=Magenta Concrete +block.minecraft.orange_concrete=Orange Concrete +block.minecraft.white_concrete=White Concrete +block.minecraft.black_concrete_powder=Black Concrete Powder +block.minecraft.red_concrete_powder=Red Concrete Powder +block.minecraft.green_concrete_powder=Green Concrete Powder +block.minecraft.brown_concrete_powder=Brown Concrete Powder +block.minecraft.blue_concrete_powder=Blue Concrete Powder +block.minecraft.purple_concrete_powder=Purple Concrete Powder +block.minecraft.cyan_concrete_powder=Cyan Concrete Powder +block.minecraft.light_gray_concrete_powder=Light Gray Concrete Powder +block.minecraft.gray_concrete_powder=Gray Concrete Powder +block.minecraft.pink_concrete_powder=Pink Concrete Powder +block.minecraft.lime_concrete_powder=Lime Concrete Powder +block.minecraft.yellow_concrete_powder=Yellow Concrete Powder +block.minecraft.light_blue_concrete_powder=Light Blue Concrete Powder +block.minecraft.magenta_concrete_powder=Magenta Concrete Powder +block.minecraft.orange_concrete_powder=Orange Concrete Powder +block.minecraft.white_concrete_powder=White Concrete Powder +block.minecraft.turtle_egg=Turtle Egg +block.minecraft.piston_head=Piston Head +block.minecraft.moving_piston=Moving Piston +block.minecraft.red_mushroom=Red Mushroom +block.minecraft.snow_block=Snow Block +block.minecraft.attached_melon_stem=Attached Melon Stem +block.minecraft.melon_stem=Melon Stem +block.minecraft.brewing_stand=Brewing Stand +block.minecraft.end_portal=End Portal +block.minecraft.flower_pot=Flower Pot +block.minecraft.potted_oak_sapling=Potted Oak Sapling +block.minecraft.potted_spruce_sapling=Potted Spruce Sapling +block.minecraft.potted_birch_sapling=Potted Birch Sapling +block.minecraft.potted_jungle_sapling=Potted Jungle Sapling +block.minecraft.potted_acacia_sapling=Potted Acacia Sapling +block.minecraft.potted_dark_oak_sapling=Potted Dark Oak Sapling +block.minecraft.potted_fern=Potted Fern +block.minecraft.potted_dandelion=Potted Dandelion +block.minecraft.potted_poppy=Potted Poppy +block.minecraft.potted_blue_orchid=Potted Blue Orchid +block.minecraft.potted_allium=Potted Allium +block.minecraft.potted_azure_bluet=Potted Azure Bluet +block.minecraft.potted_red_tulip=Potted Red Tulip +block.minecraft.potted_orange_tulip=Potted Orange Tulip +block.minecraft.potted_white_tulip=Potted White Tulip +block.minecraft.potted_pink_tulip=Potted Pink Tulip +block.minecraft.potted_oxeye_daisy=Potted Oxeye Daisy +block.minecraft.potted_cornflower=Potted Cornflower +block.minecraft.potted_lily_of_the_valley=Potted Lily of the Valley +block.minecraft.potted_wither_rose=Potted Wither Rose +block.minecraft.potted_red_mushroom=Potted Red Mushroom +block.minecraft.potted_brown_mushroom=Potted Brown Mushroom +block.minecraft.potted_dead_bush=Potted Dead Bush +block.minecraft.potted_cactus=Potted Cactus +block.minecraft.potted_bamboo=Potted Bamboo +block.minecraft.potted_crimson_fungus=Potted Crimson Fungus +block.minecraft.potted_warped_fungus=Potted Warped Fungus +block.minecraft.potted_crimson_roots=Potted Crimson Roots +block.minecraft.potted_warped_roots=Potted Warped Roots +block.minecraft.potted_azalea_bush=Potted Azalea +block.minecraft.potted_flowering_azalea_bush=Potted Flowering Azalea +block.minecraft.skeleton_wall_skull=Skeleton Wall Skull +block.minecraft.skeleton_skull=Skeleton Skull +block.minecraft.wither_skeleton_wall_skull=Wither Skeleton Wall Skull +block.minecraft.wither_skeleton_skull=Wither Skeleton Skull +block.minecraft.zombie_wall_head=Zombie Wall Head +block.minecraft.zombie_head=Zombie Head +block.minecraft.player_wall_head=Player Wall Head +block.minecraft.player_head=Player Head +block.minecraft.creeper_wall_head=Creeper Wall Head +block.minecraft.creeper_head=Creeper Head +block.minecraft.dragon_wall_head=Dragon Wall Head +block.minecraft.dragon_head=Dragon Head +block.minecraft.end_gateway=End Gateway +block.minecraft.structure_void=Structure Void +block.minecraft.structure_block=Structure Block +block.minecraft.void_air=Void Air +block.minecraft.cave_air=Cave Air +block.minecraft.bubble_column=Bubble Column +block.minecraft.dead_tube_coral_block=Dead Tube Coral Block +block.minecraft.dead_brain_coral_block=Dead Brain Coral Block +block.minecraft.dead_bubble_coral_block=Dead Bubble Coral Block +block.minecraft.dead_fire_coral_block=Dead Fire Coral Block +block.minecraft.dead_horn_coral_block=Dead Horn Coral Block +block.minecraft.tube_coral_block=Tube Coral Block +block.minecraft.brain_coral_block=Brain Coral Block +block.minecraft.bubble_coral_block=Bubble Coral Block +block.minecraft.fire_coral_block=Fire Coral Block +block.minecraft.horn_coral_block=Horn Coral Block +block.minecraft.tube_coral=Tube Coral +block.minecraft.brain_coral=Brain Coral +block.minecraft.bubble_coral=Bubble Coral +block.minecraft.fire_coral=Fire Coral +block.minecraft.horn_coral=Horn Coral +block.minecraft.dead_tube_coral=Dead Tube Coral +block.minecraft.dead_brain_coral=Dead Brain Coral +block.minecraft.dead_bubble_coral=Dead Bubble Coral +block.minecraft.dead_fire_coral=Dead Fire Coral +block.minecraft.dead_horn_coral=Dead Horn Coral +block.minecraft.tube_coral_fan=Tube Coral Fan +block.minecraft.brain_coral_fan=Brain Coral Fan +block.minecraft.bubble_coral_fan=Bubble Coral Fan +block.minecraft.fire_coral_fan=Fire Coral Fan +block.minecraft.horn_coral_fan=Horn Coral Fan +block.minecraft.dead_tube_coral_fan=Dead Tube Coral Fan +block.minecraft.dead_brain_coral_fan=Dead Brain Coral Fan +block.minecraft.dead_bubble_coral_fan=Dead Bubble Coral Fan +block.minecraft.dead_fire_coral_fan=Dead Fire Coral Fan +block.minecraft.dead_horn_coral_fan=Dead Horn Coral Fan +block.minecraft.tube_coral_wall_fan=Tube Coral Wall Fan +block.minecraft.brain_coral_wall_fan=Brain Coral Wall Fan +block.minecraft.bubble_coral_wall_fan=Bubble Coral Wall Fan +block.minecraft.fire_coral_wall_fan=Fire Coral Wall Fan +block.minecraft.horn_coral_wall_fan=Horn Coral Wall Fan +block.minecraft.dead_tube_coral_wall_fan=Dead Tube Coral Wall Fan +block.minecraft.dead_brain_coral_wall_fan=Dead Brain Coral Wall Fan +block.minecraft.dead_bubble_coral_wall_fan=Dead Bubble Coral Wall Fan +block.minecraft.dead_fire_coral_wall_fan=Dead Fire Coral Wall Fan +block.minecraft.dead_horn_coral_wall_fan=Dead Horn Coral Wall Fan +block.minecraft.loom=Loom +block.minecraft.conduit=Conduit +block.minecraft.bamboo=Bamboo +block.minecraft.bamboo_sapling=Bamboo Shoot +block.minecraft.jigsaw=Jigsaw Block +block.minecraft.composter=Composter +block.minecraft.target=Target +block.minecraft.polished_granite_stairs=Polished Granite Stairs +block.minecraft.smooth_red_sandstone_stairs=Smooth Red Sandstone Stairs +block.minecraft.mossy_stone_brick_stairs=Mossy Stone Brick Stairs +block.minecraft.polished_diorite_stairs=Polished Diorite Stairs +block.minecraft.mossy_cobblestone_stairs=Mossy Cobblestone Stairs +block.minecraft.end_stone_brick_stairs=End Stone Brick Stairs +block.minecraft.stone_stairs=Stone Stairs +block.minecraft.smooth_sandstone_stairs=Smooth Sandstone Stairs +block.minecraft.smooth_quartz_stairs=Smooth Quartz Stairs +block.minecraft.granite_stairs=Granite Stairs +block.minecraft.andesite_stairs=Andesite Stairs +block.minecraft.red_nether_brick_stairs=Red Nether Brick Stairs +block.minecraft.polished_andesite_stairs=Polished Andesite Stairs +block.minecraft.diorite_stairs=Diorite Stairs +block.minecraft.polished_granite_slab=Polished Granite Slab +block.minecraft.smooth_red_sandstone_slab=Smooth Red Sandstone Slab +block.minecraft.mossy_stone_brick_slab=Mossy Stone Brick Slab +block.minecraft.polished_diorite_slab=Polished Diorite Slab +block.minecraft.mossy_cobblestone_slab=Mossy Cobblestone Slab +block.minecraft.end_stone_brick_slab=End Stone Brick Slab +block.minecraft.smooth_sandstone_slab=Smooth Sandstone Slab +block.minecraft.smooth_quartz_slab=Smooth Quartz Slab +block.minecraft.granite_slab=Granite Slab +block.minecraft.andesite_slab=Andesite Slab +block.minecraft.red_nether_brick_slab=Red Nether Brick Slab +block.minecraft.polished_andesite_slab=Polished Andesite Slab +block.minecraft.diorite_slab=Diorite Slab +block.minecraft.brick_wall=Brick Wall +block.minecraft.prismarine_wall=Prismarine Wall +block.minecraft.red_sandstone_wall=Red Sandstone Wall +block.minecraft.mossy_stone_brick_wall=Mossy Stone Brick Wall +block.minecraft.granite_wall=Granite Wall +block.minecraft.stone_brick_wall=Stone Brick Wall +block.minecraft.nether_brick_wall=Nether Brick Wall +block.minecraft.andesite_wall=Andesite Wall +block.minecraft.red_nether_brick_wall=Red Nether Brick Wall +block.minecraft.sandstone_wall=Sandstone Wall +block.minecraft.end_stone_brick_wall=End Stone Brick Wall +block.minecraft.diorite_wall=Diorite Wall +block.minecraft.barrel=Barrel +block.minecraft.smoker=Smoker +block.minecraft.blast_furnace=Blast Furnace +block.minecraft.cartography_table=Cartography Table +block.minecraft.fletching_table=Fletching Table +block.minecraft.smithing_table=Smithing Table +block.minecraft.grindstone=Grindstone +block.minecraft.lectern=Lectern +block.minecraft.stonecutter=Stonecutter +block.minecraft.bell=Bell +block.minecraft.lantern=Lantern +block.minecraft.soul_lantern=Soul Lantern +block.minecraft.sweet_berry_bush=Sweet Berry Bush +block.minecraft.campfire=Campfire +block.minecraft.soul_campfire=Soul Campfire +block.minecraft.beehive=Beehive +block.minecraft.bee_nest=Bee Nest +block.minecraft.honey_block=Honey Block +block.minecraft.honeycomb_block=Honeycomb Block +block.minecraft.lodestone=Lodestone +block.minecraft.netherite_block=Block of Netherite +block.minecraft.ancient_debris=Ancient Debris +block.minecraft.crying_obsidian=Crying Obsidian +block.minecraft.blackstone=Blackstone +block.minecraft.blackstone_slab=Blackstone Slab +block.minecraft.blackstone_stairs=Blackstone Stairs +block.minecraft.blackstone_wall=Blackstone Wall +block.minecraft.polished_blackstone_bricks=Polished Blackstone Bricks +block.minecraft.polished_blackstone_brick_slab=Polished Blackstone Brick Slab +block.minecraft.polished_blackstone_brick_stairs=Polished Blackstone Brick Stairs +block.minecraft.polished_blackstone_brick_wall=Polished Blackstone Brick Wall +block.minecraft.chiseled_polished_blackstone=Chiseled Polished Blackstone +block.minecraft.cracked_polished_blackstone_bricks=Cracked Polished Blackstone Bricks +block.minecraft.gilded_blackstone=Gilded Blackstone +block.minecraft.polished_blackstone=Polished Blackstone +block.minecraft.polished_blackstone_wall=Polished Blackstone Wall +block.minecraft.polished_blackstone_slab=Polished Blackstone Slab +block.minecraft.polished_blackstone_stairs=Polished Blackstone Stairs +block.minecraft.polished_blackstone_pressure_plate=Polished Blackstone Pressure Plate +block.minecraft.polished_blackstone_button=Polished Blackstone Button +block.minecraft.cracked_nether_bricks=Cracked Nether Bricks +block.minecraft.chiseled_nether_bricks=Chiseled Nether Bricks +block.minecraft.quartz_bricks=Quartz Bricks +block.minecraft.chain=Chain +block.minecraft.candle=Candle +block.minecraft.white_candle=White Candle +block.minecraft.orange_candle=Orange Candle +block.minecraft.magenta_candle=Magenta Candle +block.minecraft.light_blue_candle=Light Blue Candle +block.minecraft.yellow_candle=Yellow Candle +block.minecraft.lime_candle=Lime Candle +block.minecraft.pink_candle=Pink Candle +block.minecraft.gray_candle=Gray Candle +block.minecraft.light_gray_candle=Light Gray Candle +block.minecraft.cyan_candle=Cyan Candle +block.minecraft.purple_candle=Purple Candle +block.minecraft.blue_candle=Blue Candle +block.minecraft.brown_candle=Brown Candle +block.minecraft.green_candle=Green Candle +block.minecraft.red_candle=Red Candle +block.minecraft.black_candle=Black Candle +block.minecraft.candle_cake=Cake with Candle +block.minecraft.white_candle_cake=Cake with White Candle +block.minecraft.orange_candle_cake=Cake with Orange Candle +block.minecraft.magenta_candle_cake=Cake with Magenta Candle +block.minecraft.light_blue_candle_cake=Cake with Light Blue Candle +block.minecraft.yellow_candle_cake=Cake with Yellow Candle +block.minecraft.lime_candle_cake=Cake with Lime Candle +block.minecraft.pink_candle_cake=Cake with Pink Candle +block.minecraft.gray_candle_cake=Cake with Gray Candle +block.minecraft.light_gray_candle_cake=Cake with Light Gray Candle +block.minecraft.cyan_candle_cake=Cake with Cyan Candle +block.minecraft.purple_candle_cake=Cake with Purple Candle +block.minecraft.blue_candle_cake=Cake with Blue Candle +block.minecraft.brown_candle_cake=Cake with Brown Candle +block.minecraft.green_candle_cake=Cake with Green Candle +block.minecraft.red_candle_cake=Cake with Red Candle +block.minecraft.black_candle_cake=Cake with Black Candle +block.minecraft.amethyst_block=Block of Amethyst +block.minecraft.small_amethyst_bud=Small Amethyst Bud +block.minecraft.medium_amethyst_bud=Medium Amethyst Bud +block.minecraft.large_amethyst_bud=Large Amethyst Bud +block.minecraft.amethyst_cluster=Amethyst Cluster +block.minecraft.budding_amethyst=Budding Amethyst +block.minecraft.calcite=Calcite +block.minecraft.tuff=Tuff +block.minecraft.tinted_glass=Tinted Glass +block.minecraft.dripstone_block=Dripstone Block +block.minecraft.pointed_dripstone=Pointed Dripstone +block.minecraft.copper_ore=Copper Ore +block.minecraft.deepslate_copper_ore=Deepslate Copper Ore +block.minecraft.copper_block=Block of Copper +block.minecraft.exposed_copper=Exposed Copper +block.minecraft.weathered_copper=Weathered Copper +block.minecraft.oxidized_copper=Oxidized Copper +block.minecraft.cut_copper=Cut Copper +block.minecraft.exposed_cut_copper=Exposed Cut Copper +block.minecraft.weathered_cut_copper=Weathered Cut Copper +block.minecraft.oxidized_cut_copper=Oxidized Cut Copper +block.minecraft.cut_copper_stairs=Cut Copper Stairs +block.minecraft.exposed_cut_copper_stairs=Exposed Cut Copper Stairs +block.minecraft.weathered_cut_copper_stairs=Weathered Cut Copper Stairs +block.minecraft.oxidized_cut_copper_stairs=Oxidized Cut Copper Stairs +block.minecraft.cut_copper_slab=Cut Copper Slab +block.minecraft.exposed_cut_copper_slab=Exposed Cut Copper Slab +block.minecraft.weathered_cut_copper_slab=Weathered Cut Copper Slab +block.minecraft.oxidized_cut_copper_slab=Oxidized Cut Copper Slab +block.minecraft.waxed_copper_block=Waxed Block of Copper +block.minecraft.waxed_exposed_copper=Waxed Exposed Copper +block.minecraft.waxed_weathered_copper=Waxed Weathered Copper +block.minecraft.waxed_oxidized_copper=Waxed Oxidized Copper +block.minecraft.waxed_cut_copper=Waxed Cut Copper +block.minecraft.waxed_exposed_cut_copper=Waxed Exposed Cut Copper +block.minecraft.waxed_weathered_cut_copper=Waxed Weathered Cut Copper +block.minecraft.waxed_oxidized_cut_copper=Waxed Oxidized Cut Copper +block.minecraft.waxed_cut_copper_stairs=Waxed Cut Copper Stairs +block.minecraft.waxed_exposed_cut_copper_stairs=Waxed Exposed Cut Copper Stairs +block.minecraft.waxed_weathered_cut_copper_stairs=Waxed Weathered Cut Copper Stairs +block.minecraft.waxed_oxidized_cut_copper_stairs=Waxed Oxidized Cut Copper Stairs +block.minecraft.waxed_cut_copper_slab=Waxed Cut Copper Slab +block.minecraft.waxed_exposed_cut_copper_slab=Waxed Exposed Cut Copper Slab +block.minecraft.waxed_weathered_cut_copper_slab=Waxed Weathered Cut Copper Slab +block.minecraft.waxed_oxidized_cut_copper_slab=Waxed Oxidized Cut Copper Slab +block.minecraft.lightning_rod=Lightning Rod +block.minecraft.cave_vines=Cave Vines +block.minecraft.cave_vines_plant=Cave Vines Plant +block.minecraft.spore_blossom=Spore Blossom +block.minecraft.azalea=Azalea +block.minecraft.flowering_azalea=Flowering Azalea +block.minecraft.azalea_leaves=Azalea Leaves +block.minecraft.flowering_azalea_leaves=Flowering Azalea Leaves +block.minecraft.moss_carpet=Moss Carpet +block.minecraft.moss_block=Moss Block +block.minecraft.big_dripleaf=Big Dripleaf +block.minecraft.big_dripleaf_stem=Big Dripleaf Stem +block.minecraft.small_dripleaf=Small Dripleaf +block.minecraft.rooted_dirt=Rooted Dirt +block.minecraft.hanging_roots=Hanging Roots +block.minecraft.powder_snow=Powder Snow +block.minecraft.glow_lichen=Glow Lichen +block.minecraft.sculk_sensor=Sculk Sensor +block.minecraft.deepslate=Deepslate +block.minecraft.cobbled_deepslate=Cobbled Deepslate +block.minecraft.cobbled_deepslate_slab=Cobbled Deepslate Slab +block.minecraft.cobbled_deepslate_stairs=Cobbled Deepslate Stairs +block.minecraft.cobbled_deepslate_wall=Cobbled Deepslate Wall +block.minecraft.chiseled_deepslate=Chiseled Deepslate +block.minecraft.polished_deepslate=Polished Deepslate +block.minecraft.polished_deepslate_slab=Polished Deepslate Slab +block.minecraft.polished_deepslate_stairs=Polished Deepslate Stairs +block.minecraft.polished_deepslate_wall=Polished Deepslate Wall +block.minecraft.deepslate_bricks=Deepslate Bricks +block.minecraft.deepslate_brick_slab=Deepslate Brick Slab +block.minecraft.deepslate_brick_stairs=Deepslate Brick Stairs +block.minecraft.deepslate_brick_wall=Deepslate Brick Wall +block.minecraft.deepslate_tiles=Deepslate Tiles +block.minecraft.deepslate_tile_slab=Deepslate Tile Slab +block.minecraft.deepslate_tile_stairs=Deepslate Tile Stairs +block.minecraft.deepslate_tile_wall=Deepslate Tile Wall +block.minecraft.cracked_deepslate_bricks=Cracked Deepslate Bricks +block.minecraft.cracked_deepslate_tiles=Cracked Deepslate Tiles +block.minecraft.infested_deepslate=Infested Deepslate +block.minecraft.smooth_basalt=Smooth Basalt +block.minecraft.raw_iron_block=Block of Raw Iron +block.minecraft.raw_copper_block=Block of Raw Copper +block.minecraft.raw_gold_block=Block of Raw Gold +item.minecraft.name_tag=Name Tag +item.minecraft.lead=Lead +item.minecraft.iron_shovel=Iron Shovel +item.minecraft.iron_pickaxe=Iron Pickaxe +item.minecraft.iron_axe=Iron Axe +item.minecraft.flint_and_steel=Flint and Steel +item.minecraft.apple=Apple +item.minecraft.cookie=Cookie +item.minecraft.bow=Bow +item.minecraft.bundle=Bundle +item.minecraft.arrow=Arrow +item.minecraft.spectral_arrow=Spectral Arrow +item.minecraft.tipped_arrow=Tipped Arrow +item.minecraft.dried_kelp=Dried Kelp +item.minecraft.coal=Coal +item.minecraft.charcoal=Charcoal +item.minecraft.raw_copper=Raw Copper +item.minecraft.raw_iron=Raw Iron +item.minecraft.raw_gold=Raw Gold +item.minecraft.diamond=Diamond +item.minecraft.emerald=Emerald +item.minecraft.iron_ingot=Iron Ingot +item.minecraft.copper_ingot=Copper Ingot +item.minecraft.gold_ingot=Gold Ingot +item.minecraft.iron_sword=Iron Sword +item.minecraft.wooden_sword=Wooden Sword +item.minecraft.wooden_shovel=Wooden Shovel +item.minecraft.wooden_pickaxe=Wooden Pickaxe +item.minecraft.wooden_axe=Wooden Axe +item.minecraft.stone_sword=Stone Sword +item.minecraft.stone_shovel=Stone Shovel +item.minecraft.stone_pickaxe=Stone Pickaxe +item.minecraft.stone_axe=Stone Axe +item.minecraft.diamond_sword=Diamond Sword +item.minecraft.diamond_shovel=Diamond Shovel +item.minecraft.diamond_pickaxe=Diamond Pickaxe +item.minecraft.diamond_axe=Diamond Axe +item.minecraft.stick=Stick +item.minecraft.bowl=Bowl +item.minecraft.mushroom_stew=Mushroom Stew +item.minecraft.golden_sword=Golden Sword +item.minecraft.golden_shovel=Golden Shovel +item.minecraft.golden_pickaxe=Golden Pickaxe +item.minecraft.golden_axe=Golden Axe +item.minecraft.string=String +item.minecraft.feather=Feather +item.minecraft.gunpowder=Gunpowder +item.minecraft.wooden_hoe=Wooden Hoe +item.minecraft.stone_hoe=Stone Hoe +item.minecraft.iron_hoe=Iron Hoe +item.minecraft.diamond_hoe=Diamond Hoe +item.minecraft.golden_hoe=Golden Hoe +item.minecraft.wheat_seeds=Wheat Seeds +item.minecraft.pumpkin_seeds=Pumpkin Seeds +item.minecraft.melon_seeds=Melon Seeds +item.minecraft.melon_slice=Melon Slice +item.minecraft.wheat=Wheat +item.minecraft.bread=Bread +item.minecraft.leather_helmet=Leather Cap +item.minecraft.leather_chestplate=Leather Tunic +item.minecraft.leather_leggings=Leather Pants +item.minecraft.leather_boots=Leather Boots +item.minecraft.chainmail_helmet=Chainmail Helmet +item.minecraft.chainmail_chestplate=Chainmail Chestplate +item.minecraft.chainmail_leggings=Chainmail Leggings +item.minecraft.chainmail_boots=Chainmail Boots +item.minecraft.iron_helmet=Iron Helmet +item.minecraft.iron_chestplate=Iron Chestplate +item.minecraft.iron_leggings=Iron Leggings +item.minecraft.iron_boots=Iron Boots +item.minecraft.diamond_helmet=Diamond Helmet +item.minecraft.diamond_chestplate=Diamond Chestplate +item.minecraft.diamond_leggings=Diamond Leggings +item.minecraft.diamond_boots=Diamond Boots +item.minecraft.golden_helmet=Golden Helmet +item.minecraft.golden_chestplate=Golden Chestplate +item.minecraft.golden_leggings=Golden Leggings +item.minecraft.golden_boots=Golden Boots +item.minecraft.flint=Flint +item.minecraft.porkchop=Raw Porkchop +item.minecraft.cooked_porkchop=Cooked Porkchop +item.minecraft.chicken=Raw Chicken +item.minecraft.cooked_chicken=Cooked Chicken +item.minecraft.mutton=Raw Mutton +item.minecraft.cooked_mutton=Cooked Mutton +item.minecraft.rabbit=Raw Rabbit +item.minecraft.cooked_rabbit=Cooked Rabbit +item.minecraft.rabbit_stew=Rabbit Stew +item.minecraft.rabbit_foot=Rabbit's Foot +item.minecraft.rabbit_hide=Rabbit Hide +item.minecraft.beef=Raw Beef +item.minecraft.cooked_beef=Steak +item.minecraft.painting=Painting +item.minecraft.item_frame=Item Frame +item.minecraft.golden_apple=Golden Apple +item.minecraft.enchanted_golden_apple=Enchanted Golden Apple +item.minecraft.sign=Sign +item.minecraft.bucket=Bucket +item.minecraft.water_bucket=Water Bucket +item.minecraft.lava_bucket=Lava Bucket +item.minecraft.pufferfish_bucket=Bucket of Pufferfish +item.minecraft.salmon_bucket=Bucket of Salmon +item.minecraft.cod_bucket=Bucket of Cod +item.minecraft.tropical_fish_bucket=Bucket of Tropical Fish +item.minecraft.powder_snow_bucket=Powder Snow Bucket +item.minecraft.axolotl_bucket=Bucket of Axolotl +item.minecraft.minecart=Minecart +item.minecraft.saddle=Saddle +item.minecraft.redstone=Redstone Dust +item.minecraft.snowball=Snowball +item.minecraft.oak_boat=Oak Boat +item.minecraft.spruce_boat=Spruce Boat +item.minecraft.birch_boat=Birch Boat +item.minecraft.jungle_boat=Jungle Boat +item.minecraft.acacia_boat=Acacia Boat +item.minecraft.dark_oak_boat=Dark Oak Boat +item.minecraft.leather=Leather +item.minecraft.milk_bucket=Milk Bucket +item.minecraft.brick=Brick +item.minecraft.clay_ball=Clay Ball +item.minecraft.paper=Paper +item.minecraft.book=Book +item.minecraft.slime_ball=Slimeball +item.minecraft.chest_minecart=Minecart with Chest +item.minecraft.furnace_minecart=Minecart with Furnace +item.minecraft.tnt_minecart=Minecart with TNT +item.minecraft.hopper_minecart=Minecart with Hopper +item.minecraft.command_block_minecart=Minecart with Command Block +item.minecraft.egg=Egg +item.minecraft.compass=Compass +item.minecraft.fishing_rod=Fishing Rod +item.minecraft.clock=Clock +item.minecraft.glowstone_dust=Glowstone Dust +item.minecraft.cod=Raw Cod +item.minecraft.salmon=Raw Salmon +item.minecraft.pufferfish=Pufferfish +item.minecraft.tropical_fish=Tropical Fish +item.minecraft.cooked_cod=Cooked Cod +item.minecraft.cooked_salmon=Cooked Salmon +item.minecraft.music_disc_13=Music Disc +item.minecraft.music_disc_cat=Music Disc +item.minecraft.music_disc_blocks=Music Disc +item.minecraft.music_disc_chirp=Music Disc +item.minecraft.music_disc_far=Music Disc +item.minecraft.music_disc_mall=Music Disc +item.minecraft.music_disc_mellohi=Music Disc +item.minecraft.music_disc_stal=Music Disc +item.minecraft.music_disc_strad=Music Disc +item.minecraft.music_disc_ward=Music Disc +item.minecraft.music_disc_11=Music Disc +item.minecraft.music_disc_wait=Music Disc +item.minecraft.music_disc_pigstep=Music Disc +item.minecraft.music_disc_13.desc=C418 - 13 +item.minecraft.music_disc_cat.desc=C418 - cat +item.minecraft.music_disc_blocks.desc=C418 - blocks +item.minecraft.music_disc_chirp.desc=C418 - chirp +item.minecraft.music_disc_far.desc=C418 - far +item.minecraft.music_disc_mall.desc=C418 - mall +item.minecraft.music_disc_mellohi.desc=C418 - mellohi +item.minecraft.music_disc_stal.desc=C418 - stal +item.minecraft.music_disc_strad.desc=C418 - strad +item.minecraft.music_disc_ward.desc=C418 - ward +item.minecraft.music_disc_11.desc=C418 - 11 +item.minecraft.music_disc_wait.desc=C418 - wait +item.minecraft.music_disc_pigstep.desc=Lena Raine - Pigstep +item.minecraft.bone=Bone +item.minecraft.ink_sac=Ink Sac +item.minecraft.cactus_green=Cactus Green +item.minecraft.dandelion_yellow=Dandelion Yellow +item.minecraft.rose_red=Rose Red +item.minecraft.red_dye=Red Dye +item.minecraft.green_dye=Green Dye +item.minecraft.cocoa_beans=Cocoa Beans +item.minecraft.lapis_lazuli=Lapis Lazuli +item.minecraft.purple_dye=Purple Dye +item.minecraft.cyan_dye=Cyan Dye +item.minecraft.light_gray_dye=Light Gray Dye +item.minecraft.gray_dye=Gray Dye +item.minecraft.pink_dye=Pink Dye +item.minecraft.lime_dye=Lime Dye +item.minecraft.yellow_dye=Yellow Dye +item.minecraft.light_blue_dye=Light Blue Dye +item.minecraft.magenta_dye=Magenta Dye +item.minecraft.orange_dye=Orange Dye +item.minecraft.bone_meal=Bone Meal +item.minecraft.blue_dye=Blue Dye +item.minecraft.black_dye=Black Dye +item.minecraft.brown_dye=Brown Dye +item.minecraft.white_dye=White Dye +item.minecraft.sugar=Sugar +item.minecraft.amethyst_shard=Amethyst Shard +item.minecraft.spyglass=Spyglass +item.minecraft.glow_berries=Glow Berries +block.minecraft.black_bed=Black Bed +block.minecraft.red_bed=Red Bed +block.minecraft.green_bed=Green Bed +block.minecraft.brown_bed=Brown Bed +block.minecraft.blue_bed=Blue Bed +block.minecraft.purple_bed=Purple Bed +block.minecraft.cyan_bed=Cyan Bed +block.minecraft.light_gray_bed=Light Gray Bed +block.minecraft.gray_bed=Gray Bed +block.minecraft.pink_bed=Pink Bed +block.minecraft.lime_bed=Lime Bed +block.minecraft.yellow_bed=Yellow Bed +block.minecraft.light_blue_bed=Light Blue Bed +block.minecraft.magenta_bed=Magenta Bed +block.minecraft.orange_bed=Orange Bed +block.minecraft.white_bed=White Bed +block.minecraft.repeater=Redstone Repeater +block.minecraft.comparator=Redstone Comparator +item.minecraft.filled_map=Map +item.minecraft.shears=Shears +item.minecraft.rotten_flesh=Rotten Flesh +item.minecraft.ender_pearl=Ender Pearl +item.minecraft.blaze_rod=Blaze Rod +item.minecraft.ghast_tear=Ghast Tear +item.minecraft.nether_wart=Nether Wart +item.minecraft.potion=Potion +item.minecraft.splash_potion=Splash Potion +item.minecraft.lingering_potion=Lingering Potion +item.minecraft.end_crystal=End Crystal +item.minecraft.gold_nugget=Gold Nugget +item.minecraft.glass_bottle=Glass Bottle +item.minecraft.spider_eye=Spider Eye +item.minecraft.fermented_spider_eye=Fermented Spider Eye +item.minecraft.blaze_powder=Blaze Powder +item.minecraft.magma_cream=Magma Cream +item.minecraft.cauldron=Cauldron +item.minecraft.brewing_stand=Brewing Stand +item.minecraft.ender_eye=Eye of Ender +item.minecraft.glistering_melon_slice=Glistering Melon Slice +item.minecraft.axolotl_spawn_egg=Axolotl Spawn Egg +item.minecraft.bat_spawn_egg=Bat Spawn Egg +item.minecraft.bee_spawn_egg=Bee Spawn Egg +item.minecraft.blaze_spawn_egg=Blaze Spawn Egg +item.minecraft.cat_spawn_egg=Cat Spawn Egg +item.minecraft.cave_spider_spawn_egg=Cave Spider Spawn Egg +item.minecraft.chicken_spawn_egg=Chicken Spawn Egg +item.minecraft.cod_spawn_egg=Cod Spawn Egg +item.minecraft.cow_spawn_egg=Cow Spawn Egg +item.minecraft.creeper_spawn_egg=Creeper Spawn Egg +item.minecraft.dolphin_spawn_egg=Dolphin Spawn Egg +item.minecraft.donkey_spawn_egg=Donkey Spawn Egg +item.minecraft.drowned_spawn_egg=Drowned Spawn Egg +item.minecraft.elder_guardian_spawn_egg=Elder Guardian Spawn Egg +item.minecraft.enderman_spawn_egg=Enderman Spawn Egg +item.minecraft.endermite_spawn_egg=Endermite Spawn Egg +item.minecraft.evoker_spawn_egg=Evoker Spawn Egg +item.minecraft.ghast_spawn_egg=Ghast Spawn Egg +item.minecraft.glow_squid_spawn_egg=Glow Squid Spawn Egg +item.minecraft.guardian_spawn_egg=Guardian Spawn Egg +item.minecraft.hoglin_spawn_egg=Hoglin Spawn Egg +item.minecraft.horse_spawn_egg=Horse Spawn Egg +item.minecraft.husk_spawn_egg=Husk Spawn Egg +item.minecraft.ravager_spawn_egg=Ravager Spawn Egg +item.minecraft.llama_spawn_egg=Llama Spawn Egg +item.minecraft.magma_cube_spawn_egg=Magma Cube Spawn Egg +item.minecraft.mooshroom_spawn_egg=Mooshroom Spawn Egg +item.minecraft.mule_spawn_egg=Mule Spawn Egg +item.minecraft.ocelot_spawn_egg=Ocelot Spawn Egg +item.minecraft.panda_spawn_egg=Panda Spawn Egg +item.minecraft.parrot_spawn_egg=Parrot Spawn Egg +item.minecraft.pig_spawn_egg=Pig Spawn Egg +item.minecraft.piglin_spawn_egg=Piglin Spawn Egg +item.minecraft.piglin_brute_spawn_egg=Piglin Brute Spawn Egg +item.minecraft.pillager_spawn_egg=Pillager Spawn Egg +item.minecraft.phantom_spawn_egg=Phantom Spawn Egg +item.minecraft.polar_bear_spawn_egg=Polar Bear Spawn Egg +item.minecraft.pufferfish_spawn_egg=Pufferfish Spawn Egg +item.minecraft.rabbit_spawn_egg=Rabbit Spawn Egg +item.minecraft.fox_spawn_egg=Fox Spawn Egg +item.minecraft.salmon_spawn_egg=Salmon Spawn Egg +item.minecraft.sheep_spawn_egg=Sheep Spawn Egg +item.minecraft.shulker_spawn_egg=Shulker Spawn Egg +item.minecraft.silverfish_spawn_egg=Silverfish Spawn Egg +item.minecraft.skeleton_spawn_egg=Skeleton Spawn Egg +item.minecraft.skeleton_horse_spawn_egg=Skeleton Horse Spawn Egg +item.minecraft.slime_spawn_egg=Slime Spawn Egg +item.minecraft.spider_spawn_egg=Spider Spawn Egg +item.minecraft.squid_spawn_egg=Squid Spawn Egg +item.minecraft.stray_spawn_egg=Stray Spawn Egg +item.minecraft.strider_spawn_egg=Strider Spawn Egg +item.minecraft.trader_llama_spawn_egg=Trader Llama Spawn Egg +item.minecraft.tropical_fish_spawn_egg=Tropical Fish Spawn Egg +item.minecraft.turtle_spawn_egg=Turtle Spawn Egg +item.minecraft.vex_spawn_egg=Vex Spawn Egg +item.minecraft.villager_spawn_egg=Villager Spawn Egg +item.minecraft.wandering_trader_spawn_egg=Wandering Trader Spawn Egg +item.minecraft.vindicator_spawn_egg=Vindicator Spawn Egg +item.minecraft.witch_spawn_egg=Witch Spawn Egg +item.minecraft.wither_skeleton_spawn_egg=Wither Skeleton Spawn Egg +item.minecraft.wolf_spawn_egg=Wolf Spawn Egg +item.minecraft.zoglin_spawn_egg=Zoglin Spawn Egg +item.minecraft.zombie_spawn_egg=Zombie Spawn Egg +item.minecraft.zombie_horse_spawn_egg=Zombie Horse Spawn Egg +item.minecraft.zombie_pigman_spawn_egg=Zombie Pigman Spawn Egg +item.minecraft.zombified_piglin_spawn_egg=Zombified Piglin Spawn Egg +item.minecraft.zombie_villager_spawn_egg=Zombie Villager Spawn Egg +item.minecraft.goat_spawn_egg=Goat Spawn Egg +item.minecraft.experience_bottle=Bottle o' Enchanting +item.minecraft.fire_charge=Fire Charge +item.minecraft.writable_book=Book and Quill +item.minecraft.written_book=Written Book +item.minecraft.flower_pot=Flower Pot +item.minecraft.map=Empty Map +item.minecraft.carrot=Carrot +item.minecraft.golden_carrot=Golden Carrot +item.minecraft.potato=Potato +item.minecraft.baked_potato=Baked Potato +item.minecraft.poisonous_potato=Poisonous Potato +item.minecraft.skeleton_skull=Skeleton Skull +item.minecraft.wither_skeleton_skull=Wither Skeleton Skull +item.minecraft.zombie_head=Zombie Head +item.minecraft.creeper_head=Creeper Head +item.minecraft.dragon_head=Dragon Head +item.minecraft.carrot_on_a_stick=Carrot on a Stick +item.minecraft.nether_star=Nether Star +item.minecraft.pumpkin_pie=Pumpkin Pie +item.minecraft.enchanted_book=Enchanted Book +item.minecraft.firework_rocket=Firework Rocket +item.minecraft.firework_star=Firework Star +item.minecraft.nether_brick=Nether Brick +item.minecraft.quartz=Nether Quartz +item.minecraft.armor_stand=Armor Stand +item.minecraft.iron_horse_armor=Iron Horse Armor +item.minecraft.golden_horse_armor=Golden Horse Armor +item.minecraft.diamond_horse_armor=Diamond Horse Armor +item.minecraft.leather_horse_armor=Leather Horse Armor +item.minecraft.prismarine_shard=Prismarine Shard +item.minecraft.prismarine_crystals=Prismarine Crystals +item.minecraft.chorus_fruit=Chorus Fruit +item.minecraft.popped_chorus_fruit=Popped Chorus Fruit +item.minecraft.beetroot=Beetroot +item.minecraft.beetroot_seeds=Beetroot Seeds +item.minecraft.beetroot_soup=Beetroot Soup +item.minecraft.dragon_breath=Dragon's Breath +item.minecraft.elytra=Elytra +item.minecraft.totem_of_undying=Totem of Undying +item.minecraft.shulker_shell=Shulker Shell +item.minecraft.iron_nugget=Iron Nugget +item.minecraft.knowledge_book=Knowledge Book +item.minecraft.debug_stick=Debug Stick +item.minecraft.trident=Trident +item.minecraft.scute=Scute +item.minecraft.turtle_helmet=Turtle Shell +item.minecraft.phantom_membrane=Phantom Membrane +item.minecraft.nautilus_shell=Nautilus Shell +item.minecraft.heart_of_the_sea=Heart of the Sea +item.minecraft.crossbow=Crossbow +item.minecraft.crossbow.projectile=Projectile: +item.minecraft.suspicious_stew=Suspicious Stew +item.minecraft.creeper_banner_pattern=Banner Pattern +item.minecraft.skull_banner_pattern=Banner Pattern +item.minecraft.flower_banner_pattern=Banner Pattern +item.minecraft.mojang_banner_pattern=Banner Pattern +item.minecraft.globe_banner_pattern=Banner Pattern +item.minecraft.piglin_banner_pattern=Banner Pattern +item.minecraft.creeper_banner_pattern.desc=Creeper Charge +item.minecraft.skull_banner_pattern.desc=Skull Charge +item.minecraft.flower_banner_pattern.desc=Flower Charge +item.minecraft.mojang_banner_pattern.desc=Thing +item.minecraft.globe_banner_pattern.desc=Globe +item.minecraft.piglin_banner_pattern.desc=Snout +item.minecraft.sweet_berries=Sweet Berries +item.minecraft.honey_bottle=Honey Bottle +item.minecraft.honeycomb=Honeycomb +item.minecraft.lodestone_compass=Lodestone Compass +item.minecraft.netherite_scrap=Netherite Scrap +item.minecraft.netherite_ingot=Netherite Ingot +item.minecraft.netherite_helmet=Netherite Helmet +item.minecraft.netherite_chestplate=Netherite Chestplate +item.minecraft.netherite_leggings=Netherite Leggings +item.minecraft.netherite_boots=Netherite Boots +item.minecraft.netherite_axe=Netherite Axe +item.minecraft.netherite_pickaxe=Netherite Pickaxe +item.minecraft.netherite_hoe=Netherite Hoe +item.minecraft.netherite_shovel=Netherite Shovel +item.minecraft.netherite_sword=Netherite Sword +item.minecraft.warped_fungus_on_a_stick=Warped Fungus on a Stick +item.minecraft.glow_ink_sac=Glow Ink Sac +item.minecraft.glow_item_frame=Glow Item Frame +effect.minecraft.speed=Speed +effect.minecraft.slowness=Slowness +effect.minecraft.haste=Haste +effect.minecraft.mining_fatigue=Mining Fatigue +effect.minecraft.strength=Strength +effect.minecraft.instant_health=Instant Health +effect.minecraft.instant_damage=Instant Damage +effect.minecraft.jump_boost=Jump Boost +effect.minecraft.nausea=Nausea +effect.minecraft.regeneration=Regeneration +effect.minecraft.resistance=Resistance +effect.minecraft.fire_resistance=Fire Resistance +effect.minecraft.water_breathing=Water Breathing +effect.minecraft.invisibility=Invisibility +effect.minecraft.blindness=Blindness +effect.minecraft.night_vision=Night Vision +effect.minecraft.hunger=Hunger +effect.minecraft.weakness=Weakness +effect.minecraft.poison=Poison +effect.minecraft.wither=Wither +effect.minecraft.health_boost=Health Boost +effect.minecraft.absorption=Absorption +effect.minecraft.saturation=Saturation +effect.minecraft.glowing=Glowing +effect.minecraft.luck=Luck +effect.minecraft.unluck=Bad Luck +effect.minecraft.levitation=Levitation +effect.minecraft.slow_falling=Slow Falling +effect.minecraft.conduit_power=Conduit Power +effect.minecraft.dolphins_grace=Dolphin's Grace +effect.minecraft.bad_omen=Bad Omen +effect.minecraft.hero_of_the_village=Hero of the Village +item.minecraft.tipped_arrow.effect.empty=Uncraftable Tipped Arrow +item.minecraft.tipped_arrow.effect.water=Arrow of Splashing +item.minecraft.tipped_arrow.effect.mundane=Tipped Arrow +item.minecraft.tipped_arrow.effect.thick=Tipped Arrow +item.minecraft.tipped_arrow.effect.awkward=Tipped Arrow +item.minecraft.tipped_arrow.effect.night_vision=Arrow of Night Vision +item.minecraft.tipped_arrow.effect.invisibility=Arrow of Invisibility +item.minecraft.tipped_arrow.effect.leaping=Arrow of Leaping +item.minecraft.tipped_arrow.effect.fire_resistance=Arrow of Fire Resistance +item.minecraft.tipped_arrow.effect.swiftness=Arrow of Swiftness +item.minecraft.tipped_arrow.effect.slowness=Arrow of Slowness +item.minecraft.tipped_arrow.effect.water_breathing=Arrow of Water Breathing +item.minecraft.tipped_arrow.effect.healing=Arrow of Healing +item.minecraft.tipped_arrow.effect.harming=Arrow of Harming +item.minecraft.tipped_arrow.effect.poison=Arrow of Poison +item.minecraft.tipped_arrow.effect.regeneration=Arrow of Regeneration +item.minecraft.tipped_arrow.effect.strength=Arrow of Strength +item.minecraft.tipped_arrow.effect.weakness=Arrow of Weakness +item.minecraft.tipped_arrow.effect.levitation=Arrow of Levitation +item.minecraft.tipped_arrow.effect.luck=Arrow of Luck +item.minecraft.tipped_arrow.effect.turtle_master=Arrow of the Turtle Master +item.minecraft.tipped_arrow.effect.slow_falling=Arrow of Slow Falling +item.minecraft.potion.effect.empty=Uncraftable Potion +item.minecraft.potion.effect.water=Water Bottle +item.minecraft.potion.effect.mundane=Mundane Potion +item.minecraft.potion.effect.thick=Thick Potion +item.minecraft.potion.effect.awkward=Awkward Potion +item.minecraft.potion.effect.night_vision=Potion of Night Vision +item.minecraft.potion.effect.invisibility=Potion of Invisibility +item.minecraft.potion.effect.leaping=Potion of Leaping +item.minecraft.potion.effect.fire_resistance=Potion of Fire Resistance +item.minecraft.potion.effect.swiftness=Potion of Swiftness +item.minecraft.potion.effect.slowness=Potion of Slowness +item.minecraft.potion.effect.water_breathing=Potion of Water Breathing +item.minecraft.potion.effect.healing=Potion of Healing +item.minecraft.potion.effect.harming=Potion of Harming +item.minecraft.potion.effect.poison=Potion of Poison +item.minecraft.potion.effect.regeneration=Potion of Regeneration +item.minecraft.potion.effect.strength=Potion of Strength +item.minecraft.potion.effect.weakness=Potion of Weakness +item.minecraft.potion.effect.levitation=Potion of Levitation +item.minecraft.potion.effect.luck=Potion of Luck +item.minecraft.potion.effect.turtle_master=Potion of the Turtle Master +item.minecraft.potion.effect.slow_falling=Potion of Slow Falling +item.minecraft.splash_potion.effect.empty=Splash Uncraftable Potion +item.minecraft.splash_potion.effect.water=Splash Water Bottle +item.minecraft.splash_potion.effect.mundane=Mundane Splash Potion +item.minecraft.splash_potion.effect.thick=Thick Splash Potion +item.minecraft.splash_potion.effect.awkward=Awkward Splash Potion +item.minecraft.splash_potion.effect.night_vision=Splash Potion of Night Vision +item.minecraft.splash_potion.effect.invisibility=Splash Potion of Invisibility +item.minecraft.splash_potion.effect.leaping=Splash Potion of Leaping +item.minecraft.splash_potion.effect.fire_resistance=Splash Potion of Fire Resistance +item.minecraft.splash_potion.effect.swiftness=Splash Potion of Swiftness +item.minecraft.splash_potion.effect.slowness=Splash Potion of Slowness +item.minecraft.splash_potion.effect.water_breathing=Splash Potion of Water Breathing +item.minecraft.splash_potion.effect.healing=Splash Potion of Healing +item.minecraft.splash_potion.effect.harming=Splash Potion of Harming +item.minecraft.splash_potion.effect.poison=Splash Potion of Poison +item.minecraft.splash_potion.effect.regeneration=Splash Potion of Regeneration +item.minecraft.splash_potion.effect.strength=Splash Potion of Strength +item.minecraft.splash_potion.effect.weakness=Splash Potion of Weakness +item.minecraft.splash_potion.effect.levitation=Splash Potion of Levitation +item.minecraft.splash_potion.effect.luck=Splash Potion of Luck +item.minecraft.splash_potion.effect.turtle_master=Splash Potion of the Turtle Master +item.minecraft.splash_potion.effect.slow_falling=Splash Potion of Slow Falling +item.minecraft.lingering_potion.effect.empty=Lingering Uncraftable Potion +item.minecraft.lingering_potion.effect.water=Lingering Water Bottle +item.minecraft.lingering_potion.effect.mundane=Mundane Lingering Potion +item.minecraft.lingering_potion.effect.thick=Thick Lingering Potion +item.minecraft.lingering_potion.effect.awkward=Awkward Lingering Potion +item.minecraft.lingering_potion.effect.night_vision=Lingering Potion of Night Vision +item.minecraft.lingering_potion.effect.invisibility=Lingering Potion of Invisibility +item.minecraft.lingering_potion.effect.leaping=Lingering Potion of Leaping +item.minecraft.lingering_potion.effect.fire_resistance=Lingering Potion of Fire Resistance +item.minecraft.lingering_potion.effect.swiftness=Lingering Potion of Swiftness +item.minecraft.lingering_potion.effect.slowness=Lingering Potion of Slowness +item.minecraft.lingering_potion.effect.water_breathing=Lingering Potion of Water Breathing +item.minecraft.lingering_potion.effect.healing=Lingering Potion of Healing +item.minecraft.lingering_potion.effect.harming=Lingering Potion of Harming +item.minecraft.lingering_potion.effect.poison=Lingering Potion of Poison +item.minecraft.lingering_potion.effect.regeneration=Lingering Potion of Regeneration +item.minecraft.lingering_potion.effect.strength=Lingering Potion of Strength +item.minecraft.lingering_potion.effect.weakness=Lingering Potion of Weakness +item.minecraft.lingering_potion.effect.levitation=Lingering Potion of Levitation +item.minecraft.lingering_potion.effect.luck=Lingering Potion of Luck +item.minecraft.lingering_potion.effect.turtle_master=Lingering Potion of the Turtle Master +item.minecraft.lingering_potion.effect.slow_falling=Lingering Potion of Slow Falling +enchantment.minecraft.sharpness=Sharpness +enchantment.minecraft.smite=Smite +enchantment.minecraft.bane_of_arthropods=Bane of Arthropods +enchantment.minecraft.knockback=Knockback +enchantment.minecraft.fire_aspect=Fire Aspect +enchantment.minecraft.sweeping=Sweeping Edge +enchantment.minecraft.protection=Protection +enchantment.minecraft.fire_protection=Fire Protection +enchantment.minecraft.feather_falling=Feather Falling +enchantment.minecraft.blast_protection=Blast Protection +enchantment.minecraft.projectile_protection=Projectile Protection +enchantment.minecraft.respiration=Respiration +enchantment.minecraft.aqua_affinity=Aqua Affinity +enchantment.minecraft.depth_strider=Depth Strider +enchantment.minecraft.frost_walker=Frost Walker +enchantment.minecraft.soul_speed=Soul Speed +enchantment.minecraft.efficiency=Efficiency +enchantment.minecraft.silk_touch=Silk Touch +enchantment.minecraft.unbreaking=Unbreaking +enchantment.minecraft.looting=Looting +enchantment.minecraft.fortune=Fortune +enchantment.minecraft.luck_of_the_sea=Luck of the Sea +enchantment.minecraft.lure=Lure +enchantment.minecraft.power=Power +enchantment.minecraft.flame=Flame +enchantment.minecraft.punch=Punch +enchantment.minecraft.infinity=Infinity +enchantment.minecraft.thorns=Thorns +enchantment.minecraft.mending=Mending +enchantment.minecraft.binding_curse=Curse of Binding +enchantment.minecraft.vanishing_curse=Curse of Vanishing +enchantment.minecraft.loyalty=Loyalty +enchantment.minecraft.impaling=Impaling +enchantment.minecraft.riptide=Riptide +enchantment.minecraft.channeling=Channeling +enchantment.minecraft.multishot=Multishot +enchantment.minecraft.quick_charge=Quick Charge +enchantment.minecraft.piercing=Piercing +enchantment.level.1=I +enchantment.level.2=II +enchantment.level.3=III +enchantment.level.4=IV +enchantment.level.5=V +enchantment.level.6=VI +enchantment.level.7=VII +enchantment.level.8=VIII +enchantment.level.9=IX +enchantment.level.10=X +block.minecraft.black_banner=Black Banner +block.minecraft.red_banner=Red Banner +block.minecraft.green_banner=Green Banner +block.minecraft.brown_banner=Brown Banner +block.minecraft.blue_banner=Blue Banner +block.minecraft.purple_banner=Purple Banner +block.minecraft.cyan_banner=Cyan Banner +block.minecraft.light_gray_banner=Light Gray Banner +block.minecraft.gray_banner=Gray Banner +block.minecraft.pink_banner=Pink Banner +block.minecraft.lime_banner=Lime Banner +block.minecraft.yellow_banner=Yellow Banner +block.minecraft.light_blue_banner=Light Blue Banner +block.minecraft.magenta_banner=Magenta Banner +block.minecraft.orange_banner=Orange Banner +block.minecraft.white_banner=White Banner +item.minecraft.shield=Shield \ No newline at end of file diff --git a/plugin/src/main/resources/plugin.yml b/plugin/src/main/resources/plugin.yml new file mode 100644 index 0000000..dbf6e67 --- /dev/null +++ b/plugin/src/main/resources/plugin.yml @@ -0,0 +1,93 @@ +# Do not change anything in here unless you know what you're doing! + +name: ${project.name} +main: de.epiceric.shopchest.ShopChest +version: ${project.version} +author: EpicEric +website: ${project.url} +description: Create your own nice-looking chest shops and sell your stuff to other players! +softdepend: [WorldGuard, Towny, AuthMe, PlotSquared, uSkyBlock, ASkyBlock, IslandWorld, GriefPrevention, AreaShop, Multiverse-Core, MultiWorld, BentoBox] +depend: [Vault] +api-version: 1.13 + +permissions: + shopchest.*: + description: Gives access to all ShopChest permissions. + children: + shopchest.create: true + shopchest.create.buy: true + shopchest.create.sell: true + shopchest.create.admin: true + shopchest.create.protected: true + shopchest.remove.other: true + shopchest.remove.admin: true + shopchest.buy: true + shopchest.openOther: true + shopchest.notification.update: true + shopchest.reload: true + shopchest.update: true + shopchest.limit.*: true + shopchest.config: true + shopchest.extend.other: true + shopchest.extend.protected: true + shopchest.external.bypass: true + shopchest.create: + description: Allows you to create a shop. + children: + shopchest.create.buy: true + shopchest.create.sell: true + default: true + shopchest.create.buy: + description: Allows you to create a buy-shop. + default: true + shopchest.create.sell: + description: Allows you to create a sell-shop. + default: true + shopchest.create.admin: + description: Allows you to create an admin shop. + children: + shopchest.create: true + default: op + shopchest.create.protected: + description: Allows you to create a shop on a protected chest or in a protected region. + children: + shopchest.create: true + default: op + shopchest.remove.other: + description: Allows you to remove other players' shops. + default: op + shopchest.remove.admin: + description: Allows you to remove admin shops. + default: op + shopchest.buy: + description: Allows you to buy something. + default: true + shopchest.sell: + description: Allows you to sell something. + default: true + shopchest.openOther: + description: Allows you to open other players' shops. + default: op + shopchest.notification.update: + description: Allows you to get update notification on join. + default: op + shopchest.reload: + description: Allows you to reload the shops. + default: op + shopchest.update: + description: Allows you to check for updates. + default: op + shopchest.limit.*: + default: op + shopchest.config: + description: Allows you to change configuration values per command. + default: op + shopchest.extend.other: + description: Allows you to extend other players' shops. + default: op + shopchest.extend.protected: + description: Allows you to extend shops into a protected region. + default: op + shopchest.external.bypass: + description: Allows you to to use shops regions/plots that deny shop use. + default: op