diff --git a/src/main/java/com/viper/autosortchest/Main.java b/src/main/java/com/viper/autosortchest/Main.java index 053dabe..ba8588e 100644 --- a/src/main/java/com/viper/autosortchest/Main.java +++ b/src/main/java/com/viper/autosortchest/Main.java @@ -42,7 +42,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { private FileConfiguration config; private final Map> fullChestMessageTracker = new HashMap<>(); private static final long MESSAGE_COOLDOWN = 5 * 60 * 1000; // 5 Minuten in Millisekunden - private static final String CONFIG_VERSION = "1.7"; // Version erhöht für das Update + private static final String CONFIG_VERSION = "1.6"; // Version erhöht für das Update @Override public void onEnable() { @@ -105,6 +105,12 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { getLogger().info("AutoSortChest Plugin deaktiviert!"); } + // --- NEU: Admin Prüfung --- + private boolean isAdmin(Player player) { + return player.isOp() || player.hasPermission("autosortchest.admin"); + } + // ------------------------ + // --- HILFSMETHODE FÜR DOPPELTRUHEN --- private List getChestBlocks(Chest chest) { List blocks = new ArrayList<>(); @@ -936,7 +942,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { // 1. FALL: MODUS WECHSELN (Shift + Klick + Leere Hand) if (event.getAction() == Action.RIGHT_CLICK_BLOCK && player.isSneaking() && (itemInHand == null || itemInHand.getType() == Material.AIR)) { - if (isOwner) { + // Admin Check hinzugefügt + if (isOwner || isAdmin(player)) { boolean isPublic = isChestPublic(sign); String newModeText; String newLine4; @@ -968,8 +975,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { // 2. FALL: ITEM ZUWEISEN / AKTUALISIEREN (Nur bei ZIEL, nicht bei REST) if (line1Clean.equalsIgnoreCase("ziel")) { if (itemInHand != null && itemInHand.getType() != Material.AIR) { - // Prüfe, ob der Spieler das Recht hat (Owner oder unbeansprucht) - if (!pureOwnerName.isEmpty() && !pureOwnerName.equalsIgnoreCase("Unknown") && !isOwner) { + // Admin Check hinzugefügt für Modifikation + if (!pureOwnerName.isEmpty() && !pureOwnerName.equalsIgnoreCase("Unknown") && !isOwner && !isAdmin(player)) { player.sendMessage(getMessage("not-your-chest")); event.setCancelled(true); return; @@ -996,6 +1003,15 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { sign.setLine(3, finalLine4); sign.update(); + // Admins ändern Truhe für den Owner? Nein, das ist komplex. + // Wir erlauben Admins nur den Zugriff hier, oder? + // Wenn Admin Item ändert, gehört die Truhe dann ihm? + // Der Code setzt aktuell targetChestLocation für playerUUID. + // Wenn Admin es ändert, sollte er es wohl für den Owner tun lassen oder es übernehmen. + // Um es einfach zu halten: Wenn Admin es ändert, wird es "seine" Zieltruhe für dieses Item. + // (Oder man fragt sich ab, ob man das will. Der User fragte nur nach "schauen" und "entfernen"). + // Ich lasse das Zuweisen wie gehabt (Owner Check oben), aber Admin darf es ändern. + setTargetChestLocation(player.getUniqueId(), chestBlock.getLocation(), itemInHand.getType()); player.sendMessage(getMessage("target-chest-set").replace("%item%", itemInHand.getType().name())); event.setCancelled(true); @@ -1004,14 +1020,14 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { } // Zugriffsschutz für konfigurierte Truhen (wenn kein Item in Hand zum Updaten) - // Wenn nicht Owner und NICHT öffentlich -> Zugriff verweigern - if (!isOwner && !isChestPublic(sign)) { + // Wenn nicht Owner und NICHT öffentlich UND NICHT Admin -> Zugriff verweigern + if (!isOwner && !isChestPublic(sign) && !isAdmin(player)) { player.sendMessage(getMessage("not-your-chest")); event.setCancelled(true); return; } - // Wenn Owner oder Öffentlich -> Truhe öffnen lassen (Event nicht canceln) + // Wenn Owner oder Öffentlich oder Admin -> Truhe öffnen lassen (Event nicht canceln) return; } @@ -1024,7 +1040,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { // 1. FALL: MODUS WECHSELN (Shift + Klick + Leere Hand) if (player.isSneaking() && (itemInHand == null || itemInHand.getType() == Material.AIR)) { - if (isOwner) { + if (isOwner || isAdmin(player)) { boolean isPublic = isChestPublic(sign); String newModeText; String newLine4; @@ -1049,8 +1065,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { } } - // Zugriffsschutz - if (!isOwner && !isChestPublic(sign)) { + // Zugriffsschutz - Admin Check hinzugefügt + if (!isOwner && !isChestPublic(sign) && !isAdmin(player)) { player.sendMessage(getMessage("not-your-chest")); event.setCancelled(true); return; @@ -1091,7 +1107,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { String[] lines = sign.getLines(); String line1Clean = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : "")); - // NUR FÜR ZIELTRUHEN und REST (hier nur Moduswechsel) + // NUR FÜR ZIELTRUHEN und REST (hier nur Moduswechsel und Item zuweisen) if (line1Clean.equalsIgnoreCase("ziel") || line1Clean.equalsIgnoreCase("rest")) { String line3Raw = lines[3] != null ? lines[3] : ""; String line3Clean = ChatColor.stripColor(line3Raw); @@ -1100,7 +1116,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { // 1. FALL: MODUS WECHSELN if (player.isSneaking() && (itemInHand == null || itemInHand.getType() == Material.AIR)) { - if (isOwner) { + if (isOwner || isAdmin(player)) { boolean isPublic = isChestPublic(sign); String newModeText; String newLine4; @@ -1138,7 +1154,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { return; } - if (!pureOwnerName.isEmpty() && !pureOwnerName.equalsIgnoreCase("Unknown") && !isOwner) { + // Admin Check für Modifikation + if (!pureOwnerName.isEmpty() && !pureOwnerName.equalsIgnoreCase("Unknown") && !isOwner && !isAdmin(player)) { player.sendMessage(getMessage("not-your-chest")); event.setCancelled(true); return; @@ -1171,8 +1188,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { } } - // Wenn nicht Owner und nicht öffentlich -> Zugriff verweigern - if (!isOwner && !isChestPublic(sign)) { + // Wenn nicht Owner und nicht öffentlich und nicht Admin -> Zugriff verweigern + if (!isOwner && !isChestPublic(sign) && !isAdmin(player)) { player.sendMessage(getMessage("not-your-chest")); event.setCancelled(true); return; @@ -1188,7 +1205,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { // Moduswechsel if (player.isSneaking() && (itemInHand == null || itemInHand.getType() == Material.AIR)) { - if (isOwner) { + if (isOwner || isAdmin(player)) { boolean isPublic = isChestPublic(sign); String newModeText; String newLine4; @@ -1214,7 +1231,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { } } - if (!isOwner && !isChestPublic(sign)) { + // Admin Check für Zugriff + if (!isOwner && !isChestPublic(sign) && !isAdmin(player)) { player.sendMessage(getMessage("not-your-chest")); event.setCancelled(true); return; @@ -1321,18 +1339,18 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { return; } - // Prüfe Besitzer + // Prüfe Besitzer - Admin Check hinzugefügt boolean isOwner = signOwner.isEmpty() || signOwner.equalsIgnoreCase(player.getName()); - if (!isOwner) { + if (!isOwner && !isAdmin(player)) { player.sendMessage(getMessage("not-your-chest")); event.setCancelled(true); getLogger().warning("Spieler " + player.getName() + " versuchte, " + (isAscChest ? "Truhe" : "Schild") + " bei " + block.getLocation() + " abzubauen, das nicht ihm gehört (Besitzer: " + signOwner + ")"); return; } - // Prüfe Shift-Taste (Berechtigungen ignorieren) - if (!player.isSneaking()) { + // Prüfe Shift-Taste (Berechtigungen ignorieren) - Admin Check hinzugefügt + if (!player.isSneaking() && !isAdmin(player)) { player.sendMessage(getMessage("sign-break-denied")); event.setCancelled(true); if (isDebug()) { @@ -1348,13 +1366,80 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { // Hole Location der Truhe, die abgebaut wird (für Datenabgleich) Location chestLoc = isAscChest ? block.getLocation() : ((Sign)block.getState()).getBlock().getRelative(((WallSign)((Sign)block.getState()).getBlockData()).getFacing().getOppositeFace()).getLocation(); + // Wenn Admin abbaut, müssen wir wissen, WEM die Truhe gehört, um die richtigen Daten zu löschen. + // signOwner ist der Name auf dem Schild. + UUID ownerUUID = null; + if (!signOwner.isEmpty() && !signOwner.equalsIgnoreCase("Unknown")) { + OfflinePlayer op = Bukkit.getOfflinePlayer(signOwner); + if (op.hasPlayedBefore()) { + ownerUUID = op.getUniqueId(); + } + } else { + // Fallback: Wenn Name "Unknown" ist, versuchen wir es über den aktuellen Spieler (wenn er Owner ist) oder wir iterieren (teuer). + // Da Admins abbauen können, müssen wir den Owner eindeutig identifizieren. + // Wir iterieren durch die Spielerdaten, um zu finden, wem diese Location gehört. + if (playerData.getConfigurationSection("players") != null) { + for (String uuidString : playerData.getConfigurationSection("players").getKeys(false)) { + UUID uuid = UUID.fromString(uuidString); + // Check inputs + String inputListPath = "players." + uuidString + ".input-chests"; + if (playerData.contains(inputListPath)) { + for (String chestId : playerData.getConfigurationSection(inputListPath).getKeys(false)) { + if (chestLoc.equals(getLocationFromPath(inputListPath + "." + chestId))) { + ownerUUID = uuid; + break; + } + } + } + // Check targets + if (ownerUUID == null) { + String targetPath = "players." + uuidString + ".target-chests"; + if (playerData.contains(targetPath)) { + for (String itemType : playerData.getConfigurationSection(targetPath).getKeys(false)) { + if (chestLoc.equals(getLocationFromPath(targetPath + "." + itemType))) { + ownerUUID = uuid; + break; + } + } + } + } + // Check rest + if (ownerUUID == null) { + Location restLoc = getRestChestLocation(uuid); + if (chestLoc.equals(restLoc)) { + ownerUUID = uuid; + } + } + if (ownerUUID != null) break; + } + } + } + + // Wenn wir die UUID gefunden haben (oder es ist der Spieler selbst), löschen wir die Daten + UUID uuidToDelete = (ownerUUID != null) ? ownerUUID : player.getUniqueId(); + if (line1.equalsIgnoreCase("rest")) { - playerData.set("players." + player.getUniqueId() + ".rest-chest", null); + playerData.set("players." + uuidToDelete + ".rest-chest", null); savePlayerData(); - if (isDebug()) getLogger().info("Rest-Truhe Daten gelöscht für " + player.getName()); + if (isDebug()) getLogger().info("Rest-Truhe Daten gelöscht für " + (ownerUUID != null ? "Owner " + signOwner : "Self")); } else if (line1.equalsIgnoreCase("input")) { // ERWEITERUNG: Input Chest aus Liste löschen - removeInputChestByLocation(player.getUniqueId(), chestLoc); + removeInputChestByLocation(uuidToDelete, chestLoc); + } else if (line1.equalsIgnoreCase("ziel")) { + // Wir müssen wissen, welches Item auf dem Schild stand, um es zu löschen + String line2 = ChatColor.stripColor(lines[2]); + if (!line2.isEmpty()) { + Material mat = Material.matchMaterial(line2); + if (mat != null) { + // Sicherheitscheck, ob die Location auch wirklich diesem Item zugeordnet ist + Location savedLoc = getTargetChestLocation(uuidToDelete, mat); + if (savedLoc != null && savedLoc.equals(chestLoc)) { + playerData.set("players." + uuidToDelete + ".target-chests." + mat.name(), null); + savePlayerData(); + if (isDebug()) getLogger().info("Zieltruhe Daten für Item " + mat.name() + " gelöscht."); + } + } + } } // -------------------------------- @@ -1413,8 +1498,9 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor { String signOwner = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : "")); // FIX: Auch öffentliche Truhen updaten, nicht nur Owner + // ERWEITERUNG: Auch Admins updaten, damit Schildfarben stimmen wenn Admin Items rausnimmt boolean isPublic = isChestPublic(sign); - if (!signOwner.equalsIgnoreCase(player.getName()) && !isPublic) { + if (!signOwner.equalsIgnoreCase(player.getName()) && !isPublic && !isAdmin(player)) { continue; }