From 02f184321f26d044ed9a03c7fcb7549cc86c85ec Mon Sep 17 00:00:00 2001 From: IndianBartonka Date: Sun, 28 May 2023 12:51:56 +0200 Subject: [PATCH] So manny code fixes and better working --- .idea/.gitignore | 3 + .idea/compiler.xml | 13 + .idea/discord.xml | 7 + .idea/encodings.xml | 7 + .idea/jarRepositories.xml | 35 + .idea/libraries/silnik.xml | 9 + .idea/misc.xml | 17 + .idea/uiDesigner.xml | 124 ++ .idea/vcs.xml | 6 + README.md | 2 +- pom.xml | 17 +- .../java/me/indian/enderchest/Enderchest.java | 113 ++ src/main/java/me/indian/enderchest/Test.java | 29 - .../indian/enderchest/Utils/MessageApi.java | 57 - .../enderchest/command/EnderChestCommand.java | 88 + .../OpenCommand.java} | 125 +- .../me/indian/enderchest/commands/Reload.java | 32 - .../me/indian/enderchest/commands/Set.java | 38 - .../me/indian/enderchest/commands/open.java | 75 - .../enderchest/listener/HandListener.java | 57 + .../listener/InventoryListener.java | 88 + .../listeners/CrRcHandListener.java | 54 - .../listeners/InventoryListener.java | 52 - .../enderchest/listeners/SetListener.java | 70 - .../me/indian/enderchest/main/Enderchest.java | 116 -- .../EnderchestPlaceholders.java | 143 +- .../enderchest/{others => other}/Metrics.java | 1705 ++++++++--------- .../{others => other}/UpdateChecker.java | 67 +- .../me/indian/enderchest/util/ColorUtil.java | 11 + .../{Utils => util}/ConfigUtil.java | 79 +- .../enderchest/{ => util}/EnderChestApi.java | 70 +- .../me/indian/enderchest/util/MessageApi.java | 56 + .../me/indian/enderchest/util/ReopenUtil.java | 21 + src/main/resources/config.yml | 6 +- src/main/resources/plugin.yml | 24 +- 35 files changed, 1774 insertions(+), 1642 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/discord.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/libraries/silnik.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/uiDesigner.xml create mode 100644 .idea/vcs.xml create mode 100644 src/main/java/me/indian/enderchest/Enderchest.java delete mode 100644 src/main/java/me/indian/enderchest/Test.java delete mode 100644 src/main/java/me/indian/enderchest/Utils/MessageApi.java create mode 100644 src/main/java/me/indian/enderchest/command/EnderChestCommand.java rename src/main/java/me/indian/enderchest/{others/OpenInventory.java => command/OpenCommand.java} (55%) delete mode 100644 src/main/java/me/indian/enderchest/commands/Reload.java delete mode 100644 src/main/java/me/indian/enderchest/commands/Set.java delete mode 100644 src/main/java/me/indian/enderchest/commands/open.java create mode 100644 src/main/java/me/indian/enderchest/listener/HandListener.java create mode 100644 src/main/java/me/indian/enderchest/listener/InventoryListener.java delete mode 100644 src/main/java/me/indian/enderchest/listeners/CrRcHandListener.java delete mode 100644 src/main/java/me/indian/enderchest/listeners/InventoryListener.java delete mode 100644 src/main/java/me/indian/enderchest/listeners/SetListener.java delete mode 100644 src/main/java/me/indian/enderchest/main/Enderchest.java rename src/main/java/me/indian/enderchest/{others => other}/EnderchestPlaceholders.java (68%) rename src/main/java/me/indian/enderchest/{others => other}/Metrics.java (97%) rename src/main/java/me/indian/enderchest/{others => other}/UpdateChecker.java (94%) create mode 100644 src/main/java/me/indian/enderchest/util/ColorUtil.java rename src/main/java/me/indian/enderchest/{Utils => util}/ConfigUtil.java (92%) rename src/main/java/me/indian/enderchest/{ => util}/EnderChestApi.java (56%) create mode 100644 src/main/java/me/indian/enderchest/util/MessageApi.java create mode 100644 src/main/java/me/indian/enderchest/util/ReopenUtil.java diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..3b14c01 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..30bab2a --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..d77eafd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/silnik.xml b/.idea/libraries/silnik.xml new file mode 100644 index 0000000..f41af8a --- /dev/null +++ b/.idea/libraries/silnik.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..e54f469 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 5f02a83..77a4169 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@
# Enderchest-and-Crafting + [![Discord](https://img.shields.io/discord/941850822885646366?color=7289da&logo=discord&logoColor=white&style=for-the-badge)](https://discord.gg/mF3TehkeG3) ![Last Commit](https://img.shields.io/github/last-commit/IndianBartonka/Enderchest-and-Crafting?style=for-the-badge) [![Open issues](https://img.shields.io/github/issues/IndianBartonka/Enderchest-and-Crafting?style=for-the-badge)](https://github.com/IndianBartonka/Enderchest-and-Crafting/issues) @@ -17,7 +18,6 @@ To wtyczka umożliwiąca otwarcie skrzynki kresu albo stołu rzemieślniczego tam gdzie się chcę https://www.spigotmc.org/resources/enderchest-and-crafting.99276/ - Jeśli używasz GeyserMC wiedz że plugin działa tak samo na bedrock jak i na javie , nie ma żadnych problemów diff --git a/pom.xml b/pom.xml index 142afbc..fdfeeb0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,12 @@ - 4.0.0 me.indian enderchest - 3.3 + 4.0 jar Enderchest @@ -69,17 +69,16 @@ - - org.spigotmc - spigot-api - 1.19-R0.1-SNAPSHOT - provided - me.clip placeholderapi 2.11.2 provided + + org.spigotmc + spigot-api + 1.19-R0.1-SNAPSHOT + diff --git a/src/main/java/me/indian/enderchest/Enderchest.java b/src/main/java/me/indian/enderchest/Enderchest.java new file mode 100644 index 0000000..fa0fda2 --- /dev/null +++ b/src/main/java/me/indian/enderchest/Enderchest.java @@ -0,0 +1,113 @@ +package me.indian.enderchest; + + +import me.indian.enderchest.command.EnderChestCommand; +import me.indian.enderchest.command.OpenCommand; +import me.indian.enderchest.listener.HandListener; +import me.indian.enderchest.listener.InventoryListener; +import me.indian.enderchest.other.EnderchestPlaceholders; +import me.indian.enderchest.other.Metrics; +import me.indian.enderchest.other.UpdateChecker; +import me.indian.enderchest.util.ColorUtil; +import me.indian.enderchest.util.EnderChestApi; +import me.indian.enderchest.util.MessageApi; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.plugin.PluginManager; +import org.bukkit.plugin.java.JavaPlugin; + +public final class Enderchest extends JavaPlugin implements Listener { + + private static Enderchest instance; + public final String prefix = getConfig().getString("prefix"); + public final String openName = getConfig().getString("InvName"); + public final String version = getDescription().getVersion(); + private EnderChestApi enderChestApi; + private EnderChestCommand enderChestCommand; + private OpenCommand openCommand; + + public static Enderchest getInstance() { + return instance; + } + + public EnderChestApi getApi() { + return this.enderChestApi; + } + + public EnderChestCommand getEnderChestCommand() { + return this.enderChestCommand; + } + + public OpenCommand getOpenCommand() { + return this.openCommand; + } + + @Override + public void onLoad() { + saveDefaultConfig(); + instance = this; + enderChestApi = new EnderChestApi(); + enderChestCommand = new EnderChestCommand(this); + openCommand = new OpenCommand(this); + } + + @Override + public void onEnable() { + final PluginManager pm = Bukkit.getPluginManager(); + if (pm.getPlugin("PlaceholderAPI") != null) { + new EnderchestPlaceholders(this).register(); + } else { + getLogger().info(ColorUtil.replaceColorCode("&bYou not using PlaceholderAPI, not required :^")); + } + + this.getLogger().info("------------------------------"); + this.getLogger().info("\t " + prefix + " " + version); + this.getLogger().info("------------------------------"); + + + new UpdateChecker(this, 99276).getVersion(version -> { + if (this.getDescription().getVersion().equals(version)) { + getLogger().info(ColorUtil.replaceColorCode(prefix + "&a There is not a new update available.")); + + } else { + getLogger().info(ColorUtil.replaceColorCode(prefix + "&a There is a new update available.")); + getLogger().info(ColorUtil.replaceColorCode(prefix + "&a Your version " + this.getDescription().getVersion() + " new version " + version)); + + } + }); + + new Metrics(this, 13974); + + getCommand("open").setExecutor(new OpenCommand(this)); + getCommand("enderchest").setExecutor(new EnderChestCommand(this)); + + pm.registerEvents(new InventoryListener(this), this); + pm.registerEvents(this, this); + pm.registerEvents(new HandListener(this), this); + } + + public void onDisable() { + this.getLogger().info(ColorUtil.replaceColorCode(prefix + "&c Disabling")); + this.getLogger().info(ColorUtil.replaceColorCode(prefix + "&b Version &6" + version)); + } + + @EventHandler + public void opJoin(PlayerJoinEvent e) { + Player player = e.getPlayer(); + + if (player.isOp()) { + new UpdateChecker(this, 99276).getVersion(version -> { + if (!(this.getDescription().getVersion().equals(version))) { + MessageApi.chat(player, ColorUtil.replaceColorCode(prefix + "&bThere is a new update available.")); + MessageApi.hoverMessageCopy(player, + ColorUtil.replaceColorCode(prefix + "&bYour version " + this.getDescription().getVersion() + " new version " + version), + ColorUtil.replaceColorCode("https://www.spigotmc.org/resources/enderchest-and-crafting.99276/"), + ColorUtil.replaceColorCode("Copy download link")); + } + }); + } + } +} \ No newline at end of file diff --git a/src/main/java/me/indian/enderchest/Test.java b/src/main/java/me/indian/enderchest/Test.java deleted file mode 100644 index 7c605dd..0000000 --- a/src/main/java/me/indian/enderchest/Test.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.indian.enderchest; - -import me.indian.enderchest.main.Enderchest; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public class Test implements CommandExecutor { - - private final Enderchest plugin; - - public Test(Enderchest plugin) { - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - Player p = (Player) sender; - - // plugin = Main class | p = Player | you can get boolean form your config (if true enderchest has been opened) - // refusal message , if open == false this message has been typed || closeinv if true inventory has been closed if open = false - // sorry for my english ;) - EnderChestApi.OpenEnderChest(plugin, p, false, "Enderchest not allowed", true); - EnderChestApi.OpenCrafting(plugin, p, true, "Crafting not allowed", false); - - return false; - } -} diff --git a/src/main/java/me/indian/enderchest/Utils/MessageApi.java b/src/main/java/me/indian/enderchest/Utils/MessageApi.java deleted file mode 100644 index ece08ef..0000000 --- a/src/main/java/me/indian/enderchest/Utils/MessageApi.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.indian.enderchest.Utils; - - -import net.md_5.bungee.api.ChatMessageType; -import net.md_5.bungee.api.chat.ClickEvent; -import net.md_5.bungee.api.chat.ComponentBuilder; -import net.md_5.bungee.api.chat.HoverEvent; -import net.md_5.bungee.api.chat.TextComponent; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -public class MessageApi { - - public static void ActionBar(Player p, String tekst) { - p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(tekst.replace("", p.getName()))); - } - - public static void Chat(Player p, String tekst) { - p.spigot().sendMessage(ChatMessageType.CHAT, TextComponent.fromLegacyText(tekst.replace("", p.getName()))); - } - - public static void Console(Player p, String komenda) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), komenda.replace("", p.getName())); - } - - public static void Console(String komenda) { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), komenda); - } - - public static void PlayerCommand(Player p, String komenda) { - Bukkit.dispatchCommand(p, komenda.replace("", p.getName())); - } - - public static void HoverMessage(Player p, String tekst, String hovertekst) { - TextComponent message = new TextComponent(tekst); - message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hovertekst).create())); - p.spigot().sendMessage(message); - } - - public static void HoverMessage(Player p, String tekst, String komenda, String hovertekst, Boolean run) { - TextComponent message = new TextComponent(tekst); - if (run == true) { - message.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, komenda)); - } else { - message.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, komenda)); - } - message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hovertekst).create())); - p.spigot().sendMessage(message); - } - - public static void HoverMessageCopy(Player p, String tekst, String tekstc, String hovertekst) { - TextComponent message = new TextComponent(tekst); - message.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, tekstc)); - message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hovertekst).create())); - p.spigot().sendMessage(message); - } -} \ No newline at end of file diff --git a/src/main/java/me/indian/enderchest/command/EnderChestCommand.java b/src/main/java/me/indian/enderchest/command/EnderChestCommand.java new file mode 100644 index 0000000..21c8ccc --- /dev/null +++ b/src/main/java/me/indian/enderchest/command/EnderChestCommand.java @@ -0,0 +1,88 @@ +package me.indian.enderchest.command; + +import java.util.Arrays; +import me.indian.enderchest.Enderchest; +import me.indian.enderchest.util.ColorUtil; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.Configuration; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class EnderChestCommand implements CommandExecutor { + + private final Enderchest plugin; + + public EnderChestCommand(Enderchest plugin) { + this.plugin = plugin; + } + + + @Override + public boolean onCommand(CommandSender sender, Command command, String s, String[] args) { + final Configuration config = plugin.getConfig(); + + if (sender instanceof Player) { + Player player = (Player) sender; + if (sender.hasPermission("endacrft.admin")) { + + if (args.length == 0) { + player.sendMessage(ColorUtil.replaceColorCode(plugin.prefix + "&aUsage &b/enderchest &8[set, reload]")); + } + + if (args[0].equalsIgnoreCase("set")) { + openSettings(player); + } + if (args[0].equalsIgnoreCase("reload")) { + plugin.reloadConfig(); + sender.sendMessage(ColorUtil.replaceColorCode(config.getString("config-reload"))); + plugin.getLogger().info(config.getString("config-reload")); + } + } else { + sender.sendMessage(config.getString("admin-perms")); + } + } else { + sender.sendMessage(config.getString("player-not-be")); + } + return false; + } + + + public void openSettings(Player player) { + Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, "/open options"); + + ItemStack crafting = new ItemStack(Material.CRAFTING_TABLE); + ItemMeta c = crafting.getItemMeta(); + c.setDisplayName(ChatColor.GREEN + "Crafting"); + c.setLore(Arrays.asList("§e--------", plugin.getConfig().getString("CraftInfo"))); + crafting.setItemMeta(c); + + ItemStack ender = new ItemStack(Material.ENDER_CHEST); + ItemMeta e = ender.getItemMeta(); + e.setDisplayName(ChatColor.AQUA + "EnderChest"); + e.setLore(Arrays.asList("§e--------", plugin.getConfig().getString("EnderInfo"))); + ender.setItemMeta(e); + + + ItemStack empty = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); + ItemMeta s = empty.getItemMeta(); + s.setDisplayName(ChatColor.BLACK + "empty"); + empty.setItemMeta(s); + + inv.setItem(0, empty); + inv.setItem(1, crafting); + inv.setItem(2, empty); + inv.setItem(3, ender); + inv.setItem(4, empty); + + player.openInventory(inv); + } + +} diff --git a/src/main/java/me/indian/enderchest/others/OpenInventory.java b/src/main/java/me/indian/enderchest/command/OpenCommand.java similarity index 55% rename from src/main/java/me/indian/enderchest/others/OpenInventory.java rename to src/main/java/me/indian/enderchest/command/OpenCommand.java index 6846aa5..ccc866f 100644 --- a/src/main/java/me/indian/enderchest/others/OpenInventory.java +++ b/src/main/java/me/indian/enderchest/command/OpenCommand.java @@ -1,50 +1,75 @@ -package me.indian.enderchest.others; - -import me.indian.enderchest.main.Enderchest; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import java.util.Arrays; - -public class OpenInventory { - - public static void OpenInv(Player p, Enderchest plugin) { - - Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, "/open options"); - - - ItemStack crafting = new ItemStack(Material.CRAFTING_TABLE); - ItemMeta c = crafting.getItemMeta(); - c.setDisplayName(ChatColor.GREEN + "Crafting"); - c.setLore(Arrays.asList("§e--------", plugin.getConfig().getString("CraftInfo"))); - crafting.setItemMeta(c); - - ItemStack ender = new ItemStack(Material.ENDER_CHEST); - ItemMeta e = ender.getItemMeta(); - e.setDisplayName(ChatColor.AQUA + "EnderChest"); - e.setLore(Arrays.asList("§e--------", plugin.getConfig().getString("EnderInfo"))); - ender.setItemMeta(e); - - - ItemStack empty = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); - ItemMeta s = empty.getItemMeta(); - s.setDisplayName(ChatColor.BLACK + "empty"); - empty.setItemMeta(s); - - inv.setItem(0, empty); - inv.setItem(1, crafting); - inv.setItem(2, empty); - inv.setItem(3, ender); - inv.setItem(4, empty); - - p.openInventory(inv); - - } - -} +package me.indian.enderchest.command; + +import java.util.Arrays; +import me.indian.enderchest.Enderchest; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.Configuration; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + + +public class OpenCommand implements CommandExecutor { + + private final Enderchest plugin; + + public OpenCommand(Enderchest plugin) { + this.plugin = plugin; + + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + final Configuration config = plugin.getConfig(); + + if (sender instanceof Player) { + if (sender.hasPermission("endacrft.open")) { + openEnderchestGui((Player) sender); + } else { + sender.sendMessage(config.getString("Open-Perm")); + } + } else { + sender.sendMessage(config.getString("player-not-be")); + } + return false; + } + + public void openEnderchestGui(Player player) { + Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, plugin.openName); + + ItemStack crafting = new ItemStack(Material.CRAFTING_TABLE); + ItemMeta c = crafting.getItemMeta(); + c.setDisplayName(ChatColor.GREEN + "Crafting"); + c.setLore(Arrays.asList("§e--------", plugin.getConfig().getString("CraftInfo"))); + crafting.setItemMeta(c); + + ItemStack ender = new ItemStack(Material.ENDER_CHEST); + ItemMeta e = ender.getItemMeta(); + e.setDisplayName(ChatColor.AQUA + "EnderChest"); + e.setLore(Arrays.asList("§e--------", plugin.getConfig().getString("EnderInfo"))); + ender.setItemMeta(e); + + + ItemStack empty = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); + ItemMeta s = empty.getItemMeta(); + s.setDisplayName(ChatColor.BLACK + "empty"); + empty.setItemMeta(s); + + + inv.setItem(0, empty); + inv.setItem(1, crafting); + inv.setItem(2, empty); + inv.setItem(3, ender); + inv.setItem(4, empty); + + player.openInventory(inv); + } +} + diff --git a/src/main/java/me/indian/enderchest/commands/Reload.java b/src/main/java/me/indian/enderchest/commands/Reload.java deleted file mode 100644 index 3241e2f..0000000 --- a/src/main/java/me/indian/enderchest/commands/Reload.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.indian.enderchest.commands; - -import me.indian.enderchest.main.Enderchest; -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; - -public class Reload implements CommandExecutor { - - private final Enderchest plugin; - - public Reload(Enderchest plugin) { - this.plugin = plugin; - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!sender.hasPermission("admin-perms")) { - sender.sendMessage(plugin.getConfig().getString("admin-perms")); - return false; - } - - - plugin.reloadConfig(); - sender.sendMessage(plugin.getConfig().getString("config-reload")); - Bukkit.getConsoleSender().sendMessage(plugin.getConfig().getString("config-reload")); - - - return false; - } -} diff --git a/src/main/java/me/indian/enderchest/commands/Set.java b/src/main/java/me/indian/enderchest/commands/Set.java deleted file mode 100644 index f7f2353..0000000 --- a/src/main/java/me/indian/enderchest/commands/Set.java +++ /dev/null @@ -1,38 +0,0 @@ -package me.indian.enderchest.commands; - - -import me.indian.enderchest.others.OpenInventory; -import me.indian.enderchest.main.Enderchest; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.Listener; - -public class Set implements CommandExecutor, Listener { - - private final Enderchest plugin; - - public Set(Enderchest plugin) { - this.plugin = plugin; - } - - public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args) { - if (sender instanceof Player) { - Player p = (Player) sender; - if (!sender.hasPermission("endacrft.admin")) { - sender.sendMessage(plugin.getConfig().getString("admin-perms")); - return false; - } - - if (args.length == 1) { - p.sendMessage("/set"); - } else { - OpenInventory.OpenInv(p, plugin); - } - } else { - sender.sendMessage(plugin.getConfig().getString("player-not-be")); - } - return false; - } -} diff --git a/src/main/java/me/indian/enderchest/commands/open.java b/src/main/java/me/indian/enderchest/commands/open.java deleted file mode 100644 index 09bab0b..0000000 --- a/src/main/java/me/indian/enderchest/commands/open.java +++ /dev/null @@ -1,75 +0,0 @@ -package me.indian.enderchest.commands; - -import me.indian.enderchest.main.Enderchest; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import java.util.Arrays; - - -public class open implements CommandExecutor { - - private final Enderchest plugin; - - public open(Enderchest plugin) { - this.plugin = plugin; - - } - - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - - - if (sender instanceof Player) { - if (sender.hasPermission("endacrft.open")) { - Player p = (Player) sender; - Inventory inv = Bukkit.createInventory(null, InventoryType.HOPPER, plugin.openName); - - ItemStack crafting = new ItemStack(Material.CRAFTING_TABLE); - ItemMeta c = crafting.getItemMeta(); - c.setDisplayName(ChatColor.GREEN + "Crafting"); - c.setLore(Arrays.asList("§e--------", plugin.getConfig().getString("CraftInfo"))); - crafting.setItemMeta(c); - - ItemStack ender = new ItemStack(Material.ENDER_CHEST); - ItemMeta e = ender.getItemMeta(); - e.setDisplayName(ChatColor.AQUA + "EnderChest"); - e.setLore(Arrays.asList("§e--------", plugin.getConfig().getString("EnderInfo"))); - ender.setItemMeta(e); - - - ItemStack empty = new ItemStack(Material.GRAY_STAINED_GLASS_PANE); - ItemMeta s = empty.getItemMeta(); - s.setDisplayName(ChatColor.BLACK + "empty"); - empty.setItemMeta(s); - - - inv.setItem(0, empty); - inv.setItem(1, crafting); - inv.setItem(2, empty); - inv.setItem(3, ender); - inv.setItem(4, empty); - - p.openInventory(inv); - - } else { - sender.sendMessage(plugin.getConfig().getString("Open-Perm")); - } - } else { - sender.sendMessage(plugin.getConfig().getString("player-not-be")); - } - - return false; - } -} - diff --git a/src/main/java/me/indian/enderchest/listener/HandListener.java b/src/main/java/me/indian/enderchest/listener/HandListener.java new file mode 100644 index 0000000..0e3b982 --- /dev/null +++ b/src/main/java/me/indian/enderchest/listener/HandListener.java @@ -0,0 +1,57 @@ +package me.indian.enderchest.listener; + +import me.indian.enderchest.Enderchest; +import org.bukkit.Material; +import org.bukkit.configuration.Configuration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class HandListener implements Listener { + + private final Enderchest plugin; + + public HandListener(Enderchest plugin) { + this.plugin = plugin; + } + + @EventHandler + public void InHandItem(PlayerInteractEvent event) { + final Configuration config = plugin.getConfig(); + final Player player = event.getPlayer(); + final Action action = event.getAction(); + final ItemStack mainHandItem = player.getInventory().getItemInMainHand(); + + if (mainHandItem.getType() == Material.CRAFTING_TABLE || mainHandItem.getType() == Material.ENDER_CHEST) { + if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) { + return; + } + if (mainHandItem.getType() == Material.CRAFTING_TABLE) { + if (player.hasPermission("endacrft.open") || player.hasPermission("endacrft.crafting")) { + if (plugin.getConfig().getBoolean("Crafting-Hand")) { + player.openWorkbench(player.getLocation(), true); + player.sendMessage(config.getString("Crafting-Open-Hand")); + } else { + player.sendMessage(config.getString("off-feature")); + } + } + } + + if (mainHandItem.getType() == Material.ENDER_CHEST) { + if (player.hasPermission("endacrft.open") || player.hasPermission("endacrft.enderchest")) { + if (config.getBoolean("EnderChest-Hand")) { + player.sendMessage(config.getString("EnderChest-Open-Hand")); + Inventory i = player.getEnderChest(); + player.openInventory(i); + } else { + player.sendMessage(config.getString("off-feature")); + } + } + } + } + } +} diff --git a/src/main/java/me/indian/enderchest/listener/InventoryListener.java b/src/main/java/me/indian/enderchest/listener/InventoryListener.java new file mode 100644 index 0000000..e3a0524 --- /dev/null +++ b/src/main/java/me/indian/enderchest/listener/InventoryListener.java @@ -0,0 +1,88 @@ +package me.indian.enderchest.listener; + +import me.indian.enderchest.Enderchest; +import me.indian.enderchest.util.ReopenUtil; +import org.bukkit.ChatColor; +import org.bukkit.configuration.Configuration; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; + +public class InventoryListener implements Listener { + private final Enderchest plugin; + + public InventoryListener(final Enderchest plugin) { + this.plugin = plugin; + } + + @EventHandler + public void onPlayerClickInventory(InventoryClickEvent event) { + final Player player = (Player) event.getWhoClicked(); + final Configuration config = plugin.getConfig(); + final String inventoryName = event.getView().getTitle(); + String itemName = "wrongName"; + if (event.getCurrentItem() != null && event.getCurrentItem().getItemMeta() != null) { + itemName = event.getCurrentItem().getItemMeta().getDisplayName(); + } + + if (inventoryName.equals(plugin.openName)) { + event.setCancelled(true); + + if (itemName.equals(ChatColor.GREEN + "Crafting")) { + if (config.getBoolean("Crafting")) { + player.openWorkbench(player.getLocation(), true); + } else { + player.sendMessage(config.getString("off-feature")); + ReopenUtil.reOpenEnderchestInventory(player); + } + } + + if (itemName.equals(ChatColor.AQUA + "EnderChest")) { + if (config.getBoolean("EnderChest")) { + Inventory i = player.getEnderChest(); + player.openInventory(i); + } else { + player.sendMessage(config.getString("off-feature")); + ReopenUtil.reOpenEnderchestInventory(player); + } + } + } + if (inventoryName.equals("/open options")) { + event.setCancelled(true); + if (itemName.equals(ChatColor.AQUA + "EnderChest")) { + event.setCancelled(true); + if (config.getBoolean("EnderChest")) { + config.set("EnderChest", false); + config.set("EnderInfo", config.getString("message-off")); + plugin.saveConfig(); + player.sendMessage("EnderChest " + config.getString("successfully-set") + " " + "false"); + ReopenUtil.reOpenSettingsInventory(player); + } else { + config.set("EnderChest", true); + config.set("EnderInfo", config.getString("message-on")); + plugin.saveConfig(); + player.sendMessage("EnderChest " + config.getString("successfully-set") + " " + "true"); + ReopenUtil.reOpenSettingsInventory(player); + } + } + + if (itemName.equals(ChatColor.GREEN + "Crafting")) { + if (config.getBoolean("Crafting")) { + config.set("Crafting", false); + config.set("CraftInfo", config.getString("message-off")); + plugin.saveConfig(); + player.sendMessage("Crafting " + config.getString("successfully-set") + "false"); + ReopenUtil.reOpenSettingsInventory(player); + } else { + config.set("Crafting", true); + config.set("CraftInfo", config.getString("message-on")); + plugin.saveConfig(); + player.sendMessage("Crafting " + config.getString("successfully-set") + "true"); + ReopenUtil.reOpenSettingsInventory(player); + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/me/indian/enderchest/listeners/CrRcHandListener.java b/src/main/java/me/indian/enderchest/listeners/CrRcHandListener.java deleted file mode 100644 index 2886494..0000000 --- a/src/main/java/me/indian/enderchest/listeners/CrRcHandListener.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.indian.enderchest.listeners; - -import me.indian.enderchest.main.Enderchest; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.Inventory; - -public class CrRcHandListener implements Listener { - - private final Enderchest plugin; - - public CrRcHandListener(Enderchest plugin) { - this.plugin = plugin; - } - - @EventHandler - public void InHandItem(PlayerInteractEvent e) { - Player p = (Player) e.getPlayer(); - Action a = e.getAction(); - - if (p.getInventory().getItemInMainHand().getType() == Material.CRAFTING_TABLE || p.getInventory().getItemInMainHand().getType() == Material.ENDER_CHEST) { - if (p.hasPermission("endacrft.open")) { - if (a == Action.RIGHT_CLICK_AIR || a == Action.RIGHT_CLICK_BLOCK) { - return; - } - } - if (p.getInventory().getItemInMainHand().getType() == Material.CRAFTING_TABLE) { - if (plugin.getConfig().getBoolean("Crafting-Hand")) { - p.openWorkbench(p.getLocation(), true); - p.sendMessage(plugin.getConfig().getString("Crafting-Open-Hand")); - } else { - p.sendMessage(plugin.getConfig().getString("off-feature")); - } - } - - - if (p.getInventory().getItemInMainHand().getType() == Material.ENDER_CHEST) { - if (plugin.getConfig().getBoolean("EnderChest-Hand")) { - p.sendMessage(plugin.getConfig().getString("EnderChest-Open-Hand")); - Inventory i = p.getEnderChest(); - p.openInventory(i); - - - } else { - p.sendMessage(plugin.getConfig().getString("off-feature")); - } - } - } - } -} diff --git a/src/main/java/me/indian/enderchest/listeners/InventoryListener.java b/src/main/java/me/indian/enderchest/listeners/InventoryListener.java deleted file mode 100644 index 5f0187b..0000000 --- a/src/main/java/me/indian/enderchest/listeners/InventoryListener.java +++ /dev/null @@ -1,52 +0,0 @@ -package me.indian.enderchest.listeners; - -import me.indian.enderchest.main.Enderchest; -import org.bukkit.event.inventory.*; -import org.bukkit.entity.*; -import org.bukkit.*; -import org.bukkit.inventory.*; -import org.bukkit.event.*; - -public class InventoryListener implements Listener { - private final Enderchest plugin; - - public InventoryListener(final Enderchest plugin) { - this.plugin = plugin; - } - - @EventHandler - public void onPlayerClickInventory(InventoryClickEvent e) { - Player p = (Player) e.getWhoClicked(); - - if (e.getView().getTitle().equals(plugin.openName)) { - e.setCancelled(true); - if (e.getCurrentItem().getItemMeta().getDisplayName().equals(ChatColor.GREEN + "Crafting")) { - if (plugin.getConfig().getBoolean("Crafting")) { -// Player p = (Player) e.getWhoClicked(); - p.openWorkbench(p.getLocation(), true); - - - } else { - p.sendMessage(plugin.getConfig().getString("off-feature")); - Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 5); - } - } - } - - if (e.getView().getTitle().equals(plugin.openName)) { - e.setCancelled(true); - if (e.getCurrentItem().getItemMeta().getDisplayName().equals(ChatColor.AQUA + "EnderChest")) { - if (plugin.getConfig().getBoolean("EnderChest")) { -// Player p = (Player) e.getWhoClicked(); - Inventory i = p.getEnderChest(); - p.openInventory(i); - - - } else { - p.sendMessage(plugin.getConfig().getString("off-feature")); - Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 5); - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/me/indian/enderchest/listeners/SetListener.java b/src/main/java/me/indian/enderchest/listeners/SetListener.java deleted file mode 100644 index 2b78224..0000000 --- a/src/main/java/me/indian/enderchest/listeners/SetListener.java +++ /dev/null @@ -1,70 +0,0 @@ -package me.indian.enderchest.listeners; - -import me.indian.enderchest.main.Enderchest; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; - -public class SetListener implements Listener { - - private final Enderchest plugin; - - public SetListener(Enderchest plugin) { - this.plugin = plugin; - } - - - @EventHandler - public void InventoryClickEvent(InventoryClickEvent e) { - Player p = (Player) e.getWhoClicked(); - - if (e.getView().getTitle().equals("/open options")) { - if (e.getCurrentItem().getItemMeta().getDisplayName().equals(ChatColor.AQUA + "EnderChest")) { - e.setCancelled(true); - if (plugin.getConfig().getBoolean("EnderChest") == true) { - plugin.getConfig().set("EnderChest", false); - plugin.getConfig().set("EnderInfo", plugin.getConfig().getString("message-off")); - plugin.saveConfig(); - p.sendMessage("EnderChest " + this.plugin.getConfig().getString("successfully-set") + " " + "false"); - Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 5); - } else { - plugin.getConfig().set("EnderChest", true); - plugin.getConfig().set("EnderInfo", plugin.getConfig().getString("message-on")); - plugin.saveConfig(); - p.sendMessage("EnderChest " + this.plugin.getConfig().getString("successfully-set") + " " + " true"); - Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 5); - } - } - } - if (e.getView().getTitle().equals("/open options")) { - if (e.getCurrentItem().getItemMeta().getDisplayName().equals(ChatColor.GREEN + "Crafting")) { - e.setCancelled(true); - - if (plugin.getConfig().getBoolean("Crafting") == true) { - plugin.getConfig().set("Crafting", false); - plugin.getConfig().set("CraftInfo", plugin.getConfig().getString("message-off")); - plugin.saveConfig(); - p.sendMessage("Crafting " + this.plugin.getConfig().getString("successfully-set") + "false"); - Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 5); - } else { - plugin.getConfig().set("Crafting", true); - plugin.getConfig().set("CraftInfo", plugin.getConfig().getString("message-on")); - plugin.saveConfig(); - p.sendMessage("Crafting " + this.plugin.getConfig().getString("successfully-set") + "true"); - Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 5); - } - - } - } - if (e.getView().getTitle().equals("/open options")) { - if (e.getCurrentItem().getItemMeta().getDisplayName().equals(ChatColor.BLACK + "pustka")) { - e.setCancelled(true); - } - } - } - - -} diff --git a/src/main/java/me/indian/enderchest/main/Enderchest.java b/src/main/java/me/indian/enderchest/main/Enderchest.java deleted file mode 100644 index 21b916b..0000000 --- a/src/main/java/me/indian/enderchest/main/Enderchest.java +++ /dev/null @@ -1,116 +0,0 @@ -package me.indian.enderchest.main; - - -import me.indian.enderchest.Test; -import me.indian.enderchest.EnderChestApi; -import me.indian.enderchest.Utils.MessageApi; -import me.indian.enderchest.commands.Reload; -import me.indian.enderchest.commands.Set; -import me.indian.enderchest.commands.open; -import me.indian.enderchest.listeners.CrRcHandListener; -import me.indian.enderchest.listeners.InventoryListener; -import me.indian.enderchest.listeners.SetListener; -import me.indian.enderchest.others.EnderchestPlaceholders; -import me.indian.enderchest.others.Metrics; -import me.indian.enderchest.others.UpdateChecker; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.plugin.java.JavaPlugin; - -public final class Enderchest extends JavaPlugin implements Listener { - - public EnderChestApi enderChestApi; - - String prefix = getConfig().getString("prefix"); - public String openName = getConfig().getString("InvName"); - String version = getDescription().getVersion(); - - - @Override - public void onEnable() { - - - if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { - - new EnderchestPlaceholders(this).register(); - Bukkit.getConsoleSender().sendMessage("You using PlaceholderAPI "); - } else { - Bukkit.getConsoleSender().sendMessage("You not using PlaceholderAPI, not required :^ "); - - } - - - Bukkit.getConsoleSender().sendMessage("------------------------------"); - Bukkit.getConsoleSender().sendMessage("\t " + prefix + " " + version); - Bukkit.getConsoleSender().sendMessage("------------------------------"); - - - new UpdateChecker(this, 99276).getVersion(version -> { - if (this.getDescription().getVersion().equals(version)) { - getLogger().info(prefix + "There is not a new update available."); - - } else { - getLogger().info(prefix + " There is a new update available."); - getLogger().info(prefix + " Your version " + this.getDescription().getVersion() + " new version " + version); - - } - }); - - - Metrics metrics = new Metrics(this, 13974); - - metrics.addCustomChart(new Metrics.SimplePie("chart_id", () -> "My value")); - - - saveDefaultConfig(); - - new EnderChestApi(); - - getCommand("open").setExecutor(new open(this)); - getCommand("endacrftr").setExecutor(new Reload(this)); - getCommand("set").setExecutor(new Set(this)); - getCommand("entest").setExecutor(new Test(this)); - - getServer().getPluginManager().registerEvents(new InventoryListener(this), this); - getServer().getPluginManager().registerEvents(new SetListener(this), this); - getServer().getPluginManager().registerEvents(this, this); - getServer().getPluginManager().registerEvents(new CrRcHandListener(this), this); - - - } - - public void onDisable() { - Bukkit.getConsoleSender().sendMessage(prefix + " disabling"); - Bukkit.getConsoleSender().sendMessage(prefix + " Version" + version); - } - - - @EventHandler - public void OpJoin(PlayerJoinEvent e) { - Player p = (Player) e.getPlayer(); - - - if (p.isOp()) { - new UpdateChecker(this, 99276).getVersion(version -> { - if (!(this.getDescription().getVersion().equals(version))) { - MessageApi.Chat(p, prefix + "§bThere is a new update available."); - MessageApi.HoverMessageCopy(p, - prefix + "§bYour version " + this.getDescription().getVersion() + " new version " + version, - "https://www.spigotmc.org/resources/enderchest-and-crafting.99276/", - "Copy download link"); - -// p.sendMessage( prefix + "§bYour version " + this.getDescription().getVersion() + " new version " + version); - } - }); - } - } - - -} - - - - diff --git a/src/main/java/me/indian/enderchest/others/EnderchestPlaceholders.java b/src/main/java/me/indian/enderchest/other/EnderchestPlaceholders.java similarity index 68% rename from src/main/java/me/indian/enderchest/others/EnderchestPlaceholders.java rename to src/main/java/me/indian/enderchest/other/EnderchestPlaceholders.java index 368b417..21cc10f 100644 --- a/src/main/java/me/indian/enderchest/others/EnderchestPlaceholders.java +++ b/src/main/java/me/indian/enderchest/other/EnderchestPlaceholders.java @@ -1,76 +1,67 @@ -package me.indian.enderchest.others; - -import me.clip.placeholderapi.expansion.PlaceholderExpansion; -import me.indian.enderchest.main.Enderchest; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -public class EnderchestPlaceholders extends PlaceholderExpansion { - - private final Enderchest plugin; - - public EnderchestPlaceholders(Enderchest plugin) { - this.plugin = plugin; - } - - @Override - public String getIdentifier() { - return "EnderchestAndCrafting"; - } - - @Override - public String getAuthor() { - return "IndianPL"; - } - - @Override - public String getVersion() { - return "1.0"; - } - - @Override - public boolean persist() { - return true; - } - - @Override - public String onPlaceholderRequest(Player p, String identifier) { - if (identifier.equals("version")) { - return plugin.getDescription().getVersion(); - } - if (identifier.equals("expansion_version")) { - return this.getVersion(); - } - - if (identifier.equals("crafting_status")) { - String crinfo = plugin.getConfig().getString("CraftInfo"); - return crinfo; - } - if (identifier.equals("enderchest_status")) { - String eninfo = plugin.getConfig().getString("EnderInfo"); - return eninfo; - } - if (identifier.equals("enderchest_hand_status")) { - String status = ""; - if (plugin.getConfig().getBoolean("EnderChest-Hand")) { - status = plugin.getConfig().getString("message-on"); - } else { - status = plugin.getConfig().getString("message-off"); - } - return status; - } - - if (identifier.equals("crafting_hand_status")) { - String status = ""; - if (plugin.getConfig().getBoolean("Crafting-Hand")) { - status = plugin.getConfig().getString("message-on"); - } else { - status = plugin.getConfig().getString("message-off"); - } - return status; - } - return null; - } - -} +package me.indian.enderchest.other; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import me.indian.enderchest.Enderchest; +import org.bukkit.entity.Player; + +public class EnderchestPlaceholders extends PlaceholderExpansion { + + private final Enderchest plugin; + + public EnderchestPlaceholders(Enderchest plugin) { + this.plugin = plugin; + } + + @Override + public String getIdentifier() { + return "EnderchestAndCrafting"; + } + + @Override + public String getAuthor() { + return String.valueOf(plugin.getDescription().getAuthors()).replace("[", "").replace("]", ""); + } + + @Override + public String getVersion() { + return "1.0"; + } + + @Override + public boolean persist() { + return true; + } + + @Override + public String onPlaceholderRequest(Player p, String identifier) { + if (identifier.equals("version")) { + return plugin.getDescription().getVersion(); + } + if (identifier.equals("expansion_version")) { + return this.getVersion(); + } + + if (identifier.equals("crafting_status")) { + return plugin.getConfig().getString("CraftInfo"); + } + if (identifier.equals("enderchest_status")) { + return plugin.getConfig().getString("EnderInfo"); + } + if (identifier.equals("enderchest_hand_status")) { + String status = plugin.getConfig().getString("message-off"); + if (plugin.getConfig().getBoolean("EnderChest-Hand")) { + status = plugin.getConfig().getString("message-on"); + } + return status; + } + + if (identifier.equals("crafting_hand_status")) { + String status = plugin.getConfig().getString("message-off"); + if (plugin.getConfig().getBoolean("Crafting-Hand")) { + status = plugin.getConfig().getString("message-on"); + } + return status; + } + return null; + } +} \ No newline at end of file diff --git a/src/main/java/me/indian/enderchest/others/Metrics.java b/src/main/java/me/indian/enderchest/other/Metrics.java similarity index 97% rename from src/main/java/me/indian/enderchest/others/Metrics.java rename to src/main/java/me/indian/enderchest/other/Metrics.java index 4def1c8..d6b9755 100644 --- a/src/main/java/me/indian/enderchest/others/Metrics.java +++ b/src/main/java/me/indian/enderchest/other/Metrics.java @@ -1,853 +1,852 @@ -package me.indian.enderchest.others; - -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.Method; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; -import java.util.logging.Level; -import java.util.stream.Collectors; -import java.util.zip.GZIPOutputStream; -import javax.net.ssl.HttpsURLConnection; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; - -public class Metrics { - - private final Plugin plugin; - - private final MetricsBase metricsBase; - - /** - * Creates a new Metrics instance. - * - * @param plugin Your plugin instance. - * @param serviceId The id of the service. It can be found at What is my plugin id? - */ - public Metrics(JavaPlugin plugin, int serviceId) { - this.plugin = plugin; - // Get the config file - File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); - File configFile = new File(bStatsFolder, "config.yml"); - YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); - if (!config.isSet("serverUuid")) { - config.addDefault("enabled", true); - config.addDefault("serverUuid", UUID.randomUUID().toString()); - config.addDefault("logFailedRequests", false); - config.addDefault("logSentData", false); - config.addDefault("logResponseStatusText", false); - // Inform the server owners about bStats - config - .options() - .header( - "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" - + "many people use their plugin and their total player count. It's recommended to keep bStats\n" - + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" - + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" - + "anonymous.") - .copyDefaults(true); - try { - config.save(configFile); - } catch (IOException ignored) { - } - } - // Load the data - boolean enabled = config.getBoolean("enabled", true); - String serverUUID = config.getString("serverUuid"); - boolean logErrors = config.getBoolean("logFailedRequests", false); - boolean logSentData = config.getBoolean("logSentData", false); - boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); - metricsBase = - new MetricsBase( - "bukkit", - serverUUID, - serviceId, - enabled, - this::appendPlatformData, - this::appendServiceData, - submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask), - plugin::isEnabled, - (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error), - (message) -> this.plugin.getLogger().log(Level.INFO, message), - logErrors, - logSentData, - logResponseStatusText); - } - - /** - * Adds a custom chart. - * - * @param chart The chart to add. - */ - public void addCustomChart(CustomChart chart) { - metricsBase.addCustomChart(chart); - } - - private void appendPlatformData(JsonObjectBuilder builder) { - builder.appendField("playerAmount", getPlayerAmount()); - builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0); - builder.appendField("bukkitVersion", Bukkit.getVersion()); - builder.appendField("bukkitName", Bukkit.getName()); - builder.appendField("javaVersion", System.getProperty("java.version")); - builder.appendField("osName", System.getProperty("os.name")); - builder.appendField("osArch", System.getProperty("os.arch")); - builder.appendField("osVersion", System.getProperty("os.version")); - builder.appendField("coreCount", Runtime.getRuntime().availableProcessors()); - } - - private void appendServiceData(JsonObjectBuilder builder) { - builder.appendField("pluginVersion", plugin.getDescription().getVersion()); - } - - private int getPlayerAmount() { - try { - // Around MC 1.8 the return type was changed from an array to a collection, - // This fixes java.lang.NoSuchMethodError: - // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; - Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); - return onlinePlayersMethod.getReturnType().equals(Collection.class) - ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() - : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; - } catch (Exception e) { - // Just use the new method if the reflection failed - return Bukkit.getOnlinePlayers().size(); - } - } - - public static class MetricsBase { - - /** - * The version of the Metrics class. - */ - public static final String METRICS_VERSION = "2.2.1"; - - private static final ScheduledExecutorService scheduler = - Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics")); - - private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s"; - - private final String platform; - - private final String serverUuid; - - private final int serviceId; - - private final Consumer appendPlatformDataConsumer; - - private final Consumer appendServiceDataConsumer; - - private final Consumer submitTaskConsumer; - - private final Supplier checkServiceEnabledSupplier; - - private final BiConsumer errorLogger; - - private final Consumer infoLogger; - - private final boolean logErrors; - - private final boolean logSentData; - - private final boolean logResponseStatusText; - - private final Set customCharts = new HashSet<>(); - - private final boolean enabled; - - /** - * Creates a new MetricsBase class instance. - * - * @param platform The platform of the service. - * @param serviceId The id of the service. - * @param serverUuid The server uuid. - * @param enabled Whether or not data sending is enabled. - * @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and - * appends all platform-specific data. - * @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and - * appends all service-specific data. - * @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be - * used to delegate the data collection to a another thread to prevent errors caused by - * concurrency. Can be {@code null}. - * @param checkServiceEnabledSupplier A supplier to check if the service is still enabled. - * @param errorLogger A consumer that accepts log message and an error. - * @param infoLogger A consumer that accepts info log messages. - * @param logErrors Whether or not errors should be logged. - * @param logSentData Whether or not the sent data should be logged. - * @param logResponseStatusText Whether or not the response status text should be logged. - */ - public MetricsBase( - String platform, - String serverUuid, - int serviceId, - boolean enabled, - Consumer appendPlatformDataConsumer, - Consumer appendServiceDataConsumer, - Consumer submitTaskConsumer, - Supplier checkServiceEnabledSupplier, - BiConsumer errorLogger, - Consumer infoLogger, - boolean logErrors, - boolean logSentData, - boolean logResponseStatusText) { - this.platform = platform; - this.serverUuid = serverUuid; - this.serviceId = serviceId; - this.enabled = enabled; - this.appendPlatformDataConsumer = appendPlatformDataConsumer; - this.appendServiceDataConsumer = appendServiceDataConsumer; - this.submitTaskConsumer = submitTaskConsumer; - this.checkServiceEnabledSupplier = checkServiceEnabledSupplier; - this.errorLogger = errorLogger; - this.infoLogger = infoLogger; - this.logErrors = logErrors; - this.logSentData = logSentData; - this.logResponseStatusText = logResponseStatusText; - checkRelocation(); - if (enabled) { - startSubmitting(); - } - } - - public void addCustomChart(CustomChart chart) { - this.customCharts.add(chart); - } - - private void startSubmitting() { - final Runnable submitTask = - () -> { - if (!enabled || !checkServiceEnabledSupplier.get()) { - // Submitting data or service is disabled - scheduler.shutdown(); - return; - } - if (submitTaskConsumer != null) { - submitTaskConsumer.accept(this::submitData); - } else { - this.submitData(); - } - }; - // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution - // of requests on the - // bStats backend. To circumvent this problem, we introduce some randomness into the initial - // and second delay. - // WARNING: You must not modify and part of this Metrics class, including the submit delay or - // frequency! - // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! - long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); - long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); - scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); - scheduler.scheduleAtFixedRate( - submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); - } - - private void submitData() { - final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder(); - appendPlatformDataConsumer.accept(baseJsonBuilder); - final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder(); - appendServiceDataConsumer.accept(serviceJsonBuilder); - JsonObjectBuilder.JsonObject[] chartData = - customCharts.stream() - .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors)) - .filter(Objects::nonNull) - .toArray(JsonObjectBuilder.JsonObject[]::new); - serviceJsonBuilder.appendField("id", serviceId); - serviceJsonBuilder.appendField("customCharts", chartData); - baseJsonBuilder.appendField("service", serviceJsonBuilder.build()); - baseJsonBuilder.appendField("serverUUID", serverUuid); - baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION); - JsonObjectBuilder.JsonObject data = baseJsonBuilder.build(); - scheduler.execute( - () -> { - try { - // Send the data - sendData(data); - } catch (Exception e) { - // Something went wrong! :( - if (logErrors) { - errorLogger.accept("Could not submit bStats metrics data", e); - } - } - }); - } - - private void sendData(JsonObjectBuilder.JsonObject data) throws Exception { - if (logSentData) { - infoLogger.accept("Sent bStats metrics data: " + data.toString()); - } - String url = String.format(REPORT_URL, platform); - HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); - // Compress the data to save bandwidth - byte[] compressedData = compress(data.toString()); - connection.setRequestMethod("POST"); - connection.addRequestProperty("Accept", "application/json"); - connection.addRequestProperty("Connection", "close"); - connection.addRequestProperty("Content-Encoding", "gzip"); - connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setRequestProperty("User-Agent", "Metrics-Service/1"); - connection.setDoOutput(true); - try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { - outputStream.write(compressedData); - } - StringBuilder builder = new StringBuilder(); - try (BufferedReader bufferedReader = - new BufferedReader(new InputStreamReader(connection.getInputStream()))) { - String line; - while ((line = bufferedReader.readLine()) != null) { - builder.append(line); - } - } - if (logResponseStatusText) { - infoLogger.accept("Sent data to bStats and received response: " + builder); - } - } - - /** - * Checks that the class was properly relocated. - */ - private void checkRelocation() { - // You can use the property to disable the check in your test environment - if (System.getProperty("bstats.relocatecheck") == null - || !System.getProperty("bstats.relocatecheck").equals("false")) { - // Maven's Relocate is clever and changes strings, too. So we have to use this little - // "trick" ... :D - final String defaultPackage = - new String(new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'}); - final String examplePackage = - new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); - // We want to make sure no one just copy & pastes the example and uses the wrong package - // names - if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage) - || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) { - throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); - } - } - } - - /** - * Gzips the given string. - * - * @param str The string to gzip. - * @return The gzipped string. - */ - private static byte[] compress(final String str) throws IOException { - if (str == null) { - return null; - } - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) { - gzip.write(str.getBytes(StandardCharsets.UTF_8)); - } - return outputStream.toByteArray(); - } - } - - public static class AdvancedBarChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public AdvancedBarChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue().length == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class SimpleBarChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SimpleBarChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - for (Map.Entry entry : map.entrySet()) { - valuesBuilder.appendField(entry.getKey(), new int[]{entry.getValue()}); - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class MultiLineChart extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public MultiLineChart(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public static class AdvancedPie extends CustomChart { - - private final Callable> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public AdvancedPie(String chartId, Callable> callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean allSkipped = true; - for (Map.Entry entry : map.entrySet()) { - if (entry.getValue() == 0) { - // Skip this invalid - continue; - } - allSkipped = false; - valuesBuilder.appendField(entry.getKey(), entry.getValue()); - } - if (allSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - public abstract static class CustomChart { - - private final String chartId; - - protected CustomChart(String chartId) { - if (chartId == null) { - throw new IllegalArgumentException("chartId must not be null"); - } - this.chartId = chartId; - } - - public JsonObjectBuilder.JsonObject getRequestJsonObject( - BiConsumer errorLogger, boolean logErrors) { - JsonObjectBuilder builder = new JsonObjectBuilder(); - builder.appendField("chartId", chartId); - try { - JsonObjectBuilder.JsonObject data = getChartData(); - if (data == null) { - // If the data is null we don't send the chart. - return null; - } - builder.appendField("data", data); - } catch (Throwable t) { - if (logErrors) { - errorLogger.accept("Failed to get data for custom chart with id " + chartId, t); - } - return null; - } - return builder.build(); - } - - protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception; - } - - public static class SingleLineChart extends CustomChart { - - private final Callable callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SingleLineChart(String chartId, Callable callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - int value = callable.call(); - if (value == 0) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("value", value).build(); - } - } - - public static class SimplePie extends CustomChart { - - private final Callable callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public SimplePie(String chartId, Callable callable) { - super(chartId); - this.callable = callable; - } - - @Override - protected JsonObjectBuilder.JsonObject getChartData() throws Exception { - String value = callable.call(); - if (value == null || value.isEmpty()) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("value", value).build(); - } - } - - public static class DrilldownPie extends CustomChart { - - private final Callable>> callable; - - /** - * Class constructor. - * - * @param chartId The id of the chart. - * @param callable The callable which is used to request the chart data. - */ - public DrilldownPie(String chartId, Callable>> callable) { - super(chartId); - this.callable = callable; - } - - @Override - public JsonObjectBuilder.JsonObject getChartData() throws Exception { - JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); - Map> map = callable.call(); - if (map == null || map.isEmpty()) { - // Null = skip the chart - return null; - } - boolean reallyAllSkipped = true; - for (Map.Entry> entryValues : map.entrySet()) { - JsonObjectBuilder valueBuilder = new JsonObjectBuilder(); - boolean allSkipped = true; - for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { - valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue()); - allSkipped = false; - } - if (!allSkipped) { - reallyAllSkipped = false; - valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build()); - } - } - if (reallyAllSkipped) { - // Null = skip the chart - return null; - } - return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); - } - } - - /** - * An extremely simple JSON builder. - * - *

While this class is neither feature-rich nor the most performant one, it's sufficient enough - * for its use-case. - */ - public static class JsonObjectBuilder { - - private StringBuilder builder = new StringBuilder(); - - private boolean hasAtLeastOneField = false; - - public JsonObjectBuilder() { - builder.append("{"); - } - - /** - * Appends a null field to the JSON. - * - * @param key The key of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendNull(String key) { - appendFieldUnescaped(key, "null"); - return this; - } - - /** - * Appends a string field to the JSON. - * - * @param key The key of the field. - * @param value The value of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, String value) { - if (value == null) { - throw new IllegalArgumentException("JSON value must not be null"); - } - appendFieldUnescaped(key, "\"" + escape(value) + "\""); - return this; - } - - /** - * Appends an integer field to the JSON. - * - * @param key The key of the field. - * @param value The value of the field. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, int value) { - appendFieldUnescaped(key, String.valueOf(value)); - return this; - } - - /** - * Appends an object to the JSON. - * - * @param key The key of the field. - * @param object The object. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, JsonObject object) { - if (object == null) { - throw new IllegalArgumentException("JSON object must not be null"); - } - appendFieldUnescaped(key, object.toString()); - return this; - } - - /** - * Appends a string array to the JSON. - * - * @param key The key of the field. - * @param values The string array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, String[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values) - .map(value -> "\"" + escape(value) + "\"") - .collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends an integer array to the JSON. - * - * @param key The key of the field. - * @param values The integer array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, int[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends an object array to the JSON. - * - * @param key The key of the field. - * @param values The integer array. - * @return A reference to this object. - */ - public JsonObjectBuilder appendField(String key, JsonObject[] values) { - if (values == null) { - throw new IllegalArgumentException("JSON values must not be null"); - } - String escapedValues = - Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(",")); - appendFieldUnescaped(key, "[" + escapedValues + "]"); - return this; - } - - /** - * Appends a field to the object. - * - * @param key The key of the field. - * @param escapedValue The escaped value of the field. - */ - private void appendFieldUnescaped(String key, String escapedValue) { - if (builder == null) { - throw new IllegalStateException("JSON has already been built"); - } - if (key == null) { - throw new IllegalArgumentException("JSON key must not be null"); - } - if (hasAtLeastOneField) { - builder.append(","); - } - builder.append("\"").append(escape(key)).append("\":").append(escapedValue); - hasAtLeastOneField = true; - } - - /** - * Builds the JSON string and invalidates this builder. - * - * @return The built JSON string. - */ - public JsonObject build() { - if (builder == null) { - throw new IllegalStateException("JSON has already been built"); - } - JsonObject object = new JsonObject(builder.append("}").toString()); - builder = null; - return object; - } - - /** - * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt. - * - *

This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'. - * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n"). - * - * @param value The value to escape. - * @return The escaped value. - */ - private static String escape(String value) { - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < value.length(); i++) { - char c = value.charAt(i); - if (c == '"') { - builder.append("\\\""); - } else if (c == '\\') { - builder.append("\\\\"); - } else if (c <= '\u000F') { - builder.append("\\u000").append(Integer.toHexString(c)); - } else if (c <= '\u001F') { - builder.append("\\u00").append(Integer.toHexString(c)); - } else { - builder.append(c); - } - } - return builder.toString(); - } - - /** - * A super simple representation of a JSON object. - * - *

This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not - * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String, - * JsonObject)}. - */ - public static class JsonObject { - - private final String value; - - private JsonObject(String value) { - this.value = value; - } - - @Override - public String toString() { - return value; - } - } - } -} +package me.indian.enderchest.other; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.zip.GZIPOutputStream; +import javax.net.ssl.HttpsURLConnection; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +public class Metrics { + + private final Plugin plugin; + + private final MetricsBase metricsBase; + + /** + * Creates a new Metrics instance. + * + * @param plugin Your plugin instance. + * @param serviceId The id of the service. It can be found at What is my plugin id? + */ + public Metrics(JavaPlugin plugin, int serviceId) { + this.plugin = plugin; + // Get the config file + File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); + File configFile = new File(bStatsFolder, "config.yml"); + YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); + if (!config.isSet("serverUuid")) { + config.addDefault("enabled", true); + config.addDefault("serverUuid", UUID.randomUUID().toString()); + config.addDefault("logFailedRequests", false); + config.addDefault("logSentData", false); + config.addDefault("logResponseStatusText", false); + // Inform the server owners about bStats + config + .options() + .header( + "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" + + "many people use their plugin and their total player count. It's recommended to keep bStats\n" + + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" + + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" + + "anonymous.") + .copyDefaults(true); + try { + config.save(configFile); + } catch (IOException ignored) { + } + } + // Load the data + boolean enabled = config.getBoolean("enabled", true); + String serverUUID = config.getString("serverUuid"); + boolean logErrors = config.getBoolean("logFailedRequests", false); + boolean logSentData = config.getBoolean("logSentData", false); + boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); + metricsBase = + new MetricsBase( + "bukkit", + serverUUID, + serviceId, + enabled, + this::appendPlatformData, + this::appendServiceData, + submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask), + plugin::isEnabled, + (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error), + (message) -> this.plugin.getLogger().log(Level.INFO, message), + logErrors, + logSentData, + logResponseStatusText); + } + + /** + * Adds a custom chart. + * + * @param chart The chart to add. + */ + public void addCustomChart(CustomChart chart) { + metricsBase.addCustomChart(chart); + } + + private void appendPlatformData(JsonObjectBuilder builder) { + builder.appendField("playerAmount", getPlayerAmount()); + builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0); + builder.appendField("bukkitVersion", Bukkit.getVersion()); + builder.appendField("bukkitName", Bukkit.getName()); + builder.appendField("javaVersion", System.getProperty("java.version")); + builder.appendField("osName", System.getProperty("os.name")); + builder.appendField("osArch", System.getProperty("os.arch")); + builder.appendField("osVersion", System.getProperty("os.version")); + builder.appendField("coreCount", Runtime.getRuntime().availableProcessors()); + } + + private void appendServiceData(JsonObjectBuilder builder) { + builder.appendField("pluginVersion", plugin.getDescription().getVersion()); + } + + private int getPlayerAmount() { + try { + // Around MC 1.8 the return type was changed from an array to a collection, + // This fixes java.lang.NoSuchMethodError: + // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; + Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); + return onlinePlayersMethod.getReturnType().equals(Collection.class) + ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() + : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; + } catch (Exception e) { + // Just use the new method if the reflection failed + return Bukkit.getOnlinePlayers().size(); + } + } + + public static class MetricsBase { + + /** + * The version of the Metrics class. + */ + public static final String METRICS_VERSION = "2.2.1"; + + private static final ScheduledExecutorService scheduler = + Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics")); + + private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s"; + + private final String platform; + + private final String serverUuid; + + private final int serviceId; + + private final Consumer appendPlatformDataConsumer; + + private final Consumer appendServiceDataConsumer; + + private final Consumer submitTaskConsumer; + + private final Supplier checkServiceEnabledSupplier; + + private final BiConsumer errorLogger; + + private final Consumer infoLogger; + + private final boolean logErrors; + + private final boolean logSentData; + + private final boolean logResponseStatusText; + + private final Set customCharts = new HashSet<>(); + + private final boolean enabled; + + /** + * Creates a new MetricsBase class instance. + * + * @param platform The platform of the service. + * @param serviceId The id of the service. + * @param serverUuid The server uuid. + * @param enabled Whether or not data sending is enabled. + * @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and + * appends all platform-specific data. + * @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and + * appends all service-specific data. + * @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be + * used to delegate the data collection to a another thread to prevent errors caused by + * concurrency. Can be {@code null}. + * @param checkServiceEnabledSupplier A supplier to check if the service is still enabled. + * @param errorLogger A consumer that accepts log message and an error. + * @param infoLogger A consumer that accepts info log messages. + * @param logErrors Whether or not errors should be logged. + * @param logSentData Whether or not the sent data should be logged. + * @param logResponseStatusText Whether or not the response status text should be logged. + */ + public MetricsBase( + String platform, + String serverUuid, + int serviceId, + boolean enabled, + Consumer appendPlatformDataConsumer, + Consumer appendServiceDataConsumer, + Consumer submitTaskConsumer, + Supplier checkServiceEnabledSupplier, + BiConsumer errorLogger, + Consumer infoLogger, + boolean logErrors, + boolean logSentData, + boolean logResponseStatusText) { + this.platform = platform; + this.serverUuid = serverUuid; + this.serviceId = serviceId; + this.enabled = enabled; + this.appendPlatformDataConsumer = appendPlatformDataConsumer; + this.appendServiceDataConsumer = appendServiceDataConsumer; + this.submitTaskConsumer = submitTaskConsumer; + this.checkServiceEnabledSupplier = checkServiceEnabledSupplier; + this.errorLogger = errorLogger; + this.infoLogger = infoLogger; + this.logErrors = logErrors; + this.logSentData = logSentData; + this.logResponseStatusText = logResponseStatusText; + checkRelocation(); + if (enabled) { + startSubmitting(); + } + } + + /** + * Gzips the given string. + * + * @param str The string to gzip. + * @return The gzipped string. + */ + private static byte[] compress(final String str) throws IOException { + if (str == null) { + return null; + } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) { + gzip.write(str.getBytes(StandardCharsets.UTF_8)); + } + return outputStream.toByteArray(); + } + + public void addCustomChart(CustomChart chart) { + this.customCharts.add(chart); + } + + private void startSubmitting() { + final Runnable submitTask = + () -> { + if (!enabled || !checkServiceEnabledSupplier.get()) { + // Submitting data or service is disabled + scheduler.shutdown(); + return; + } + if (submitTaskConsumer != null) { + submitTaskConsumer.accept(this::submitData); + } else { + this.submitData(); + } + }; + // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution + // of requests on the + // bStats backend. To circumvent this problem, we introduce some randomness into the initial + // and second delay. + // WARNING: You must not modify and part of this Metrics class, including the submit delay or + // frequency! + // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! + long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); + long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); + scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); + scheduler.scheduleAtFixedRate( + submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); + } + + private void submitData() { + final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder(); + appendPlatformDataConsumer.accept(baseJsonBuilder); + final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder(); + appendServiceDataConsumer.accept(serviceJsonBuilder); + JsonObjectBuilder.JsonObject[] chartData = + customCharts.stream() + .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors)) + .filter(Objects::nonNull) + .toArray(JsonObjectBuilder.JsonObject[]::new); + serviceJsonBuilder.appendField("id", serviceId); + serviceJsonBuilder.appendField("customCharts", chartData); + baseJsonBuilder.appendField("service", serviceJsonBuilder.build()); + baseJsonBuilder.appendField("serverUUID", serverUuid); + baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION); + JsonObjectBuilder.JsonObject data = baseJsonBuilder.build(); + scheduler.execute( + () -> { + try { + // Send the data + sendData(data); + } catch (Exception e) { + // Something went wrong! :( + if (logErrors) { + errorLogger.accept("Could not submit bStats metrics data", e); + } + } + }); + } + + private void sendData(JsonObjectBuilder.JsonObject data) throws Exception { + if (logSentData) { + infoLogger.accept("Sent bStats metrics data: " + data.toString()); + } + String url = String.format(REPORT_URL, platform); + HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); + // Compress the data to save bandwidth + byte[] compressedData = compress(data.toString()); + connection.setRequestMethod("POST"); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.addRequestProperty("Content-Encoding", "gzip"); + connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("User-Agent", "Metrics-Service/1"); + connection.setDoOutput(true); + try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { + outputStream.write(compressedData); + } + StringBuilder builder = new StringBuilder(); + try (BufferedReader bufferedReader = + new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + builder.append(line); + } + } + if (logResponseStatusText) { + infoLogger.accept("Sent data to bStats and received response: " + builder); + } + } + + /** + * Checks that the class was properly relocated. + */ + private void checkRelocation() { + // You can use the property to disable the check in your test environment + if (System.getProperty("bstats.relocatecheck") == null + || !System.getProperty("bstats.relocatecheck").equals("false")) { + // Maven's Relocate is clever and changes strings, too. So we have to use this little + // "trick" ... :D + final String defaultPackage = + new String(new byte[]{'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'}); + final String examplePackage = + new String(new byte[]{'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); + // We want to make sure no one just copy & pastes the example and uses the wrong package + // names + if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage) + || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) { + throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); + } + } + } + } + + public static class AdvancedBarChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public AdvancedBarChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue().length == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class SimpleBarChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SimpleBarChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + for (Map.Entry entry : map.entrySet()) { + valuesBuilder.appendField(entry.getKey(), new int[]{entry.getValue()}); + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class MultiLineChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public MultiLineChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class AdvancedPie extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public AdvancedPie(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public abstract static class CustomChart { + + private final String chartId; + + protected CustomChart(String chartId) { + if (chartId == null) { + throw new IllegalArgumentException("chartId must not be null"); + } + this.chartId = chartId; + } + + public JsonObjectBuilder.JsonObject getRequestJsonObject( + BiConsumer errorLogger, boolean logErrors) { + JsonObjectBuilder builder = new JsonObjectBuilder(); + builder.appendField("chartId", chartId); + try { + JsonObjectBuilder.JsonObject data = getChartData(); + if (data == null) { + // If the data is null we don't send the chart. + return null; + } + builder.appendField("data", data); + } catch (Throwable t) { + if (logErrors) { + errorLogger.accept("Failed to get data for custom chart with id " + chartId, t); + } + return null; + } + return builder.build(); + } + + protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception; + } + + public static class SingleLineChart extends CustomChart { + + private final Callable callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SingleLineChart(String chartId, Callable callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + int value = callable.call(); + if (value == 0) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("value", value).build(); + } + } + + public static class SimplePie extends CustomChart { + + private final Callable callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SimplePie(String chartId, Callable callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + String value = callable.call(); + if (value == null || value.isEmpty()) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("value", value).build(); + } + } + + public static class DrilldownPie extends CustomChart { + + private final Callable>> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public DrilldownPie(String chartId, Callable>> callable) { + super(chartId); + this.callable = callable; + } + + @Override + public JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map> map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean reallyAllSkipped = true; + for (Map.Entry> entryValues : map.entrySet()) { + JsonObjectBuilder valueBuilder = new JsonObjectBuilder(); + boolean allSkipped = true; + for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { + valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue()); + allSkipped = false; + } + if (!allSkipped) { + reallyAllSkipped = false; + valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build()); + } + } + if (reallyAllSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + /** + * An extremely simple JSON builder. + * + *

While this class is neither feature-rich nor the most performant one, it's sufficient enough + * for its use-case. + */ + public static class JsonObjectBuilder { + + private StringBuilder builder = new StringBuilder(); + + private boolean hasAtLeastOneField = false; + + public JsonObjectBuilder() { + builder.append("{"); + } + + /** + * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt. + * + *

This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'. + * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n"). + * + * @param value The value to escape. + * @return The escaped value. + */ + private static String escape(String value) { + final StringBuilder builder = new StringBuilder(); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (c == '"') { + builder.append("\\\""); + } else if (c == '\\') { + builder.append("\\\\"); + } else if (c <= '\u000F') { + builder.append("\\u000").append(Integer.toHexString(c)); + } else if (c <= '\u001F') { + builder.append("\\u00").append(Integer.toHexString(c)); + } else { + builder.append(c); + } + } + return builder.toString(); + } + + /** + * Appends a null field to the JSON. + * + * @param key The key of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendNull(String key) { + appendFieldUnescaped(key, "null"); + return this; + } + + /** + * Appends a string field to the JSON. + * + * @param key The key of the field. + * @param value The value of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, String value) { + if (value == null) { + throw new IllegalArgumentException("JSON value must not be null"); + } + appendFieldUnescaped(key, "\"" + escape(value) + "\""); + return this; + } + + /** + * Appends an integer field to the JSON. + * + * @param key The key of the field. + * @param value The value of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, int value) { + appendFieldUnescaped(key, String.valueOf(value)); + return this; + } + + /** + * Appends an object to the JSON. + * + * @param key The key of the field. + * @param object The object. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, JsonObject object) { + if (object == null) { + throw new IllegalArgumentException("JSON object must not be null"); + } + appendFieldUnescaped(key, object.toString()); + return this; + } + + /** + * Appends a string array to the JSON. + * + * @param key The key of the field. + * @param values The string array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, String[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = + Arrays.stream(values) + .map(value -> "\"" + escape(value) + "\"") + .collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends an integer array to the JSON. + * + * @param key The key of the field. + * @param values The integer array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, int[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = + Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends an object array to the JSON. + * + * @param key The key of the field. + * @param values The integer array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, JsonObject[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = + Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends a field to the object. + * + * @param key The key of the field. + * @param escapedValue The escaped value of the field. + */ + private void appendFieldUnescaped(String key, String escapedValue) { + if (builder == null) { + throw new IllegalStateException("JSON has already been built"); + } + if (key == null) { + throw new IllegalArgumentException("JSON key must not be null"); + } + if (hasAtLeastOneField) { + builder.append(","); + } + builder.append("\"").append(escape(key)).append("\":").append(escapedValue); + hasAtLeastOneField = true; + } + + /** + * Builds the JSON string and invalidates this builder. + * + * @return The built JSON string. + */ + public JsonObject build() { + if (builder == null) { + throw new IllegalStateException("JSON has already been built"); + } + JsonObject object = new JsonObject(builder.append("}").toString()); + builder = null; + return object; + } + + /** + * A super simple representation of a JSON object. + * + *

This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not + * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String, + * JsonObject)}. + */ + public static class JsonObject { + + private final String value; + + private JsonObject(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + } + } +} diff --git a/src/main/java/me/indian/enderchest/others/UpdateChecker.java b/src/main/java/me/indian/enderchest/other/UpdateChecker.java similarity index 94% rename from src/main/java/me/indian/enderchest/others/UpdateChecker.java rename to src/main/java/me/indian/enderchest/other/UpdateChecker.java index 9f20636..f94cf7b 100644 --- a/src/main/java/me/indian/enderchest/others/UpdateChecker.java +++ b/src/main/java/me/indian/enderchest/other/UpdateChecker.java @@ -1,34 +1,33 @@ -package me.indian.enderchest.others; - -import org.bukkit.Bukkit; -import org.bukkit.plugin.java.JavaPlugin; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Scanner; -import java.util.function.Consumer; - -// From: https://www.spigotmc.org/wiki/creating-an-update-checker-that-checks-for-updates -public class UpdateChecker { - - private final JavaPlugin plugin; - private final int resourceId; - - public UpdateChecker(JavaPlugin plugin, int resourceId) { - this.plugin = plugin; - this.resourceId = resourceId; - } - - public void getVersion(final Consumer consumer) { - Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> { - try (InputStream inputStream = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.resourceId).openStream(); Scanner scanner = new Scanner(inputStream)) { - if (scanner.hasNext()) { - consumer.accept(scanner.next()); - } - } catch (IOException exception) { - plugin.getLogger().info("Unable to check for updates: " + exception.getMessage()); - } - }); - } -} +package me.indian.enderchest.other; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Scanner; +import java.util.function.Consumer; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +// From: https://www.spigotmc.org/wiki/creating-an-update-checker-that-checks-for-updates +public class UpdateChecker { + + private final JavaPlugin plugin; + private final int resourceId; + + public UpdateChecker(JavaPlugin plugin, int resourceId) { + this.plugin = plugin; + this.resourceId = resourceId; + } + + public void getVersion(final Consumer consumer) { + Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> { + try (InputStream inputStream = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.resourceId).openStream(); Scanner scanner = new Scanner(inputStream)) { + if (scanner.hasNext()) { + consumer.accept(scanner.next()); + } + } catch (IOException exception) { + plugin.getLogger().info("Unable to check for updates: " + exception.getMessage()); + } + }); + } +} diff --git a/src/main/java/me/indian/enderchest/util/ColorUtil.java b/src/main/java/me/indian/enderchest/util/ColorUtil.java new file mode 100644 index 0000000..f6b4e29 --- /dev/null +++ b/src/main/java/me/indian/enderchest/util/ColorUtil.java @@ -0,0 +1,11 @@ +package me.indian.enderchest.util; + +import org.bukkit.ChatColor; + +public class ColorUtil { + + public static String replaceColorCode(String msg) { + return ChatColor.translateAlternateColorCodes('&', msg); + } + +} diff --git a/src/main/java/me/indian/enderchest/Utils/ConfigUtil.java b/src/main/java/me/indian/enderchest/util/ConfigUtil.java similarity index 92% rename from src/main/java/me/indian/enderchest/Utils/ConfigUtil.java rename to src/main/java/me/indian/enderchest/util/ConfigUtil.java index 4f75498..e415ae3 100644 --- a/src/main/java/me/indian/enderchest/Utils/ConfigUtil.java +++ b/src/main/java/me/indian/enderchest/util/ConfigUtil.java @@ -1,40 +1,39 @@ -package me.indian.enderchest.Utils; - -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.plugin.Plugin; - -import java.io.File; - -public class ConfigUtil { - private File file; - private FileConfiguration config; - - public ConfigUtil(Plugin plugin, String patch) { - this(plugin.getDataFolder().getAbsolutePath() + "/" + patch); - - } - - public ConfigUtil(String patch) { - this.file = new File(patch); - this.config = YamlConfiguration.loadConfiguration(this.file); - } - - public boolean save() { - try { - this.config.save(this.file); - return true; - } catch (Exception e) { - e.printStackTrace(); - return false; - } - } - - public File getFile() { - return this.file; - } - - public FileConfiguration getConfig() { - return this.config; - } -} +package me.indian.enderchest.util; + +import java.io.File; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.Plugin; + +public class ConfigUtil { + private File file; + private FileConfiguration config; + + public ConfigUtil(Plugin plugin, String patch) { + this(plugin.getDataFolder().getAbsolutePath() + "/" + patch); + + } + + public ConfigUtil(String patch) { + this.file = new File(patch); + this.config = YamlConfiguration.loadConfiguration(this.file); + } + + public boolean save() { + try { + this.config.save(this.file); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public File getFile() { + return this.file; + } + + public FileConfiguration getConfig() { + return this.config; + } +} diff --git a/src/main/java/me/indian/enderchest/EnderChestApi.java b/src/main/java/me/indian/enderchest/util/EnderChestApi.java similarity index 56% rename from src/main/java/me/indian/enderchest/EnderChestApi.java rename to src/main/java/me/indian/enderchest/util/EnderChestApi.java index 830a50d..eb6804b 100644 --- a/src/main/java/me/indian/enderchest/EnderChestApi.java +++ b/src/main/java/me/indian/enderchest/util/EnderChestApi.java @@ -1,36 +1,34 @@ -package me.indian.enderchest; - -import me.indian.enderchest.main.Enderchest; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.inventory.Inventory; - -public class EnderChestApi { - - public static void OpenCrafting(Enderchest plugin, Player p, Boolean open, String refusal, Boolean closeinv) { - - if (open == true) { - p.openWorkbench(p.getLocation(), true); - } else { - p.sendMessage(refusal); - if (closeinv == true) { - Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 20); - } - } - } - - public static void OpenEnderChest(Enderchest plugin, Player p, Boolean open, String refusal, Boolean closeinv) { - - if (open == true) { - - Inventory inv = p.getEnderChest(); - p.openInventory(inv); - - } else { - p.sendMessage(refusal); - if (closeinv == true) { - Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 20); - } - } - } -} +package me.indian.enderchest.util; + +import me.indian.enderchest.Enderchest; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +public class EnderChestApi { + // this will be developed later + private final Enderchest plugin = Enderchest.getInstance(); + + public void openCrafting(Player p, Boolean open, String refusal, Boolean closeinv) { + if (open) { + p.openWorkbench(p.getLocation(), true); + } else { + p.sendMessage(refusal); + if (closeinv) { + Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 20); + } + } + } + + public void openEnderChest(Player p, Boolean open, String refusal, Boolean closeinv) { + if (open) { + Inventory inv = p.getEnderChest(); + p.openInventory(inv); + } else { + p.sendMessage(refusal); + if (closeinv) { + Bukkit.getScheduler().runTaskLater(plugin, () -> p.closeInventory(), 20); + } + } + } +} diff --git a/src/main/java/me/indian/enderchest/util/MessageApi.java b/src/main/java/me/indian/enderchest/util/MessageApi.java new file mode 100644 index 0000000..e2ad73d --- /dev/null +++ b/src/main/java/me/indian/enderchest/util/MessageApi.java @@ -0,0 +1,56 @@ +package me.indian.enderchest.util; + +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class MessageApi { + + public static void actionBar(Player p, String text) { + p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(text.replace("", p.getName()))); + } + + public static void chat(Player p, String text) { + p.spigot().sendMessage(ChatMessageType.CHAT, TextComponent.fromLegacyText(text.replace("", p.getName()))); + } + + public static void console(Player p, String command) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("", p.getName())); + } + + public static void console(String command) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command); + } + + public static void playerCommand(Player p, String command) { + Bukkit.dispatchCommand(p, command.replace("", p.getName())); + } + + public static void hoverMessage(Player p, String text, String hovertext) { + TextComponent message = new TextComponent(text); + message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hovertext).create())); + p.spigot().sendMessage(message); + } + + public static void hoverMessage(Player p, String text, String command, String hovertext, Boolean run) { + TextComponent message = new TextComponent(text); + if (run == true) { + message.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command)); + } else { + message.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, command)); + } + message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hovertext).create())); + p.spigot().sendMessage(message); + } + + public static void hoverMessageCopy(Player p, String text1, String text2, String hovertext) { + TextComponent message = new TextComponent(text1); + message.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, text2)); + message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hovertext).create())); + p.spigot().sendMessage(message); + } +} \ No newline at end of file diff --git a/src/main/java/me/indian/enderchest/util/ReopenUtil.java b/src/main/java/me/indian/enderchest/util/ReopenUtil.java new file mode 100644 index 0000000..e92ce27 --- /dev/null +++ b/src/main/java/me/indian/enderchest/util/ReopenUtil.java @@ -0,0 +1,21 @@ +package me.indian.enderchest.util; + +import me.indian.enderchest.Enderchest; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class ReopenUtil { + + private static final Enderchest plugin = Enderchest.getInstance(); + + public static void reOpenSettingsInventory(Player player) { + Bukkit.getScheduler().runTaskLater(plugin, () -> player.closeInventory(), 5); + Bukkit.getScheduler().runTaskLater(plugin, () -> plugin.getEnderChestCommand().openSettings(player), 5); + } + + public static void reOpenEnderchestInventory(Player player) { + Bukkit.getScheduler().runTaskLater(plugin, () -> player.closeInventory(), 5); + Bukkit.getScheduler().runTaskLater(plugin, () -> plugin.getOpenCommand().openEnderchestGui(player), 5); + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 6ebedd9..0a8f09d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -2,11 +2,11 @@ # EnderChest and Carfting plugin # By: Indian Bartonka # Support: https://discord.gg/aq6NaXsy2k -# § for colors +# § for colors (later i add fully support for &) #------------------------------------------------------------------------- # #Prefix -prefix: "§6[§bEnderChest §aand §eCrafting§6]§r " +prefix: "&6[&bEnderChest &aand &eCrafting&6]&r " #/open inventory name (You must reload server or restart) InvName: "Crafting and Enderchest" #Permissions messages @@ -18,7 +18,7 @@ player-not-be: "You must be a Player" #Other messages off-feature: "§cThis feature is disabled by admin " successfully-set: "Successfully set to " -config-reload: "Config has been reload" +config-reload: "&aConfig has been reload" #Option that allows you to use crafting or enderchest w / open EnderChest: true Crafting: true diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index a6a4dbe..7b2dd7a 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,26 +1,16 @@ name: EnderchestAndCrafting version: '${project.version}' -main: me.indian.enderchest.main.Enderchest +main: me.indian.enderchest.Enderchest api-version: 1.19 author: IndianPL prefix: Enderchest and crafting -softdepend: [PlaceholderAPI] +softdepend: [ PlaceholderAPI ] description: Polski plugin commands: - open: - description: enderchest and crafting - aliases: - - otworz - endacrftr: - description: reload command + open: + description: enderchest and crafting aliases: - - eacreload - - er - set: - description: - aliases: - - ustaw - - entest: - description: + - otworz + enderchest: + description: enderchest menagment command