From f5750bc2cfb3bf9e31e46b992e32a59d5eeae030 Mon Sep 17 00:00:00 2001 From: M_Viper Date: Mon, 11 Aug 2025 15:35:52 +0000 Subject: [PATCH] src/main/java/TpPlugin.java aktualisiert --- src/main/java/TpPlugin.java | 1107 +++++++++++++++++++---------------- 1 file changed, 606 insertions(+), 501 deletions(-) diff --git a/src/main/java/TpPlugin.java b/src/main/java/TpPlugin.java index b8b1f86..6de9e60 100644 --- a/src/main/java/TpPlugin.java +++ b/src/main/java/TpPlugin.java @@ -1,502 +1,607 @@ -import org.bukkit.plugin.java.JavaPlugin; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.block.SignChangeEvent; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.bukkit.block.Sign; -import org.bukkit.ChatColor; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.Map; - -public class TpPlugin extends JavaPlugin implements Listener { - private File tpFile; - private FileConfiguration tpConfig; - private File configFile; - private FileConfiguration config; - private Map tps; - private Map signLocations; - private String prefix; - private Material defaultItem; - private String signLine1Color; - private String signLine2Color; - private String signLine3Text; - private String signLine4Text; - private static final String CONFIG_VERSION = "1.3.3"; - private static final String PLUGIN_AUTHOR = "M_Viper"; - - @Override - public void onEnable() { - getServer().getPluginManager().registerEvents(this, this); - tps = new HashMap<>(); - signLocations = new HashMap<>(); - loadConfig(); - updateConfig(); - loadConfig(); - loadTps(); - - // Konsolenmeldung beim Plugin-Start - getLogger().info("[>] ========================================== [<]"); - getLogger().info(" TpPlugin - " + getDescription().getVersion()); - getLogger().info(" Ersteller: " + PLUGIN_AUTHOR); - getLogger().info("[>] ========================================== [<]"); - } - - @Override - public void onDisable() { - saveTps(); - } - - private void loadConfig() { - configFile = new File(getDataFolder(), "config.yml"); - if (!getDataFolder().exists()) { - getDataFolder().mkdirs(); - } - if (!configFile.exists()) { - saveResource("config.yml", false); - getLogger().info("config.yml wurde erstellt."); - } - config = YamlConfiguration.loadConfiguration(configFile); - prefix = config.getString("prefix", "tp"); - String itemName = config.getString("default-item", "OAK_SIGN"); - signLine1Color = config.getString("sign.line1-color", "&1"); - signLine2Color = config.getString("sign.line2-color", "&6"); - signLine3Text = config.getString("sign.line3-text", "Teleport"); - signLine4Text = config.getString("sign.line4-text", "Klick mich!"); - try { - defaultItem = Material.valueOf(itemName.toUpperCase()); - getLogger().info("Default item gesetzt auf: " + defaultItem.name()); - } catch (IllegalArgumentException e) { - getLogger().warning("Ungültiges default-item in config.yml: " + itemName + ". Fallback auf OAK_SIGN."); - defaultItem = Material.OAK_SIGN; - } - } - - private void updateConfig() { - InputStream defaultConfigStream = getResource("config.yml"); - if (defaultConfigStream == null) { - getLogger().severe("Konnte Standard-config.yml nicht aus Ressourcen laden!"); - return; - } - YamlConfiguration defaultConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(defaultConfigStream)); - String currentVersion = config.getString("version", "0.0.0"); - - if (!currentVersion.equals(CONFIG_VERSION)) { - getLogger().info("Aktualisiere config.yml von Version " + currentVersion + " zu " + CONFIG_VERSION); - boolean updated = false; - - for (String key : defaultConfig.getKeys(true)) { - if (key.equals("version")) { - continue; - } - if (!config.isSet(key)) { - config.set(key, defaultConfig.get(key)); - updated = true; - getLogger().info("Neuer Config-Schlüssel hinzugefügt: " + key); - } - } - - if (config.isSet("messages.tpinfo")) { - config.set("messages.tpinfo", null); - updated = true; - getLogger().info("Veralteter Config-Schlüssel entfernt: messages.tpinfo"); - } - - config.set("version", CONFIG_VERSION); - updated = true; - - if (updated) { - try { - config.save(configFile); - getLogger().info("config.yml erfolgreich aktualisiert."); - } catch (IOException e) { - getLogger().severe("Fehler beim Speichern der aktualisierten Config: " + e.getMessage()); - } - } else { - getLogger().info("Keine Updates für config.yml erforderlich."); - } - } - } - - private void loadTps() { - tpFile = new File(getDataFolder(), "tps.yml"); - if (!getDataFolder().exists()) { - getDataFolder().mkdirs(); - } - if (!tpFile.exists()) { - try { - tpFile.createNewFile(); - getLogger().info("tps.yml created."); - } catch (IOException e) { - getLogger().severe("Error creating tps.yml: " + e.getMessage()); - return; - } - } - tps.clear(); // Bestehende TP-Punkte leeren - signLocations.clear(); // Bestehende Schilder leeren - tpConfig = YamlConfiguration.loadConfiguration(tpFile); - if (tpConfig == null) { - getLogger().severe("Failed to load tps.yml!"); - return; - } - getLogger().info("tps.yml loaded."); - - if (tpConfig.contains("tps")) { - for (String key : tpConfig.getConfigurationSection("tps").getKeys(false)) { - Location loc = tpConfig.getLocation("tps." + key + ".location"); - if (loc != null) { - tps.put(key, loc); - } - } - } - - if (tpConfig.contains("signs")) { - for (String key : tpConfig.getConfigurationSection("signs").getKeys(false)) { - Location loc = tpConfig.getLocation("signs." + key); - if (loc != null) { - signLocations.put(loc, key); - } - } - } - - } - - private void saveTps() { - if (tpConfig == null) { - getLogger().severe("Fehler: tps.yml konnte nicht gespeichert werden, da tpConfig null ist!"); - return; - } - - for (Map.Entry entry : tps.entrySet()) { - tpConfig.set("tps." + entry.getKey() + ".location", entry.getValue()); - } - - try { - tpConfig.save(tpFile); - getLogger().info("tps.yml erfolgreich gespeichert."); - } catch (IOException e) { - getLogger().severe("Fehler beim Speichern von tps.yml: " + e.getMessage()); - } - } - - private String getMessage(String key) { - String message = config.getString("messages." + key, "Message not found: " + key); - return ChatColor.translateAlternateColorCodes('&', message); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!(sender instanceof Player)) { - sender.sendMessage(getMessage("player-only")); - return true; - } - - Player player = (Player) sender; - - if (command.getName().equalsIgnoreCase("tp")) { - if (!player.hasPermission("tpplugin.use")) { - player.sendMessage(getMessage("no-permission-use")); - return true; - } - - if (args.length == 0) { - openTpGUI(player); - return true; - } - - String tpName = args[0]; - if (tps.containsKey(tpName)) { - player.teleport(tps.get(tpName)); - player.sendMessage(getMessage("teleport-success").replace("%tp%", tpName)); - } else { - player.sendMessage(getMessage("tp-not-found").replace("%tp%", tpName)); - } - return true; - } - - if (command.getName().equalsIgnoreCase("settp")) { - if (!player.hasPermission("tpplugin.admin")) { - player.sendMessage(getMessage("no-permission-admin")); - return true; - } - - if (args.length != 1) { - player.sendMessage(getMessage("settp-usage")); - return true; - } - - String tpName = args[0]; - if (tps.containsKey(tpName)) { - player.sendMessage(getMessage("tp-exists").replace("%tp%", tpName)); - return true; - } - - ItemStack item = player.getInventory().getItemInMainHand(); - if (item.getType() == Material.AIR) { - item = new ItemStack(defaultItem); - } - - if (tpConfig == null) { - player.sendMessage(getMessage("config-error")); - getLogger().severe("tpConfig ist null in settp!"); - return true; - } - - tps.put(tpName, player.getLocation()); - tpConfig.set("tps." + tpName + ".location", player.getLocation()); - tpConfig.set("tps." + tpName + ".item", item); - saveTps(); - player.sendMessage(getMessage("settp-success").replace("%tp%", tpName)); - return true; - } - - if (command.getName().equalsIgnoreCase("deltp")) { - if (!player.hasPermission("tpplugin.admin")) { - player.sendMessage(getMessage("no-permission-admin")); - return true; - } - - if (args.length != 1) { - player.sendMessage(getMessage("deltp-usage")); - return true; - } - - String tpName = args[0]; - if (!tps.containsKey(tpName)) { - player.sendMessage(getMessage("tp-not-found").replace("%tp%", tpName)); - return true; - } - - if (tpConfig == null) { - player.sendMessage(getMessage("config-error")); - getLogger().severe("tpConfig ist null in deltp!"); - return true; - } - - tps.remove(tpName); - tpConfig.set("tps." + tpName, null); - - List signsToRemove = new ArrayList<>(); - for (Map.Entry entry : signLocations.entrySet()) { - if (entry.getValue().equals(tpName)) { - signsToRemove.add(entry.getKey()); - Location loc = entry.getKey(); - if (loc.getBlock().getState() instanceof Sign) { - loc.getBlock().setType(Material.AIR); - } - } - } - - for (Location loc : signsToRemove) { - signLocations.remove(loc); - tpConfig.set("signs." + loc.toString(), null); - } - - saveTps(); - player.sendMessage(getMessage("deltp-success").replace("%tp%", tpName)); - return true; - } - - if (command.getName().equalsIgnoreCase("tpphelp")) { - player.sendMessage(getMessage("help-title")); - player.sendMessage(getMessage("help-tp")); - player.sendMessage(getMessage("help-settp")); - player.sendMessage(getMessage("help-deltp")); - player.sendMessage(getMessage("help-tpinfo")); - return true; - } - - if (command.getName().equalsIgnoreCase("tpinfo")) { - String message = ChatColor.translateAlternateColorCodes('&', - "&6&m------------------&r &6TpPlugin &6&m------------------\n" + - "&7Version: &e%version%\n" + - "&7Ersteller: &e%author%\n" + - "&7Beschreibung: &fEin Plugin zum Verwalten von Teleportationspunkten\n" + - "&7Befehle: &e/tp, /settp, /deltp, /tpphelp, /tpinfo, /tpreload\n" + - "&6&m----------------------------------------" - ).replace("%version%", getDescription().getVersion()) - .replace("%author%", PLUGIN_AUTHOR); - player.sendMessage(message); - return true; - } - - if (command.getName().equalsIgnoreCase("tpreload")) { - if (!player.hasPermission("tpplugin.admin")) { - player.sendMessage(getMessage("no-permission-admin")); - return true; - } - - loadConfig(); - loadTps(); - player.sendMessage(getMessage("reload-success")); - return true; - } - - return false; - } - - private void openTpGUI(Player player) { - Inventory gui = getServer().createInventory(null, 27, getMessage("gui-title")); - - for (Map.Entry entry : tps.entrySet()) { - String tpName = entry.getKey(); - ItemStack savedItem = (ItemStack) tpConfig.get("tps." + tpName + ".item"); - if (savedItem != null) { - ItemStack guiItem = new ItemStack(savedItem.getType()); - ItemMeta meta = guiItem.getItemMeta(); - if (meta != null) { - List lore = new ArrayList<>(); - lore.add(ChatColor.translateAlternateColorCodes('&', "&7TP: &6" + tpName)); - meta.setLore(lore); - guiItem.setItemMeta(meta); - gui.addItem(guiItem); - } - } - } - - player.openInventory(gui); - } - - @EventHandler - public void onInventoryClick(InventoryClickEvent event) { - if (!event.getView().getTitle().equals(getMessage("gui-title"))) return; - - event.setCancelled(true); - if (!(event.getWhoClicked() instanceof Player)) return; - - Player player = (Player) event.getWhoClicked(); - ItemStack clickedItem = event.getCurrentItem(); - if (clickedItem == null || !clickedItem.hasItemMeta() || !clickedItem.getItemMeta().hasLore()) return; - - List lore = clickedItem.getItemMeta().getLore(); - for (String line : lore) { - if (line.startsWith(ChatColor.translateAlternateColorCodes('&', "&7TP: &6"))) { - String tpName = ChatColor.stripColor(line).replace("TP: ", ""); - if (tps.containsKey(tpName)) { - player.teleport(tps.get(tpName)); - player.sendMessage(getMessage("teleport-success").replace("%tp%", tpName)); - player.closeInventory(); - } - break; - } - } - } - - @EventHandler - public void onSignChange(SignChangeEvent event) { - if (!event.getPlayer().hasPermission("tpplugin.admin")) return; - - if (event.getLine(0).equalsIgnoreCase("[" + prefix + "]")) { - String tpName = event.getLine(1); - if (!tps.containsKey(tpName)) { - event.getPlayer().sendMessage(getMessage("tp-not-found").replace("%tp%", tpName)); - event.setCancelled(true); - return; - } - - event.setLine(0, ChatColor.translateAlternateColorCodes('&', signLine1Color + "[" + prefix + "]")); - event.setLine(1, ChatColor.translateAlternateColorCodes('&', signLine2Color + tpName)); - event.setLine(2, ChatColor.translateAlternateColorCodes('&', signLine3Text)); - event.setLine(3, ChatColor.translateAlternateColorCodes('&', signLine4Text)); - signLocations.put(event.getBlock().getLocation(), tpName); - if (tpConfig != null) { - tpConfig.set("signs." + event.getBlock().getLocation().toString(), tpName); - saveTps(); - } else { - event.getPlayer().sendMessage(getMessage("config-error")); - getLogger().severe("tpConfig ist null in onSignChange!"); - } - } - } - - @EventHandler - public void onPlayerInteract(PlayerInteractEvent event) { - if (event.getClickedBlock() == null || !(event.getClickedBlock().getState() instanceof Sign)) return; - - Sign sign = (Sign) event.getClickedBlock().getState(); - if (!sign.getLine(0).equals(ChatColor.translateAlternateColorCodes('&', signLine1Color + "[" + prefix + "]"))) return; - - Player player = event.getPlayer(); - String tpName = ChatColor.stripColor(sign.getLine(1)); - - if (event.getAction() == Action.LEFT_CLICK_BLOCK && player.hasPermission("tpplugin.admin") && player.isSneaking()) { - if (tpConfig != null) { - Location loc = event.getClickedBlock().getLocation(); - signLocations.remove(loc); - tpConfig.set("signs." + loc.toString(), null); - event.getClickedBlock().setType(Material.AIR); - saveTps(); - player.sendMessage(getMessage("sign-removed").replace("%tp%", tpName)); - } else { - player.sendMessage(getMessage("config-error")); - getLogger().severe("tpConfig ist null in onPlayerInteract!"); - } - event.setCancelled(true); - return; - } - - if ((event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK) && - player.hasPermission("tpplugin.use")) { - if (!player.hasPermission("tpplugin.admin") || !player.isSneaking()) { - if (tps.containsKey(tpName)) { - player.teleport(tps.get(tpName)); - player.sendMessage(getMessage("teleport-success").replace("%tp%", tpName)); - } - event.setCancelled(true); - } - } else { - player.sendMessage(getMessage("no-permission-use")); - event.setCancelled(true); - } - } - - @EventHandler - public void onBlockBreak(BlockBreakEvent event) { - if (!(event.getBlock().getState() instanceof Sign)) return; - - Location loc = event.getBlock().getLocation(); - if (signLocations.containsKey(loc)) { - Player player = event.getPlayer(); - if (!player.hasPermission("tpplugin.admin")) { - event.setCancelled(true); - player.sendMessage(getMessage("no-permission-break-sign")); - return; - } - if (!player.isSneaking()) { - event.setCancelled(true); - player.sendMessage(getMessage("must-sneak-to-break")); - return; - } - - String tpName = signLocations.get(loc); - signLocations.remove(loc); - if (tpConfig != null) { - tpConfig.set("signs." + loc.toString(), null); - saveTps(); - player.sendMessage(getMessage("sign-removed").replace("%tp%", tpName)); - } else { - player.sendMessage(getMessage("config-error")); - getLogger().severe("tpConfig ist null in onBlockBreak!"); - } - } - } +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.SignChangeEvent; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.block.Sign; +import org.bukkit.ChatColor; + +// NEU: bStats +import org.bstats.bukkit.Metrics; + +// NEU: Spigot UpdateChecker +import org.bukkit.Bukkit; +import org.bukkit.event.player.PlayerJoinEvent; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Scanner; +import java.util.function.Consumer; + +import org.json.JSONObject; // Wichtig für JSON Parsing + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.HashMap; +import java.util.Map; + +public class TpPlugin extends JavaPlugin implements Listener { + private File tpFile; + private FileConfiguration tpConfig; + private File configFile; + private FileConfiguration config; + private Map tps; + private Map signLocations; + private String prefix; + private Material defaultItem; + private String signLine1Color; + private String signLine2Color; + private String signLine3Text; + private String signLine4Text; + private static final String CONFIG_VERSION = "1.3.3"; + private static final String PLUGIN_AUTHOR = "M_Viper"; + + // NEU: bStats & Updater + private Metrics metrics; + private String latestVersion = null; + private static final int RESOURCE_ID = 127829; // Spigot-Resource-ID anpassen + private static final int BSTATS_ID = 26873; // bStats-Service-ID anpassen + + @Override +public void onEnable() { + getServer().getPluginManager().registerEvents(this, this); + getServer().getPluginManager().registerEvents(new UpdateNotifyListener(), this); + + tps = new HashMap<>(); + signLocations = new HashMap<>(); + loadConfig(); + updateConfig(); + loadConfig(); + loadTps(); + + // bStats initialisieren + metrics = new Metrics(this, BSTATS_ID); + getLogger().info("bStats initialisiert."); + + // Update-Check starten (Spiget API mit JSON Parsing, Normalisierung & numerischem Vergleich) + getLatestVersion(latest -> { + String current = getDescription().getVersion(); + + // Führendes "version", "v" oder "v." am Anfang entfernen, danach trimmen + String normalizedLatest = latest.replaceFirst("(?i)^(version\\s*|v\\.?\\s*)", "").trim(); + String normalizedCurrent = current.replaceFirst("(?i)^(version\\s*|v\\.?\\s*)", "").trim(); + + if (isNewerVersion(normalizedLatest, normalizedCurrent)) { + latestVersion = latest; + getLogger().info("Neue Version verfügbar: " + latest + " (aktuell: " + current + ")"); + getLogger().info("Download: https://www.spigotmc.org/resources/" + RESOURCE_ID + "/"); + + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.isOp()) { + player.sendMessage("§aEine neue Version von §e" + getDescription().getName() + + " §aist verfügbar: §e" + latest + " §7(aktuell: " + current + ")"); + player.sendMessage("§eDownload: §bhttps://www.spigotmc.org/resources/" + RESOURCE_ID + "/"); + } + } + } + }); + + // Konsolenmeldung beim Plugin-Start + getLogger().info("[>] ========================================== [<]"); + getLogger().info(" TpPlugin - " + getDescription().getVersion()); + getLogger().info(" Ersteller: " + PLUGIN_AUTHOR); + getLogger().info("[>] ========================================== [<]"); +} + +@Override +public void onDisable() { + saveTps(); +} + +// NEU: UpdateChecker-Methode mit Spiget-API und JSON Parsing +private void getLatestVersion(Consumer consumer) { + getServer().getScheduler().runTaskAsynchronously(this, () -> { + try { + HttpURLConnection connection = (HttpURLConnection) + new URL("https://api.spiget.org/v2/resources/" + RESOURCE_ID + "/versions/latest").openConnection(); + connection.setRequestMethod("GET"); + connection.addRequestProperty("User-Agent", "Mozilla/5.0"); + try (Scanner scanner = new Scanner(connection.getInputStream())) { + String response = scanner.useDelimiter("\\A").next(); + JSONObject json = new JSONObject(response); + String versionName = json.optString("name", "").trim(); + consumer.accept(versionName); + } + } catch (Exception e) { + getLogger().warning("Konnte keine Update-Info abrufen: " + e.getMessage()); + consumer.accept(""); + } + }); +} + +// Numerischer Versionsvergleich (SemVer-ähnlich) +private boolean isNewerVersion(String latest, String current) { + try { + String[] latestParts = latest.split("\\."); + String[] currentParts = current.split("\\."); + int length = Math.max(latestParts.length, currentParts.length); + + for (int i = 0; i < length; i++) { + int latestPart = (i < latestParts.length) ? Integer.parseInt(latestParts[i]) : 0; + int currentPart = (i < currentParts.length) ? Integer.parseInt(currentParts[i]) : 0; + if (latestPart > currentPart) return true; + if (latestPart < currentPart) return false; + } + return false; // gleich oder älter + } catch (NumberFormatException e) { + // Fallback: falls Versionsstring nicht als Zahl parsebar ist + return !latest.equalsIgnoreCase(current); + } +} + +// NEU: Listener für Join-Nachricht +public class UpdateNotifyListener implements Listener { + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + if (player.isOp() && latestVersion != null) { + String currentVersion = getDescription().getVersion(); + player.sendMessage("§aEine neue Version von §e" + getDescription().getName() + + " §aist verfügbar: §e" + latestVersion + + " §7(aktuell: " + currentVersion + ")"); + player.sendMessage("§eDownload: §bhttps://www.spigotmc.org/resources/" + RESOURCE_ID + "/"); + } + } +} + + + private void loadConfig() { + configFile = new File(getDataFolder(), "config.yml"); + if (!getDataFolder().exists()) { + getDataFolder().mkdirs(); + } + if (!configFile.exists()) { + saveResource("config.yml", false); + getLogger().info("config.yml wurde erstellt."); + } + config = YamlConfiguration.loadConfiguration(configFile); + prefix = config.getString("prefix", "tp"); + String itemName = config.getString("default-item", "OAK_SIGN"); + signLine1Color = config.getString("sign.line1-color", "&1"); + signLine2Color = config.getString("sign.line2-color", "&6"); + signLine3Text = config.getString("sign.line3-text", "Teleport"); + signLine4Text = config.getString("sign.line4-text", "Klick mich!"); + try { + defaultItem = Material.valueOf(itemName.toUpperCase()); + getLogger().info("Default item gesetzt auf: " + defaultItem.name()); + } catch (IllegalArgumentException e) { + getLogger().warning("Ungültiges default-item in config.yml: " + itemName + ". Fallback auf OAK_SIGN."); + defaultItem = Material.OAK_SIGN; + } + } + + private void updateConfig() { + InputStream defaultConfigStream = getResource("config.yml"); + if (defaultConfigStream == null) { + getLogger().severe("Konnte Standard-config.yml nicht aus Ressourcen laden!"); + return; + } + YamlConfiguration defaultConfig = YamlConfiguration.loadConfiguration(new InputStreamReader(defaultConfigStream)); + String currentVersion = config.getString("version", "0.0.0"); + + if (!currentVersion.equals(CONFIG_VERSION)) { + getLogger().info("Aktualisiere config.yml von Version " + currentVersion + " zu " + CONFIG_VERSION); + boolean updated = false; + + for (String key : defaultConfig.getKeys(true)) { + if (key.equals("version")) { + continue; + } + if (!config.isSet(key)) { + config.set(key, defaultConfig.get(key)); + updated = true; + getLogger().info("Neuer Config-Schlüssel hinzugefügt: " + key); + } + } + + if (config.isSet("messages.tpinfo")) { + config.set("messages.tpinfo", null); + updated = true; + getLogger().info("Veralteter Config-Schlüssel entfernt: messages.tpinfo"); + } + + config.set("version", CONFIG_VERSION); + updated = true; + + if (updated) { + try { + config.save(configFile); + getLogger().info("config.yml erfolgreich aktualisiert."); + } catch (IOException e) { + getLogger().severe("Fehler beim Speichern der aktualisierten Config: " + e.getMessage()); + } + } else { + getLogger().info("Keine Updates für config.yml erforderlich."); + } + } + } + + private void loadTps() { + tpFile = new File(getDataFolder(), "tps.yml"); + if (!getDataFolder().exists()) { + getDataFolder().mkdirs(); + } + if (!tpFile.exists()) { + try { + tpFile.createNewFile(); + getLogger().info("tps.yml created."); + } catch (IOException e) { + getLogger().severe("Error creating tps.yml: " + e.getMessage()); + return; + } + } + tps.clear(); // Bestehende TP-Punkte leeren + signLocations.clear(); // Bestehende Schilder leeren + tpConfig = YamlConfiguration.loadConfiguration(tpFile); + if (tpConfig == null) { + getLogger().severe("Failed to load tps.yml!"); + return; + } + getLogger().info("tps.yml loaded."); + + if (tpConfig.contains("tps")) { + for (String key : tpConfig.getConfigurationSection("tps").getKeys(false)) { + Location loc = tpConfig.getLocation("tps." + key + ".location"); + if (loc != null) { + tps.put(key, loc); + } + } + } + + if (tpConfig.contains("signs")) { + for (String key : tpConfig.getConfigurationSection("signs").getKeys(false)) { + Location loc = tpConfig.getLocation("signs." + key); + if (loc != null) { + signLocations.put(loc, key); + } + } + } + + } + + private void saveTps() { + if (tpConfig == null) { + getLogger().severe("Fehler: tps.yml konnte nicht gespeichert werden, da tpConfig null ist!"); + return; + } + + for (Map.Entry entry : tps.entrySet()) { + tpConfig.set("tps." + entry.getKey() + ".location", entry.getValue()); + } + + try { + tpConfig.save(tpFile); + getLogger().info("tps.yml erfolgreich gespeichert."); + } catch (IOException e) { + getLogger().severe("Fehler beim Speichern von tps.yml: " + e.getMessage()); + } + } + + private String getMessage(String key) { + String message = config.getString("messages." + key, "Message not found: " + key); + return ChatColor.translateAlternateColorCodes('&', message); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + sender.sendMessage(getMessage("player-only")); + return true; + } + + Player player = (Player) sender; + + if (command.getName().equalsIgnoreCase("tp")) { + if (!player.hasPermission("tpplugin.use")) { + player.sendMessage(getMessage("no-permission-use")); + return true; + } + + if (args.length == 0) { + openTpGUI(player); + return true; + } + + String tpName = args[0]; + if (tps.containsKey(tpName)) { + player.teleport(tps.get(tpName)); + player.sendMessage(getMessage("teleport-success").replace("%tp%", tpName)); + } else { + player.sendMessage(getMessage("tp-not-found").replace("%tp%", tpName)); + } + return true; + } + + if (command.getName().equalsIgnoreCase("settp")) { + if (!player.hasPermission("tpplugin.admin")) { + player.sendMessage(getMessage("no-permission-admin")); + return true; + } + + if (args.length != 1) { + player.sendMessage(getMessage("settp-usage")); + return true; + } + + String tpName = args[0]; + if (tps.containsKey(tpName)) { + player.sendMessage(getMessage("tp-exists").replace("%tp%", tpName)); + return true; + } + + ItemStack item = player.getInventory().getItemInMainHand(); + if (item.getType() == Material.AIR) { + item = new ItemStack(defaultItem); + } + + if (tpConfig == null) { + player.sendMessage(getMessage("config-error")); + getLogger().severe("tpConfig ist null in settp!"); + return true; + } + + tps.put(tpName, player.getLocation()); + tpConfig.set("tps." + tpName + ".location", player.getLocation()); + tpConfig.set("tps." + tpName + ".item", item); + saveTps(); + player.sendMessage(getMessage("settp-success").replace("%tp%", tpName)); + return true; + } + + if (command.getName().equalsIgnoreCase("deltp")) { + if (!player.hasPermission("tpplugin.admin")) { + player.sendMessage(getMessage("no-permission-admin")); + return true; + } + + if (args.length != 1) { + player.sendMessage(getMessage("deltp-usage")); + return true; + } + + String tpName = args[0]; + if (!tps.containsKey(tpName)) { + player.sendMessage(getMessage("tp-not-found").replace("%tp%", tpName)); + return true; + } + + if (tpConfig == null) { + player.sendMessage(getMessage("config-error")); + getLogger().severe("tpConfig ist null in deltp!"); + return true; + } + + tps.remove(tpName); + tpConfig.set("tps." + tpName, null); + + List signsToRemove = new ArrayList<>(); + for (Map.Entry entry : signLocations.entrySet()) { + if (entry.getValue().equals(tpName)) { + signsToRemove.add(entry.getKey()); + Location loc = entry.getKey(); + if (loc.getBlock().getState() instanceof Sign) { + loc.getBlock().setType(Material.AIR); + } + } + } + + for (Location loc : signsToRemove) { + signLocations.remove(loc); + tpConfig.set("signs." + loc.toString(), null); + } + + saveTps(); + player.sendMessage(getMessage("deltp-success").replace("%tp%", tpName)); + return true; + } + + if (command.getName().equalsIgnoreCase("tpphelp")) { + player.sendMessage(getMessage("help-title")); + player.sendMessage(getMessage("help-tp")); + player.sendMessage(getMessage("help-settp")); + player.sendMessage(getMessage("help-deltp")); + player.sendMessage(getMessage("help-tpinfo")); + return true; + } + + if (command.getName().equalsIgnoreCase("tpinfo")) { + String message = ChatColor.translateAlternateColorCodes('&', + "&6&m------------------&r &6TpPlugin &6&m------------------\n" + + "&7Version: &e%version%\n" + + "&7Ersteller: &e%author%\n" + + "&7Beschreibung: &fEin Plugin zum Verwalten von Teleportationspunkten\n" + + "&7Befehle: &e/tp, /settp, /deltp, /tpphelp, /tpinfo, /tpreload\n" + + "&6&m----------------------------------------" + ).replace("%version%", getDescription().getVersion()) + .replace("%author%", PLUGIN_AUTHOR); + player.sendMessage(message); + return true; + } + + if (command.getName().equalsIgnoreCase("tpreload")) { + if (!player.hasPermission("tpplugin.admin")) { + player.sendMessage(getMessage("no-permission-admin")); + return true; + } + + loadConfig(); + loadTps(); + player.sendMessage(getMessage("reload-success")); + return true; + } + + return false; + } + + private void openTpGUI(Player player) { + Inventory gui = getServer().createInventory(null, 27, getMessage("gui-title")); + + for (Map.Entry entry : tps.entrySet()) { + String tpName = entry.getKey(); + ItemStack savedItem = (ItemStack) tpConfig.get("tps." + tpName + ".item"); + if (savedItem != null) { + ItemStack guiItem = new ItemStack(savedItem.getType()); + ItemMeta meta = guiItem.getItemMeta(); + if (meta != null) { + List lore = new ArrayList<>(); + lore.add(ChatColor.translateAlternateColorCodes('&', "&7TP: &6" + tpName)); + meta.setLore(lore); + guiItem.setItemMeta(meta); + gui.addItem(guiItem); + } + } + } + + player.openInventory(gui); + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + if (!event.getView().getTitle().equals(getMessage("gui-title"))) return; + + event.setCancelled(true); + if (!(event.getWhoClicked() instanceof Player)) return; + + Player player = (Player) event.getWhoClicked(); + ItemStack clickedItem = event.getCurrentItem(); + if (clickedItem == null || !clickedItem.hasItemMeta() || !clickedItem.getItemMeta().hasLore()) return; + + List lore = clickedItem.getItemMeta().getLore(); + for (String line : lore) { + if (line.startsWith(ChatColor.translateAlternateColorCodes('&', "&7TP: &6"))) { + String tpName = ChatColor.stripColor(line).replace("TP: ", ""); + if (tps.containsKey(tpName)) { + player.teleport(tps.get(tpName)); + player.sendMessage(getMessage("teleport-success").replace("%tp%", tpName)); + player.closeInventory(); + } + break; + } + } + } + + @EventHandler + public void onSignChange(SignChangeEvent event) { + if (!event.getPlayer().hasPermission("tpplugin.admin")) return; + + if (event.getLine(0).equalsIgnoreCase("[" + prefix + "]")) { + String tpName = event.getLine(1); + if (!tps.containsKey(tpName)) { + event.getPlayer().sendMessage(getMessage("tp-not-found").replace("%tp%", tpName)); + event.setCancelled(true); + return; + } + + event.setLine(0, ChatColor.translateAlternateColorCodes('&', signLine1Color + "[" + prefix + "]")); + event.setLine(1, ChatColor.translateAlternateColorCodes('&', signLine2Color + tpName)); + event.setLine(2, ChatColor.translateAlternateColorCodes('&', signLine3Text)); + event.setLine(3, ChatColor.translateAlternateColorCodes('&', signLine4Text)); + signLocations.put(event.getBlock().getLocation(), tpName); + if (tpConfig != null) { + tpConfig.set("signs." + event.getBlock().getLocation().toString(), tpName); + saveTps(); + } else { + event.getPlayer().sendMessage(getMessage("config-error")); + getLogger().severe("tpConfig ist null in onSignChange!"); + } + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getClickedBlock() == null || !(event.getClickedBlock().getState() instanceof Sign)) return; + + Sign sign = (Sign) event.getClickedBlock().getState(); + if (!sign.getLine(0).equals(ChatColor.translateAlternateColorCodes('&', signLine1Color + "[" + prefix + "]"))) return; + + Player player = event.getPlayer(); + String tpName = ChatColor.stripColor(sign.getLine(1)); + + if (event.getAction() == Action.LEFT_CLICK_BLOCK && player.hasPermission("tpplugin.admin") && player.isSneaking()) { + if (tpConfig != null) { + Location loc = event.getClickedBlock().getLocation(); + signLocations.remove(loc); + tpConfig.set("signs." + loc.toString(), null); + event.getClickedBlock().setType(Material.AIR); + saveTps(); + player.sendMessage(getMessage("sign-removed").replace("%tp%", tpName)); + } else { + player.sendMessage(getMessage("config-error")); + getLogger().severe("tpConfig ist null in onPlayerInteract!"); + } + event.setCancelled(true); + return; + } + + if ((event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK) && + player.hasPermission("tpplugin.use")) { + if (!player.hasPermission("tpplugin.admin") || !player.isSneaking()) { + if (tps.containsKey(tpName)) { + player.teleport(tps.get(tpName)); + player.sendMessage(getMessage("teleport-success").replace("%tp%", tpName)); + } + event.setCancelled(true); + } + } else { + player.sendMessage(getMessage("no-permission-use")); + event.setCancelled(true); + } + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + if (!(event.getBlock().getState() instanceof Sign)) return; + + Location loc = event.getBlock().getLocation(); + if (signLocations.containsKey(loc)) { + Player player = event.getPlayer(); + if (!player.hasPermission("tpplugin.admin")) { + event.setCancelled(true); + player.sendMessage(getMessage("no-permission-break-sign")); + return; + } + if (!player.isSneaking()) { + event.setCancelled(true); + player.sendMessage(getMessage("must-sneak-to-break")); + return; + } + + String tpName = signLocations.get(loc); + signLocations.remove(loc); + if (tpConfig != null) { + tpConfig.set("signs." + loc.toString(), null); + saveTps(); + player.sendMessage(getMessage("sign-removed").replace("%tp%", tpName)); + } else { + player.sendMessage(getMessage("config-error")); + getLogger().severe("tpConfig ist null in onBlockBreak!"); + } + } + } } \ No newline at end of file