10 Commits
1.5 ... 1.8

4 changed files with 493 additions and 304 deletions

View File

@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.viper</groupId>
<artifactId>AutoSortChest</artifactId>
<version>1.5</version>
<version>1.8</version>
<name>AutoSortChest</name>
<repositories>

View File

@@ -1,9 +1,14 @@
package com.viper.autosortchest;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.Chest;
import org.bukkit.block.DoubleChest;
import org.bukkit.block.Sign;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.command.Command;
@@ -20,12 +25,10 @@ import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import java.io.File;
import java.io.IOException;
@@ -39,7 +42,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
private FileConfiguration config;
private final Map<UUID, Map<Material, Long>> fullChestMessageTracker = new HashMap<>();
private static final long MESSAGE_COOLDOWN = 5 * 60 * 1000; // 5 Minuten in Millisekunden
private static final String CONFIG_VERSION = "1.5";
private static final String CONFIG_VERSION = "1.7"; // Version erhöht für das Update
@Override
public void onEnable() {
@@ -80,6 +83,9 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
updateConfig();
updateExistingSigns();
// ERWEITERUNG: Migration alter Daten in das neue Listen-System
migrateInputChests();
// ASCII ART LOGO
getLogger().info("");
getLogger().info(" ___ _ _____ _ _____ _ _ ");
@@ -99,6 +105,27 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
getLogger().info("AutoSortChest Plugin deaktiviert!");
}
// --- HILFSMETHODE FÜR DOPPELTRUHEN ---
private List<Block> getChestBlocks(Chest chest) {
List<Block> blocks = new ArrayList<>();
InventoryHolder holder = chest.getInventory().getHolder();
if (holder instanceof DoubleChest) {
DoubleChest doubleChest = (DoubleChest) holder;
// Finde beide Blöcke der Doppeltruhe
if (doubleChest.getLeftSide() instanceof Chest) {
blocks.add(((Chest) doubleChest.getLeftSide()).getBlock());
}
if (doubleChest.getRightSide() instanceof Chest) {
blocks.add(((Chest) doubleChest.getRightSide()).getBlock());
}
} else if (holder instanceof Chest) {
blocks.add(chest.getBlock());
}
return blocks;
}
// -----------------------------------------
private void savePlayerData() {
if (playerData == null || playerDataFile == null) {
getLogger().warning("Kann players.yml nicht speichern: playerData oder playerDataFile ist null");
@@ -393,6 +420,55 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
}
}
// --- ERWEITERUNG: Hilfsmethode zum Laden von Location aus einem beliebigen Pfad ---
private Location getLocationFromPath(String path) {
String worldName = playerData.getString(path + ".world");
World world = getServer().getWorld(worldName);
if (world == null) return null;
int x = playerData.getInt(path + ".x");
int y = playerData.getInt(path + ".y");
int z = playerData.getInt(path + ".z");
return new Location(world, x, y, z);
}
// -----------------------------------------------------------------------
// --- ERWEITERUNG: Methode zum Migrieren alter Daten ---
private void migrateInputChests() {
if (playerData.getConfigurationSection("players") == null) return;
boolean migrated = false;
for (String uuidString : playerData.getConfigurationSection("players").getKeys(false)) {
String oldPath = "players." + uuidString + ".input-chest";
// Prüfen, ob der alte Eintrag existiert
if (playerData.contains(oldPath)) {
try {
UUID uuid = UUID.fromString(uuidString);
String world = playerData.getString(oldPath + ".world");
int x = playerData.getInt(oldPath + ".x");
int y = playerData.getInt(oldPath + ".y");
int z = playerData.getInt(oldPath + ".z");
World w = Bukkit.getWorld(world);
if (w != null) {
Location loc = new Location(w, x, y, z);
// Neue Methode aufrufen, die in die Liste speichert
addInputChestLocation(uuid, loc);
// Alten Eintrag löschen
playerData.set(oldPath, null);
migrated = true;
getLogger().info("Eingangstruhe für Spieler " + uuidString + " in neues System migriert.");
}
} catch (IllegalArgumentException e) {
getLogger().warning("Ungültige UUID beim Migrieren: " + uuidString);
}
}
}
if (migrated) {
savePlayerData();
}
}
// -----------------------------------------------------------------------
private void updateExistingSigns() {
if (playerData == null) {
getLogger().warning("playerData ist null. Kann bestehende Schilder nicht aktualisieren.");
@@ -412,35 +488,38 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
continue;
}
String path = "players." + uuidString;
String basePath = "players." + uuidString;
// Eingangstruhe
String inputPath = path + ".input-chest";
if (playerData.contains(inputPath)) {
String worldName = playerData.getString(inputPath + ".world");
World world = getServer().getWorld(worldName);
if (world == null) {
getLogger().warning("Welt " + worldName + " für Eingangstruhe von Spieler UUID " + uuidString + " nicht gefunden");
continue;
// --- ERWEITERUNG: Eingangstruhe (Jetzt Liste) ---
String inputListPath = basePath + ".input-chests";
// Fallback für altes Format (sollte durch Migration eigentlich weg sein, aber zur Sicherheit)
String oldInputPath = basePath + ".input-chest";
List<Location> inputLocs = new ArrayList<>();
if (playerData.contains(inputListPath)) {
for (String chestId : playerData.getConfigurationSection(inputListPath).getKeys(false)) {
Location loc = getLocationFromPath(inputListPath + "." + chestId);
if (loc != null) inputLocs.add(loc);
}
int x = playerData.getInt(inputPath + ".x");
int y = playerData.getInt(inputPath + ".y");
int z = playerData.getInt(inputPath + ".z");
Location chestLocation = new Location(world, x, y, z);
} else if (playerData.contains(oldInputPath)) {
Location loc = getLocationFromPath(oldInputPath);
if (loc != null) inputLocs.add(loc);
}
for (Location chestLocation : inputLocs) {
Block chestBlock = chestLocation.getBlock();
if (!(chestBlock.getState() instanceof Chest)) continue;
if (!(chestBlock.getState() instanceof Chest)) {
getLogger().warning("Eingangstruhe bei " + chestLocation + " ist keine Truhe");
continue;
}
List<Block> blocks = getChestBlocks((Chest) chestBlock.getState());
for (Block b : blocks) {
for (Block face : new Block[] {
chestBlock.getRelative(1, 0, 0),
chestBlock.getRelative(-1, 0, 0),
chestBlock.getRelative(0, 0, 1),
chestBlock.getRelative(0, 0, -1)
b.getRelative(1, 0, 0),
b.getRelative(-1, 0, 0),
b.getRelative(0, 0, 1),
b.getRelative(0, 0, -1)
}) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chestBlock)) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, b)) {
String[] lines = sign.getLines();
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
@@ -457,22 +536,17 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
}
}
}
}
// ----------------------------------------------
// Zieltruhen
String targetPath = path + ".target-chests";
String targetPath = basePath + ".target-chests";
if (playerData.contains(targetPath)) {
for (String itemType : playerData.getConfigurationSection(targetPath).getKeys(false)) {
String targetChestPath = targetPath + "." + itemType;
String worldName = playerData.getString(targetChestPath + ".world");
World world = getServer().getWorld(worldName);
if (world == null) {
getLogger().warning("Welt " + worldName + " für Zieltruhe von Item " + itemType + " nicht gefunden");
continue;
}
int x = playerData.getInt(targetChestPath + ".x");
int y = playerData.getInt(targetChestPath + ".y");
int z = playerData.getInt(targetChestPath + ".z");
Location chestLocation = new Location(world, x, y, z);
Location chestLocation = getLocationFromPath(targetChestPath);
if (chestLocation == null) continue;
Block chestBlock = chestLocation.getBlock();
if (!(chestBlock.getState() instanceof Chest)) {
@@ -484,13 +558,15 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
Inventory inventory = chest.getInventory();
boolean isFull = isInventoryFull(inventory);
List<Block> blocks = getChestBlocks(chest);
for (Block b : blocks) {
for (Block face : new Block[] {
chestBlock.getRelative(1, 0, 0),
chestBlock.getRelative(-1, 0, 0),
chestBlock.getRelative(0, 0, 1),
chestBlock.getRelative(0, 0, -1)
b.getRelative(1, 0, 0),
b.getRelative(-1, 0, 0),
b.getRelative(0, 0, 1),
b.getRelative(0, 0, -1)
}) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chestBlock)) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, b)) {
String[] lines = sign.getLines();
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
@@ -511,20 +587,14 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
}
}
}
}
// --- NEU: Rest-Truhe aktualisieren ---
String restPath = path + ".rest-chest";
String restPath = basePath + ".rest-chest";
if (playerData.contains(restPath)) {
String worldName = playerData.getString(restPath + ".world");
World world = getServer().getWorld(worldName);
if (world == null) {
getLogger().warning("Welt " + worldName + " für Rest-Truhe von UUID " + uuidString + " nicht gefunden");
continue;
}
int x = playerData.getInt(restPath + ".x");
int y = playerData.getInt(restPath + ".y");
int z = playerData.getInt(restPath + ".z");
Location chestLocation = new Location(world, x, y, z);
Location chestLocation = getLocationFromPath(restPath);
if (chestLocation == null) continue;
Block chestBlock = chestLocation.getBlock();
if (!(chestBlock.getState() instanceof Chest)) {
@@ -536,13 +606,15 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
Inventory inventory = chest.getInventory();
boolean isFull = isInventoryFull(inventory);
List<Block> blocks = getChestBlocks(chest);
for (Block b : blocks) {
for (Block face : new Block[] {
chestBlock.getRelative(1, 0, 0),
chestBlock.getRelative(-1, 0, 0),
chestBlock.getRelative(0, 0, 1),
chestBlock.getRelative(0, 0, -1)
b.getRelative(1, 0, 0),
b.getRelative(-1, 0, 0),
b.getRelative(0, 0, 1),
b.getRelative(0, 0, -1)
}) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chestBlock)) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, b)) {
String[] lines = sign.getLines();
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
@@ -560,6 +632,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
}
}
}
}
// -------------------------------
}
}
@@ -613,8 +686,12 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
return attached;
}
private void setInputChestLocation(UUID playerUUID, Location location) {
String path = "players." + playerUUID + ".input-chest";
// --- ERWEITERUNG: Methode zum Hinzufügen einer Input Chest (Liste) ---
private void addInputChestLocation(UUID playerUUID, Location location) {
String basePath = "players." + playerUUID + ".input-chests";
String id = UUID.randomUUID().toString(); // Eindeutige ID für jede Truhe
String path = basePath + "." + id;
playerData.set(path + ".world", location.getWorld().getName());
playerData.set(path + ".x", location.getBlockX());
playerData.set(path + ".y", location.getBlockY());
@@ -622,6 +699,12 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
savePlayerData();
}
// Original-Methode als Wrapper beibehalten (damit onSignChange nicht geändert werden muss)
private void setInputChestLocation(UUID playerUUID, Location location) {
addInputChestLocation(playerUUID, location);
}
// -----------------------------------------------------------------
private void setTargetChestLocation(UUID playerUUID, Location location, Material itemType) {
String path = "players." + playerUUID + ".target-chests." + itemType.name();
playerData.set(path + ".world", location.getWorld().getName());
@@ -737,6 +820,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
loadPlayerData();
updateConfig();
updateExistingSigns();
migrateInputChests(); // ERWEITERUNG: Migration erneut aufrufen
player.sendMessage(getMessage("reload-success"));
getLogger().info("Konfiguration und Spielerdaten neu geladen durch " + player.getName());
return true;
@@ -747,7 +831,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
return true;
}
@EventHandler
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) // <- Geändert: Priorität erhöht und Cancel ignoriert
public void onSignChange(SignChangeEvent event) {
Player player = event.getPlayer();
UUID playerUUID = player.getUniqueId();
@@ -756,6 +840,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
// --- NEU: Sign Change für Rest-Truhe ---
if (lines.length >= 2 && lines[0].equalsIgnoreCase("[asc]") && lines[1].equalsIgnoreCase("rest")) {
event.setCancelled(false); // <- HIER: WorldGuard Cancel rückgängig machen
Block chestBlock = null;
if (signBlock.getBlockData() instanceof WallSign wallSign) {
Block attachedBlock = signBlock.getRelative(wallSign.getFacing().getOppositeFace());
@@ -776,11 +862,13 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
setRestChestLocation(playerUUID, chestBlock.getLocation());
player.sendMessage(getMessage("rest-chest-set"));
getLogger().info("Rest-Truhe für " + player.getName() + " gesetzt bei " + chestBlock.getLocation());
return; // Wichtig, damit nicht input/target Logik auch greift
return;
}
// -------------------------------
if (lines.length >= 2 && lines[0].equalsIgnoreCase("[asc]") && lines[1].equalsIgnoreCase("input")) {
event.setCancelled(false); // <- HIER: WorldGuard Cancel rückgängig machen
Block chestBlock = null;
if (signBlock.getBlockData() instanceof WallSign wallSign) {
Block attachedBlock = signBlock.getRelative(wallSign.getFacing().getOppositeFace());
@@ -798,7 +886,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
event.setLine(0, getSignColor("input", "line1") + "[asc]");
event.setLine(1, getSignColor("input", "line2") + "input");
event.setLine(3, getSignColor("input", "line4") + player.getName());
setInputChestLocation(playerUUID, chestBlock.getLocation());
setInputChestLocation(playerUUID, chestBlock.getLocation()); // Ruft nun addInputChestLocation auf
player.sendMessage(getMessage("input-chest-set"));
getLogger().info("Eingangstruhe für " + player.getName() + " gesetzt bei " + chestBlock.getLocation());
}
@@ -977,18 +1065,23 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
Block chestBlock = clickedBlock;
Block signBlock = null;
// Suche Schild
// Suche Schild an beiden Hälften falls Doppeltruhe
List<Block> blocks = getChestBlocks((Chest) chestBlock.getState());
outerLoop:
for (Block b : blocks) {
for (Block face : new Block[] {
chestBlock.getRelative(1, 0, 0),
chestBlock.getRelative(-1, 0, 0),
chestBlock.getRelative(0, 0, 1),
chestBlock.getRelative(0, 0, -1)
b.getRelative(1, 0, 0),
b.getRelative(-1, 0, 0),
b.getRelative(0, 0, 1),
b.getRelative(0, 0, -1)
}) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chestBlock)) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, b)) {
String[] lines = sign.getLines();
if (lines.length >= 2 && ChatColor.stripColor((String) (lines[0] != null ? lines[0] : "")).equalsIgnoreCase("[asc]")) {
signBlock = face;
break;
break outerLoop; // Schild gefunden
}
}
}
}
@@ -1131,6 +1224,36 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
}
}
// --- ERWEITERUNG: Hilfsmethode zum Entfernen einer Input Chest ---
private void removeInputChestByLocation(UUID uuid, Location loc) {
String basePath = "players." + uuid + ".input-chests";
String oldPath = "players." + uuid + ".input-chest";
// Prüfe neues Listen-Format
if (playerData.contains(basePath)) {
for (String chestId : playerData.getConfigurationSection(basePath).getKeys(false)) {
String path = basePath + "." + chestId;
Location savedLoc = getLocationFromPath(path);
if (savedLoc != null && savedLoc.equals(loc)) {
playerData.set(path, null);
savePlayerData();
if (isDebug()) getLogger().info("Eingangstruhe entfernt bei " + loc);
return;
}
}
}
// Prüfe altes Einzel-Format (Fallback)
if (playerData.contains(oldPath)) {
Location oldLoc = getLocationFromPath(oldPath);
if (oldLoc != null && oldLoc.equals(loc)) {
playerData.set(oldPath, null);
savePlayerData();
}
}
}
// ---------------------------------------------------------------
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockBreak(BlockBreakEvent event) {
Block block = event.getBlock();
@@ -1160,13 +1283,18 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
// Fall 2: Truhe wird abgebaut
if (block.getState() instanceof Chest chestBlock) {
// Prüfe beide Hälften auf Schilder
List<Block> blocks = getChestBlocks(chestBlock);
outerLoop:
for (Block b : blocks) {
for (Block face : new Block[] {
block.getRelative(1, 0, 0),
block.getRelative(-1, 0, 0),
block.getRelative(0, 0, 1),
block.getRelative(0, 0, -1)
b.getRelative(1, 0, 0),
b.getRelative(-1, 0, 0),
b.getRelative(0, 0, 1),
b.getRelative(0, 0, -1)
}) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, block)) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, b)) {
String[] lines = sign.getLines();
if (lines.length >= 2 && ChatColor.stripColor((String) (lines[0] != null ? lines[0] : "")).equalsIgnoreCase("[asc]") &&
(ChatColor.stripColor((String) (lines[1] != null ? lines[1] : "")).equalsIgnoreCase("input") ||
@@ -1178,7 +1306,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
if (isDebug()) {
getLogger().fine("Truhe mit [asc]-Schild erkannt bei " + block.getLocation() + ", Schild bei " + face.getLocation() + ", Besitzer: " + signOwner);
}
break;
break outerLoop;
}
}
}
}
@@ -1215,10 +1344,17 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
// --- Daten bereinigen beim Abbauen ---
String[] lines = ((Sign) (isAscChest ? signBlock.getState() : block.getState())).getLines();
String line1 = ChatColor.stripColor(lines[1]);
// 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();
if (line1.equalsIgnoreCase("rest")) {
playerData.set("players." + player.getUniqueId() + ".rest-chest", null);
savePlayerData();
if (isDebug()) getLogger().info("Rest-Truhe Daten gelöscht für " + player.getName());
} else if (line1.equalsIgnoreCase("input")) {
// ERWEITERUNG: Input Chest aus Liste löschen
removeInputChestByLocation(player.getUniqueId(), chestLoc);
}
// --------------------------------
@@ -1229,9 +1365,23 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
@EventHandler
public void onInventoryClose(InventoryCloseEvent event) {
if (!(event.getInventory().getHolder() instanceof Chest chest)) return;
InventoryHolder holder = event.getInventory().getHolder();
List<Chest> chestsToCheck = new ArrayList<>();
// FIX: Double Chest Handling
if (holder instanceof Chest) {
chestsToCheck.add((Chest) holder);
} else if (holder instanceof DoubleChest) {
DoubleChest dc = (DoubleChest) holder;
if (dc.getLeftSide() instanceof Chest) chestsToCheck.add((Chest) dc.getLeftSide());
if (dc.getRightSide() instanceof Chest) chestsToCheck.add((Chest) dc.getRightSide());
} else {
return;
}
Player player = (Player) event.getPlayer();
for (Chest chest : chestsToCheck) {
Block chestBlock = chest.getBlock();
Block signBlock = null;
String signType = "target"; // default
@@ -1255,16 +1405,17 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
}
if (signBlock == null) {
if (isDebug()) getLogger().fine("Keine Zieltruhe/Rest-Truhe Schild an Truhe bei " + chestBlock.getLocation());
return;
continue;
}
Sign sign = (Sign) signBlock.getState();
String[] lines = sign.getLines();
String signOwner = ChatColor.stripColor((String) (lines[3] != null ? lines[3] : ""));
if (!signOwner.equalsIgnoreCase(player.getName())) {
if (isDebug()) getLogger().fine("Schild bei " + signBlock.getLocation() + " gehört nicht Spieler " + player.getName() + " (Besitzer: " + signOwner + ")");
return;
// FIX: Auch öffentliche Truhen updaten, nicht nur Owner
boolean isPublic = isChestPublic(sign);
if (!signOwner.equalsIgnoreCase(player.getName()) && !isPublic) {
continue;
}
boolean isFull = isInventoryFull(chest.getInventory());
@@ -1288,6 +1439,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
}
}
}
}
// --- HILFSMETHODE zum Entfernen alter Einträge ---
private void removeOldTargetEntry(UUID uuid, Location loc, String newItemType) {
@@ -1372,14 +1524,18 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
String signOwner = "Unbekannt";
Block signBlock = null;
// Sign Check erlaubt sowohl "ziel" als auch "rest"
// Sign Check erlaubt sowohl "ziel" als auch "rest" und prüft beide Hälften bei Doppeltruhen
List<Block> chestBlocks = getChestBlocks(targetChest);
outerLoop:
for (Block b : chestBlocks) {
for (Block face : new Block[] {
targetChest.getBlock().getRelative(1, 0, 0),
targetChest.getBlock().getRelative(-1, 0, 0),
targetChest.getBlock().getRelative(0, 0, 1),
targetChest.getBlock().getRelative(0, 0, -1)
b.getRelative(1, 0, 0),
b.getRelative(-1, 0, 0),
b.getRelative(0, 0, 1),
b.getRelative(0, 0, -1)
}) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, targetChest.getBlock())) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, b)) {
String[] lines = sign.getLines();
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
@@ -1399,13 +1555,14 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
if (isDebug()) {
getLogger().fine("Gültiges Zieltruhe-Schild gefunden bei " + face.getLocation() + " für Spieler " + player.getName());
}
break;
break outerLoop;
}
} else if (isDebug()) {
getLogger().fine("Zieltruhe-Schild bei " + face.getLocation() + " hat ungültige Zeilen oder Typ passt nicht: [asc]=" + line0 + ", typ=" + line1);
}
}
}
}
if (!isValidTarget) {
if (canSendFullChestMessage(playerUUID, item.getType())) {
@@ -1484,41 +1641,67 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
continue;
}
String path = "players." + uuidString + ".input-chest";
if (!playerData.contains(path)) continue;
// --- ERWEITERUNG: Eingangstruhe (Jetzt Liste) ---
String inputListPath = "players." + uuidString + ".input-chests";
// Fallback für altes Format (falls Migration noch nicht lief oder Fehler)
String oldInputPath = "players." + uuidString + ".input-chest";
String worldName = playerData.getString(path + ".world");
World world = getServer().getWorld(worldName);
if (world == null) {
getLogger().warning("Welt " + worldName + " für Eingangstruhe von UUID " + uuidString + " nicht gefunden");
continue;
}
List<String> chestsToCheck = new ArrayList<>();
int x = playerData.getInt(path + ".x");
int y = playerData.getInt(path + ".y");
int z = playerData.getInt(path + ".z");
Location location = new Location(world, x, y, z);
if (!(location.getBlock().getState() instanceof Chest)) {
if (isDebug()) {
getLogger().fine("Eingangstruhe bei " + location + " existiert nicht");
if (playerData.contains(inputListPath)) {
chestsToCheck.addAll(playerData.getConfigurationSection(inputListPath).getKeys(false));
} else if (playerData.contains(oldInputPath)) {
// Hier führen wir keine Migration durch (nur lesen), da das im laufenden Betrieb zu Problemen führen könnte.
// Wir markieren es für den Task, damit es bei下一次 Update erledigt wird.
Location loc = getLocationFromPath(oldInputPath);
if (loc != null) {
checkSingleInputChest(ownerUUID, loc, "legacy");
}
continue;
}
if (chestsToCheck.isEmpty()) continue;
for (String chestId : chestsToCheck) {
String path = inputListPath + "." + chestId;
Location loc = getLocationFromPath(path);
if (loc == null) {
playerData.set(path, null); // Ungültigen Eintrag löschen
continue;
}
boolean stillValid = checkSingleInputChest(ownerUUID, loc, chestId);
if (!stillValid) {
playerData.set(path, null);
savePlayerData();
}
}
// -------------------------------------------------
}
}
// --- ERWEITERUNG: Hilfsmethode zum Prüfen einzelner Eingangstruhe ---
private boolean checkSingleInputChest(UUID ownerUUID, Location location, String debugId) {
if (!(location.getBlock().getState() instanceof Chest)) return false;
Chest chest = (Chest) location.getBlock().getState();
Block inputSignBlock = null;
boolean isPublic = false;
String ownerName = "Unknown";
// Schild suchen und Status prüfen
// FIX: Suche Schild an beiden Hälften bei Doppeltruhen
List<Block> chestBlocks = getChestBlocks(chest);
outerLoop:
for (Block b : chestBlocks) {
for (Block face : new Block[] {
chest.getBlock().getRelative(1, 0, 0),
chest.getBlock().getRelative(-1, 0, 0),
chest.getBlock().getRelative(0, 0, 1),
chest.getBlock().getRelative(0, 0, -1)
b.getRelative(1, 0, 0),
b.getRelative(-1, 0, 0),
b.getRelative(0, 0, 1),
b.getRelative(0, 0, -1)
}) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, chest.getBlock())) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, b)) {
String[] lines = sign.getLines();
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
@@ -1530,14 +1713,15 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
isPublic = line3Clean.toLowerCase().endsWith("[public]");
ownerName = line3Clean.replace(" [Public]", "").replace(" [public]", "").trim();
break;
break outerLoop;
}
}
}
}
if (inputSignBlock == null) {
if (isDebug()) getLogger().fine("Kein Eingangsschild an Truhe bei " + location);
continue;
if (isDebug()) getLogger().fine("Kein Eingangsschild an Truhe " + debugId);
return false;
}
// Wenn das Inventar leer ist, brauchen wir nichts tun
@@ -1548,7 +1732,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
break;
}
}
if (!hasItems) continue;
if (!hasItems) return true;
// Jetzt kommt der entscheidende Teil für die Multiplayer-Funktionalität:
// Wenn PRIVATE: Nur sortieren, wenn der Owner ONLINE ist.
@@ -1560,7 +1744,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
if (!isPublic) {
// Privat: Nur wenn Owner online
if (ownerPlayer == null || !ownerPlayer.isOnline()) continue;
if (ownerPlayer == null || !ownerPlayer.isOnline()) return true;
} else {
// Öffentlich: Wenn Owner offline, können wir keine "Truhe voll" Nachrichten an den Owner senden.
// Wir sortieren trotzdem.
@@ -1571,16 +1755,13 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
}
// Wir rufen distributeItemsForOwner auf.
// WICHTIG: distributeItemsForOwner nutzt `player.getUniqueId()` um die Zieltruhen zu finden.
// Das funktioniert auch, wenn ownerPlayer null ist, solange wir die UUID übergeben.
// Wir müssen aber aufpassen, dass `distributeItemsForOwner` nicht crasht, wenn player null ist.
distributeItemsForOwner(ownerUUID, ownerPlayer, chest.getInventory());
}
distributeItemsForOwner(ownerUUID, ownerPlayer, chest.getInventory(), ownerName);
return true;
}
// ----------------------------------------------------------------------
// 4. KORRIGIERTE distributeItemsForOwner Methode:
private void distributeItemsForOwner(UUID ownerUUID, Player ownerPlayer, Inventory sourceInventory) {
private void distributeItemsForOwner(UUID ownerUUID, Player ownerPlayer, Inventory sourceInventory, String ownerNameOverride) {
boolean hasItems = false;
for (ItemStack item : sourceInventory.getContents()) {
if (item != null && item.getType() != Material.AIR) {
@@ -1592,7 +1773,9 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
// Owner-Name ermitteln
String ownerName = "Unknown";
if (ownerPlayer != null) {
if (ownerNameOverride != null && !ownerNameOverride.isEmpty()) {
ownerName = ownerNameOverride;
} else if (ownerPlayer != null) {
ownerName = ownerPlayer.getName();
} else {
// Offline-Namen aus PlayerData holen wenn möglich
@@ -1642,13 +1825,18 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
boolean isValidTarget = false;
Block signBlock = null;
// FIX: Suche Schild an beiden Hälften
List<Block> chestBlocks = getChestBlocks(targetChest);
outerLoop:
for (Block b : chestBlocks) {
for (Block face : new Block[] {
targetChest.getBlock().getRelative(1, 0, 0),
targetChest.getBlock().getRelative(-1, 0, 0),
targetChest.getBlock().getRelative(0, 0, 1),
targetChest.getBlock().getRelative(0, 0, -1)
b.getRelative(1, 0, 0),
b.getRelative(-1, 0, 0),
b.getRelative(0, 0, 1),
b.getRelative(0, 0, -1)
}) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, targetChest.getBlock())) {
if (face.getState() instanceof Sign sign && isSignAttachedToChest(face, b)) {
String[] lines = sign.getLines();
String line0 = ChatColor.stripColor((String) (lines[0] != null ? lines[0] : ""));
String line1 = ChatColor.stripColor((String) (lines[1] != null ? lines[1] : ""));
@@ -1663,7 +1851,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
if (signOwnerName.equalsIgnoreCase(ownerName) || signOwnerName.equalsIgnoreCase("Unknown")) {
isValidTarget = true;
signBlock = face;
break;
break outerLoop;
}
}
}
}

View File

@@ -1,4 +1,4 @@
version: "1.5"
version: "1.6"
debug: false
messages:
no-chest-near-sign: "&cKeine Truhe in der Nähe des Schildes!"

View File

@@ -1,5 +1,5 @@
name: AutoSortChest
version: 1.4
version: 1.8
main: com.viper.autosortchest.Main
api-version: 1.21
authors: [M_Viper]