Update from Git Manager GUI
This commit is contained in:
@@ -222,7 +222,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
private final Map<String, Long> fullChestLocationCache = new HashMap<>();
|
private final Map<String, Long> fullChestLocationCache = new HashMap<>();
|
||||||
private static final long FULL_CHEST_CACHE_DURATION = 10_000L; // 10 Sekunden
|
private static final long FULL_CHEST_CACHE_DURATION = 10_000L; // 10 Sekunden
|
||||||
|
|
||||||
private static final String CONFIG_VERSION = "2.1"; // BungeeCord NEU: 2.0 → 2.1
|
private static final String CONFIG_VERSION = "2.2"; // Multi-Rest: 2.1 → 2.2
|
||||||
|
|
||||||
private boolean updateAvailable = false;
|
private boolean updateAvailable = false;
|
||||||
private String latestVersion = "";
|
private String latestVersion = "";
|
||||||
@@ -343,14 +343,29 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
mysqlManager.setTargetChest(uuidString, item, world, x, y, z, isPublic);
|
mysqlManager.setTargetChest(uuidString, item, world, x, y, z, isPublic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String restPath = "players." + uuidString + ".rest-chest";
|
// BUG FIX: Mehrere Rest-Truhen migrieren (neues Format + Legacy)
|
||||||
if (playerData.contains(restPath)) {
|
String restBasePath = "players." + uuidString + ".rest-chests";
|
||||||
String world = playerData.getString(restPath + ".world");
|
if (playerData.contains(restBasePath)) {
|
||||||
int x = playerData.getInt(restPath + ".x");
|
for (String slotKey : playerData.getConfigurationSection(restBasePath).getKeys(false)) {
|
||||||
int y = playerData.getInt(restPath + ".y");
|
String rPath = restBasePath + "." + slotKey;
|
||||||
int z = playerData.getInt(restPath + ".z");
|
String world = playerData.getString(rPath + ".world");
|
||||||
boolean isPublic = playerData.getBoolean(restPath + ".public", false);
|
int x = playerData.getInt(rPath + ".x");
|
||||||
mysqlManager.setRestChest(uuidString, world, x, y, z, isPublic);
|
int y = playerData.getInt(rPath + ".y");
|
||||||
|
int z = playerData.getInt(rPath + ".z");
|
||||||
|
boolean isPublic = playerData.getBoolean(rPath + ".public", false);
|
||||||
|
mysqlManager.setRestChest(uuidString, world, x, y, z, isPublic);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Legacy: altes single rest-chest Format
|
||||||
|
String restPath = "players." + uuidString + ".rest-chest";
|
||||||
|
if (playerData.contains(restPath)) {
|
||||||
|
String world = playerData.getString(restPath + ".world");
|
||||||
|
int x = playerData.getInt(restPath + ".x");
|
||||||
|
int y = playerData.getInt(restPath + ".y");
|
||||||
|
int z = playerData.getInt(restPath + ".z");
|
||||||
|
boolean isPublic = playerData.getBoolean(restPath + ".public", false);
|
||||||
|
mysqlManager.setRestChest(uuidString, world, x, y, z, isPublic);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getLogger().info("Migration der YAML-Daten nach MySQL abgeschlossen.");
|
getLogger().info("Migration der YAML-Daten nach MySQL abgeschlossen.");
|
||||||
@@ -405,9 +420,11 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
exportData.set(path + ".public", chest.get("public"));
|
exportData.set(path + ".public", chest.get("public"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> restChest = mysqlManager.getRestChest(uuidString);
|
// BUG FIX: Alle Rest-Truhen exportieren
|
||||||
if (restChest != null) {
|
List<Map<String, Object>> restChests = mysqlManager.getRestChests(uuidString);
|
||||||
String path = "players." + uuidString + ".rest-chest";
|
for (Map<String, Object> restChest : restChests) {
|
||||||
|
int restSlot = (int) restChest.get("slot");
|
||||||
|
String path = "players." + uuidString + ".rest-chests." + restSlot;
|
||||||
exportData.set(path + ".world", restChest.get("world"));
|
exportData.set(path + ".world", restChest.get("world"));
|
||||||
exportData.set(path + ".x", restChest.get("x"));
|
exportData.set(path + ".x", restChest.get("x"));
|
||||||
exportData.set(path + ".y", restChest.get("y"));
|
exportData.set(path + ".y", restChest.get("y"));
|
||||||
@@ -689,10 +706,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
if (!config.contains("messages.rest-chest-set")) config.set("messages.rest-chest-set", defaultConfig.getString("messages.rest-chest-set", "&aRest-Truhe (Fallback) erfolgreich gesetzt!"));
|
if (!config.contains("messages.rest-chest-set")) config.set("messages.rest-chest-set", defaultConfig.getString("messages.rest-chest-set", "&aRest-Truhe (Fallback) erfolgreich gesetzt!"));
|
||||||
if (!config.contains("messages.target-chest-missing")) config.set("messages.target-chest-missing", defaultConfig.getString("messages.target-chest-missing", "&cZieltruhe für %item% fehlt!"));
|
if (!config.contains("messages.target-chest-missing")) config.set("messages.target-chest-missing", defaultConfig.getString("messages.target-chest-missing", "&cZieltruhe für %item% fehlt!"));
|
||||||
|
|
||||||
String targetChestFull = config.getString("messages.target-chest-full", "");
|
if (!config.contains("messages.target-chest-full")) {
|
||||||
String defaultTargetChestFull = defaultConfig.getString("messages.target-chest-full", "&cZieltruhe für %item% ist voll! Koordinaten: (%x%, %y%, %z%)");
|
config.set("messages.target-chest-full", defaultConfig.getString("messages.target-chest-full", "&cZieltruhe für %item% ist voll! Koordinaten: (%x%, %y%, %z%)"));
|
||||||
if (!config.contains("messages.target-chest-full") || !targetChestFull.equals(defaultTargetChestFull)) {
|
|
||||||
config.set("messages.target-chest-full", defaultTargetChestFull);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.contains("messages.mode-changed")) config.set("messages.mode-changed", defaultConfig.getString("messages.mode-changed", "&aModus gewechselt: &e%mode%"));
|
if (!config.contains("messages.mode-changed")) config.set("messages.mode-changed", defaultConfig.getString("messages.mode-changed", "&aModus gewechselt: &e%mode%"));
|
||||||
@@ -825,9 +840,9 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String restPath = basePath + ".rest-chest";
|
// BUG FIX: Alle Rest-Truhen iterieren (neues Multi-Format + Legacy)
|
||||||
if (playerData.contains(restPath)) {
|
List<Location> restLocations = getRestChestLocations(playerUUID);
|
||||||
Location chestLocation = getLocationFromPath(restPath);
|
for (Location chestLocation : restLocations) {
|
||||||
if (chestLocation == null) continue;
|
if (chestLocation == null) continue;
|
||||||
Block chestBlock = chestLocation.getBlock();
|
Block chestBlock = chestLocation.getBlock();
|
||||||
if (!(chestBlock.getState() instanceof Chest)) continue;
|
if (!(chestBlock.getState() instanceof Chest)) continue;
|
||||||
@@ -928,13 +943,27 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String restPath = "players." + uuid + ".rest-chest";
|
// BUG FIX: Neues Multi-Format für Rest-Truhen
|
||||||
if (playerData.contains(restPath + ".world")) {
|
String restBasePath = "players." + uuid + ".rest-chests";
|
||||||
if (world.equals(playerData.getString(restPath + ".world"))
|
if (playerData.contains(restBasePath)) {
|
||||||
&& x == playerData.getInt(restPath + ".x")
|
for (String slotKey : playerData.getConfigurationSection(restBasePath).getKeys(false)) {
|
||||||
&& y == playerData.getInt(restPath + ".y")
|
String rPath = restBasePath + "." + slotKey;
|
||||||
&& z == playerData.getInt(restPath + ".z")) {
|
if (world.equals(playerData.getString(rPath + ".world"))
|
||||||
if (playerData.getBoolean(restPath + ".public", false)) return true;
|
&& x == playerData.getInt(rPath + ".x")
|
||||||
|
&& y == playerData.getInt(rPath + ".y")
|
||||||
|
&& z == playerData.getInt(rPath + ".z")) {
|
||||||
|
if (playerData.getBoolean(rPath + ".public", false)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Legacy
|
||||||
|
String legacyRestPath = "players." + uuid + ".rest-chest";
|
||||||
|
if (playerData.contains(legacyRestPath + ".world")) {
|
||||||
|
if (world.equals(playerData.getString(legacyRestPath + ".world"))
|
||||||
|
&& x == playerData.getInt(legacyRestPath + ".x")
|
||||||
|
&& y == playerData.getInt(legacyRestPath + ".y")
|
||||||
|
&& z == playerData.getInt(legacyRestPath + ".z")) {
|
||||||
|
if (playerData.getBoolean(legacyRestPath + ".public", false)) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -987,7 +1016,9 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
String chestId = null;
|
String chestId = null;
|
||||||
List<Map<String, Object>> chests = mysqlManager.getInputChests(playerUUID.toString());
|
List<Map<String, Object>> chests = mysqlManager.getInputChests(playerUUID.toString());
|
||||||
for (Map<String, Object> chest : chests) {
|
for (Map<String, Object> chest : chests) {
|
||||||
if (chest.get("world").equals(location.getWorld().getName())
|
String chestWorld = (String) chest.get("world");
|
||||||
|
if (chestWorld == null) continue; // NPE-Schutz: korrupter DB-Eintrag
|
||||||
|
if (chestWorld.equals(location.getWorld().getName())
|
||||||
&& ((int) chest.get("x")) == location.getBlockX()
|
&& ((int) chest.get("x")) == location.getBlockX()
|
||||||
&& ((int) chest.get("y")) == location.getBlockY()
|
&& ((int) chest.get("y")) == location.getBlockY()
|
||||||
&& ((int) chest.get("z")) == location.getBlockZ()) {
|
&& ((int) chest.get("z")) == location.getBlockZ()) {
|
||||||
@@ -1075,13 +1106,34 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
|
|
||||||
private void setRestChestLocation(UUID playerUUID, Location location, boolean isPublic) {
|
private void setRestChestLocation(UUID playerUUID, Location location, boolean isPublic) {
|
||||||
if (mysqlEnabled && mysqlManager != null) {
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
// ── BungeeCord NEU: serverName mitgeben ───────────────────────────
|
// ── BungeeCord + Multi-Rest: serverName und auto-slot ─────────────────
|
||||||
mysqlManager.setRestChest(playerUUID.toString(),
|
mysqlManager.setRestChest(playerUUID.toString(),
|
||||||
location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ(),
|
location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ(),
|
||||||
isPublic, serverName);
|
isPublic, serverName);
|
||||||
mysqlManager.savePlayer(playerUUID.toString(), Bukkit.getOfflinePlayer(playerUUID).getName());
|
mysqlManager.savePlayer(playerUUID.toString(), Bukkit.getOfflinePlayer(playerUUID).getName());
|
||||||
} else {
|
} else {
|
||||||
String path = "players." + playerUUID + ".rest-chest";
|
// YAML: mehrere Rest-Truhen unter rest-chests.<slot>
|
||||||
|
String basePath = "players." + playerUUID + ".rest-chests";
|
||||||
|
// Prüfen ob diese Location schon registriert ist (Update)
|
||||||
|
if (playerData.contains(basePath)) {
|
||||||
|
for (String slotKey : playerData.getConfigurationSection(basePath).getKeys(false)) {
|
||||||
|
String path = basePath + "." + slotKey;
|
||||||
|
if (location.getWorld().getName().equals(playerData.getString(path + ".world"))
|
||||||
|
&& location.getBlockX() == playerData.getInt(path + ".x")
|
||||||
|
&& location.getBlockY() == playerData.getInt(path + ".y")
|
||||||
|
&& location.getBlockZ() == playerData.getInt(path + ".z")) {
|
||||||
|
playerData.set(path + ".public", isPublic);
|
||||||
|
savePlayerData();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Neuen Slot anlegen
|
||||||
|
int nextSlot = 0;
|
||||||
|
if (playerData.contains(basePath)) {
|
||||||
|
nextSlot = playerData.getConfigurationSection(basePath).getKeys(false).size();
|
||||||
|
}
|
||||||
|
String path = basePath + "." + nextSlot;
|
||||||
playerData.set(path + ".world", location.getWorld().getName());
|
playerData.set(path + ".world", location.getWorld().getName());
|
||||||
playerData.set(path + ".x", location.getBlockX());
|
playerData.set(path + ".x", location.getBlockX());
|
||||||
playerData.set(path + ".y", location.getBlockY());
|
playerData.set(path + ".y", location.getBlockY());
|
||||||
@@ -1091,23 +1143,48 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Location getRestChestLocation(UUID playerUUID) {
|
/** Gibt alle Rest-Truhen-Locations zurück (für mehrere Rest-Truhen). */
|
||||||
|
private List<Location> getRestChestLocations(UUID playerUUID) {
|
||||||
|
List<Location> result = new ArrayList<>();
|
||||||
if (mysqlEnabled && mysqlManager != null) {
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
Map<String, Object> map = mysqlManager.getRestChest(playerUUID.toString());
|
List<Map<String, Object>> maps = mysqlManager.getRestChests(playerUUID.toString());
|
||||||
if (map == null) return null;
|
for (Map<String, Object> map : maps) {
|
||||||
// ── BungeeCord NEU: Remote-Truhen nicht lokal auflösen ─────────────
|
if (isRemoteChest(map)) continue;
|
||||||
if (isRemoteChest(map)) return null;
|
World w = Bukkit.getWorld((String) map.get("world"));
|
||||||
World w = Bukkit.getWorld((String) map.get("world"));
|
if (w == null) continue;
|
||||||
if (w == null) return null;
|
result.add(new Location(w, (int) map.get("x"), (int) map.get("y"), (int) map.get("z")));
|
||||||
return new Location(w, (int) map.get("x"), (int) map.get("y"), (int) map.get("z"));
|
}
|
||||||
} else {
|
} else {
|
||||||
String path = "players." + playerUUID + ".rest-chest";
|
// Neues Multi-Format
|
||||||
if (!playerData.contains(path)) return null;
|
String basePath = "players." + playerUUID + ".rest-chests";
|
||||||
String worldName = playerData.getString(path + ".world");
|
if (playerData.contains(basePath)) {
|
||||||
World world = getServer().getWorld(worldName);
|
for (String slotKey : playerData.getConfigurationSection(basePath).getKeys(false)) {
|
||||||
if (world == null) return null;
|
String path = basePath + "." + slotKey;
|
||||||
return new Location(world, playerData.getInt(path + ".x"), playerData.getInt(path + ".y"), playerData.getInt(path + ".z"));
|
String worldName = playerData.getString(path + ".world");
|
||||||
|
World world = getServer().getWorld(worldName);
|
||||||
|
if (world == null) continue;
|
||||||
|
result.add(new Location(world, playerData.getInt(path + ".x"),
|
||||||
|
playerData.getInt(path + ".y"), playerData.getInt(path + ".z")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Legacy-Fallback: altes single rest-chest Format
|
||||||
|
String legacyPath = "players." + playerUUID + ".rest-chest";
|
||||||
|
if (result.isEmpty() && playerData.contains(legacyPath)) {
|
||||||
|
String worldName = playerData.getString(legacyPath + ".world");
|
||||||
|
World world = getServer().getWorld(worldName);
|
||||||
|
if (world != null) {
|
||||||
|
result.add(new Location(world, playerData.getInt(legacyPath + ".x"),
|
||||||
|
playerData.getInt(legacyPath + ".y"), playerData.getInt(legacyPath + ".z")));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Legacy: Gibt die erste Rest-Truhe zurück (oder null). */
|
||||||
|
private Location getRestChestLocation(UUID playerUUID) {
|
||||||
|
List<Location> locs = getRestChestLocations(playerUUID);
|
||||||
|
return locs.isEmpty() ? null : locs.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Location getTargetChestLocation(UUID playerUUID, Material itemType) {
|
private Location getTargetChestLocation(UUID playerUUID, Material itemType) {
|
||||||
@@ -1171,15 +1248,25 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
if (!command.getName().equalsIgnoreCase("asc")) return false;
|
if (!command.getName().equalsIgnoreCase("asc")) return false;
|
||||||
if (!(sender instanceof Player)) {
|
|
||||||
sender.sendMessage(ChatColor.RED + "Dieser Befehl ist nur für Spieler!");
|
String lang = config != null ? config.getString("language", "de") : "de";
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Player player = (Player) sender;
|
|
||||||
String lang = config.getString("language", "de");
|
|
||||||
if (lang == null) lang = "de";
|
if (lang == null) lang = "de";
|
||||||
|
|
||||||
|
// reload, import und export sind auch von der Konsole erlaubt
|
||||||
|
boolean isPlayer = sender instanceof Player;
|
||||||
|
if (!isPlayer) {
|
||||||
|
if (args.length == 0 || (!args[0].equalsIgnoreCase("reload")
|
||||||
|
&& !args[0].equalsIgnoreCase("import")
|
||||||
|
&& !args[0].equalsIgnoreCase("export"))) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Dieser Befehl ist nur für Spieler! (Konsole: reload, import, export)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Player player = isPlayer ? (Player) sender : null;
|
||||||
|
|
||||||
if (args.length == 0 || args[0].equalsIgnoreCase("help")) {
|
if (args.length == 0 || args[0].equalsIgnoreCase("help")) {
|
||||||
|
if (player == null) { sender.sendMessage(ChatColor.RED + "Verwendung: /asc [reload|import|export]"); return true; }
|
||||||
String helpMessage = lang.equalsIgnoreCase("en") ? HELP_EN : HELP_DE;
|
String helpMessage = lang.equalsIgnoreCase("en") ? HELP_EN : HELP_DE;
|
||||||
helpMessage = ChatColor.translateAlternateColorCodes('&', helpMessage);
|
helpMessage = ChatColor.translateAlternateColorCodes('&', helpMessage);
|
||||||
player.sendMessage(helpMessage.split("\n"));
|
player.sendMessage(helpMessage.split("\n"));
|
||||||
@@ -1194,13 +1281,13 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
.replace("%server_name%", serverName.isEmpty() ? "(nicht gesetzt)" : serverName) // BungeeCord NEU
|
.replace("%server_name%", serverName.isEmpty() ? "(nicht gesetzt)" : serverName) // BungeeCord NEU
|
||||||
.replace("%author%", String.join(", ", getDescription().getAuthors()));
|
.replace("%author%", String.join(", ", getDescription().getAuthors()));
|
||||||
infoMessage = ChatColor.translateAlternateColorCodes('&', infoMessage);
|
infoMessage = ChatColor.translateAlternateColorCodes('&', infoMessage);
|
||||||
player.sendMessage(infoMessage.split("\n"));
|
sender.sendMessage(infoMessage.split("\n"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args[0].equalsIgnoreCase("reload")) {
|
if (args[0].equalsIgnoreCase("reload")) {
|
||||||
if (!player.hasPermission("autosortchest.reload")) {
|
if (!sender.hasPermission("autosortchest.reload")) {
|
||||||
player.sendMessage(getMessage("no-permission"));
|
sender.sendMessage(getMessage("no-permission"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1240,8 +1327,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
migrateInputChests();
|
migrateInputChests();
|
||||||
startTasks();
|
startTasks();
|
||||||
|
|
||||||
player.sendMessage(getMessage("reload-success"));
|
sender.sendMessage(getMessage("reload-success"));
|
||||||
getLogger().info("Plugin erfolgreich neu geladen von " + player.getName()
|
getLogger().info("Plugin erfolgreich neu geladen von " + sender.getName()
|
||||||
+ " (sort_interval_ticks=" + sortIntervalTicks + ", server_name=\"" + serverName + "\")");
|
+ " (sort_interval_ticks=" + sortIntervalTicks + ", server_name=\"" + serverName + "\")");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1250,22 +1337,22 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
// /asc import – YAML → MySQL
|
// /asc import – YAML → MySQL
|
||||||
// -------------------------------------------------------
|
// -------------------------------------------------------
|
||||||
if (args[0].equalsIgnoreCase("import")) {
|
if (args[0].equalsIgnoreCase("import")) {
|
||||||
if (!player.hasPermission("autosortchest.import")) {
|
if (!sender.hasPermission("autosortchest.import")) {
|
||||||
player.sendMessage(getMessage("no-permission"));
|
sender.sendMessage(getMessage("no-permission"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!mysqlEnabled || mysqlManager == null) {
|
if (!mysqlEnabled || mysqlManager == null) {
|
||||||
player.sendMessage(ChatColor.RED + "MySQL ist nicht aktiviert! Aktiviere MySQL in der config.yml zuerst.");
|
sender.sendMessage(ChatColor.RED + "MySQL ist nicht aktiviert! Aktiviere MySQL in der config.yml zuerst.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (playerData == null || playerData.getConfigurationSection("players") == null
|
if (playerData == null || playerData.getConfigurationSection("players") == null
|
||||||
|| playerData.getConfigurationSection("players").getKeys(false).isEmpty()) {
|
|| playerData.getConfigurationSection("players").getKeys(false).isEmpty()) {
|
||||||
player.sendMessage(ChatColor.RED + "Die players.yml ist leer oder enthält keine Spielerdaten!");
|
sender.sendMessage(ChatColor.RED + "Die players.yml ist leer oder enthält keine Spielerdaten!");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendMessage(ChatColor.YELLOW + "Importiere Daten aus players.yml nach MySQL...");
|
sender.sendMessage(ChatColor.YELLOW + "Importiere Daten aus players.yml nach MySQL...");
|
||||||
player.sendMessage(ChatColor.GRAY + "Bestehende MySQL-Daten werden nicht überschrieben (REPLACE INTO).");
|
sender.sendMessage(ChatColor.GRAY + "Bestehende MySQL-Daten werden nicht überschrieben (REPLACE INTO).");
|
||||||
|
|
||||||
new BukkitRunnable() {
|
new BukkitRunnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -1311,26 +1398,41 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String restPath = "players." + uuidString + ".rest-chest";
|
// BUG FIX: Mehrere Rest-Truhen importieren (neues Format + Legacy)
|
||||||
if (playerData.contains(restPath + ".world")) {
|
String restBasePath2 = "players." + uuidString + ".rest-chests";
|
||||||
String world = playerData.getString(restPath + ".world");
|
if (playerData.contains(restBasePath2)) {
|
||||||
int x = playerData.getInt(restPath + ".x");
|
for (String slotKey : playerData.getConfigurationSection(restBasePath2).getKeys(false)) {
|
||||||
int y = playerData.getInt(restPath + ".y");
|
String rPath = restBasePath2 + "." + slotKey;
|
||||||
int z = playerData.getInt(restPath + ".z");
|
String world = playerData.getString(rPath + ".world");
|
||||||
boolean isPublic = playerData.getBoolean(restPath + ".public", false);
|
int x = playerData.getInt(rPath + ".x");
|
||||||
mysqlManager.setRestChest(uuidString, world, x, y, z, isPublic);
|
int y = playerData.getInt(rPath + ".y");
|
||||||
restCount++;
|
int z = playerData.getInt(rPath + ".z");
|
||||||
|
boolean isPublic = playerData.getBoolean(rPath + ".public", false);
|
||||||
|
mysqlManager.setRestChest(uuidString, world, x, y, z, isPublic);
|
||||||
|
restCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String restPath = "players." + uuidString + ".rest-chest";
|
||||||
|
if (playerData.contains(restPath + ".world")) {
|
||||||
|
String world = playerData.getString(restPath + ".world");
|
||||||
|
int x = playerData.getInt(restPath + ".x");
|
||||||
|
int y = playerData.getInt(restPath + ".y");
|
||||||
|
int z = playerData.getInt(restPath + ".z");
|
||||||
|
boolean isPublic = playerData.getBoolean(restPath + ".public", false);
|
||||||
|
mysqlManager.setRestChest(uuidString, world, x, y, z, isPublic);
|
||||||
|
restCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final int fp = playerCount, fi = inputCount, ft = targetCount, fr = restCount;
|
final int fp = playerCount, fi = inputCount, ft = targetCount, fr = restCount;
|
||||||
Bukkit.getScheduler().runTask(Main.this, () -> {
|
Bukkit.getScheduler().runTask(Main.this, () -> {
|
||||||
player.sendMessage(ChatColor.GREEN + "Import erfolgreich abgeschlossen!");
|
sender.sendMessage(ChatColor.GREEN + "Import erfolgreich abgeschlossen!");
|
||||||
player.sendMessage(ChatColor.GRAY + " Spieler: " + ChatColor.WHITE + fp);
|
sender.sendMessage(ChatColor.GRAY + " Spieler: " + ChatColor.WHITE + fp);
|
||||||
player.sendMessage(ChatColor.GRAY + " Eingangstruhen: " + ChatColor.WHITE + fi);
|
sender.sendMessage(ChatColor.GRAY + " Eingangstruhen: " + ChatColor.WHITE + fi);
|
||||||
player.sendMessage(ChatColor.GRAY + " Zieltruhen: " + ChatColor.WHITE + ft);
|
sender.sendMessage(ChatColor.GRAY + " Zieltruhen: " + ChatColor.WHITE + ft);
|
||||||
player.sendMessage(ChatColor.GRAY + " Rest-Truhen: " + ChatColor.WHITE + fr);
|
sender.sendMessage(ChatColor.GRAY + " Rest-Truhen: " + ChatColor.WHITE + fr);
|
||||||
getLogger().info("Import durch " + player.getName() + " abgeschlossen: "
|
getLogger().info("Import durch " + sender.getName() + " abgeschlossen: "
|
||||||
+ fp + " Spieler, " + fi + " Input, " + ft + " Target, " + fr + " Rest.");
|
+ fp + " Spieler, " + fi + " Input, " + ft + " Target, " + fr + " Rest.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1342,17 +1444,17 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
// /asc export – MySQL → YAML
|
// /asc export – MySQL → YAML
|
||||||
// -------------------------------------------------------
|
// -------------------------------------------------------
|
||||||
if (args[0].equalsIgnoreCase("export")) {
|
if (args[0].equalsIgnoreCase("export")) {
|
||||||
if (!player.hasPermission("autosortchest.export")) {
|
if (!sender.hasPermission("autosortchest.export")) {
|
||||||
player.sendMessage(getMessage("no-permission"));
|
sender.sendMessage(getMessage("no-permission"));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!mysqlEnabled || mysqlManager == null) {
|
if (!mysqlEnabled || mysqlManager == null) {
|
||||||
player.sendMessage(ChatColor.RED + "MySQL ist nicht aktiviert! Der Export benötigt eine aktive MySQL-Verbindung.");
|
sender.sendMessage(ChatColor.RED + "MySQL ist nicht aktiviert! Der Export benötigt eine aktive MySQL-Verbindung.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendMessage(ChatColor.YELLOW + "Exportiere Daten aus MySQL nach players.yml...");
|
sender.sendMessage(ChatColor.YELLOW + "Exportiere Daten aus MySQL nach players.yml...");
|
||||||
player.sendMessage(ChatColor.GRAY + "Ein Backup der aktuellen players.yml wird erstellt.");
|
sender.sendMessage(ChatColor.GRAY + "Ein Backup der aktuellen players.yml wird erstellt.");
|
||||||
|
|
||||||
new BukkitRunnable() {
|
new BukkitRunnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -1370,7 +1472,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
java.nio.file.Files.copy(playerDataFile.toPath(), backupFile.toPath());
|
java.nio.file.Files.copy(playerDataFile.toPath(), backupFile.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Bukkit.getScheduler().runTask(Main.this, () ->
|
Bukkit.getScheduler().runTask(Main.this, () ->
|
||||||
player.sendMessage(ChatColor.RED + "Backup fehlgeschlagen: " + e.getMessage()));
|
sender.sendMessage(ChatColor.RED + "Backup fehlgeschlagen: " + e.getMessage()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1410,9 +1512,11 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
targetCount++;
|
targetCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> restChest = mysqlManager.getRestChest(uuidString);
|
// BUG FIX: Alle Rest-Truhen exportieren
|
||||||
if (restChest != null) {
|
List<Map<String, Object>> restChests = mysqlManager.getRestChests(uuidString);
|
||||||
String path = "players." + uuidString + ".rest-chest";
|
for (Map<String, Object> restChest : restChests) {
|
||||||
|
int restSlot = (int) restChest.get("slot");
|
||||||
|
String path = "players." + uuidString + ".rest-chests." + restSlot;
|
||||||
exportData.set(path + ".world", restChest.get("world"));
|
exportData.set(path + ".world", restChest.get("world"));
|
||||||
exportData.set(path + ".x", restChest.get("x"));
|
exportData.set(path + ".x", restChest.get("x"));
|
||||||
exportData.set(path + ".y", restChest.get("y"));
|
exportData.set(path + ".y", restChest.get("y"));
|
||||||
@@ -1430,24 +1534,24 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
|
|
||||||
Bukkit.getScheduler().runTask(Main.this, () -> {
|
Bukkit.getScheduler().runTask(Main.this, () -> {
|
||||||
playerData = finalExport;
|
playerData = finalExport;
|
||||||
player.sendMessage(ChatColor.GREEN + "Export erfolgreich abgeschlossen!");
|
sender.sendMessage(ChatColor.GREEN + "Export erfolgreich abgeschlossen!");
|
||||||
if (finalBackupName != null) {
|
if (finalBackupName != null) {
|
||||||
player.sendMessage(ChatColor.GRAY + " Backup: " + ChatColor.WHITE + finalBackupName);
|
sender.sendMessage(ChatColor.GRAY + " Backup: " + ChatColor.WHITE + finalBackupName);
|
||||||
} else {
|
} else {
|
||||||
player.sendMessage(ChatColor.GRAY + " Backup: " + ChatColor.DARK_GRAY + "Übersprungen (players.yml war leer)");
|
sender.sendMessage(ChatColor.GRAY + " Backup: " + ChatColor.DARK_GRAY + "Übersprungen (players.yml war leer)");
|
||||||
}
|
}
|
||||||
player.sendMessage(ChatColor.GRAY + " Spieler: " + ChatColor.WHITE + fp);
|
sender.sendMessage(ChatColor.GRAY + " Spieler: " + ChatColor.WHITE + fp);
|
||||||
player.sendMessage(ChatColor.GRAY + " Eingangstruhen: " + ChatColor.WHITE + fi);
|
sender.sendMessage(ChatColor.GRAY + " Eingangstruhen: " + ChatColor.WHITE + fi);
|
||||||
player.sendMessage(ChatColor.GRAY + " Zieltruhen: " + ChatColor.WHITE + ft);
|
sender.sendMessage(ChatColor.GRAY + " Zieltruhen: " + ChatColor.WHITE + ft);
|
||||||
player.sendMessage(ChatColor.GRAY + " Rest-Truhen: " + ChatColor.WHITE + fr);
|
sender.sendMessage(ChatColor.GRAY + " Rest-Truhen: " + ChatColor.WHITE + fr);
|
||||||
getLogger().info("Export durch " + player.getName() + " abgeschlossen: "
|
getLogger().info("Export durch " + sender.getName() + " abgeschlossen: "
|
||||||
+ fp + " Spieler, " + fi + " Input, " + ft + " Target, " + fr + " Rest."
|
+ fp + " Spieler, " + fi + " Input, " + ft + " Target, " + fr + " Rest."
|
||||||
+ (finalBackupName != null ? " Backup: " + finalBackupName : " Kein Backup."));
|
+ (finalBackupName != null ? " Backup: " + finalBackupName : " Kein Backup."));
|
||||||
});
|
});
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Bukkit.getScheduler().runTask(Main.this, () ->
|
Bukkit.getScheduler().runTask(Main.this, () ->
|
||||||
player.sendMessage(ChatColor.RED + "Export fehlgeschlagen: " + e.getMessage()));
|
sender.sendMessage(ChatColor.RED + "Export fehlgeschlagen: " + e.getMessage()));
|
||||||
getLogger().warning("Export fehlgeschlagen: " + e.getMessage());
|
getLogger().warning("Export fehlgeschlagen: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1455,6 +1559,11 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unbekannter Befehl → Hilfe (nur für Spieler)
|
||||||
|
if (player == null) {
|
||||||
|
sender.sendMessage(ChatColor.RED + "Verwendung: /asc [reload|import|export]");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
String helpMessage = lang.equalsIgnoreCase("en") ? HELP_EN : HELP_DE;
|
String helpMessage = lang.equalsIgnoreCase("en") ? HELP_EN : HELP_DE;
|
||||||
helpMessage = ChatColor.translateAlternateColorCodes('&', helpMessage);
|
helpMessage = ChatColor.translateAlternateColorCodes('&', helpMessage);
|
||||||
player.sendMessage(helpMessage.split("\n"));
|
player.sendMessage(helpMessage.split("\n"));
|
||||||
@@ -1486,14 +1595,40 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
// ── Limit-Pruefung: Rest-Truhe ─────────────────────────────────────
|
// ── Limit-Pruefung: Rest-Truhe ─────────────────────────────────────
|
||||||
if (chestLimitsEnabled) {
|
if (chestLimitsEnabled) {
|
||||||
int maxRest = getChestLimitForPlayer(player, "rest");
|
int maxRest = getChestLimitForPlayer(player, "rest");
|
||||||
boolean hasRestAlready = false;
|
int currentRest = 0;
|
||||||
|
final Block finalChestBlockRest = chestBlock;
|
||||||
|
boolean alreadyRest = false;
|
||||||
if (mysqlEnabled && mysqlManager != null) {
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
hasRestAlready = mysqlManager.getRestChest(playerUUID.toString()) != null;
|
currentRest = mysqlManager.countRestChests(playerUUID.toString());
|
||||||
|
// Prüfen ob diese Truhe bereits als Rest-Truhe registriert ist (Update erlaubt)
|
||||||
|
alreadyRest = mysqlManager.getRestSlotForLocation(
|
||||||
|
playerUUID.toString(),
|
||||||
|
finalChestBlockRest.getWorld().getName(),
|
||||||
|
finalChestBlockRest.getX(),
|
||||||
|
finalChestBlockRest.getY(),
|
||||||
|
finalChestBlockRest.getZ()) >= 0;
|
||||||
} else {
|
} else {
|
||||||
hasRestAlready = playerData.contains("players." + playerUUID + ".rest-chest");
|
String basePath = "players." + playerUUID + ".rest-chests";
|
||||||
|
if (playerData.contains(basePath)) {
|
||||||
|
for (String slotKey : playerData.getConfigurationSection(basePath).getKeys(false)) {
|
||||||
|
String rPath = basePath + "." + slotKey;
|
||||||
|
if (finalChestBlockRest.getWorld().getName().equals(playerData.getString(rPath + ".world"))
|
||||||
|
&& finalChestBlockRest.getX() == playerData.getInt(rPath + ".x")
|
||||||
|
&& finalChestBlockRest.getY() == playerData.getInt(rPath + ".y")
|
||||||
|
&& finalChestBlockRest.getZ() == playerData.getInt(rPath + ".z")) {
|
||||||
|
alreadyRest = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!alreadyRest) currentRest = playerData.getConfigurationSection(basePath).getKeys(false).size();
|
||||||
|
}
|
||||||
|
// Legacy fallback
|
||||||
|
if (!alreadyRest && currentRest == 0 && playerData.contains("players." + playerUUID + ".rest-chest")) {
|
||||||
|
currentRest = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hasRestAlready && maxRest <= 1) {
|
if (!alreadyRest && currentRest >= maxRest) {
|
||||||
player.sendMessage(ChatColor.RED + "Du hast bereits eine Rest-Truhe! (Limit: " + maxRest + ")");
|
player.sendMessage(ChatColor.RED + "Du hast das Limit deiner Rest-Truhen erreicht! (" + maxRest + ")");
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1530,11 +1665,14 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
final Block finalChestBlock = chestBlock;
|
final Block finalChestBlock = chestBlock;
|
||||||
boolean alreadyInput = false;
|
boolean alreadyInput = false;
|
||||||
if (mysqlEnabled && mysqlManager != null) {
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
alreadyInput = mysqlManager.getInputChests(playerUUID.toString()).stream().anyMatch(c ->
|
alreadyInput = mysqlManager.getInputChests(playerUUID.toString()).stream().anyMatch(c -> {
|
||||||
c.get("world").equals(finalChestBlock.getWorld().getName())
|
String cWorld = (String) c.get("world");
|
||||||
&& (int)c.get("x") == finalChestBlock.getX()
|
return cWorld != null
|
||||||
&& (int)c.get("y") == finalChestBlock.getY()
|
&& cWorld.equals(finalChestBlock.getWorld().getName())
|
||||||
&& (int)c.get("z") == finalChestBlock.getZ());
|
&& (int)c.get("x") == finalChestBlock.getX()
|
||||||
|
&& (int)c.get("y") == finalChestBlock.getY()
|
||||||
|
&& (int)c.get("z") == finalChestBlock.getZ();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!alreadyInput && currentInput >= maxInput) {
|
if (!alreadyInput && currentInput >= maxInput) {
|
||||||
player.sendMessage(ChatColor.RED + "Du hast das Limit deiner Eingangstruhen erreicht! (" + maxInput + ")");
|
player.sendMessage(ChatColor.RED + "Du hast das Limit deiner Eingangstruhen erreicht! (" + maxInput + ")");
|
||||||
@@ -1564,8 +1702,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
if (attachedBlock.getState() instanceof Chest) chestBlock = attachedBlock;
|
if (attachedBlock.getState() instanceof Chest) chestBlock = attachedBlock;
|
||||||
}
|
}
|
||||||
if (chestBlock == null) { player.sendMessage(getMessage("no-chest-near-sign")); return; }
|
if (chestBlock == null) { player.sendMessage(getMessage("no-chest-near-sign")); return; }
|
||||||
event.setLine(0, "[asc]");
|
event.setLine(0, getSignColor("target", "line1") + "[asc]");
|
||||||
event.setLine(1, "ziel");
|
event.setLine(1, getSignColor("target", "line2") + "ziel");
|
||||||
event.setLine(2, "");
|
event.setLine(2, "");
|
||||||
event.setLine(3, "");
|
event.setLine(3, "");
|
||||||
}
|
}
|
||||||
@@ -2017,7 +2155,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!player.isSneaking() && !isAdmin(player)) {
|
// BUG FIX: autosortchest.bypass erlaubt Abbau ohne Shift-Taste
|
||||||
|
if (!player.isSneaking() && !isAdmin(player) && !player.hasPermission("autosortchest.bypass")) {
|
||||||
player.sendMessage(getMessage("sign-break-denied"));
|
player.sendMessage(getMessage("sign-break-denied"));
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
return;
|
return;
|
||||||
@@ -2052,8 +2191,10 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ownerUUID == null) {
|
if (ownerUUID == null) {
|
||||||
Location restLoc = getRestChestLocation(uuid);
|
// BUG FIX: Alle Rest-Truhen des Spielers prüfen (nicht nur erste)
|
||||||
if (chestLoc.equals(restLoc)) ownerUUID = uuid;
|
for (Location restLoc : getRestChestLocations(uuid)) {
|
||||||
|
if (chestLoc.equals(restLoc)) { ownerUUID = uuid; break; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ownerUUID != null) break;
|
if (ownerUUID != null) break;
|
||||||
}
|
}
|
||||||
@@ -2062,9 +2203,33 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
UUID uuidToDelete = (ownerUUID != null) ? ownerUUID : player.getUniqueId();
|
UUID uuidToDelete = (ownerUUID != null) ? ownerUUID : player.getUniqueId();
|
||||||
|
|
||||||
if (line1.equalsIgnoreCase("rest")) {
|
if (line1.equalsIgnoreCase("rest")) {
|
||||||
playerData.set("players." + uuidToDelete + ".rest-chest", null);
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
savePlayerData();
|
// BUG FIX: Nur die spezifische Location löschen, nicht alle Rest-Truhen
|
||||||
if (mysqlEnabled && mysqlManager != null) mysqlManager.removeRestChest(uuidToDelete.toString());
|
mysqlManager.removeRestChestByLocation(uuidToDelete.toString(),
|
||||||
|
chestLoc.getWorld().getName(), chestLoc.getBlockX(), chestLoc.getBlockY(), chestLoc.getBlockZ());
|
||||||
|
} else {
|
||||||
|
// YAML: Spezifische Location aus rest-chests entfernen
|
||||||
|
boolean removedFromNew = false;
|
||||||
|
String basePath = "players." + uuidToDelete + ".rest-chests";
|
||||||
|
if (playerData.contains(basePath)) {
|
||||||
|
for (String slotKey : new ArrayList<>(playerData.getConfigurationSection(basePath).getKeys(false))) {
|
||||||
|
String rPath = basePath + "." + slotKey;
|
||||||
|
if (chestLoc.getWorld().getName().equals(playerData.getString(rPath + ".world"))
|
||||||
|
&& chestLoc.getBlockX() == playerData.getInt(rPath + ".x")
|
||||||
|
&& chestLoc.getBlockY() == playerData.getInt(rPath + ".y")
|
||||||
|
&& chestLoc.getBlockZ() == playerData.getInt(rPath + ".z")) {
|
||||||
|
playerData.set(rPath, null);
|
||||||
|
removedFromNew = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Legacy-Fallback
|
||||||
|
if (!removedFromNew) {
|
||||||
|
playerData.set("players." + uuidToDelete + ".rest-chest", null);
|
||||||
|
}
|
||||||
|
savePlayerData();
|
||||||
|
}
|
||||||
} else if (line1.equalsIgnoreCase("input")) {
|
} else if (line1.equalsIgnoreCase("input")) {
|
||||||
removeInputChestByLocation(uuidToDelete, chestLoc);
|
removeInputChestByLocation(uuidToDelete, chestLoc);
|
||||||
} else if (line1.equalsIgnoreCase("ziel")) {
|
} else if (line1.equalsIgnoreCase("ziel")) {
|
||||||
@@ -2072,11 +2237,24 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
if (!line2.isEmpty()) {
|
if (!line2.isEmpty()) {
|
||||||
Material mat = Material.matchMaterial(line2);
|
Material mat = Material.matchMaterial(line2);
|
||||||
if (mat != null) {
|
if (mat != null) {
|
||||||
Location savedLoc = getTargetChestLocation(uuidToDelete, mat);
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
if (savedLoc != null && savedLoc.equals(chestLoc)) {
|
// BUG FIX: Nur bei MySQL → kein playerData-Zugriff nötig
|
||||||
playerData.set("players." + uuidToDelete + ".target-chests." + mat.name(), null);
|
mysqlManager.removeTargetChest(uuidToDelete.toString(), mat.name());
|
||||||
savePlayerData();
|
} else {
|
||||||
if (mysqlEnabled && mysqlManager != null) mysqlManager.removeTargetChest(uuidToDelete.toString(), mat.name());
|
// YAML: Slot mit passender Location finden und löschen
|
||||||
|
String basePath = "players." + uuidToDelete + ".target-chests";
|
||||||
|
if (playerData.contains(basePath)) {
|
||||||
|
String path = basePath + "." + mat.name();
|
||||||
|
if (playerData.contains(path)) {
|
||||||
|
Location savedLoc = getLocationFromPath(path);
|
||||||
|
if (savedLoc != null && savedLoc.getBlockX() == chestLoc.getBlockX()
|
||||||
|
&& savedLoc.getBlockY() == chestLoc.getBlockY()
|
||||||
|
&& savedLoc.getBlockZ() == chestLoc.getBlockZ()) {
|
||||||
|
playerData.set(path, null);
|
||||||
|
savePlayerData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2144,16 +2322,36 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void removeOldTargetEntry(UUID uuid, Location loc, String newItemType) {
|
private void removeOldTargetEntry(UUID uuid, Location loc, String newItemType) {
|
||||||
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
|
// MySQL: Alle Zieltruhen dieser Location löschen, die ein anderes Item haben
|
||||||
|
List<Map<String, Object>> existing = mysqlManager.getTargetChests(uuid.toString());
|
||||||
|
for (Map<String, Object> e : existing) {
|
||||||
|
String existingItem = (String) e.get("item");
|
||||||
|
if (existingItem.equalsIgnoreCase(newItemType)) continue;
|
||||||
|
String w = (String) e.get("world");
|
||||||
|
if (w.equals(loc.getWorld().getName())
|
||||||
|
&& (int) e.get("x") == loc.getBlockX()
|
||||||
|
&& (int) e.get("y") == loc.getBlockY()
|
||||||
|
&& (int) e.get("z") == loc.getBlockZ()) {
|
||||||
|
mysqlManager.removeTargetChest(uuid.toString(), existingItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// YAML-Modus
|
||||||
String basePath = "players." + uuid + ".target-chests";
|
String basePath = "players." + uuid + ".target-chests";
|
||||||
if (!playerData.contains(basePath)) return;
|
if (!playerData.contains(basePath)) return;
|
||||||
for (String existingType : playerData.getConfigurationSection(basePath).getKeys(false)) {
|
for (String existingType : playerData.getConfigurationSection(basePath).getKeys(false)) {
|
||||||
if (existingType.equalsIgnoreCase(newItemType)) continue;
|
if (existingType.equalsIgnoreCase(newItemType)) continue;
|
||||||
String path = basePath + "." + existingType;
|
String path = basePath + "." + existingType;
|
||||||
if (playerData.getString(path + ".world").equals(loc.getWorld().getName())
|
String savedWorld = playerData.getString(path + ".world");
|
||||||
|
if (savedWorld == null) continue; // NPE-Schutz: korrupter Eintrag überspringen
|
||||||
|
if (savedWorld.equals(loc.getWorld().getName())
|
||||||
&& playerData.getInt(path + ".x") == loc.getBlockX()
|
&& playerData.getInt(path + ".x") == loc.getBlockX()
|
||||||
&& playerData.getInt(path + ".y") == loc.getBlockY()
|
&& playerData.getInt(path + ".y") == loc.getBlockY()
|
||||||
&& playerData.getInt(path + ".z") == loc.getBlockZ()) {
|
&& playerData.getInt(path + ".z") == loc.getBlockZ()) {
|
||||||
playerData.set(path, null);
|
playerData.set(path, null);
|
||||||
|
savePlayerData(); // Änderung direkt auf Disk schreiben
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2352,7 +2550,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
});
|
});
|
||||||
// Preload Zieltruhen+Rest nur wenn es lokale Input-Truhen gibt
|
// Preload Zieltruhen+Rest nur wenn es lokale Input-Truhen gibt
|
||||||
List<Map<String, Object>> preTargets = anyLocal ? mysqlManager.getTargetChests(uuidString) : new ArrayList<>();
|
List<Map<String, Object>> preTargets = anyLocal ? mysqlManager.getTargetChests(uuidString) : new ArrayList<>();
|
||||||
Map<String, Object> preRest = anyLocal ? mysqlManager.getRestChest(uuidString) : null;
|
// BUG FIX: Alle Rest-Truhen vorladen (nicht nur eine)
|
||||||
|
List<Map<String, Object>> preRests = anyLocal ? mysqlManager.getRestChests(uuidString) : new ArrayList<>();
|
||||||
|
|
||||||
for (Map<String, Object> chest : chests) {
|
for (Map<String, Object> chest : chests) {
|
||||||
if (crosslink) {
|
if (crosslink) {
|
||||||
@@ -2361,7 +2560,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
String worldName = (String) chest.get("world");
|
String worldName = (String) chest.get("world");
|
||||||
boolean isLocal = Bukkit.getWorld(worldName) != null;
|
boolean isLocal = Bukkit.getWorld(worldName) != null;
|
||||||
jobs.add(new Object[]{ ownerUUID, chest, isLocal, preTargets, preRest });
|
jobs.add(new Object[]{ ownerUUID, chest, isLocal, preTargets, preRests });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -2383,7 +2582,8 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<Map<String, Object>> preTargets = (List<Map<String, Object>>) job[3];
|
List<Map<String, Object>> preTargets = (List<Map<String, Object>>) job[3];
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, Object> preRest = (Map<String, Object>) job[4];
|
// BUG FIX: preRests ist jetzt eine Liste
|
||||||
|
List<Map<String, Object>> preRests = (List<Map<String, Object>>) job[4];
|
||||||
|
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
World world = Bukkit.getWorld((String) chest.get("world"));
|
World world = Bukkit.getWorld((String) chest.get("world"));
|
||||||
@@ -2400,14 +2600,17 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
targetLocs.computeIfAbsent((String) tc.get("item"), k -> new ArrayList<>())
|
targetLocs.computeIfAbsent((String) tc.get("item"), k -> new ArrayList<>())
|
||||||
.add(new Location(w, (int) tc.get("x"), (int) tc.get("y"), (int) tc.get("z")));
|
.add(new Location(w, (int) tc.get("x"), (int) tc.get("y"), (int) tc.get("z")));
|
||||||
}
|
}
|
||||||
Location restLoc = null;
|
// BUG FIX: Alle Rest-Truhen als Liste konvertieren
|
||||||
if (preRest != null && !isRemoteChest(preRest)) {
|
List<Location> restLocs = new ArrayList<>();
|
||||||
World w = Bukkit.getWorld((String) preRest.get("world"));
|
for (Map<String, Object> preRest : preRests) {
|
||||||
if (w != null) restLoc = new Location(w,
|
if (preRest != null && !isRemoteChest(preRest)) {
|
||||||
(int) preRest.get("x"), (int) preRest.get("y"), (int) preRest.get("z"));
|
World w = Bukkit.getWorld((String) preRest.get("world"));
|
||||||
|
if (w != null) restLocs.add(new Location(w,
|
||||||
|
(int) preRest.get("x"), (int) preRest.get("y"), (int) preRest.get("z")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkSingleInputChest(ownerUUID, loc, (String) chest.get("chest_id"), false, targetLocs, restLoc);
|
checkSingleInputChest(ownerUUID, loc, (String) chest.get("chest_id"), false, targetLocs, restLocs);
|
||||||
} else if (crosslink) {
|
} else if (crosslink) {
|
||||||
checkRemoteInputChest(ownerUUID, chest);
|
checkRemoteInputChest(ownerUUID, chest);
|
||||||
}
|
}
|
||||||
@@ -2457,20 +2660,21 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
.add(new Location(world, (int) tc.get("x"), (int) tc.get("y"), (int) tc.get("z")));
|
.add(new Location(world, (int) tc.get("x"), (int) tc.get("y"), (int) tc.get("z")));
|
||||||
}
|
}
|
||||||
|
|
||||||
Location localRestChest = getRestChestLocation(ownerUUID);
|
// BUG FIX: Alle lokalen Rest-Truhen laden
|
||||||
|
List<Location> localRestChests = getRestChestLocations(ownerUUID);
|
||||||
|
|
||||||
if (localTargets.isEmpty() && localRestChest == null) return;
|
if (localTargets.isEmpty() && localRestChests.isEmpty()) return;
|
||||||
|
|
||||||
OfflinePlayer op = Bukkit.getOfflinePlayer(ownerUUID);
|
OfflinePlayer op = Bukkit.getOfflinePlayer(ownerUUID);
|
||||||
String ownerName = op.getName() != null ? op.getName() : ownerUUID.toString();
|
String ownerName = op.getName() != null ? op.getName() : ownerUUID.toString();
|
||||||
|
|
||||||
distributeFromRemoteInputChest(ownerUUID, ownerName, inputChestData, localTargets, localRestChest);
|
distributeFromRemoteInputChest(ownerUUID, ownerName, inputChestData, localTargets, localRestChests);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void distributeFromRemoteInputChest(UUID ownerUUID, String ownerName,
|
private void distributeFromRemoteInputChest(UUID ownerUUID, String ownerName,
|
||||||
Map<String, Object> inputChestData,
|
Map<String, Object> inputChestData,
|
||||||
Map<String, List<Location>> localTargets,
|
Map<String, List<Location>> localTargets,
|
||||||
Location localRestChest) {
|
List<Location> localRestChests) {
|
||||||
|
|
||||||
if (!mysqlEnabled || mysqlManager == null) return;
|
if (!mysqlEnabled || mysqlManager == null) return;
|
||||||
|
|
||||||
@@ -2495,7 +2699,12 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
for (Location l : slots) {
|
for (Location l : slots) {
|
||||||
if (l != null && !isChestCachedFull(l)) { targetLoc = l; break; }
|
if (l != null && !isChestCachedFull(l)) { targetLoc = l; break; }
|
||||||
}
|
}
|
||||||
if (targetLoc == null) targetLoc = localRestChest;
|
// BUG FIX: Alle lokalen Rest-Truhen als Fallback versuchen
|
||||||
|
if (targetLoc == null) {
|
||||||
|
for (Location restLoc : localRestChests) {
|
||||||
|
if (restLoc != null && !isChestCachedFull(restLoc)) { targetLoc = restLoc; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
if (targetLoc == null) continue;
|
if (targetLoc == null) continue;
|
||||||
|
|
||||||
if (!(targetLoc.getBlock().getState() instanceof Chest)) continue;
|
if (!(targetLoc.getBlock().getState() instanceof Chest)) continue;
|
||||||
@@ -2523,7 +2732,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
/** Legacy-Ueberladung: laedt Truhen-Locations synchron (nur fuer InventoryMoveItemEvent). */
|
/** Legacy-Ueberladung: laedt Truhen-Locations synchron (nur fuer InventoryMoveItemEvent). */
|
||||||
private void distributeItemsForOwner(UUID ownerUUID, Player ownerPlayer, Inventory sourceInventory,
|
private void distributeItemsForOwner(UUID ownerUUID, Player ownerPlayer, Inventory sourceInventory,
|
||||||
String ownerNameOverride, Location sourceLocation) {
|
String ownerNameOverride, Location sourceLocation) {
|
||||||
Location restLoc = getRestChestLocation(ownerUUID);
|
List<Location> restLocs = getRestChestLocations(ownerUUID);
|
||||||
Map<String, List<Location>> targets = new HashMap<>();
|
Map<String, List<Location>> targets = new HashMap<>();
|
||||||
if (mysqlEnabled && mysqlManager != null) {
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
for (Map<String, Object> tc : mysqlManager.getTargetChests(ownerUUID.toString())) {
|
for (Map<String, Object> tc : mysqlManager.getTargetChests(ownerUUID.toString())) {
|
||||||
@@ -2546,7 +2755,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
distributeItemsForOwner(ownerUUID, ownerPlayer, sourceInventory, ownerNameOverride, sourceLocation, targets, restLoc);
|
distributeItemsForOwner(ownerUUID, ownerPlayer, sourceInventory, ownerNameOverride, sourceLocation, targets, restLocs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkSingleInputChest(UUID ownerUUID, Location location, String debugId, boolean crosslinkMode) {
|
private boolean checkSingleInputChest(UUID ownerUUID, Location location, String debugId, boolean crosslinkMode) {
|
||||||
@@ -2554,7 +2763,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkSingleInputChest(UUID ownerUUID, Location location, String debugId, boolean crosslinkMode,
|
private boolean checkSingleInputChest(UUID ownerUUID, Location location, String debugId, boolean crosslinkMode,
|
||||||
Map<String, List<Location>> preloadedTargets, Location preloadedRest) {
|
Map<String, List<Location>> preloadedTargets, List<Location> preloadedRests) {
|
||||||
if (isWorldBlacklisted(location.getWorld())) return true;
|
if (isWorldBlacklisted(location.getWorld())) return true;
|
||||||
if (!(location.getBlock().getState() instanceof Chest)) return false;
|
if (!(location.getBlock().getState() instanceof Chest)) return false;
|
||||||
|
|
||||||
@@ -2599,7 +2808,7 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
|
|
||||||
// Wenn preloadedTargets null: synchron laden (Fallback)
|
// Wenn preloadedTargets null: synchron laden (Fallback)
|
||||||
Map<String, List<Location>> effectiveTargets = preloadedTargets;
|
Map<String, List<Location>> effectiveTargets = preloadedTargets;
|
||||||
Location effectiveRest = preloadedRest;
|
List<Location> effectiveRests = preloadedRests;
|
||||||
if (effectiveTargets == null) {
|
if (effectiveTargets == null) {
|
||||||
effectiveTargets = new HashMap<>();
|
effectiveTargets = new HashMap<>();
|
||||||
if (mysqlEnabled && mysqlManager != null) {
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
@@ -2625,22 +2834,23 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (effectiveRest == null && preloadedTargets == null) {
|
// BUG FIX: Rest-Truhen als Liste laden wenn nicht vorgeladen
|
||||||
effectiveRest = getRestChestLocation(ownerUUID);
|
if (effectiveRests == null) {
|
||||||
|
effectiveRests = getRestChestLocations(ownerUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
distributeItemsForOwner(ownerUUID, ownerPlayer, chest.getInventory(), ownerName, location, effectiveTargets, effectiveRest);
|
distributeItemsForOwner(ownerUUID, ownerPlayer, chest.getInventory(), ownerName, location, effectiveTargets, effectiveRests);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Oeffentliche Variante mit vorgeladenen Truhen-Locations (kein DB-Hit im Main Thread).
|
* Oeffentliche Variante mit vorgeladenen Truhen-Locations (kein DB-Hit im Main Thread).
|
||||||
* targetChestMap: Material-Name → Location (lokale Zieltruhen)
|
* targetChestMap: Material-Name → Location (lokale Zieltruhen)
|
||||||
* restChestLoc: lokale Rest-Truhe oder null
|
* restChestLocs: lokale Rest-Truhen oder leere Liste
|
||||||
*/
|
*/
|
||||||
private void distributeItemsForOwner(UUID ownerUUID, Player ownerPlayer, Inventory sourceInventory,
|
private void distributeItemsForOwner(UUID ownerUUID, Player ownerPlayer, Inventory sourceInventory,
|
||||||
String ownerNameOverride, Location sourceLocation,
|
String ownerNameOverride, Location sourceLocation,
|
||||||
Map<String, List<Location>> targetChestMap, Location restChestLoc) {
|
Map<String, List<Location>> targetChestMap, List<Location> restChestLocs) {
|
||||||
|
|
||||||
boolean hasItems = false;
|
boolean hasItems = false;
|
||||||
for (ItemStack item : sourceInventory.getContents()) {
|
for (ItemStack item : sourceInventory.getContents()) {
|
||||||
@@ -2658,8 +2868,11 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
if (offlinePlayer.hasPlayedBefore()) ownerName = offlinePlayer.getName();
|
if (offlinePlayer.hasPlayedBefore()) ownerName = offlinePlayer.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
Location restChestLocation = restChestLoc;
|
// BUG FIX: Rest-Truhen als Liste verwalten
|
||||||
boolean restChestKnownFull = (restChestLocation != null) && isChestCachedFull(restChestLocation);
|
List<Location> restChestLocations = (restChestLocs != null) ? restChestLocs : new ArrayList<>();
|
||||||
|
// Alle vollen Rest-Truhen ermitteln
|
||||||
|
boolean allRestChestsFull = !restChestLocations.isEmpty()
|
||||||
|
&& restChestLocations.stream().allMatch(l -> l != null && isChestCachedFull(l));
|
||||||
|
|
||||||
for (int slot = 0; slot < sourceInventory.getSize(); slot++) {
|
for (int slot = 0; slot < sourceInventory.getSize(); slot++) {
|
||||||
ItemStack item = sourceInventory.getItem(slot);
|
ItemStack item = sourceInventory.getItem(slot);
|
||||||
@@ -2676,12 +2889,16 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
boolean isRestChest = false;
|
boolean isRestChest = false;
|
||||||
boolean isCrosslink = false;
|
boolean isCrosslink = false;
|
||||||
|
// Aktive Rest-Truhe für dieses Item (erste nicht-volle)
|
||||||
|
Location activeRestChestLocation = null;
|
||||||
|
for (Location loc : restChestLocations) {
|
||||||
|
if (loc != null && !isChestCachedFull(loc)) { activeRestChestLocation = loc; break; }
|
||||||
|
}
|
||||||
|
|
||||||
if (targetChestLocation == null) {
|
if (targetChestLocation == null) {
|
||||||
if (serverCrosslink && mysqlEnabled && mysqlManager != null) {
|
if (serverCrosslink && mysqlEnabled && mysqlManager != null) {
|
||||||
Map<String, Object> raw = mysqlManager.getTargetChest(ownerUUID.toString(), item.getType().name());
|
Map<String, Object> raw = mysqlManager.getTargetChest(ownerUUID.toString(), item.getType().name());
|
||||||
if (raw != null && isRemoteChest(raw)) {
|
if (raw != null && isRemoteChest(raw)) {
|
||||||
// ── BungeeCord NEU: expliziten Ziel-Server mitgeben ───────────
|
|
||||||
String targetServerName = getChestServer(raw);
|
String targetServerName = getChestServer(raw);
|
||||||
isCrosslink = true;
|
isCrosslink = true;
|
||||||
mysqlManager.setupTransferTable();
|
mysqlManager.setupTransferTable();
|
||||||
@@ -2698,27 +2915,31 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isCrosslink) {
|
if (!isCrosslink) {
|
||||||
if (restChestKnownFull) continue;
|
// BUG FIX: Alle Rest-Truhen prüfen, nicht nur eine
|
||||||
|
if (allRestChestsFull) continue;
|
||||||
|
|
||||||
if (restChestLocation != null) {
|
if (activeRestChestLocation != null) {
|
||||||
targetChestLocation = restChestLocation;
|
targetChestLocation = activeRestChestLocation;
|
||||||
isRestChest = true;
|
isRestChest = true;
|
||||||
} else if (serverCrosslink && mysqlEnabled && mysqlManager != null) {
|
} else if (serverCrosslink && mysqlEnabled && mysqlManager != null) {
|
||||||
Map<String, Object> raw = mysqlManager.getRestChest(ownerUUID.toString());
|
// Crosslink: Remote Rest-Truhe suchen
|
||||||
if (raw != null && isRemoteChest(raw)) {
|
for (Map<String, Object> raw : mysqlManager.getRestChests(ownerUUID.toString())) {
|
||||||
// ── BungeeCord NEU: expliziten Ziel-Server mitgeben ─────
|
if (raw != null && isRemoteChest(raw)) {
|
||||||
String targetServerName = getChestServer(raw);
|
String targetServerName = getChestServer(raw);
|
||||||
mysqlManager.setupTransferTable();
|
mysqlManager.setupTransferTable();
|
||||||
mysqlManager.addTransfer(ownerUUID.toString(), item.getType().name(), item.getAmount(),
|
mysqlManager.addTransfer(ownerUUID.toString(), item.getType().name(), item.getAmount(),
|
||||||
(String) raw.get("world"), targetServerName, serverName);
|
(String) raw.get("world"), targetServerName, serverName);
|
||||||
sourceInventory.setItem(slot, null);
|
sourceInventory.setItem(slot, null);
|
||||||
if (isDebug()) {
|
if (isDebug()) {
|
||||||
getLogger().info("[CrossLink] " + item.getAmount() + "x " + item.getType().name()
|
getLogger().info("[CrossLink] " + item.getAmount() + "x " + item.getType().name()
|
||||||
+ " → Server:'" + (targetServerName.isEmpty() ? "?" : targetServerName)
|
+ " → Server:'" + (targetServerName.isEmpty() ? "?" : targetServerName)
|
||||||
+ "' Welt:'" + raw.get("world") + "' (Rest-Transfer-DB)");
|
+ "' Welt:'" + raw.get("world") + "' (Rest-Transfer-DB)");
|
||||||
|
}
|
||||||
|
isCrosslink = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
if (isCrosslink) continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -2741,9 +2962,36 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
if (ownerPlayer != null && canSendFullChestMessage(ownerUUID, item.getType())) {
|
if (ownerPlayer != null && canSendFullChestMessage(ownerUUID, item.getType())) {
|
||||||
ownerPlayer.sendMessage(getMessage("target-chest-missing").replace("%item%", isRestChest ? "Rest-Truhe" : item.getType().name()));
|
ownerPlayer.sendMessage(getMessage("target-chest-missing").replace("%item%", isRestChest ? "Rest-Truhe" : item.getType().name()));
|
||||||
}
|
}
|
||||||
if (isRestChest) playerData.set("players." + ownerUUID + ".rest-chest", null);
|
// BUG FIX: Beim MySQL-Modus playerData nicht anfassen; bei YAML korrekte Pfade
|
||||||
else playerData.set("players." + ownerUUID + ".target-chests." + item.getType().name(), null);
|
if (isRestChest) {
|
||||||
savePlayerData();
|
if (mysqlEnabled && mysqlManager != null) {
|
||||||
|
mysqlManager.removeRestChestByLocation(ownerUUID.toString(),
|
||||||
|
targetChestLocation.getWorld().getName(),
|
||||||
|
targetChestLocation.getBlockX(), targetChestLocation.getBlockY(), targetChestLocation.getBlockZ());
|
||||||
|
} else {
|
||||||
|
String basePath = "players." + ownerUUID + ".rest-chests";
|
||||||
|
if (playerData.contains(basePath)) {
|
||||||
|
for (String slotKey : new ArrayList<>(playerData.getConfigurationSection(basePath).getKeys(false))) {
|
||||||
|
String rPath = basePath + "." + slotKey;
|
||||||
|
if (targetChestLocation.getWorld().getName().equals(playerData.getString(rPath + ".world"))
|
||||||
|
&& targetChestLocation.getBlockX() == playerData.getInt(rPath + ".x")
|
||||||
|
&& targetChestLocation.getBlockY() == playerData.getInt(rPath + ".y")
|
||||||
|
&& targetChestLocation.getBlockZ() == playerData.getInt(rPath + ".z")) {
|
||||||
|
playerData.set(rPath, null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Legacy
|
||||||
|
playerData.set("players." + ownerUUID + ".rest-chest", null);
|
||||||
|
savePlayerData();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!mysqlEnabled) {
|
||||||
|
playerData.set("players." + ownerUUID + ".target-chests." + item.getType().name(), null);
|
||||||
|
savePlayerData();
|
||||||
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2782,7 +3030,6 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
|
|
||||||
if (isFull) {
|
if (isFull) {
|
||||||
markChestFull(targetChestLocation);
|
markChestFull(targetChestLocation);
|
||||||
if (isRestChest) restChestKnownFull = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signBlock != null) {
|
if (signBlock != null) {
|
||||||
@@ -2829,19 +3076,41 @@ public class Main extends JavaPlugin implements Listener, CommandExecutor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isFull && isRestChest) {
|
if (isFull && isRestChest) {
|
||||||
if (ownerPlayer != null && canSendFullChestMessage(ownerUUID, item.getType())) {
|
// BUG FIX: Nächste Rest-Truhe versuchen
|
||||||
String message = getMessage("target-chest-full")
|
Location nextRestLoc = null;
|
||||||
.replace("%item%", item.getType().name())
|
for (Location loc : restChestLocations) {
|
||||||
.replace("%x%", String.valueOf(targetChestLocation.getBlockX()))
|
if (loc != null && !isChestCachedFull(loc) && !loc.equals(targetChestLocation)) {
|
||||||
.replace("%y%", String.valueOf(targetChestLocation.getBlockY()))
|
nextRestLoc = loc; break;
|
||||||
.replace("%z%", String.valueOf(targetChestLocation.getBlockZ()));
|
}
|
||||||
ownerPlayer.sendMessage(message);
|
|
||||||
}
|
}
|
||||||
for (ItemStack leftoverItem : leftover.values()) {
|
if (nextRestLoc != null && nextRestLoc.getBlock().getState() instanceof Chest) {
|
||||||
if (leftoverItem != null && leftoverItem.getType() == item.getType()) {
|
Chest nextRestChest = (Chest) nextRestLoc.getBlock().getState();
|
||||||
item.setAmount(leftoverItem.getAmount());
|
Map<Integer, ItemStack> leftover2 = nextRestChest.getInventory().addItem(
|
||||||
|
leftover.isEmpty() ? new ItemStack(item.getType(), 0) : leftover.get(0).clone());
|
||||||
|
if (leftover2.isEmpty()) {
|
||||||
|
sourceInventory.setItem(slot, null);
|
||||||
|
spawnTransferParticles(null, nextRestLoc);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
item.setAmount(leftover2.get(0).getAmount());
|
||||||
sourceInventory.setItem(slot, item);
|
sourceInventory.setItem(slot, item);
|
||||||
break;
|
}
|
||||||
|
} else {
|
||||||
|
// Alle Rest-Truhen voll: Nachricht senden
|
||||||
|
if (ownerPlayer != null && canSendFullChestMessage(ownerUUID, item.getType())) {
|
||||||
|
String message = getMessage("target-chest-full")
|
||||||
|
.replace("%item%", item.getType().name())
|
||||||
|
.replace("%x%", String.valueOf(targetChestLocation.getBlockX()))
|
||||||
|
.replace("%y%", String.valueOf(targetChestLocation.getBlockY()))
|
||||||
|
.replace("%z%", String.valueOf(targetChestLocation.getBlockZ()));
|
||||||
|
ownerPlayer.sendMessage(message);
|
||||||
|
}
|
||||||
|
for (ItemStack leftoverItem : leftover.values()) {
|
||||||
|
if (leftoverItem != null && leftoverItem.getType() == item.getType()) {
|
||||||
|
item.setAmount(leftoverItem.getAmount());
|
||||||
|
sourceInventory.setItem(slot, item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,39 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migriert den PRIMARY KEY der asc_rest_chests von (uuid) auf (uuid, slot) falls nötig.
|
||||||
|
* Ermöglicht mehrere Rest-Truhen pro Spieler.
|
||||||
|
*/
|
||||||
|
private void migrateRestChestPrimaryKey(Statement st) {
|
||||||
|
try {
|
||||||
|
// Slot-Spalte zuerst sicherstellen
|
||||||
|
if (!columnExists("asc_rest_chests", "slot")) {
|
||||||
|
st.execute("ALTER TABLE asc_rest_chests ADD COLUMN slot INT NOT NULL DEFAULT 0;");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüfen ob slot bereits im PRIMARY KEY ist
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"SELECT COUNT(*) FROM information_schema.KEY_COLUMN_USAGE " +
|
||||||
|
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'asc_rest_chests' " +
|
||||||
|
"AND CONSTRAINT_NAME = 'PRIMARY' AND COLUMN_NAME = 'slot';")) {
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if (rs.next() && rs.getInt(1) > 0) {
|
||||||
|
rs.close();
|
||||||
|
return; // Bereits migriert
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alten PK droppen und neuen mit slot anlegen
|
||||||
|
st.execute("ALTER TABLE asc_rest_chests DROP PRIMARY KEY, ADD PRIMARY KEY(uuid, slot);");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
if (!e.getMessage().toLowerCase().contains("primary")) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migriert den PRIMARY KEY von (uuid, item) auf (uuid, item, slot) falls nötig.
|
* Migriert den PRIMARY KEY von (uuid, item) auf (uuid, item, slot) falls nötig.
|
||||||
* Nutzt DATABASE() um nur die aktuelle DB zu prüfen (kein Cross-DB-Problem).
|
* Nutzt DATABASE() um nur die aktuelle DB zu prüfen (kein Cross-DB-Problem).
|
||||||
@@ -88,7 +121,7 @@ public class MySQLManager {
|
|||||||
*/
|
*/
|
||||||
private void tryAlterColumn(Statement st, String table, String column, String definition) {
|
private void tryAlterColumn(Statement st, String table, String column, String definition) {
|
||||||
try {
|
try {
|
||||||
ResultSet rs = st.getConnection().getMetaData().getColumns(null, null, table, column);
|
ResultSet rs = st.getConnection().getMetaData().getColumns(connection.getCatalog(), null, table, column);
|
||||||
if (!rs.next()) {
|
if (!rs.next()) {
|
||||||
st.execute("ALTER TABLE " + table + " ADD COLUMN " + column + " " + definition + ";");
|
st.execute("ALTER TABLE " + table + " ADD COLUMN " + column + " " + definition + ";");
|
||||||
}
|
}
|
||||||
@@ -105,7 +138,7 @@ public class MySQLManager {
|
|||||||
*/
|
*/
|
||||||
private boolean columnExists(String table, String column) {
|
private boolean columnExists(String table, String column) {
|
||||||
try {
|
try {
|
||||||
ResultSet rs = connection.getMetaData().getColumns(null, null, table, column);
|
ResultSet rs = connection.getMetaData().getColumns(connection.getCatalog(), null, table, column);
|
||||||
boolean exists = rs.next();
|
boolean exists = rs.next();
|
||||||
rs.close();
|
rs.close();
|
||||||
return exists;
|
return exists;
|
||||||
@@ -168,9 +201,10 @@ public class MySQLManager {
|
|||||||
");");
|
");");
|
||||||
|
|
||||||
st.execute("CREATE TABLE IF NOT EXISTS asc_rest_chests (" +
|
st.execute("CREATE TABLE IF NOT EXISTS asc_rest_chests (" +
|
||||||
"uuid VARCHAR(36), world VARCHAR(32)," +
|
"uuid VARCHAR(36), slot INT NOT NULL DEFAULT 0," +
|
||||||
|
"world VARCHAR(32)," +
|
||||||
"x INT, y INT, z INT, `public` BOOLEAN DEFAULT FALSE," +
|
"x INT, y INT, z INT, `public` BOOLEAN DEFAULT FALSE," +
|
||||||
"PRIMARY KEY(uuid)" +
|
"PRIMARY KEY(uuid, slot)" +
|
||||||
");");
|
");");
|
||||||
|
|
||||||
// ── asc_transfers: immer beim Start sicherstellen ─────────────────────
|
// ── asc_transfers: immer beim Start sicherstellen ─────────────────────
|
||||||
@@ -207,6 +241,9 @@ public class MySQLManager {
|
|||||||
// v2 → v3 (Multi-Target): slot-Spalte + PRIMARY KEY Migration
|
// v2 → v3 (Multi-Target): slot-Spalte + PRIMARY KEY Migration
|
||||||
migrateTargetChestPrimaryKey(st);
|
migrateTargetChestPrimaryKey(st);
|
||||||
|
|
||||||
|
// v2 → v3 (Multi-Rest): slot-Spalte + PRIMARY KEY Migration fuer Rest-Truhen
|
||||||
|
migrateRestChestPrimaryKey(st);
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -593,32 +630,93 @@ public class MySQLManager {
|
|||||||
setRestChest(uuid, world, x, y, z, isPublic, "");
|
setRestChest(uuid, world, x, y, z, isPublic, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** BungeeCord-Überladung mit serverName. */
|
/** BungeeCord-Überladung mit serverName – ermittelt automatisch den nächsten freien Slot. */
|
||||||
public void setRestChest(String uuid, String world, int x, int y, int z,
|
public void setRestChest(String uuid, String world, int x, int y, int z,
|
||||||
boolean isPublic, String serverName) {
|
boolean isPublic, String serverName) {
|
||||||
|
// Prüfen ob diese exakte Location bereits als Rest-Truhe registriert ist (Update)
|
||||||
|
int slot = getRestSlotForLocation(uuid, world, x, y, z);
|
||||||
|
if (slot < 0) {
|
||||||
|
// Neue Truhe: nächsten freien Slot ermitteln
|
||||||
|
slot = getNextRestSlot(uuid);
|
||||||
|
}
|
||||||
|
setRestChest(uuid, slot, world, x, y, z, isPublic, serverName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Vollständige Überladung mit explizitem slot. */
|
||||||
|
public void setRestChest(String uuid, int slot, String world, int x, int y, int z,
|
||||||
|
boolean isPublic, String serverName) {
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"REPLACE INTO asc_rest_chests (uuid, world, x, y, z, `public`, server) " +
|
"REPLACE INTO asc_rest_chests (uuid, slot, world, x, y, z, `public`, server) " +
|
||||||
"VALUES (?, ?, ?, ?, ?, ?, ?);")) {
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?);")) {
|
||||||
ps.setString(1, uuid);
|
ps.setString(1, uuid);
|
||||||
ps.setString(2, world);
|
ps.setInt(2, slot);
|
||||||
ps.setInt(3, x);
|
ps.setString(3, world);
|
||||||
ps.setInt(4, y);
|
ps.setInt(4, x);
|
||||||
ps.setInt(5, z);
|
ps.setInt(5, y);
|
||||||
ps.setBoolean(6, isPublic);
|
ps.setInt(6, z);
|
||||||
ps.setString(7, serverName != null ? serverName : "");
|
ps.setBoolean(7, isPublic);
|
||||||
|
ps.setString(8, serverName != null ? serverName : "");
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> getRestChest(String uuid) {
|
/** Gibt den nächsten freien Slot für Rest-Truhen zurück. */
|
||||||
|
public int getNextRestSlot(String uuid) {
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"SELECT * FROM asc_rest_chests WHERE uuid=?;")) {
|
"SELECT COALESCE(MAX(slot)+1, 0) AS next_slot FROM asc_rest_chests WHERE uuid=?;")) {
|
||||||
ps.setString(1, uuid);
|
ps.setString(1, uuid);
|
||||||
ResultSet rs = ps.executeQuery();
|
ResultSet rs = ps.executeQuery();
|
||||||
if (rs.next()) {
|
if (rs.next()) return rs.getInt("next_slot");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gibt den Slot zurück, den diese Location bereits belegt, oder -1 wenn nicht gefunden.
|
||||||
|
*/
|
||||||
|
public int getRestSlotForLocation(String uuid, String world, int x, int y, int z) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"SELECT slot FROM asc_rest_chests WHERE uuid=? AND world=? AND x=? AND y=? AND z=?;")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.setString(2, world);
|
||||||
|
ps.setInt(3, x);
|
||||||
|
ps.setInt(4, y);
|
||||||
|
ps.setInt(5, z);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if (rs.next()) return rs.getInt("slot");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Zählt wie viele Rest-Truhen ein Spieler hat. */
|
||||||
|
public int countRestChests(String uuid) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"SELECT COUNT(*) FROM asc_rest_chests WHERE uuid=?;")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if (rs.next()) return rs.getInt(1);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gibt ALLE Rest-Truhen eines Spielers zurück, sortiert nach slot. */
|
||||||
|
public List<Map<String, Object>> getRestChests(String uuid) {
|
||||||
|
List<Map<String, Object>> list = new ArrayList<>();
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"SELECT * FROM asc_rest_chests WHERE uuid=? ORDER BY slot ASC;")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
while (rs.next()) {
|
||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("slot", rs.getInt("slot"));
|
||||||
map.put("world", rs.getString("world"));
|
map.put("world", rs.getString("world"));
|
||||||
map.put("x", rs.getInt("x"));
|
map.put("x", rs.getInt("x"));
|
||||||
map.put("y", rs.getInt("y"));
|
map.put("y", rs.getInt("y"));
|
||||||
@@ -626,14 +724,72 @@ public class MySQLManager {
|
|||||||
map.put("public", rs.getBoolean("public"));
|
map.put("public", rs.getBoolean("public"));
|
||||||
try { map.put("server", rs.getString("server")); }
|
try { map.put("server", rs.getString("server")); }
|
||||||
catch (SQLException ignored) { map.put("server", ""); }
|
catch (SQLException ignored) { map.put("server", ""); }
|
||||||
return map;
|
list.add(map);
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Gibt die erste Rest-Truhe (slot=0) zurück – Legacy-Kompatibilität. */
|
||||||
|
public Map<String, Object> getRestChest(String uuid) {
|
||||||
|
List<Map<String, Object>> all = getRestChests(uuid);
|
||||||
|
return all.isEmpty() ? null : all.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Löscht eine spezifische Rest-Truhe anhand ihrer Location. */
|
||||||
|
public void removeRestChestByLocation(String uuid, String world, int x, int y, int z) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"DELETE FROM asc_rest_chests WHERE uuid=? AND world=? AND x=? AND y=? AND z=?;")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.setString(2, world);
|
||||||
|
ps.setInt(3, x);
|
||||||
|
ps.setInt(4, y);
|
||||||
|
ps.setInt(5, z);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
// Slots nach dem gelöschten nach unten schieben um Lücken zu vermeiden
|
||||||
|
compactRestSlots(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Löscht eine spezifische Rest-Truhe anhand des Slots. */
|
||||||
|
public void removeRestChestSlot(String uuid, int slot) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"DELETE FROM asc_rest_chests WHERE uuid=? AND slot=?;")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.setInt(2, slot);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
compactRestSlots(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Schiebt Rest-Slots nach dem gelöschten nach unten (keine Lücken). */
|
||||||
|
private void compactRestSlots(String uuid) {
|
||||||
|
try {
|
||||||
|
List<Map<String, Object>> remaining = getRestChests(uuid);
|
||||||
|
for (int i = 0; i < remaining.size(); i++) {
|
||||||
|
int currentSlot = (int) remaining.get(i).get("slot");
|
||||||
|
if (currentSlot != i) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"UPDATE asc_rest_chests SET slot=? WHERE uuid=? AND slot=?;")) {
|
||||||
|
ps.setInt(1, i);
|
||||||
|
ps.setString(2, uuid);
|
||||||
|
ps.setInt(3, currentSlot);
|
||||||
|
ps.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Löscht ALLE Rest-Truhen eines Spielers. */
|
||||||
public void removeRestChest(String uuid) {
|
public void removeRestChest(String uuid) {
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"DELETE FROM asc_rest_chests WHERE uuid=?;")) {
|
"DELETE FROM asc_rest_chests WHERE uuid=?;")) {
|
||||||
@@ -694,11 +850,12 @@ public class MySQLManager {
|
|||||||
|
|
||||||
public Map<String, Object> getAnyRestChest() {
|
public Map<String, Object> getAnyRestChest() {
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"SELECT * FROM asc_rest_chests WHERE public=1 LIMIT 1;")) {
|
"SELECT * FROM asc_rest_chests WHERE `public`=1 ORDER BY uuid, slot LIMIT 1;")) {
|
||||||
ResultSet rs = ps.executeQuery();
|
ResultSet rs = ps.executeQuery();
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
map.put("uuid", rs.getString("uuid"));
|
map.put("uuid", rs.getString("uuid"));
|
||||||
|
map.put("slot", rs.getInt("slot"));
|
||||||
map.put("world", rs.getString("world"));
|
map.put("world", rs.getString("world"));
|
||||||
map.put("x", rs.getInt("x"));
|
map.put("x", rs.getInt("x"));
|
||||||
map.put("y", rs.getInt("y"));
|
map.put("y", rs.getInt("y"));
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# --- GRUNDLEGUNG ---
|
# --- GRUNDLEGUNG ---
|
||||||
# Version der Konfigurationsdatei. Nicht ändern, um Fehler zu vermeiden!
|
# Version der Konfigurationsdatei. Nicht ändern, um Fehler zu vermeiden!
|
||||||
|
|
||||||
version: "2.0"
|
version: "2.2"
|
||||||
|
|
||||||
# Debug-Modus (true = Ausführliche Logs in der Server-Konsole, nur zum Entwickeln nutzen)
|
# Debug-Modus (true = Ausführliche Logs in der Server-Konsole, nur zum Entwickeln nutzen)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: AutoSortChest
|
name: AutoSortChest
|
||||||
version: 2.2
|
version: 2.3
|
||||||
main: com.viper.autosortchest.Main
|
main: com.viper.autosortchest.Main
|
||||||
api-version: 1.21
|
api-version: 1.21
|
||||||
authors: [M_Viper]
|
authors: [M_Viper]
|
||||||
@@ -24,4 +24,10 @@ permissions:
|
|||||||
default: op
|
default: op
|
||||||
autosortchest.admin:
|
autosortchest.admin:
|
||||||
description: Erlaubt OPs/Admins Zugriff auf fremde AutoSortChest-Truhen (Öffnen, Entnehmen, Abbauen)
|
description: Erlaubt OPs/Admins Zugriff auf fremde AutoSortChest-Truhen (Öffnen, Entnehmen, Abbauen)
|
||||||
default: op
|
default: op
|
||||||
|
autosortchest.limit.<gruppe>:
|
||||||
|
description: >
|
||||||
|
Limits fuer eine benutzerdefinierte Gruppe aus der config.yml.
|
||||||
|
Ersetze <gruppe> durch den Gruppennamen (z.B. autosortchest.limit.vip).
|
||||||
|
Die Gruppen und ihre Limits werden ausschliesslich in der config.yml definiert.
|
||||||
|
default: false
|
||||||
Reference in New Issue
Block a user