Upload folder via GUI - src
This commit is contained in:
@@ -1,17 +1,24 @@
|
||||
package de.viper.autoworldreset;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.WorldCreator;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ResetManager {
|
||||
|
||||
@@ -22,6 +29,11 @@ public class ResetManager {
|
||||
}
|
||||
|
||||
public void resetWorld() {
|
||||
if (!Bukkit.isPrimaryThread()) {
|
||||
Bukkit.getScheduler().runTask(plugin, this::resetWorld);
|
||||
return;
|
||||
}
|
||||
|
||||
String worldName = plugin.getConfig().getString("world-name");
|
||||
|
||||
if (worldName == null || worldName.isEmpty()) {
|
||||
@@ -29,6 +41,8 @@ public class ResetManager {
|
||||
return;
|
||||
}
|
||||
|
||||
executeConfiguredCommands("pre-reset-commands", "Pre-Reset", worldName);
|
||||
|
||||
// BUG FIX #6: Die Backup-Prüfung wurde aus resetWorld() entfernt und korrekt
|
||||
// platziert. Zuvor wurde backup.enabled geprüft, um einen RESTORE abzubrechen –
|
||||
// das ist logisch falsch. Das Flag sollte nur das automatische Erstellen eines
|
||||
@@ -37,7 +51,10 @@ public class ResetManager {
|
||||
boolean success = restoreBackup(worldName);
|
||||
if (!success) {
|
||||
plugin.getLogger().warning("Reset fehlgeschlagen: Backup konnte nicht wiederhergestellt werden.");
|
||||
return;
|
||||
}
|
||||
|
||||
executeConfiguredCommands("post-reset-commands", "Post-Reset", worldName);
|
||||
}
|
||||
|
||||
public boolean createBackup() {
|
||||
@@ -156,6 +173,242 @@ public class ResetManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void executeConfiguredCommands(String pathPrefix, String label, String worldName) {
|
||||
if (!plugin.getConfig().getBoolean(pathPrefix + ".enabled", false)) return;
|
||||
|
||||
List<String> commands = plugin.getConfig().getStringList(pathPrefix + ".commands");
|
||||
if (commands.isEmpty()) return;
|
||||
|
||||
String configuredHomeName = plugin.getConfig().getString("home-name", worldName);
|
||||
String homeName = (configuredHomeName == null || configuredHomeName.isBlank())
|
||||
? worldName
|
||||
: configuredHomeName;
|
||||
|
||||
for (String command : commands) {
|
||||
if (command.startsWith("@cmi-deletehomes-world")) {
|
||||
String resolved = command
|
||||
.replace("{world}", worldName)
|
||||
.replace("{home}", homeName);
|
||||
|
||||
String[] parts = resolved.split("\\s+");
|
||||
String targetWorld = parts.length >= 2 ? parts[1] : worldName;
|
||||
|
||||
plugin.getLogger().info("Führe " + label + "-Spezialbefehl aus: CMI Homes in Welt '" + targetWorld + "' löschen");
|
||||
boolean success = deleteCmiHomesInWorldViaApi(targetWorld);
|
||||
if (!success) {
|
||||
plugin.getLogger().warning("CMI API-Löschung fehlgeschlagen. Prüfe, ob CMI geladen ist und Homes vorhanden sind.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (command.contains("{player}")) {
|
||||
int executed = 0;
|
||||
for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) {
|
||||
if (!offlinePlayer.isOnline() && !offlinePlayer.hasPlayedBefore()) continue;
|
||||
|
||||
String playerName = offlinePlayer.getName();
|
||||
if (playerName == null || playerName.isBlank()) continue;
|
||||
|
||||
String resolved = command
|
||||
.replace("{world}", worldName)
|
||||
.replace("{home}", homeName)
|
||||
.replace("{player}", playerName);
|
||||
|
||||
plugin.getLogger().info("Führe " + label + "-Befehl aus: " + resolved);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), resolved);
|
||||
executed++;
|
||||
}
|
||||
plugin.getLogger().info(label + "-Befehl mit {player} für " + executed + " Spieler ausgeführt.");
|
||||
continue;
|
||||
}
|
||||
|
||||
String resolved = command
|
||||
.replace("{world}", worldName)
|
||||
.replace("{home}", homeName);
|
||||
plugin.getLogger().info("Führe " + label + "-Befehl aus: " + resolved);
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), resolved);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean deleteCmiHomesInWorldViaApi(String worldName) {
|
||||
Plugin cmiPlugin = Bukkit.getPluginManager().getPlugin("CMI");
|
||||
if (cmiPlugin == null || !cmiPlugin.isEnabled()) {
|
||||
plugin.getLogger().warning("CMI ist nicht geladen oder nicht aktiv.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> cmiClass = Class.forName("com.Zrips.CMI.CMI");
|
||||
Method getInstance = cmiClass.getMethod("getInstance");
|
||||
Object cmiInstance = getInstance.invoke(null);
|
||||
if (cmiInstance == null) return false;
|
||||
|
||||
Object playerManager = invokeNoArg(cmiInstance, "getPlayerManager");
|
||||
if (playerManager == null) {
|
||||
plugin.getLogger().warning("CMI PlayerManager konnte nicht gefunden werden.");
|
||||
return false;
|
||||
}
|
||||
|
||||
int removed = 0;
|
||||
int checked = 0;
|
||||
int usersCount = 0;
|
||||
|
||||
Map<String, Object> users = collectCmiUsers(playerManager);
|
||||
for (Map.Entry<String, Object> entry : users.entrySet()) {
|
||||
String playerName = entry.getKey();
|
||||
Object user = entry.getValue();
|
||||
if (playerName == null || playerName.isBlank() || user == null) continue;
|
||||
usersCount++;
|
||||
|
||||
List<String> homesInWorld = getHomeNamesForWorld(user, worldName);
|
||||
checked += homesInWorld.size();
|
||||
|
||||
for (String home : homesInWorld) {
|
||||
String cmd = "cmi removehome " + home + " " + playerName;
|
||||
boolean ok = Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd);
|
||||
if (ok) removed++;
|
||||
}
|
||||
}
|
||||
|
||||
plugin.getLogger().info("CMI API: User geprüft=" + usersCount + ", Homes in Welt '" + worldName + "' gefunden=" + checked + ", entfernt=" + removed + ".");
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
plugin.getLogger().warning("CMI API-Integration fehlgeschlagen: " + t.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> collectCmiUsers(Object playerManager) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
|
||||
// Primär: direkt aus CMI PlayerManager lesen (umfasst mehr als Bukkit Offline-Cache)
|
||||
Object usersObj = invokeNoArg(playerManager, "getAllUsers");
|
||||
if (usersObj == null) usersObj = invokeNoArg(playerManager, "getUsers");
|
||||
if (usersObj == null) usersObj = invokeNoArg(playerManager, "getUsersMap");
|
||||
|
||||
if (usersObj instanceof Map<?, ?> map) {
|
||||
for (Object value : map.values()) {
|
||||
String name = extractCmiUserName(value);
|
||||
if (name != null && !name.isBlank()) {
|
||||
result.putIfAbsent(name, value);
|
||||
}
|
||||
}
|
||||
} else if (usersObj instanceof Collection<?> collection) {
|
||||
for (Object value : collection) {
|
||||
String name = extractCmiUserName(value);
|
||||
if (name != null && !name.isBlank()) {
|
||||
result.putIfAbsent(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Bukkit OfflinePlayer durchprobieren
|
||||
for (OfflinePlayer offlinePlayer : Bukkit.getOfflinePlayers()) {
|
||||
if (!offlinePlayer.isOnline() && !offlinePlayer.hasPlayedBefore()) continue;
|
||||
|
||||
String playerName = offlinePlayer.getName();
|
||||
if (playerName == null || playerName.isBlank() || result.containsKey(playerName)) continue;
|
||||
|
||||
Object user = getCmiUser(playerManager, offlinePlayer, playerName);
|
||||
if (user != null) {
|
||||
result.put(playerName, user);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private String extractCmiUserName(Object cmiUser) {
|
||||
if (cmiUser == null) return null;
|
||||
|
||||
Object name = invokeNoArg(cmiUser, "getName");
|
||||
if (name instanceof String s && !s.isBlank()) return s;
|
||||
|
||||
Object playerName = invokeNoArg(cmiUser, "getPlayerName");
|
||||
if (playerName instanceof String s && !s.isBlank()) return s;
|
||||
|
||||
Object offline = invokeNoArg(cmiUser, "getOfflinePlayer");
|
||||
if (offline instanceof OfflinePlayer op && op.getName() != null && !op.getName().isBlank()) {
|
||||
return op.getName();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object getCmiUser(Object playerManager, OfflinePlayer offlinePlayer, String playerName) {
|
||||
Object user = invokeOneArg(playerManager, "getUser", UUID.class, offlinePlayer.getUniqueId());
|
||||
if (user != null) return user;
|
||||
|
||||
user = invokeOneArg(playerManager, "getUser", String.class, playerName);
|
||||
if (user != null) return user;
|
||||
|
||||
return invokeOneArg(playerManager, "getUser", OfflinePlayer.class, offlinePlayer);
|
||||
}
|
||||
|
||||
private List<String> getHomeNamesForWorld(Object cmiUser, String worldName) {
|
||||
List<String> result = new ArrayList<>();
|
||||
Object homesObj = invokeNoArg(cmiUser, "getHomes");
|
||||
if (!(homesObj instanceof Map<?, ?> homesMap)) return result;
|
||||
|
||||
for (Map.Entry<?, ?> entry : homesMap.entrySet()) {
|
||||
String homeName = String.valueOf(entry.getKey());
|
||||
Object homeObj = entry.getValue();
|
||||
|
||||
if (homeName == null || homeName.isBlank() || homeObj == null) continue;
|
||||
if (isHomeInWorld(homeObj, worldName)) {
|
||||
result.add(homeName);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isHomeInWorld(Object homeObj, String worldName) {
|
||||
String lowerWorld = worldName.toLowerCase();
|
||||
|
||||
Object worldNameObj = invokeNoArg(homeObj, "getWorldName");
|
||||
if (worldNameObj instanceof String s && s.equalsIgnoreCase(worldName)) return true;
|
||||
|
||||
Object worldObj = invokeNoArg(homeObj, "getWorld");
|
||||
if (worldObj instanceof World w && w.getName().equalsIgnoreCase(worldName)) return true;
|
||||
if (worldObj instanceof String s && s.equalsIgnoreCase(worldName)) return true;
|
||||
|
||||
Object locationObj = invokeNoArg(homeObj, "getLoc");
|
||||
if (locationObj == null) locationObj = invokeNoArg(homeObj, "getLocation");
|
||||
if (locationObj != null) {
|
||||
Object locWorld = invokeNoArg(locationObj, "getWorld");
|
||||
if (locWorld instanceof World w && w.getName().equalsIgnoreCase(worldName)) return true;
|
||||
|
||||
Object locWorldName = invokeNoArg(locationObj, "getWorldName");
|
||||
if (locWorldName instanceof String s && s.equalsIgnoreCase(worldName)) return true;
|
||||
}
|
||||
|
||||
// Fallback: Einige CMI Home-Objekte enthalten den Weltnamen in toString().
|
||||
return homeObj.toString().toLowerCase().contains(lowerWorld);
|
||||
}
|
||||
|
||||
private Object invokeNoArg(Object target, String methodName) {
|
||||
if (target == null) return null;
|
||||
try {
|
||||
Method method = target.getClass().getMethod(methodName);
|
||||
method.setAccessible(true);
|
||||
return method.invoke(target);
|
||||
} catch (Throwable ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Object invokeOneArg(Object target, String methodName, Class<?> argType, Object arg) {
|
||||
if (target == null) return null;
|
||||
try {
|
||||
Method method = target.getClass().getMethod(methodName, argType);
|
||||
method.setAccessible(true);
|
||||
return method.invoke(target, arg);
|
||||
} catch (Throwable ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteFolder(Path path) throws IOException {
|
||||
if (Files.notExists(path)) return;
|
||||
if (Files.isDirectory(path)) {
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
# Weltname, die zurückgesetzt werden soll
|
||||
world-name: "world"
|
||||
|
||||
# Home-Name für Home-Plugins (falls Home-Name nicht dem Weltnamen entspricht)
|
||||
# Beispiel: Test-01 -> /cmi removehome Test-01 <spieler>
|
||||
home-name: "world"
|
||||
|
||||
# Ob beim Serverstart automatisch ein Reset durchgeführt werden soll
|
||||
auto-reset-on-startup: false
|
||||
|
||||
@@ -36,6 +40,38 @@ scheduler:
|
||||
# "0 0 */6 * * ?" → Alle 6 Stunden
|
||||
cron: "0 0 4 * * ?"
|
||||
|
||||
# Befehle, die VOR dem Reset als Konsole ausgeführt werden.
|
||||
# Nützlich um z.B. Homes in der zurückgesetzten Welt zu löschen.
|
||||
# Platzhalter: {world} = Name der Welt, die zurückgesetzt wird
|
||||
# {home} = Home-Name aus 'home-name' (Fallback: {world})
|
||||
# {player} = Spielername (Befehl wird für alle bekannten Spieler ausgeführt)
|
||||
#
|
||||
# Bekannte Befehle für verbreitete Home-Plugins:
|
||||
# HuskHomes: "huskhomes delete homes {world}"
|
||||
# Optional: "huskhomes delete homes {world} <server_name> confirm"
|
||||
# UltimateHomes: "delhome {world}"
|
||||
# Für alle bekannten Spieler: "delhome {player} {world}"
|
||||
# CMI: "@cmi-deletehomes-world {world}"
|
||||
# (interner Spezialbefehl von AutoWorldReset, löscht alle CMI-Homes in dieser Welt)
|
||||
#
|
||||
# Eigenen Befehl einfach eintragen – wird als Konsole ausgeführt.
|
||||
pre-reset-commands:
|
||||
enabled: false
|
||||
commands:
|
||||
# - "huskhomes delete homes {world} confirm" # HuskHomes
|
||||
# - "huskhomes delete homes {world} s1 confirm" # HuskHomes (mit Servername + confirm)
|
||||
# - "uh deleteallhomesinworld {world}" # UltimateHomes Wichtig! der Befehl muss in der config von Ultimatehomes auf true gestellt werden, damit er funktioniert: enableDeleteAllHomesInWorldAdminCommand true
|
||||
# - "cmi removehome {home} {player}" # CMI (besser in post-reset)
|
||||
|
||||
# Befehle, die NACH dem erfolgreichen Reset ausgeführt werden.
|
||||
# Nützlich für Plugin-Reloads oder Cache-Refresh (z.B. Home-GUIs).
|
||||
post-reset-commands:
|
||||
enabled: false
|
||||
commands:
|
||||
# - "@cmi-deletehomes-world {world}" # CMI API: alle Homes dieser Welt löschen
|
||||
# - "cmi saveall" # CMI Daten direkt persistent speichern
|
||||
# - "cmi reload" # CMI Cache/GUI neu laden
|
||||
|
||||
# Nachrichten – können vollständig in lang.yml angepasst werden.
|
||||
# lang.yml hat Vorrang vor den Werten hier.
|
||||
messages:
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
name: AutoWorldReset
|
||||
version: 1.2
|
||||
version: 1.3
|
||||
main: de.viper.autoworldreset.AutoWorldReset
|
||||
api-version: 1.21
|
||||
description: Automatisches Welt-Reset Plugin mit Backup-System & Quartz Cron-Scheduler
|
||||
author: M_Viper
|
||||
softdepend: [CMI]
|
||||
|
||||
commands:
|
||||
autoworldreset:
|
||||
|
||||
Reference in New Issue
Block a user