diff --git a/src/main/java/TpPlugin.java b/src/main/java/TpPlugin.java new file mode 100644 index 0000000..b8b1f86 --- /dev/null +++ b/src/main/java/TpPlugin.java @@ -0,0 +1,502 @@ +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!"); + } + } + } +} \ No newline at end of file