Update from Git Manager GUI
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -111,6 +111,26 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stellt sicher, dass die Verbindung offen ist.
|
||||||
|
* Reconnect-Logik für den Fall, dass die MySQL-Verbindung abgelaufen ist
|
||||||
|
* (z.B. nach wait_timeout, Netzwerk-Unterbrechung).
|
||||||
|
* Wird vor jeder DB-Operation aufgerufen.
|
||||||
|
*/
|
||||||
|
private void ensureConnected() {
|
||||||
|
try {
|
||||||
|
if (connection == null || connection.isClosed() || !connection.isValid(2)) {
|
||||||
|
connection = DriverManager.getConnection(
|
||||||
|
"jdbc:mysql://" + host + ":" + port + "/" + database
|
||||||
|
+ "?useSSL=false&autoReconnect=true&characterEncoding=UTF-8&serverTimezone=UTC",
|
||||||
|
user, password
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
// BungeeCord-Erweiterung: Sanfte Schema-Migration
|
// BungeeCord-Erweiterung: Sanfte Schema-Migration
|
||||||
// Fügt eine Spalte hinzu, falls sie noch nicht existiert.
|
// Fügt eine Spalte hinzu, falls sie noch nicht existiert.
|
||||||
@@ -179,6 +199,7 @@ public class MySQLManager {
|
|||||||
* asc_transfers (CrossLink Transfers)
|
* asc_transfers (CrossLink Transfers)
|
||||||
*/
|
*/
|
||||||
public void setupTables() {
|
public void setupTables() {
|
||||||
|
ensureConnected();
|
||||||
try (Statement st = connection.createStatement()) {
|
try (Statement st = connection.createStatement()) {
|
||||||
|
|
||||||
// ── Basis-Tabellen anlegen (falls nicht vorhanden) ────────────────────
|
// ── Basis-Tabellen anlegen (falls nicht vorhanden) ────────────────────
|
||||||
@@ -229,6 +250,17 @@ public class MySQLManager {
|
|||||||
// Jede Migration ist idempotent – mehrfaches Ausführen schadet nicht.
|
// Jede Migration ist idempotent – mehrfaches Ausführen schadet nicht.
|
||||||
// ══════════════════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
// ── Mülltruchen-Tabellen ──────────────────────────────────────────────
|
||||||
|
st.execute("CREATE TABLE IF NOT EXISTS asc_trash_chests (" +
|
||||||
|
"uuid VARCHAR(36) PRIMARY KEY, world VARCHAR(32)," +
|
||||||
|
"x INT, y INT, z INT, server VARCHAR(64) DEFAULT ''" +
|
||||||
|
");");
|
||||||
|
|
||||||
|
st.execute("CREATE TABLE IF NOT EXISTS asc_trash_items (" +
|
||||||
|
"uuid VARCHAR(36), item VARCHAR(64)," +
|
||||||
|
"PRIMARY KEY(uuid, item)" +
|
||||||
|
");");
|
||||||
|
|
||||||
// v1 → v2 (BungeeCord): server-Spalten
|
// v1 → v2 (BungeeCord): server-Spalten
|
||||||
tryAlterColumn(st, "asc_input_chests", "server", "VARCHAR(64) DEFAULT ''");
|
tryAlterColumn(st, "asc_input_chests", "server", "VARCHAR(64) DEFAULT ''");
|
||||||
tryAlterColumn(st, "asc_target_chests", "server", "VARCHAR(64) DEFAULT ''");
|
tryAlterColumn(st, "asc_target_chests", "server", "VARCHAR(64) DEFAULT ''");
|
||||||
@@ -265,6 +297,7 @@ public class MySQLManager {
|
|||||||
*/
|
*/
|
||||||
public void heartbeat(String serverName) {
|
public void heartbeat(String serverName) {
|
||||||
if (serverName == null || serverName.isEmpty()) return;
|
if (serverName == null || serverName.isEmpty()) return;
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"REPLACE INTO asc_servers (server_name, last_seen) VALUES (?, NOW());")) {
|
"REPLACE INTO asc_servers (server_name, last_seen) VALUES (?, NOW());")) {
|
||||||
ps.setString(1, serverName);
|
ps.setString(1, serverName);
|
||||||
@@ -280,6 +313,7 @@ public class MySQLManager {
|
|||||||
*/
|
*/
|
||||||
public void addTransfer(String uuid, String item, int amount,
|
public void addTransfer(String uuid, String item, int amount,
|
||||||
String targetWorld, String targetServer, String sourceServer) {
|
String targetWorld, String targetServer, String sourceServer) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"INSERT INTO asc_transfers (uuid, item, amount, target_world, target_server, source_server) " +
|
"INSERT INTO asc_transfers (uuid, item, amount, target_world, target_server, source_server) " +
|
||||||
"VALUES (?, ?, ?, ?, ?, ?);")) {
|
"VALUES (?, ?, ?, ?, ?, ?);")) {
|
||||||
@@ -348,6 +382,7 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void deleteTransfer(long id) {
|
public void deleteTransfer(long id) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"DELETE FROM asc_transfers WHERE id=?;")) {
|
"DELETE FROM asc_transfers WHERE id=?;")) {
|
||||||
ps.setLong(1, id);
|
ps.setLong(1, id);
|
||||||
@@ -358,6 +393,7 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateTransferAmount(long id, int newAmount) {
|
public void updateTransferAmount(long id, int newAmount) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"UPDATE asc_transfers SET amount=? WHERE id=?;")) {
|
"UPDATE asc_transfers SET amount=? WHERE id=?;")) {
|
||||||
ps.setInt(1, newAmount);
|
ps.setInt(1, newAmount);
|
||||||
@@ -371,6 +407,7 @@ public class MySQLManager {
|
|||||||
// --- Spieler ---
|
// --- Spieler ---
|
||||||
|
|
||||||
public void savePlayer(String uuid, String name) {
|
public void savePlayer(String uuid, String name) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"REPLACE INTO asc_players (uuid, name) VALUES (?, ?);")) {
|
"REPLACE INTO asc_players (uuid, name) VALUES (?, ?);")) {
|
||||||
ps.setString(1, uuid);
|
ps.setString(1, uuid);
|
||||||
@@ -382,6 +419,7 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Map<String, Object>> getAllPlayers() {
|
public List<Map<String, Object>> getAllPlayers() {
|
||||||
|
ensureConnected();
|
||||||
List<Map<String, Object>> list = new ArrayList<>();
|
List<Map<String, Object>> list = new ArrayList<>();
|
||||||
try (Statement st = connection.createStatement();
|
try (Statement st = connection.createStatement();
|
||||||
ResultSet rs = st.executeQuery("SELECT uuid, name FROM asc_players;")) {
|
ResultSet rs = st.executeQuery("SELECT uuid, name FROM asc_players;")) {
|
||||||
@@ -410,6 +448,7 @@ public class MySQLManager {
|
|||||||
/** BungeeCord-Überladung mit serverName. */
|
/** BungeeCord-Überladung mit serverName. */
|
||||||
public void addInputChest(String uuid, String chestId, String world,
|
public void addInputChest(String uuid, String chestId, String world,
|
||||||
int x, int y, int z, boolean isPublic, String serverName) {
|
int x, int y, int z, boolean isPublic, String serverName) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"REPLACE INTO asc_input_chests (uuid, chest_id, world, x, y, z, `public`, server) " +
|
"REPLACE INTO asc_input_chests (uuid, chest_id, world, x, y, z, `public`, server) " +
|
||||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?);")) {
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?);")) {
|
||||||
@@ -428,6 +467,7 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeInputChest(String uuid, String chestId) {
|
public void removeInputChest(String uuid, String chestId) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"DELETE FROM asc_input_chests WHERE uuid=? AND chest_id=?;")) {
|
"DELETE FROM asc_input_chests WHERE uuid=? AND chest_id=?;")) {
|
||||||
ps.setString(1, uuid);
|
ps.setString(1, uuid);
|
||||||
@@ -439,6 +479,7 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Map<String, Object>> getInputChests(String uuid) {
|
public List<Map<String, Object>> getInputChests(String uuid) {
|
||||||
|
ensureConnected();
|
||||||
List<Map<String, Object>> list = new ArrayList<>();
|
List<Map<String, Object>> list = new ArrayList<>();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"SELECT * FROM asc_input_chests WHERE uuid=?;")) {
|
"SELECT * FROM asc_input_chests WHERE uuid=?;")) {
|
||||||
@@ -481,6 +522,7 @@ public class MySQLManager {
|
|||||||
/** Vollständige Überladung mit slot für Multi-Target-Support. */
|
/** Vollständige Überladung mit slot für Multi-Target-Support. */
|
||||||
public void setTargetChest(String uuid, String item, int slot, String world,
|
public void setTargetChest(String uuid, String item, int slot, String world,
|
||||||
int x, int y, int z, boolean isPublic, String serverName) {
|
int x, int y, int z, boolean isPublic, String serverName) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"REPLACE INTO asc_target_chests (uuid, item, slot, world, x, y, z, `public`, server) " +
|
"REPLACE INTO asc_target_chests (uuid, item, slot, world, x, y, z, `public`, server) " +
|
||||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);")) {
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);")) {
|
||||||
@@ -558,6 +600,7 @@ public class MySQLManager {
|
|||||||
|
|
||||||
/** Gibt ALLE Zieltruhen für ein bestimmtes Item zurück, sortiert nach slot. */
|
/** Gibt ALLE Zieltruhen für ein bestimmtes Item zurück, sortiert nach slot. */
|
||||||
public List<Map<String, Object>> getTargetChestsForItem(String uuid, String item) {
|
public List<Map<String, Object>> getTargetChestsForItem(String uuid, String item) {
|
||||||
|
ensureConnected();
|
||||||
List<Map<String, Object>> list = new ArrayList<>();
|
List<Map<String, Object>> list = new ArrayList<>();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"SELECT * FROM asc_target_chests WHERE uuid=? AND item=? ORDER BY slot ASC;")) {
|
"SELECT * FROM asc_target_chests WHERE uuid=? AND item=? ORDER BY slot ASC;")) {
|
||||||
@@ -584,6 +627,7 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeTargetChest(String uuid, String item) {
|
public void removeTargetChest(String uuid, String item) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"DELETE FROM asc_target_chests WHERE uuid=? AND item=?;")) {
|
"DELETE FROM asc_target_chests WHERE uuid=? AND item=?;")) {
|
||||||
ps.setString(1, uuid);
|
ps.setString(1, uuid);
|
||||||
@@ -596,6 +640,7 @@ public class MySQLManager {
|
|||||||
|
|
||||||
/** Gibt alle Zieltruhen eines Spielers zurück, sortiert nach item + slot. */
|
/** Gibt alle Zieltruhen eines Spielers zurück, sortiert nach item + slot. */
|
||||||
public List<Map<String, Object>> getTargetChests(String uuid) {
|
public List<Map<String, Object>> getTargetChests(String uuid) {
|
||||||
|
ensureConnected();
|
||||||
List<Map<String, Object>> list = new ArrayList<>();
|
List<Map<String, Object>> list = new ArrayList<>();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"SELECT * FROM asc_target_chests WHERE uuid=? ORDER BY item ASC, slot ASC;")) {
|
"SELECT * FROM asc_target_chests WHERE uuid=? ORDER BY item ASC, slot ASC;")) {
|
||||||
@@ -645,6 +690,7 @@ public class MySQLManager {
|
|||||||
/** Vollständige Überladung mit explizitem slot. */
|
/** Vollständige Überladung mit explizitem slot. */
|
||||||
public void setRestChest(String uuid, int slot, String world, int x, int y, int z,
|
public void setRestChest(String uuid, int slot, String world, int x, int y, int z,
|
||||||
boolean isPublic, String serverName) {
|
boolean isPublic, String serverName) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"REPLACE INTO asc_rest_chests (uuid, slot, world, x, y, z, `public`, server) " +
|
"REPLACE INTO asc_rest_chests (uuid, slot, world, x, y, z, `public`, server) " +
|
||||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?);")) {
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?);")) {
|
||||||
@@ -696,6 +742,7 @@ public class MySQLManager {
|
|||||||
|
|
||||||
/** Zählt wie viele Rest-Truhen ein Spieler hat. */
|
/** Zählt wie viele Rest-Truhen ein Spieler hat. */
|
||||||
public int countRestChests(String uuid) {
|
public int countRestChests(String uuid) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"SELECT COUNT(*) FROM asc_rest_chests WHERE uuid=?;")) {
|
"SELECT COUNT(*) FROM asc_rest_chests WHERE uuid=?;")) {
|
||||||
ps.setString(1, uuid);
|
ps.setString(1, uuid);
|
||||||
@@ -709,6 +756,7 @@ public class MySQLManager {
|
|||||||
|
|
||||||
/** Gibt ALLE Rest-Truhen eines Spielers zurück, sortiert nach slot. */
|
/** Gibt ALLE Rest-Truhen eines Spielers zurück, sortiert nach slot. */
|
||||||
public List<Map<String, Object>> getRestChests(String uuid) {
|
public List<Map<String, Object>> getRestChests(String uuid) {
|
||||||
|
ensureConnected();
|
||||||
List<Map<String, Object>> list = new ArrayList<>();
|
List<Map<String, Object>> list = new ArrayList<>();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"SELECT * FROM asc_rest_chests WHERE uuid=? ORDER BY slot ASC;")) {
|
"SELECT * FROM asc_rest_chests WHERE uuid=? ORDER BY slot ASC;")) {
|
||||||
@@ -740,6 +788,7 @@ public class MySQLManager {
|
|||||||
|
|
||||||
/** Löscht eine spezifische Rest-Truhe anhand ihrer Location. */
|
/** Löscht eine spezifische Rest-Truhe anhand ihrer Location. */
|
||||||
public void removeRestChestByLocation(String uuid, String world, int x, int y, int z) {
|
public void removeRestChestByLocation(String uuid, String world, int x, int y, int z) {
|
||||||
|
ensureConnected();
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"DELETE FROM asc_rest_chests WHERE uuid=? AND world=? AND x=? AND y=? AND z=?;")) {
|
"DELETE FROM asc_rest_chests WHERE uuid=? AND world=? AND x=? AND y=? AND z=?;")) {
|
||||||
ps.setString(1, uuid);
|
ps.setString(1, uuid);
|
||||||
@@ -870,4 +919,198 @@ public class MySQLManager {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// MÜLLTRUCHEN (asc_trash_chests + asc_trash_items)
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
/** Legt eine Mülltruche an oder aktualisiert sie. */
|
||||||
|
public void setTrashChest(String uuid, String world, int x, int y, int z, String server) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"INSERT INTO asc_trash_chests (uuid, world, x, y, z, server) VALUES (?,?,?,?,?,?) " +
|
||||||
|
"ON DUPLICATE KEY UPDATE world=VALUES(world), x=VALUES(x), y=VALUES(y), z=VALUES(z), server=VALUES(server)")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.setString(2, world);
|
||||||
|
ps.setInt(3, x);
|
||||||
|
ps.setInt(4, y);
|
||||||
|
ps.setInt(5, z);
|
||||||
|
ps.setString(6, server == null ? "" : server);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gibt die Mülltruche eines Spielers zurück (nur die des eigenen Servers). */
|
||||||
|
public Map<String, Object> getTrashChest(String uuid, String serverName) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"SELECT * FROM asc_trash_chests WHERE uuid=? AND (server=? OR server='') LIMIT 1")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.setString(2, serverName == null ? "" : serverName);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("world", rs.getString("world"));
|
||||||
|
map.put("x", rs.getInt("x"));
|
||||||
|
map.put("y", rs.getInt("y"));
|
||||||
|
map.put("z", rs.getInt("z"));
|
||||||
|
map.put("server", rs.getString("server"));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gibt ALLE Mülltruchen zurück (für sign-update oder cross-server). */
|
||||||
|
public List<Map<String, Object>> getAllTrashChests() {
|
||||||
|
List<Map<String, Object>> list = new ArrayList<>();
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement("SELECT * FROM asc_trash_chests")) {
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
while (rs.next()) {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("uuid", rs.getString("uuid"));
|
||||||
|
map.put("world", rs.getString("world"));
|
||||||
|
map.put("x", rs.getInt("x"));
|
||||||
|
map.put("y", rs.getInt("y"));
|
||||||
|
map.put("z", rs.getInt("z"));
|
||||||
|
map.put("server", rs.getString("server"));
|
||||||
|
list.add(map);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Entfernt die Mülltruche eines Spielers. */
|
||||||
|
public void removeTrashChest(String uuid) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"DELETE FROM asc_trash_chests WHERE uuid=?")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Speichert die komplette Filter-Liste (ersetzt alte Einträge). */
|
||||||
|
public void setTrashItems(String uuid, List<String> items) {
|
||||||
|
try (PreparedStatement del = connection.prepareStatement(
|
||||||
|
"DELETE FROM asc_trash_items WHERE uuid=?")) {
|
||||||
|
del.setString(1, uuid);
|
||||||
|
del.executeUpdate();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
if (items == null || items.isEmpty()) return;
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"INSERT IGNORE INTO asc_trash_items (uuid, item) VALUES (?,?)")) {
|
||||||
|
for (String item : items) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.setString(2, item);
|
||||||
|
ps.addBatch();
|
||||||
|
}
|
||||||
|
ps.executeBatch();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Lädt die Filter-Liste eines Spielers. */
|
||||||
|
public List<String> getTrashItems(String uuid) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"SELECT item FROM asc_trash_items WHERE uuid=?")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
while (rs.next()) list.add(rs.getString("item"));
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fügt ein einzelnes Item zur Filter-Liste hinzu. */
|
||||||
|
public void addTrashItem(String uuid, String item) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"INSERT IGNORE INTO asc_trash_items (uuid, item) VALUES (?,?)")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.setString(2, item);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Entfernt ein einzelnes Item aus der Filter-Liste. */
|
||||||
|
public void removeTrashItem(String uuid, String item) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"DELETE FROM asc_trash_items WHERE uuid=? AND item=?")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.setString(2, item);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Entfernt alle Filter-Items eines Spielers. */
|
||||||
|
public void removeAllTrashItems(String uuid) {
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"DELETE FROM asc_trash_items WHERE uuid=?")) {
|
||||||
|
ps.setString(1, uuid);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) { e.printStackTrace(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
// FIX: Einzelne UNION-Abfrage statt 3 separater Queries für isChestPublic()
|
||||||
|
// Reduziert Main-Thread-Blockierung bei MySQL um ~66%.
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
/**
|
||||||
|
* Prüft ob eine Truhen-Location in IRGENDEINER Tabelle als public markiert ist.
|
||||||
|
* Kombiniert Input-, Target- und Rest-Tabelle in einer einzigen UNION-Abfrage.
|
||||||
|
* @return true wenn mindestens eine Zeile `public=TRUE` enthält.
|
||||||
|
*/
|
||||||
|
public boolean isLocationPublic(String world, int x, int y, int z) {
|
||||||
|
ensureConnected();
|
||||||
|
// MySQL erfordert Klammern um einzelne SELECT-Statements wenn LIMIT verwendet wird
|
||||||
|
String sql =
|
||||||
|
"(SELECT 1 FROM asc_input_chests WHERE world=? AND x=? AND y=? AND z=? AND `public`=TRUE LIMIT 1) " +
|
||||||
|
"UNION ALL " +
|
||||||
|
"(SELECT 1 FROM asc_target_chests WHERE world=? AND x=? AND y=? AND z=? AND `public`=TRUE LIMIT 1) " +
|
||||||
|
"UNION ALL " +
|
||||||
|
"(SELECT 1 FROM asc_rest_chests WHERE world=? AND x=? AND y=? AND z=? AND `public`=TRUE LIMIT 1)";
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(sql)) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
int base = i * 4;
|
||||||
|
ps.setString(base + 1, world);
|
||||||
|
ps.setInt (base + 2, x);
|
||||||
|
ps.setInt (base + 3, y);
|
||||||
|
ps.setInt (base + 4, z);
|
||||||
|
}
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
boolean result = rs.next();
|
||||||
|
rs.close();
|
||||||
|
return result;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
// FIX: MySQL-Implementierung für findItemForChestLocation()
|
||||||
|
// Wurde bisher übersprungen – Clean-Sign-Modus + MySQL war dadurch broken.
|
||||||
|
// ═══════════════════════════════════════════════════════════════════
|
||||||
|
/**
|
||||||
|
* Findet den Item-Typ (z.B. "IRON_ORE") der einer Truhen-Location als Zieltruhe
|
||||||
|
* zugewiesen ist. Wird von findItemForChestLocation() im Clean-Sign-Modus benötigt.
|
||||||
|
* @return Material-Name oder null wenn nicht gefunden.
|
||||||
|
*/
|
||||||
|
public String getItemForLocation(String uuid, String world, int x, int y, int z) {
|
||||||
|
ensureConnected();
|
||||||
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
|
"SELECT item FROM asc_target_chests WHERE uuid=? AND world=? AND x=? AND y=? AND z=? LIMIT 1;")) {
|
||||||
|
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()) {
|
||||||
|
String item = rs.getString("item");
|
||||||
|
rs.close();
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
512
src/main/java/com/viper/autosortchest/TrashChestManager.java
Normal file
512
src/main/java/com/viper/autosortchest/TrashChestManager.java
Normal file
@@ -0,0 +1,512 @@
|
|||||||
|
package com.viper.autosortchest;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Chest;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
|
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta;
|
||||||
|
import org.bukkit.profile.PlayerProfile;
|
||||||
|
import org.bukkit.profile.PlayerTextures;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verwaltet Mülltruhen für das AutoSortChest-Plugin.
|
||||||
|
*
|
||||||
|
* Speicherung:
|
||||||
|
* MySQL (wenn aktiv):
|
||||||
|
* asc_trash_chests : uuid, world, x, y, z, server
|
||||||
|
* asc_trash_items : uuid, item
|
||||||
|
* YAML (Fallback):
|
||||||
|
* players.<uuid>.trash-chest.world / x / y / z
|
||||||
|
* players.<uuid>.trash-items (StringList)
|
||||||
|
*/
|
||||||
|
public class TrashChestManager {
|
||||||
|
|
||||||
|
private static final String SKULL_TEXTURE =
|
||||||
|
"http://textures.minecraft.net/texture/942e7fb9b8eae22d55e32b8222f38eca7b2c41948b15d769b716d80f9d113611";
|
||||||
|
|
||||||
|
/** Gibt den sprachabhängigen GUI-Titel zurück (Farbe aus chest-titles.trash). */
|
||||||
|
private String getGuiTitle() {
|
||||||
|
boolean isEn = "en".equalsIgnoreCase(plugin.getConfig().getString("language", "de"));
|
||||||
|
String colorPrefix = getChestTitleColor();
|
||||||
|
String label = isEn ? "Configure Trash Chest" : "Mülltruhe konfigurieren";
|
||||||
|
return colorPrefix + ChatColor.BOLD + label;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Main plugin;
|
||||||
|
|
||||||
|
/** UUID → Truhen-Location (In-Memory-Cache für diesen Server) */
|
||||||
|
private final Map<UUID, Location> trashChestLocations = new HashMap<>();
|
||||||
|
/** UUID → Filter-Liste */
|
||||||
|
private final Map<UUID, List<String>> trashFilterLists = new HashMap<>();
|
||||||
|
/** Location-Key → Besitzer-UUID */
|
||||||
|
private final Map<String, UUID> locationToOwner = new HashMap<>();
|
||||||
|
/** Spieler-UUID → Truhen-Besitzer-UUID (offene GUIs) */
|
||||||
|
private final Map<UUID, UUID> openGuiOwners = new HashMap<>();
|
||||||
|
|
||||||
|
private BukkitTask autoTrashTask = null;
|
||||||
|
|
||||||
|
public TrashChestManager(Main plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
loadAllTrashChests();
|
||||||
|
plugin.getServer().getPluginManager().registerEvents(new GuiListener(), plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// LADEN
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
private void loadAllTrashChests() {
|
||||||
|
if (plugin.isMysqlEnabled() && plugin.getMysqlManager() != null) {
|
||||||
|
loadMySQL();
|
||||||
|
} else {
|
||||||
|
loadYaml();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadMySQL() {
|
||||||
|
MySQLManager db = plugin.getMysqlManager();
|
||||||
|
String myServer = plugin.getServerName();
|
||||||
|
for (Map<String, Object> row : db.getAllTrashChests()) {
|
||||||
|
String srv = (String) row.getOrDefault("server", "");
|
||||||
|
if (!srv.isEmpty() && !srv.equals(myServer)) continue;
|
||||||
|
try {
|
||||||
|
UUID uuid = UUID.fromString((String) row.get("uuid"));
|
||||||
|
World world = Bukkit.getWorld((String) row.get("world"));
|
||||||
|
if (world == null) continue;
|
||||||
|
Location loc = new Location(world, (int) row.get("x"), (int) row.get("y"), (int) row.get("z"));
|
||||||
|
trashChestLocations.put(uuid, loc);
|
||||||
|
locationToOwner.put(locKey(loc), uuid);
|
||||||
|
trashFilterLists.put(uuid, new ArrayList<>(db.getTrashItems(uuid.toString())));
|
||||||
|
} catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadYaml() {
|
||||||
|
FileConfiguration data = plugin.getPlayerData();
|
||||||
|
if (data == null || data.getConfigurationSection("players") == null) return;
|
||||||
|
for (String uuidStr : data.getConfigurationSection("players").getKeys(false)) {
|
||||||
|
try {
|
||||||
|
UUID uuid = UUID.fromString(uuidStr);
|
||||||
|
String base = "players." + uuidStr + ".trash-chest";
|
||||||
|
if (!data.contains(base + ".world")) continue;
|
||||||
|
World world = Bukkit.getWorld(data.getString(base + ".world"));
|
||||||
|
if (world == null) continue;
|
||||||
|
Location loc = new Location(world,
|
||||||
|
data.getInt(base + ".x"), data.getInt(base + ".y"), data.getInt(base + ".z"));
|
||||||
|
trashChestLocations.put(uuid, loc);
|
||||||
|
locationToOwner.put(locKey(loc), uuid);
|
||||||
|
trashFilterLists.put(uuid, new ArrayList<>(data.getStringList("players." + uuidStr + ".trash-items")));
|
||||||
|
} catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// SPEICHERN
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
private void saveTrashChest(UUID uuid) {
|
||||||
|
if (plugin.isMysqlEnabled() && plugin.getMysqlManager() != null) {
|
||||||
|
saveMySQL(uuid);
|
||||||
|
} else {
|
||||||
|
saveYaml(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveMySQL(UUID uuid) {
|
||||||
|
MySQLManager db = plugin.getMysqlManager();
|
||||||
|
String uuidStr = uuid.toString();
|
||||||
|
Location loc = trashChestLocations.get(uuid);
|
||||||
|
if (loc != null && loc.getWorld() != null) {
|
||||||
|
db.setTrashChest(uuidStr, loc.getWorld().getName(),
|
||||||
|
loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(),
|
||||||
|
plugin.getServerName());
|
||||||
|
db.savePlayer(uuidStr, Bukkit.getOfflinePlayer(uuid).getName());
|
||||||
|
} else {
|
||||||
|
db.removeTrashChest(uuidStr);
|
||||||
|
}
|
||||||
|
db.setTrashItems(uuidStr, trashFilterLists.getOrDefault(uuid, new ArrayList<>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveYaml(UUID uuid) {
|
||||||
|
FileConfiguration data = plugin.getPlayerData();
|
||||||
|
String uuidStr = uuid.toString();
|
||||||
|
Location loc = trashChestLocations.get(uuid);
|
||||||
|
if (loc != null && loc.getWorld() != null) {
|
||||||
|
String path = "players." + uuidStr + ".trash-chest";
|
||||||
|
data.set(path + ".world", loc.getWorld().getName());
|
||||||
|
data.set(path + ".x", loc.getBlockX());
|
||||||
|
data.set(path + ".y", loc.getBlockY());
|
||||||
|
data.set(path + ".z", loc.getBlockZ());
|
||||||
|
} else {
|
||||||
|
data.set("players." + uuidStr + ".trash-chest", null);
|
||||||
|
}
|
||||||
|
data.set("players." + uuidStr + ".trash-items",
|
||||||
|
trashFilterLists.getOrDefault(uuid, new ArrayList<>()));
|
||||||
|
plugin.savePlayerDataPublic();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// TRUHE VERWALTEN
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
public void setTrashChestLocation(UUID uuid, Location loc) {
|
||||||
|
Location old = trashChestLocations.get(uuid);
|
||||||
|
if (old != null) locationToOwner.remove(locKey(old));
|
||||||
|
trashChestLocations.put(uuid, loc);
|
||||||
|
locationToOwner.put(locKey(loc), uuid);
|
||||||
|
trashFilterLists.putIfAbsent(uuid, new ArrayList<>());
|
||||||
|
saveTrashChest(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTrashChest(UUID uuid) {
|
||||||
|
Location loc = trashChestLocations.remove(uuid);
|
||||||
|
if (loc != null) locationToOwner.remove(locKey(loc));
|
||||||
|
trashFilterLists.remove(uuid);
|
||||||
|
if (plugin.isMysqlEnabled() && plugin.getMysqlManager() != null) {
|
||||||
|
plugin.getMysqlManager().removeTrashChest(uuid.toString());
|
||||||
|
plugin.getMysqlManager().removeAllTrashItems(uuid.toString());
|
||||||
|
} else {
|
||||||
|
FileConfiguration data = plugin.getPlayerData();
|
||||||
|
data.set("players." + uuid + ".trash-chest", null);
|
||||||
|
data.set("players." + uuid + ".trash-items", null);
|
||||||
|
plugin.savePlayerDataPublic();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getTrashChestOwner(Location loc) {
|
||||||
|
return locationToOwner.get(locKey(loc));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getTrashChestLocation(UUID uuid) {
|
||||||
|
return trashChestLocations.get(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<UUID, Location> getAllTrashChests() {
|
||||||
|
return new HashMap<>(trashChestLocations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTrashItem(UUID uuid, Material mat) {
|
||||||
|
if (!trashChestLocations.containsKey(uuid)) return false;
|
||||||
|
List<String> filter = trashFilterLists.getOrDefault(uuid, new ArrayList<>());
|
||||||
|
// Leerer Filter = keine Items werden weitergeleitet (Mülltruhe deaktiviert)
|
||||||
|
return !filter.isEmpty() && filter.contains(mat.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// ITEM-VERARBEITUNG
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
public void processTrashChestInventory(UUID ownerUUID, Inventory inv) {
|
||||||
|
List<String> filter = trashFilterLists.getOrDefault(ownerUUID, new ArrayList<>());
|
||||||
|
// Leerer Filter = keine Items löschen (Mülltruhe deaktiviert bis Items konfiguriert sind)
|
||||||
|
if (filter.isEmpty()) return;
|
||||||
|
for (int i = 0; i < inv.getSize(); i++) {
|
||||||
|
ItemStack item = inv.getItem(i);
|
||||||
|
if (item == null || item.getType() == Material.AIR) continue;
|
||||||
|
if (filter.contains(item.getType().name())) inv.setItem(i, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearTrashChest(UUID ownerUUID) {
|
||||||
|
Location loc = trashChestLocations.get(ownerUUID);
|
||||||
|
if (loc == null || loc.getWorld() == null) return;
|
||||||
|
if (loc.getBlock().getState() instanceof Chest chest) chest.getInventory().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// FILTER-LISTE
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
public boolean addToFilter(UUID uuid, Material mat) {
|
||||||
|
List<String> filter = trashFilterLists.computeIfAbsent(uuid, k -> new ArrayList<>());
|
||||||
|
if (filter.contains(mat.name())) return false;
|
||||||
|
filter.add(mat.name());
|
||||||
|
if (plugin.isMysqlEnabled() && plugin.getMysqlManager() != null) {
|
||||||
|
plugin.getMysqlManager().addTrashItem(uuid.toString(), mat.name());
|
||||||
|
} else {
|
||||||
|
saveTrashChest(uuid);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeFromFilter(UUID uuid, Material mat) {
|
||||||
|
List<String> filter = trashFilterLists.get(uuid);
|
||||||
|
if (filter == null) return false;
|
||||||
|
boolean removed = filter.remove(mat.name());
|
||||||
|
if (removed) {
|
||||||
|
if (plugin.isMysqlEnabled() && plugin.getMysqlManager() != null) {
|
||||||
|
plugin.getMysqlManager().removeTrashItem(uuid.toString(), mat.name());
|
||||||
|
} else {
|
||||||
|
saveTrashChest(uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getFilter(UUID uuid) {
|
||||||
|
return trashFilterLists.getOrDefault(uuid, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// AUTO-CLEAR-TASK
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
public void startAutoTrashTask() {
|
||||||
|
stopAutoTrashTask();
|
||||||
|
int intervalSeconds = plugin.getConfig().getInt("trash.auto_clear_interval_seconds", 0);
|
||||||
|
if (intervalSeconds <= 0) return;
|
||||||
|
long ticks = intervalSeconds * 20L;
|
||||||
|
autoTrashTask = new BukkitRunnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (Map.Entry<UUID, Location> entry : new HashMap<>(trashChestLocations).entrySet()) {
|
||||||
|
Location loc = entry.getValue();
|
||||||
|
if (loc == null || loc.getWorld() == null) continue;
|
||||||
|
if (loc.getBlock().getState() instanceof Chest chest) {
|
||||||
|
processTrashChestInventory(entry.getKey(), chest.getInventory());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.runTaskTimer(plugin, ticks, ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopAutoTrashTask() {
|
||||||
|
if (autoTrashTask != null) { autoTrashTask.cancel(); autoTrashTask = null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// KONFIGURATIONS-GUI
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
public void openConfigGui(Player player, UUID ownerUUID) {
|
||||||
|
openGuiOwners.put(player.getUniqueId(), ownerUUID);
|
||||||
|
Inventory gui = Bukkit.createInventory(null, 54, getGuiTitle());
|
||||||
|
|
||||||
|
List<String> filter = trashFilterLists.getOrDefault(ownerUUID, new ArrayList<>());
|
||||||
|
int displaySlot = 0;
|
||||||
|
for (String matName : filter) {
|
||||||
|
if (displaySlot >= 45) break;
|
||||||
|
Material mat = Material.matchMaterial(matName);
|
||||||
|
if (mat == null || mat == Material.AIR) continue;
|
||||||
|
ItemStack display = new ItemStack(mat, 1);
|
||||||
|
ItemMeta meta = display.getItemMeta();
|
||||||
|
if (meta != null) {
|
||||||
|
meta.setDisplayName(getSignColor("trash", "line1") + formatMaterialName(matName));
|
||||||
|
meta.setLore(Arrays.asList(getSignColor("trash", "line4") + "Rechtsklick: Entfernen"));
|
||||||
|
display.setItemMeta(meta);
|
||||||
|
}
|
||||||
|
gui.setItem(displaySlot++, display);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack filler = new ItemStack(Material.BLACK_STAINED_GLASS_PANE);
|
||||||
|
ItemMeta fillerMeta = filler.getItemMeta();
|
||||||
|
if (fillerMeta != null) { fillerMeta.setDisplayName(" "); filler.setItemMeta(fillerMeta); }
|
||||||
|
for (int i = 45; i <= 53; i++) gui.setItem(i, filler.clone());
|
||||||
|
|
||||||
|
ItemStack modeInfo = new ItemStack(filter.isEmpty() ? Material.BARRIER : Material.WATER_BUCKET);
|
||||||
|
ItemMeta modeMeta = modeInfo.getItemMeta();
|
||||||
|
if (modeMeta != null) {
|
||||||
|
if (filter.isEmpty()) {
|
||||||
|
modeMeta.setDisplayName(getSignColor("trash", "line2") + "" + ChatColor.BOLD + "Modus: Deaktiviert");
|
||||||
|
modeMeta.setLore(Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Kein Filter gesetzt –",
|
||||||
|
ChatColor.GRAY + "Items werden NICHT gelöscht.",
|
||||||
|
getSignColor("trash", "line1") + "Füge Items hinzu um die Mülltruhe",
|
||||||
|
getSignColor("trash", "line1") + "zu aktivieren."));
|
||||||
|
} else {
|
||||||
|
modeMeta.setDisplayName(getSignColor("trash", "line4") + "" + ChatColor.BOLD + "Modus: Filter aktiv");
|
||||||
|
modeMeta.setLore(Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Nur gefilterte Items",
|
||||||
|
ChatColor.GRAY + "werden gelöscht."));
|
||||||
|
}
|
||||||
|
modeInfo.setItemMeta(modeMeta);
|
||||||
|
}
|
||||||
|
gui.setItem(48, modeInfo);
|
||||||
|
|
||||||
|
ItemStack addBtn = new ItemStack(Material.LIME_STAINED_GLASS_PANE);
|
||||||
|
ItemMeta addMeta = addBtn.getItemMeta();
|
||||||
|
if (addMeta != null) {
|
||||||
|
addMeta.setDisplayName(getSignColor("trash", "line1") + "" + ChatColor.BOLD + "Item hinzufügen");
|
||||||
|
addMeta.setLore(Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Item in die Hand nehmen",
|
||||||
|
ChatColor.GRAY + "und diesen Button klicken."));
|
||||||
|
addBtn.setItemMeta(addMeta);
|
||||||
|
}
|
||||||
|
gui.setItem(49, addBtn);
|
||||||
|
gui.setItem(53, buildSkullButton());
|
||||||
|
player.openInventory(gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getGuiOwner(UUID playerUUID) {
|
||||||
|
return openGuiOwners.get(playerUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack buildSkullButton() {
|
||||||
|
ItemStack skull;
|
||||||
|
try {
|
||||||
|
skull = new ItemStack(Material.PLAYER_HEAD);
|
||||||
|
SkullMeta meta = (SkullMeta) skull.getItemMeta();
|
||||||
|
if (meta != null) {
|
||||||
|
PlayerProfile profile = Bukkit.createPlayerProfile(UUID.randomUUID(), "TrashBtn");
|
||||||
|
PlayerTextures textures = profile.getTextures();
|
||||||
|
textures.setSkin(new URL(SKULL_TEXTURE));
|
||||||
|
profile.setTextures(textures);
|
||||||
|
meta.setOwnerProfile(profile);
|
||||||
|
meta.setDisplayName(getChestTitleColor() + "" + ChatColor.BOLD + "Mülltruhe leeren");
|
||||||
|
meta.setLore(Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Klicken um alle Items",
|
||||||
|
ChatColor.GRAY + "sofort zu löschen."));
|
||||||
|
skull.setItemMeta(meta);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
skull = new ItemStack(Material.RED_DYE);
|
||||||
|
ItemMeta meta = skull.getItemMeta();
|
||||||
|
if (meta != null) {
|
||||||
|
meta.setDisplayName(getChestTitleColor() + "" + ChatColor.BOLD + "Mülltruhe leeren");
|
||||||
|
meta.setLore(Arrays.asList(
|
||||||
|
ChatColor.GRAY + "Klicken um alle Items",
|
||||||
|
ChatColor.GRAY + "sofort zu löschen."));
|
||||||
|
skull.setItemMeta(meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return skull;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// GUI-LISTENER
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
private class GuiListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
|
if (!(event.getWhoClicked() instanceof Player player)) return;
|
||||||
|
if (!getGuiTitle().equals(event.getView().getTitle())) return;
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
int clickedSlot = event.getRawSlot();
|
||||||
|
UUID ownerUUID = openGuiOwners.get(player.getUniqueId());
|
||||||
|
if (ownerUUID == null) return;
|
||||||
|
|
||||||
|
if (clickedSlot == 53) {
|
||||||
|
clearTrashChest(ownerUUID);
|
||||||
|
player.sendMessage(getMessage("trash-cleared"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clickedSlot == 49) {
|
||||||
|
ItemStack inHand = player.getInventory().getItemInMainHand();
|
||||||
|
if (inHand.getType() == Material.AIR) {
|
||||||
|
player.sendMessage(getMessage("no-item-in-hand"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Material mat = inHand.getType();
|
||||||
|
if (addToFilter(ownerUUID, mat)) {
|
||||||
|
player.sendMessage(getMessage("trash-item-added").replace("%item%", formatMaterialName(mat.name())));
|
||||||
|
} else {
|
||||||
|
player.sendMessage(getMessage("trash-item-already"));
|
||||||
|
}
|
||||||
|
openConfigGui(player, ownerUUID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clickedSlot >= 45) return;
|
||||||
|
|
||||||
|
if (event.isRightClick()) {
|
||||||
|
ItemStack clicked = event.getCurrentItem();
|
||||||
|
if (clicked == null || clicked.getType() == Material.AIR) return;
|
||||||
|
Material mat = clicked.getType();
|
||||||
|
if (removeFromFilter(ownerUUID, mat)) {
|
||||||
|
player.sendMessage(getMessage("trash-item-removed").replace("%item%", formatMaterialName(mat.name())));
|
||||||
|
openConfigGui(player, ownerUUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInventoryClose(InventoryCloseEvent event) {
|
||||||
|
if (event.getPlayer() instanceof Player player) {
|
||||||
|
openGuiOwners.remove(player.getUniqueId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
// HILFSMETHODEN
|
||||||
|
// ══════════════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
|
private String getMessage(String key) {
|
||||||
|
String msg = plugin.getConfig().getString("messages." + key, "messages." + key + " fehlt");
|
||||||
|
return org.bukkit.ChatColor.translateAlternateColorCodes('&', msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liest eine Schildfarbe aus sign-colors.<type>.<line> in der Config.
|
||||||
|
* Gibt übersetzten §-Code zurück (z.B. §6 für &6).
|
||||||
|
*/
|
||||||
|
private String getSignColor(String type, String line) {
|
||||||
|
String raw = plugin.getConfig().getString("sign-colors." + type + "." + line, "&f");
|
||||||
|
return ChatColor.translateAlternateColorCodes('&', raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liest nur den Farb-Präfix aus chest-titles.trash (ohne Titeltext).
|
||||||
|
* Gibt übersetzten §-Code zurück.
|
||||||
|
*/
|
||||||
|
private String getChestTitleColor() {
|
||||||
|
boolean isEn = "en".equalsIgnoreCase(plugin.getConfig().getString("language", "de"));
|
||||||
|
String lang = isEn ? "en" : "de";
|
||||||
|
String full = plugin.getConfig().getString("chest-titles.trash." + lang,
|
||||||
|
isEn ? "&4Trash Chest" : "&4Mülltruhe");
|
||||||
|
// Nur die führenden &X / &l Codes extrahieren
|
||||||
|
StringBuilder codes = new StringBuilder();
|
||||||
|
for (int i = 0; i + 1 < full.length(); i++) {
|
||||||
|
if (full.charAt(i) == '&' && "0123456789abcdefklmnor".indexOf(full.charAt(i + 1)) >= 0) {
|
||||||
|
codes.append(full, i, i + 2);
|
||||||
|
i++; // Zeichen überspringen
|
||||||
|
} else {
|
||||||
|
break; // erster Nicht-Code-Zeichenblock → abbrechen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ChatColor.translateAlternateColorCodes('&', codes.length() > 0 ? codes.toString() : "&4");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String locKey(Location loc) {
|
||||||
|
return loc.getWorld().getName() + ":" + loc.getBlockX() + ":" + loc.getBlockY() + ":" + loc.getBlockZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String formatMaterialName(String name) {
|
||||||
|
if (name == null || name.isEmpty()) return "";
|
||||||
|
String[] parts = name.split("_");
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String part : parts) {
|
||||||
|
if (sb.length() > 0) sb.append(' ');
|
||||||
|
if (!part.isEmpty()) {
|
||||||
|
sb.append(Character.toUpperCase(part.charAt(0)));
|
||||||
|
if (part.length() > 1) sb.append(part.substring(1).toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,7 @@ public class UpdateChecker {
|
|||||||
|
|
||||||
public void getVersion(final Consumer<String> consumer) {
|
public void getVersion(final Consumer<String> consumer) {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(this.plugin, () -> {
|
||||||
try (InputStream is = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.resourceId + "/~").openStream();
|
try (InputStream is = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.resourceId).openStream();
|
||||||
Scanner scann = new Scanner(is)) {
|
Scanner scann = new Scanner(is)) {
|
||||||
if (scann.hasNext()) {
|
if (scann.hasNext()) {
|
||||||
consumer.accept(scann.next());
|
consumer.accept(scann.next());
|
||||||
|
|||||||
@@ -7,19 +7,24 @@
|
|||||||
#
|
#
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
# --- GRUNDLEGUNG ---
|
# ============================================================
|
||||||
# Version der Konfigurationsdatei. Nicht ändern, um Fehler zu vermeiden!
|
# ALLGEMEIN
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
version: "2.2"
|
# Version der Konfigurationsdatei – bitte nicht ändern!
|
||||||
|
version: "2.3"
|
||||||
# Debug-Modus (true = Ausführliche Logs in der Server-Konsole, nur zum Entwickeln nutzen)
|
|
||||||
|
|
||||||
|
# Debug-Modus: true = Ausführliche Logs in der Konsole (nur zum Entwickeln)
|
||||||
debug: false
|
debug: false
|
||||||
|
|
||||||
# ---------------------------------------------------
|
# Sprache der Benutzeroberfläche
|
||||||
# DATENBANK (MySQL/MariaDB) - Optional
|
# Mögliche Werte: 'de' (Deutsch) oder 'en' (Englisch)
|
||||||
# ---------------------------------------------------
|
# Betrifft: /asc help, /asc info und die Truhen-Fenstertitel
|
||||||
# Aktiviere MySQL/MariaDB Speicherung (true/false)
|
language: "de"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# DATENBANK (MySQL / MariaDB) – Optional
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
mysql:
|
mysql:
|
||||||
enabled: false
|
enabled: false
|
||||||
@@ -29,111 +34,80 @@ mysql:
|
|||||||
user: "autosortchest"
|
user: "autosortchest"
|
||||||
password: "autosortchest"
|
password: "autosortchest"
|
||||||
|
|
||||||
# Soll serverübergreifendes Sortieren (mit MySQL) erlaubt sein?
|
# ============================================================
|
||||||
server_crosslink: true
|
|
||||||
|
|
||||||
# ---------------------------------------------------
|
|
||||||
# BUNGEE CORD / MULTI-SERVER SETUP
|
# BUNGEE CORD / MULTI-SERVER SETUP
|
||||||
# ---------------------------------------------------
|
# ============================================================
|
||||||
|
# Soll serverübergreifendes Sortieren (über MySQL) erlaubt sein?
|
||||||
|
server_crosslink: false
|
||||||
|
|
||||||
# Eindeutiger Name dieses Servers im BungeeCord-Netzwerk.
|
# Eindeutiger Name dieses Servers im BungeeCord-Netzwerk.
|
||||||
# WICHTIG: Jeder Server braucht einen anderen Namen!
|
# WICHTIG: Jeder Server braucht einen anderen Namen!
|
||||||
#
|
#
|
||||||
# Beispiele:
|
# Beispiele: lobby | survival | creative
|
||||||
# server_name: "lobby"
|
|
||||||
# server_name: "survival"
|
|
||||||
# server_name: "creative"
|
|
||||||
#
|
#
|
||||||
# Leer lassen = Legacy-Modus (welt-basierte Erkennung, kein BungeeCord).
|
# Leer lassen = Legacy-Modus (welt-basierte Erkennung, kein BungeeCord).
|
||||||
# Fuer BungeeCord MUSS mysql.enabled: true gesetzt sein!
|
# Für BungeeCord MUSS mysql.enabled: true gesetzt sein!
|
||||||
#
|
#
|
||||||
# Setup-Schritte:
|
# Setup:
|
||||||
# 1. Gleiche MySQL-Datenbank auf allen Servern eintragen.
|
# 1. Gleiche MySQL-Datenbank auf allen Servern eintragen.
|
||||||
# 2. Auf jedem Server einen einzigartigen server_name setzen.
|
# 2. Auf jedem Server einen einzigartigen server_name setzen.
|
||||||
# 3. mysql.enabled: true und server_crosslink: true setzen.
|
# 3. mysql.enabled: true und server_crosslink: true setzen.
|
||||||
# 4. Alle Server neu starten - Schema wird automatisch migriert.
|
# 4. Alle Server neu starten – Schema wird automatisch migriert.
|
||||||
|
|
||||||
server_name: ""
|
server_name: ""
|
||||||
|
|
||||||
# ---------------------------------------------------
|
# ============================================================
|
||||||
# SPRACHE (Language)
|
# WELTEN-BLACKLIST
|
||||||
# ---------------------------------------------------
|
# ============================================================
|
||||||
# Mögliche Werte: 'de' für Deutsch oder 'en' für Englisch
|
|
||||||
# Ändert den Text von /asc help und /asc info
|
|
||||||
language: "de"
|
|
||||||
|
|
||||||
# ---------------------------------------------------
|
|
||||||
# BLACKLIST FÜR WELTEN (Optional)
|
|
||||||
# ---------------------------------------------------
|
|
||||||
# Welten, in denen AutoSortChest NICHT funktioniert
|
# Welten, in denen AutoSortChest NICHT funktioniert
|
||||||
|
|
||||||
world_blacklist:
|
world_blacklist:
|
||||||
- "world_nether"
|
- "world_nether"
|
||||||
- "world_the_end"
|
- "world_the_end"
|
||||||
|
|
||||||
# ---------------------------------------------------
|
# ============================================================
|
||||||
# VISUELLE EFFEKTE (PARTIKEL & TÖNE)
|
|
||||||
# ---------------------------------------------------
|
|
||||||
|
|
||||||
# Einstellungen für den Regenbogen-Effekt beim Sortieren
|
|
||||||
effects:
|
|
||||||
# Sollen Effekte angezeigt werden?
|
|
||||||
enabled: false
|
|
||||||
# Soll ein Ton gespielt werden, wenn Items ankommen?
|
|
||||||
sound: false
|
|
||||||
# Der Partikel-Typ.
|
|
||||||
# 'DUST' ist zwingend für den bunten Regenbogen-Effekt im aktuellen Code.
|
|
||||||
type: "DUST"
|
|
||||||
|
|
||||||
# ---------------------------------------------------
|
|
||||||
# SORTIER-INTERVALL (Ticks)
|
# SORTIER-INTERVALL (Ticks)
|
||||||
# ---------------------------------------------------
|
# ============================================================
|
||||||
# Wie oft soll sortiert werden? (1 Tick = 0,05s)
|
# Wie oft soll sortiert werden? (1 Tick = 0,05 Sekunden)
|
||||||
#
|
|
||||||
# Wähle hier je nach Server-Leistung:
|
|
||||||
#
|
|
||||||
# 1 = SEHR SCHNELL (Items verschwinden sofort)
|
|
||||||
# WARNUNG: Kann bei vielen Truhen Lagg verursachen!
|
|
||||||
#
|
|
||||||
# 5 = SCHNELL (Sehr flüssig, gute Balance)
|
|
||||||
# Empfohlen für schnelle Server.
|
|
||||||
#
|
|
||||||
# 10 = FLÜSSIG (0,5s Verzögerung)
|
|
||||||
# Spart Ressourcen, fühlt sich noch schnell an.
|
|
||||||
#
|
|
||||||
# 20 = STANDARD (1 Sekunde)
|
|
||||||
# Standard-Wert, minimale Last.
|
|
||||||
#
|
|
||||||
# 30+ = SPARSAM (>1,5 Sekunden)
|
|
||||||
# Für sehr große Server mit schwacher Hardware.
|
|
||||||
#
|
#
|
||||||
|
# 1 = Sehr schnell – Items verschwinden sofort
|
||||||
|
# WARNUNG: Kann bei vielen Truhen Lag verursachen!
|
||||||
|
# 5 = Schnell – Sehr flüssig, gute Balance
|
||||||
|
# 10 = Flüssig – 0,5s Verzögerung, spart Ressourcen <- Empfohlen
|
||||||
|
# 20 = Standard – 1 Sekunde, minimale Last
|
||||||
|
# 30+ = Sparsam – Für große Server mit schwacher Hardware
|
||||||
|
|
||||||
sort_interval_ticks: 5
|
sort_interval_ticks: 10
|
||||||
|
|
||||||
# ---------------------------------------------------
|
# Wie oft werden Rest-Truhen neu einsortiert? (in Ticks)
|
||||||
# LIMITS FÜR SORTIERKISTEN (Optional)
|
rest_resort_interval_ticks: 400 # 400 Ticks = 20 Sekunden
|
||||||
# ---------------------------------------------------
|
|
||||||
# Maximale Anzahl an Sortierkisten pro Spielergruppe
|
# ============================================================
|
||||||
|
# TRUHEN-LIMITS
|
||||||
|
# ============================================================
|
||||||
|
# Maximale Anzahl an Sortiertruhen pro Spielergruppe.
|
||||||
|
# Sollen Limits aktiv sein? (true = ja, false = keine Beschränkung)
|
||||||
|
|
||||||
chest_limits:
|
chest_limits:
|
||||||
# Sollen Truhen-Limits aktiv sein? (true = ja, false = keine Beschraenkung)
|
enabled: false
|
||||||
enabled: true
|
|
||||||
|
|
||||||
# Jede Gruppe hat eigene Limits fuer input, rest und target.
|
|
||||||
# Spieler benoetigen die Permission: autosortchest.limit.<gruppe>
|
|
||||||
|
|
||||||
|
# Spieler benötigen die Permission: autosortchest.limit.<gruppe>
|
||||||
|
# WICHTIG: Spieler OHNE jegliche autosortchest.limit.*-Permission können bei
|
||||||
|
# aktivierten Limits KEINE Truhen erstellen (Limit = 0).
|
||||||
|
# Vergib autosortchest.limit.default an alle normalen Spieler (z.B. in LuckPerms).
|
||||||
default:
|
default:
|
||||||
input: 1 # Eingangstruhen (Input)
|
input: 1 # Eingangstruhen
|
||||||
rest: 1 # Rest-Truhen (Fallback)
|
rest: 1 # Rest-Truhen (Fallback)
|
||||||
target: 50 # Zieltruhen gesamt
|
target: 50 # Zieltruhen gesamt
|
||||||
target_per_item: 1 # Wie viele Zieltruhen pro Item-Typ erlaubt sind
|
target_per_item: 1 # Zieltruhen pro Item-Typ
|
||||||
|
|
||||||
vip:
|
vip:
|
||||||
input: 2
|
input: 2
|
||||||
rest: 2
|
rest: 2
|
||||||
target: 100
|
target: 100
|
||||||
target_per_item: 3
|
target_per_item: 3
|
||||||
|
|
||||||
# Weitere Gruppen:
|
# Weitere Gruppen (auskommentiert):
|
||||||
# supporter:
|
# supporter:
|
||||||
# input: 3
|
# input: 3
|
||||||
# rest: 2
|
# rest: 2
|
||||||
@@ -145,61 +119,197 @@ chest_limits:
|
|||||||
# target: 200
|
# target: 200
|
||||||
# target_per_item: 10
|
# target_per_item: 10
|
||||||
|
|
||||||
# ---------------------------------------------------
|
# ============================================================
|
||||||
# SCHILDFARBEN (Farbcodes wie im Chat)
|
# MÜLLTRUHE
|
||||||
# &c = Rot, &a = Grün, &e = Gelb, &6 = Gold, &f = Weiß, &0 = Schwarz
|
# ============================================================
|
||||||
# ---------------------------------------------------
|
# auto_clear_interval_seconds:
|
||||||
|
# 0 = Deaktiviert (Truhe wird nur beim Schließen geleert)
|
||||||
|
# 300 = Alle 5 Minuten
|
||||||
|
# 3600 = Stündlich
|
||||||
|
|
||||||
|
trash:
|
||||||
|
auto_clear_interval_seconds: 0
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# VISUELLE EFFEKTE (Partikel & Töne)
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
effects:
|
||||||
|
# Sollen Partikel-Effekte angezeigt werden?
|
||||||
|
enabled: false
|
||||||
|
# Soll ein Ton gespielt werden, wenn Items ankommen?
|
||||||
|
sound: false
|
||||||
|
# Partikel-Typ ('DUST' = bunter Regenbogen-Effekt)
|
||||||
|
type: "DUST"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# SCHILD-STIL
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
sign-style:
|
||||||
|
# Saubere Zieltruhen-Schilder (ohne Item-Namen auf dem Schild)
|
||||||
|
# true = Clean-Modus aktiviert
|
||||||
|
clean-target: false
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# SCHILDFARBEN
|
||||||
|
# ============================================================
|
||||||
|
# Farbcodes: &0-&9, &a-&f | &l = Fett, &o = Kursiv, &r = Reset
|
||||||
|
#
|
||||||
|
# &0 Schwarz &1 Dunkelblau &2 Dunkelgrün &3 Cyan
|
||||||
|
# &4 Dunkelrot &5 Lila &6 Gold &7 Grau
|
||||||
|
# &8 Dunkelgrau &9 Blau &a Grün &b Aqua
|
||||||
|
# &c Rot &d Pink &e Gelb &f Weiß
|
||||||
|
|
||||||
sign-colors:
|
sign-colors:
|
||||||
# Farben für die Eingangstruhe ([asc] / input)
|
|
||||||
input:
|
|
||||||
line1: "&6" # Zeile 1: [asc]
|
|
||||||
line2: "&0" # Zeile 2: input
|
|
||||||
line4: "&1" # Zeile 4: Spielername
|
|
||||||
|
|
||||||
# Farben für die Zieltruhe ([asc] / ziel)
|
|
||||||
target:
|
|
||||||
line1: "&6" # Zeile 1: [asc]
|
|
||||||
line2: "&0" # Zeile 2: ziel
|
|
||||||
line3: "&f" # Zeile 3: Item-Name
|
|
||||||
line4: "&1" # Zeile 4: Spielername
|
|
||||||
|
|
||||||
# Farben für volle Truhen (Automatische Erkennung)
|
|
||||||
full:
|
|
||||||
line1: "&c" # Zeile 1: [asc]
|
|
||||||
line2: "&4" # Zeile 2: ziel / rest (Rot)
|
|
||||||
line3: "&e" # Zeile 3: Item-Name (Gelb)
|
|
||||||
line4: "&1" # Zeile 4: Spielername
|
|
||||||
|
|
||||||
# Farben für die Rest-Truhe ([asc] / rest)
|
|
||||||
rest:
|
|
||||||
line1: "&6" # Zeile 1: [asc]
|
|
||||||
line2: "&0" # Zeile 2: rest
|
|
||||||
line3: "&f" # Zeile 3: (Leer)
|
|
||||||
line4: "&1" # Zeile 4: Spielername
|
|
||||||
|
|
||||||
# ---------------------------------------------------
|
# Eingangstruhe ([asc] / input)
|
||||||
# SYSTEM NACHRICHTEN (Spieler-Feedback)
|
input:
|
||||||
|
line1: "&6" # Zeile 1: [asc]
|
||||||
|
line2: "&0" # Zeile 2: input
|
||||||
|
line4: "&1" # Zeile 4: Spielername
|
||||||
|
|
||||||
|
# Zieltruhe ([asc] / ziel)
|
||||||
|
target:
|
||||||
|
line1: "&6" # Zeile 1: [asc]
|
||||||
|
line2: "&0" # Zeile 2: ziel
|
||||||
|
line3: "&f" # Zeile 3: Item-Name
|
||||||
|
line4: "&1" # Zeile 4: Spielername
|
||||||
|
|
||||||
|
# Volle Zieltruhe (automatische Erkennung)
|
||||||
|
full:
|
||||||
|
line1: "&c" # Zeile 1: [asc]
|
||||||
|
line2: "&4" # Zeile 2: ziel / rest
|
||||||
|
line3: "&e" # Zeile 3: Item-Name
|
||||||
|
line4: "&1" # Zeile 4: Spielername
|
||||||
|
|
||||||
|
# Rest-Truhe ([asc] / rest)
|
||||||
|
rest:
|
||||||
|
line1: "&6" # Zeile 1: [asc]
|
||||||
|
line2: "&0" # Zeile 2: rest
|
||||||
|
line3: "&f" # Zeile 3: (leer)
|
||||||
|
line4: "&1" # Zeile 4: Spielername
|
||||||
|
|
||||||
|
# Mülltruhe ([asc] / trash)
|
||||||
|
trash:
|
||||||
|
line1: "&6" # Zeile 1: [asc]
|
||||||
|
line2: "&0" # Zeile 2: trash
|
||||||
|
line4: "&1" # Zeile 4: Spielername
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# CLEAN-MODUS SCHILDFARBEN (sign-style.clean-target: true)
|
||||||
|
# ============================================================
|
||||||
|
# Eigene Farben für den sauberen Schild-Stil.
|
||||||
|
# Farbcodes: &0-&9, &a-&f | &l = Fett, &o = Kursiv, &r = Reset
|
||||||
|
#
|
||||||
|
# Layout im Clean-Modus (Zeile 4 = versteckter Typ-Marker, nicht konfigurierbar):
|
||||||
|
#
|
||||||
|
# input → Z1: Spielername | Z2: "Eingang/Input" | Z3: Öffentlich/Privat
|
||||||
|
# target → Z1: Item-Name | Z2: Spielername | Z3: Öffentlich/Privat
|
||||||
|
# full → Z1: Item-Name | Z2: Spielername | Z3: Öffentlich/Privat (volle Truhe)
|
||||||
|
# rest → Z1: Spielername | Z2: "Rest" | Z3: Öffentlich/Privat
|
||||||
|
# trash → Z1: Spielername | Z2: "Müll/Trash" | Z3: (leer)
|
||||||
|
|
||||||
|
sign-colors-clean:
|
||||||
|
|
||||||
|
# Eingangstruhe (Clean)
|
||||||
|
input:
|
||||||
|
line1: "&1" # Zeile 1: Spielername
|
||||||
|
line2: "&0" # Zeile 2: "Eingang" / "Input"
|
||||||
|
line3: "&a" # Zeile 3: Öffentlich / Privat
|
||||||
|
|
||||||
|
# Zieltruhe (Clean)
|
||||||
|
target:
|
||||||
|
line1: "&f" # Zeile 1: Item-Name
|
||||||
|
line2: "&1" # Zeile 2: Spielername
|
||||||
|
line3: "&a" # Zeile 3: Öffentlich / Privat
|
||||||
|
|
||||||
|
# Volle Zieltruhe (Clean)
|
||||||
|
full:
|
||||||
|
line1: "&c" # Zeile 1: Item-Name (volle Truhe) → Rot
|
||||||
|
line2: "&1" # Zeile 2: Spielername
|
||||||
|
line3: "&a" # Zeile 3: Öffentlich / Privat
|
||||||
|
|
||||||
|
# Rest-Truhe (Clean)
|
||||||
|
rest:
|
||||||
|
line1: "&1" # Zeile 1: Spielername
|
||||||
|
line2: "&0" # Zeile 2: "Rest"
|
||||||
|
line3: "&a" # Zeile 3: Öffentlich / Privat
|
||||||
|
|
||||||
|
# Mülltruhe (Clean)
|
||||||
|
trash:
|
||||||
|
line1: "&1" # Zeile 1: Spielername
|
||||||
|
line2: "&0" # Zeile 2: "Müll" / "Trash"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# TRUHEN-FENSTERTITEL
|
||||||
|
# ============================================================
|
||||||
|
# Farbe & Text des Titels, wenn ein Spieler eine ASC-Truhe öffnet.
|
||||||
|
# Farbcodes wie oben.
|
||||||
|
#
|
||||||
|
# Platzhalter für Zieltruhen:
|
||||||
|
# %item% -> wird durch den Item-Namen ersetzt (z.B. "Iron Ore")
|
||||||
|
# Beispiel: "&6%item%" zeigt "Iron Ore" in Gold
|
||||||
|
|
||||||
|
chest-titles:
|
||||||
|
input:
|
||||||
|
de: "&6Eingangstruhe"
|
||||||
|
en: "&6Input Chest"
|
||||||
|
target:
|
||||||
|
de: "&6%item%"
|
||||||
|
en: "&6%item%"
|
||||||
|
rest:
|
||||||
|
de: "&6Rest-Truhe"
|
||||||
|
en: "&6Rest Chest"
|
||||||
|
trash:
|
||||||
|
de: "&4Mülltruhe"
|
||||||
|
en: "&4Trash Chest"
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# SYSTEM-NACHRICHTEN (Spieler-Feedback)
|
||||||
|
# ============================================================
|
||||||
# Platzhalter: %player%, %item%, %x%, %y%, %z%, %mode%
|
# Platzhalter: %player%, %item%, %x%, %y%, %z%, %mode%
|
||||||
# ---------------------------------------------------
|
|
||||||
|
|
||||||
messages:
|
messages:
|
||||||
# --- FEHLERMELDUNGEN ---
|
|
||||||
no-chest-near-sign: "&cKeine Truhe in der Nähe des Schildes!"
|
# --- Fehlermeldungen ---
|
||||||
no-item-in-hand: "&cDu musst ein Item in der Hand halten!"
|
no-chest-near-sign: "&cKeine Truhe in der Nähe des Schildes!"
|
||||||
not-your-chest: "&cDiese Truhe gehört dir nicht!"
|
no-item-in-hand: "&cDu musst ein Item in der Hand halten!"
|
||||||
|
not-your-chest: "&cDiese Truhe gehört dir nicht!"
|
||||||
target-chest-missing: "&cZieltruhe für %item% fehlt!"
|
target-chest-missing: "&cZieltruhe für %item% fehlt!"
|
||||||
sign-break-denied: "&cDu musst Shift gedrückt halten, um dieses Schild oder die Truhe abzubauen!"
|
sign-break-denied: "&cDu musst Shift gedrückt halten, um dieses Schild oder die Truhe abzubauen!"
|
||||||
no-permission: "&cDu hast keine Berechtigung für diesen Befehl!"
|
no-permission: "&cDu hast keine Berechtigung für diesen Befehl!"
|
||||||
|
world-blacklisted: "&cIn dieser Welt kannst du keine AutoSortChest erstellen!"
|
||||||
|
|
||||||
# --- ERFOLGSMELDUNGEN ---
|
# --- Limit-Fehlermeldungen ---
|
||||||
input-chest-set: "&aEingangstruhe erfolgreich gesetzt!"
|
# Platzhalter: %max% = erlaubtes Limit, %item% = Item-Name
|
||||||
target-chest-set: "&aZieltruhe erfolgreich für %item% eingerichtet!"
|
limit-input-reached: "&cDu hast das Limit deiner Eingangstruhen erreicht! &7(%max%)"
|
||||||
rest-chest-set: "&aRest-Truhe (Fallback) erfolgreich gesetzt!"
|
limit-rest-reached: "&cDu hast das Limit deiner Rest-Truhen erreicht! &7(%max%)"
|
||||||
reload-success: "&aKonfiguration erfolgreich neu geladen!"
|
limit-target-reached: "&cDu hast das Limit deiner Zieltruhen erreicht! &7(%max%)"
|
||||||
|
limit-target-per-item: "&cDu hast das Limit für %item%-Truhen erreicht! &7(%max%)"
|
||||||
|
limit-no-permission: "&cDu hast keine Berechtigung um Truhen zu erstellen!"
|
||||||
|
|
||||||
# --- HINWEIS MELDUNGEN ---
|
# --- Erfolgsmeldungen ---
|
||||||
|
input-chest-set: "&aEingangstruhe erfolgreich gesetzt!"
|
||||||
|
target-chest-set: "&aZieltruhe erfolgreich für %item% eingerichtet!"
|
||||||
|
rest-chest-set: "&aRest-Truhe (Fallback) erfolgreich gesetzt!"
|
||||||
|
trash-chest-set: "&aMülltruhe erfolgreich eingerichtet!"
|
||||||
|
trash-chest-hint: "&7Rechtsklicke das Schild um Items zu konfigurieren."
|
||||||
|
reload-success: "&aKonfiguration erfolgreich neu geladen!"
|
||||||
|
|
||||||
|
# --- Mülltruhe GUI ---
|
||||||
|
trash-cleared: "&a✔ Mülltruhe wurde geleert!"
|
||||||
|
trash-item-added: "&a✔ &e%item% &azur Müll-Liste hinzugefügt."
|
||||||
|
trash-item-already: "&eDiseses Item ist bereits in der Müll-Liste."
|
||||||
|
trash-item-removed: "&c✖ &e%item% &caus der Müll-Liste entfernt."
|
||||||
|
|
||||||
|
# --- Mülltruhe Info (erscheint im Chat beim Öffnen der Truhe) ---
|
||||||
|
# Platzhalter: %items% = kommagetrennte Item-Liste
|
||||||
|
trash-info-empty: "&4Mülltruhe &8(Deaktiviert) &7– Rechtsklick Schild zum Konfigurieren"
|
||||||
|
trash-info-filter: "&4Müll: &f%items% &8| Schild-Rechtsklick: Konfigurieren"
|
||||||
|
|
||||||
|
# --- Hinweise ---
|
||||||
target-chest-full: "&cZieltruhe für %item% ist voll! Koordinaten: (%x%, %y%, %z%)"
|
target-chest-full: "&cZieltruhe für %item% ist voll! Koordinaten: (%x%, %y%, %z%)"
|
||||||
mode-changed: "&aModus gewechselt: &e%mode%"
|
mode-changed: "&aModus gewechselt: &e%mode%"
|
||||||
mode-public: "&aÖffentlich"
|
mode-public: "&aÖffentlich"
|
||||||
mode-private: "&cPrivat"
|
mode-private: "&cPrivat"
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name: AutoSortChest
|
name: AutoSortChest
|
||||||
version: 2.3
|
version: 2.5
|
||||||
main: com.viper.autosortchest.Main
|
main: com.viper.autosortchest.Main
|
||||||
api-version: 1.21
|
api-version: 1.21
|
||||||
authors: [M_Viper]
|
authors: [M_Viper]
|
||||||
@@ -10,6 +10,9 @@ commands:
|
|||||||
usage: /<command> [help|info|reload|import|export]
|
usage: /<command> [help|info|reload|import|export]
|
||||||
aliases: [autosortchest]
|
aliases: [autosortchest]
|
||||||
permissions:
|
permissions:
|
||||||
|
autosortchest.use:
|
||||||
|
description: Erlaubt das Erstellen von AutoSortChest-Schildern (Eingang, Ziel, Rest, Muelltruhe)
|
||||||
|
default: true
|
||||||
autosortchest.reload:
|
autosortchest.reload:
|
||||||
description: Erlaubt das Neuladen der Konfiguration mit /asc reload
|
description: Erlaubt das Neuladen der Konfiguration mit /asc reload
|
||||||
default: op
|
default: op
|
||||||
@@ -20,14 +23,20 @@ permissions:
|
|||||||
description: Erlaubt den Export von MySQL nach players.yml mit /asc export
|
description: Erlaubt den Export von MySQL nach players.yml mit /asc export
|
||||||
default: op
|
default: op
|
||||||
autosortchest.bypass:
|
autosortchest.bypass:
|
||||||
description: Erlaubt das Abbauen von ASC-Schildern ohne Shift-Taste und unabhängig vom Besitzer
|
description: Erlaubt das Abbauen von ASC-Schildern ohne Shift-Taste und unabhaengig vom Besitzer
|
||||||
|
default: op
|
||||||
|
autosortchest.limit.bypass:
|
||||||
|
description: Umgeht alle Truhen-Limits (input, rest, target) – OPs haben dies automatisch
|
||||||
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
|
||||||
default: op
|
default: op
|
||||||
autosortchest.limit.<gruppe>:
|
autosortchest.limit.<gruppe>:
|
||||||
description: >
|
description: >
|
||||||
Limits fuer eine benutzerdefinierte Gruppe aus der config.yml.
|
Limits fuer eine benutzerdefinierte Gruppe aus der config.yml.
|
||||||
Ersetze <gruppe> durch den Gruppennamen (z.B. autosortchest.limit.vip).
|
Ersetze <gruppe> durch den Gruppennamen (z.B. autosortchest.limit.vip).
|
||||||
Die Gruppen und ihre Limits werden ausschliesslich in der config.yml definiert.
|
Die Gruppen und ihre Limits werden ausschliesslich in der config.yml definiert.
|
||||||
|
WICHTIG: Spieler ohne jegliche autosortchest.limit.*-Permission koennen bei
|
||||||
|
aktivierten Limits (chest_limits.enabled: true) KEINE Truhen erstellen.
|
||||||
|
Vergib autosortchest.limit.default fuer den Standard-Rang.
|
||||||
default: false
|
default: false
|
||||||
Reference in New Issue
Block a user