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

This commit is contained in:
2026-01-08 14:58:17 +00:00
parent 5597f99a87
commit 0174522ede
4 changed files with 242 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
package net.viper.status.stats;
import java.util.UUID;
public class PlayerStats {
public final UUID uuid;
public String name;
public long firstSeen;
public long lastSeen;
public long totalPlaytime;
public long currentSessionStart;
public int joins;
public PlayerStats(UUID uuid, String name) {
this.uuid = uuid;
this.name = name;
long now = System.currentTimeMillis() / 1000L;
this.firstSeen = now;
this.lastSeen = now;
this.totalPlaytime = 0;
this.currentSessionStart = 0;
this.joins = 0;
}
public synchronized void onJoin() {
long now = System.currentTimeMillis() / 1000L;
if (this.currentSessionStart == 0) this.currentSessionStart = now;
this.lastSeen = now;
this.joins++;
if (this.firstSeen == 0) this.firstSeen = now;
}
public synchronized void onQuit() {
long now = System.currentTimeMillis() / 1000L;
if (this.currentSessionStart > 0) {
long session = now - this.currentSessionStart;
if (session > 0) this.totalPlaytime += session;
this.currentSessionStart = 0;
}
this.lastSeen = now;
}
public synchronized long getPlaytimeWithCurrentSession() {
long now = System.currentTimeMillis() / 1000L;
if (this.currentSessionStart > 0) return totalPlaytime + (now - currentSessionStart);
return totalPlaytime;
}
public synchronized String toLine() {
return uuid + "|" + name.replace("|", "_") + "|" + firstSeen + "|" + lastSeen + "|" + totalPlaytime + "|" + currentSessionStart + "|" + joins;
}
public static PlayerStats fromLine(String line) {
String[] parts = line.split("\\|", -1);
if (parts.length < 7) return null;
try {
UUID uuid = UUID.fromString(parts[0]);
String name = parts[1];
PlayerStats ps = new PlayerStats(uuid, name);
ps.firstSeen = Long.parseLong(parts[2]);
ps.lastSeen = Long.parseLong(parts[3]);
ps.totalPlaytime = Long.parseLong(parts[4]);
ps.currentSessionStart = Long.parseLong(parts[5]);
ps.joins = Integer.parseInt(parts[6]);
return ps;
} catch (Exception e) {
return null;
}
}
}

View File

@@ -0,0 +1,35 @@
package net.viper.status.stats;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class StatsManager {
private final ConcurrentHashMap<UUID, PlayerStats> map = new ConcurrentHashMap<>();
public PlayerStats get(UUID uuid, String name) {
return map.compute(uuid, (k, v) -> {
if (v == null) {
return new PlayerStats(uuid, name != null ? name : "");
} else {
if (name != null && !name.isEmpty()) v.name = name;
return v;
}
});
}
public PlayerStats getIfPresent(UUID uuid) {
return map.get(uuid);
}
public Iterable<PlayerStats> all() {
return map.values();
}
public void put(PlayerStats ps) {
map.put(ps.uuid, ps);
}
public void remove(UUID uuid) {
map.remove(uuid);
}
}

View File

@@ -0,0 +1,100 @@
package net.viper.status.stats;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.PostLoginEvent;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import net.viper.status.module.Module;
import java.util.concurrent.TimeUnit;
/**
* StatsModule: Kümmert sich eigenständig um das Tracking der Spielerdaten.
* Implementiert Module (für das Lifecycle) und Listener (für die Events).
*/
public class StatsModule implements Module, Listener {
private StatsManager manager;
private StatsStorage storage;
@Override
public String getName() {
return "StatsModule";
}
@Override
public void onEnable(Plugin plugin) {
// Initialisierung
manager = new StatsManager();
storage = new StatsStorage(plugin.getDataFolder());
// Laden
try {
storage.load(manager);
plugin.getLogger().info("Player-Stats wurden erfolgreich geladen.");
} catch (Exception e) {
plugin.getLogger().warning("Fehler beim Laden der Stats: " + e.getMessage());
}
// Event Listener registrieren
plugin.getProxy().getPluginManager().registerListener(plugin, this);
// Auto-Save Task (alle 5 Minuten)
plugin.getProxy().getScheduler().schedule(plugin, () -> {
try {
storage.save(manager);
plugin.getLogger().info("Auto-Save: Player-Stats gespeichert.");
} catch (Exception e) {
plugin.getLogger().warning("Fehler beim Auto-Save: " + e.getMessage());
}
}, 5, 5, TimeUnit.MINUTES);
}
@Override
public void onDisable(Plugin plugin) {
if (manager != null && storage != null) {
// Laufende Sessions beenden vor dem Speichern
long now = System.currentTimeMillis() / 1000L;
for (PlayerStats ps : manager.all()) {
synchronized (ps) {
if (ps.currentSessionStart > 0) {
long delta = now - ps.currentSessionStart;
if (delta > 0) {
ps.totalPlaytime += delta;
}
ps.currentSessionStart = 0; // Session beenden
}
}
}
try {
storage.save(manager);
plugin.getLogger().info("Player-Stats beim Shutdown gespeichert.");
} catch (Exception e) {
plugin.getLogger().warning("Fehler beim Speichern (Shutdown): " + e.getMessage());
}
}
}
// Öffentlicher Zugriff für den WebServer
public StatsManager getManager() {
return manager;
}
// --- Events ---
@EventHandler
public void onJoin(PostLoginEvent e) {
try {
manager.get(e.getPlayer().getUniqueId(), e.getPlayer().getName()).onJoin();
} catch (Exception ignored) {}
}
@EventHandler
public void onQuit(PlayerDisconnectEvent e) {
try {
PlayerStats ps = manager.getIfPresent(e.getPlayer().getUniqueId());
if (ps != null) ps.onQuit();
} catch (Exception ignored) {}
}
}

View File

@@ -0,0 +1,37 @@
package net.viper.status.stats;
import java.io.*;
public class StatsStorage {
private final File file;
public StatsStorage(File pluginFolder) {
if (!pluginFolder.exists()) pluginFolder.mkdirs();
this.file = new File(pluginFolder, "stats.dat");
}
public void save(StatsManager manager) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
for (PlayerStats ps : manager.all()) {
bw.write(ps.toLine());
bw.newLine();
}
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
public void load(StatsManager manager) {
if (!file.exists()) return;
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
PlayerStats ps = PlayerStats.fromLine(line);
if (ps != null) manager.put(ps);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}