Dateien nach "src/main/java/net/viper/status" hochladen

This commit is contained in:
2026-01-08 14:57:53 +00:00
parent 841b726842
commit 5597f99a87
3 changed files with 496 additions and 0 deletions

View File

@@ -0,0 +1,310 @@
package net.viper.status;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.viper.status.module.ModuleManager;
import net.viper.status.stats.PlayerStats;
import net.viper.status.stats.StatsModule;
import net.viper.status.modules.verify.VerifyModule;
import net.viper.status.modules.globalchat.GlobalChatModule;
import net.viper.status.modules.navigation.NavigationModule;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class StatusAPI extends Plugin implements Runnable {
private Thread thread;
private int port = 9191;
// Das neue Modul-System
private ModuleManager moduleManager;
// Alte Komponenten (UpdateChecker/FileDownloader bleiben hier, da sie Core-Updates steuern)
private UpdateChecker updateChecker;
private FileDownloader fileDownloader;
@Override
public void onEnable() {
getLogger().info("StatusAPI Core wird initialisiert...");
// 1. Ordner sicherstellen
if (!getDataFolder().exists()) {
getDataFolder().mkdirs();
}
// 2. Modul-System starten
moduleManager = new ModuleManager();
// 3. MODULE REGISTRIEREN (Hier erweiterst du die API in Zukunft!)
// Um ein neues Feature hinzuzufügen, erstelle eine Klasse, die 'Module' implementiert
// und füge hier eine Zeile hinzu: moduleManager.registerModule(new MeinNeuesModul());
moduleManager.registerModule(new StatsModule()); // Statistik System laden
moduleManager.registerModule(new VerifyModule()); // Verify Modul
moduleManager.registerModule(new GlobalChatModule()); // GlobalChat
moduleManager.registerModule(new NavigationModule()); //Server Switcher
// 4. Alle Module aktivieren
moduleManager.enableAll(this);
// 5. WebServer Thread starten
getLogger().info("Starte Web-Server auf Port " + port + "...");
thread = new Thread(this, "StatusAPI-HTTP-Server");
thread.start();
// 6. Update System Initialisieren
String currentVersion = getDescription() != null ? getDescription().getVersion() : "0.0.0";
updateChecker = new UpdateChecker(this, currentVersion, 6);
fileDownloader = new FileDownloader(this);
File pluginFile = getFile();
File backupFile = new File(pluginFile.getParentFile(), "StatusAPI.jar.bak");
// Backup Cleanup
if (backupFile.exists()) {
ProxyServer.getInstance().getScheduler().schedule(this, () -> {
if (backupFile.exists()) backupFile.delete();
}, 1, TimeUnit.MINUTES);
}
// Sofortiger Check
checkAndMaybeUpdate();
// Regelmäßiger Check
ProxyServer.getInstance().getScheduler().schedule(this, this::checkAndMaybeUpdate, 6, 6, TimeUnit.HOURS);
}
@Override
public void onDisable() {
getLogger().info("Stoppe Module...");
if (moduleManager != null) {
moduleManager.disableAll(this);
}
getLogger().info("Stoppe Web-Server...");
if (thread != null) {
thread.interrupt();
try { thread.join(1000); } catch (InterruptedException ignored) {}
}
}
// --- Update Logik (unverändert) ---
private void checkAndMaybeUpdate() {
try {
updateChecker.checkNow();
String currentVersion = getDescription() != null ? getDescription().getVersion() : "0.0.0";
if (updateChecker.isUpdateAvailable(currentVersion)) {
String newVersion = updateChecker.getLatestVersion();
String url = updateChecker.getLatestUrl();
getLogger().warning("----------------------------------------");
getLogger().warning("Neue Version verfügbar: " + newVersion);
getLogger().warning("Starte automatisches Update...");
getLogger().warning("----------------------------------------");
File pluginFile = getFile();
File newFile = new File(pluginFile.getParentFile(), "StatusAPI.jar.new");
fileDownloader.downloadFile(url, newFile, () -> triggerUpdateScript(pluginFile, newFile));
}
} catch (Exception e) {
getLogger().severe("Fehler beim Update-Check: " + e.getMessage());
}
}
private void triggerUpdateScript(File currentFile, File newFile) {
try {
File pluginsFolder = currentFile.getParentFile();
File rootFolder = pluginsFolder.getParentFile();
File batFile = new File(rootFolder, "StatusAPI_Update_" + System.currentTimeMillis() + ".bat");
String batContent = "@echo off\n" +
"echo Bitte warten, der Server fährt herunter...\n" +
"timeout /t 5 /nobreak >nul\n" +
"cd /d \"" + pluginsFolder.getAbsolutePath().replace("\\", "/") + "\"\n" +
"echo Fuehre Datei-Tausch durch...\n" +
"if exist StatusAPI.jar.bak del StatusAPI.jar.bak\n" +
"if exist StatusAPI.jar (\n" +
" ren StatusAPI.jar StatusAPI.jar.bak\n" +
")\n" +
"if exist StatusAPI.new.jar (\n" +
" ren StatusAPI.new.jar StatusAPI.jar\n" +
" echo Update erfolgreich!\n" +
") else (\n" +
" echo FEHLER: StatusAPI.new.jar nicht gefunden!\n" +
" pause\n" +
")\n" +
"del \"%~f0\"";
try (PrintWriter out = new PrintWriter(batFile)) { out.println(batContent); }
for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
p.disconnect("§cServer fährt für ein Update neu herunter. Bitte etwas warten.");
}
getLogger().info("Starte Update-Skript...");
Runtime.getRuntime().exec("cmd /c start \"Update_Proc\" \"" + batFile.getAbsolutePath() + "\"");
ProxyServer.getInstance().stop();
} catch (Exception e) {
getLogger().severe("Fehler beim Vorbereiten des Updates: " + e.getMessage());
}
}
// --- WebServer & JSON ---
@Override
public void run() {
try (ServerSocket serverSocket = new ServerSocket(port)) {
serverSocket.setSoTimeout(1000);
while (!Thread.interrupted()) {
try {
Socket clientSocket = serverSocket.accept();
handleConnection(clientSocket);
} catch (java.net.SocketTimeoutException e) {}
catch (IOException e) {
getLogger().warning("Fehler beim Akzeptieren einer Verbindung: " + e.getMessage());
}
}
} catch (IOException e) {
getLogger().severe("Konnte ServerSocket nicht starten: " + e.getMessage());
}
}
private void handleConnection(Socket clientSocket) {
try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"));
OutputStream out = clientSocket.getOutputStream()) {
String inputLine = in.readLine();
if (inputLine != null && inputLine.startsWith("GET")) {
Map<String, Object> data = new LinkedHashMap<>();
data.put("online", true);
// Version & Info
String versionRaw = ProxyServer.getInstance().getVersion();
String versionClean = (versionRaw != null && versionRaw.contains(":")) ? versionRaw.split(":")[2].trim() : versionRaw;
data.put("version", versionClean);
data.put("max_players", String.valueOf(ProxyServer.getInstance().getConfig().getPlayerLimit()));
String motd = "BungeeCord";
try {
Iterator<ListenerInfo> it = ProxyServer.getInstance().getConfig().getListeners().iterator();
if (it.hasNext()) motd = it.next().getMotd();
} catch (Exception ignored) {}
data.put("motd", motd);
// StatsModul holen (Service Locator)
StatsModule statsModule = (StatsModule) moduleManager.getModule("StatsModule");
boolean luckPermsEnabled = ProxyServer.getInstance().getPluginManager().getPlugin("LuckPerms") != null;
List<Map<String, Object>> playersList = new ArrayList<>();
for (ProxiedPlayer p : ProxyServer.getInstance().getPlayers()) {
Map<String, Object> playerInfo = new LinkedHashMap<>();
playerInfo.put("name", p.getName());
try { playerInfo.put("uuid", p.getUniqueId().toString()); } catch (Exception ignored) {}
String prefix = "";
if (luckPermsEnabled) {
try {
Class<?> providerClass = Class.forName("net.luckperms.api.LuckPermsProvider");
Object luckPermsApi = providerClass.getMethod("get").invoke(null);
Object userManager = luckPermsApi.getClass().getMethod("getUserManager").invoke(luckPermsApi);
Object user = userManager.getClass().getMethod("getUser", UUID.class).invoke(userManager, p.getUniqueId());
if (user != null) {
Class<?> queryOptionsClass = Class.forName("net.luckperms.api.query.QueryOptions");
Object queryOptions = queryOptionsClass.getMethod("defaultContextualOptions").invoke(null);
Object cachedData = user.getClass().getMethod("getCachedData").invoke(user);
Object metaData = cachedData.getClass().getMethod("getMetaData", queryOptionsClass).invoke(cachedData, queryOptions);
Object result = metaData.getClass().getMethod("getPrefix").invoke(metaData);
if (result != null) prefix = (String) result;
}
} catch (Exception ignored) {}
}
playerInfo.put("prefix", prefix);
// Stats Integration via Modul
if (statsModule != null) {
PlayerStats ps = statsModule.getManager().getIfPresent(p.getUniqueId());
if (ps != null) {
playerInfo.put("playtime", ps.getPlaytimeWithCurrentSession());
playerInfo.put("joins", ps.joins);
playerInfo.put("first_seen", ps.firstSeen);
playerInfo.put("last_seen", ps.lastSeen);
}
}
playersList.add(playerInfo);
}
data.put("players", playersList);
String json = buildJsonString(data);
byte[] jsonBytes = json.getBytes("UTF-8");
StringBuilder response = new StringBuilder();
response.append("HTTP/1.1 200 OK\r\n");
response.append("Content-Type: application/json; charset=UTF-8\r\n");
response.append("Access-Control-Allow-Origin: *\r\n");
response.append("Content-Length: ").append(jsonBytes.length).append("\r\n");
response.append("Connection: close\r\n\r\n");
out.write(response.toString().getBytes("UTF-8"));
out.write(jsonBytes);
out.flush();
}
} catch (Exception e) {
getLogger().severe("Fehler beim Verarbeiten der Anfrage: " + e.getMessage());
}
}
private String buildJsonString(Map<String, Object> data) {
StringBuilder sb = new StringBuilder("{");
boolean first = true;
for (Map.Entry<String, Object> entry : data.entrySet()) {
if (!first) sb.append(",");
first = false;
sb.append("\"").append(escapeJson(entry.getKey())).append("\":").append(valueToString(entry.getValue()));
}
sb.append("}");
return sb.toString();
}
private String valueToString(Object value) {
if (value == null) return "null";
else if (value instanceof Boolean) return value.toString();
else if (value instanceof Number) return value.toString();
else if (value instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> m = (Map<String, Object>) value;
return buildJsonString(m);
} else if (value instanceof List) {
StringBuilder sb = new StringBuilder("[");
List<?> list = (List<?>) value;
for (int i = 0; i < list.size(); i++) {
if (i > 0) sb.append(",");
Object item = list.get(i);
if (item instanceof Map) sb.append(buildJsonString((Map<String, Object>) item));
else if (item instanceof Number) sb.append(item.toString());
else sb.append("\"").append(escapeJson(String.valueOf(item))).append("\"");
}
sb.append("]");
return sb.toString();
}
else return "\"" + escapeJson(String.valueOf(value)) + "\"";
}
private String escapeJson(String s) {
if (s == null) return "";
return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r");
}
}