Update from Git Manager GUI

This commit is contained in:
2026-02-27 00:44:25 +01:00
parent f74701ecbe
commit e718d06473
20 changed files with 3679 additions and 0 deletions

View File

@@ -0,0 +1,333 @@
package de.fussball.plugin.commands;
import de.fussball.plugin.Fussball;
import de.fussball.plugin.arena.Arena;
import de.fussball.plugin.game.Ball;
import de.fussball.plugin.game.Game;
import de.fussball.plugin.game.GameState;
import de.fussball.plugin.stats.StatsManager;
import de.fussball.plugin.utils.MessageUtil;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
import java.util.*;
public class FussballCommand implements CommandExecutor, TabCompleter {
private final Fussball plugin;
public FussballCommand(Fussball plugin) { this.plugin = plugin; }
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) { sendHelp(sender); return true; }
switch (args[0].toLowerCase()) {
// ── Spieler-Befehle ──────────────────────────────────────────────
case "join" -> {
if (!(sender instanceof Player player)) { sender.sendMessage("Nur für Spieler!"); return true; }
if (args.length < 2) { player.sendMessage(MessageUtil.error("Benutze: /fb join <arena>")); return true; }
Arena arena = plugin.getArenaManager().getArena(args[1]);
if (arena == null) { player.sendMessage(MessageUtil.error("Arena §e" + args[1] + " §cnicht gefunden!")); return true; }
if (!arena.isSetupComplete()) { player.sendMessage(MessageUtil.error("Arena nicht vollständig eingerichtet!")); return true; }
if (plugin.getGameManager().isInAnyGame(player)) { player.sendMessage(MessageUtil.error("Du bist bereits in einem Spiel! Tippe §e/fb leave§c.")); return true; }
plugin.getGameManager().createGame(arena).addPlayer(player);
}
case "leave" -> {
if (!(sender instanceof Player player)) { sender.sendMessage("Nur für Spieler!"); return true; }
// Aus Spiel
Game game = plugin.getGameManager().getPlayerGame(player);
if (game != null) { game.removePlayer(player); player.sendMessage(MessageUtil.success("Du hast das Spiel verlassen!")); return true; }
// Aus Zuschauer
Game specGame = plugin.getGameManager().getSpectatorGame(player);
if (specGame != null) { specGame.removeSpectator(player); player.sendMessage(MessageUtil.success("Du hast das Zuschauen beendet!")); return true; }
// Aus Warteschlange
plugin.getGameManager().removeFromAllQueues(player);
player.sendMessage(MessageUtil.warn("Du bist in keinem Spiel und in keiner Warteschlange."));
}
case "spectate", "spec" -> {
if (!(sender instanceof Player player)) { sender.sendMessage("Nur für Spieler!"); return true; }
if (args.length < 2) { player.sendMessage(MessageUtil.error("Benutze: /fb spectate <arena>")); return true; }
Arena arena = plugin.getArenaManager().getArena(args[1]);
if (arena == null) { player.sendMessage(MessageUtil.error("Arena nicht gefunden!")); return true; }
if (plugin.getGameManager().isInAnyGame(player)) { player.sendMessage(MessageUtil.error("Verlasse zuerst dein aktuelles Spiel!")); return true; }
Game game = plugin.getGameManager().getGame(arena.getName());
if (game == null) { player.sendMessage(MessageUtil.error("Kein laufendes Spiel in dieser Arena!")); return true; }
game.addSpectator(player);
}
case "list" -> {
sender.sendMessage(MessageUtil.header("⚽ Verfügbare Arenen"));
Collection<Arena> arenas = plugin.getArenaManager().getAllArenas();
if (arenas.isEmpty()) { sender.sendMessage(MessageUtil.warn("Keine Arenen vorhanden.")); return true; }
for (Arena a : arenas) {
Game g = plugin.getGameManager().getGame(a.getName());
int queueSize = plugin.getGameManager().getQueueSize(a.getName());
String status = g != null ? statusDot(g.getState()) : "§a●";
String players = g != null ? g.getAllPlayers().size() + "/" + a.getMaxPlayers() : "0/" + a.getMaxPlayers();
String setup = a.isSetupComplete() ? "§a✔" : "§c✗";
String queue = queueSize > 0 ? " §8(§e" + queueSize + " §8warten)" : "";
sender.sendMessage("§7 " + status + " §e" + a.getName() + " §7[" + players + "] " + setup + queue);
}
}
case "stats" -> {
if (!(sender instanceof Player player)) { sender.sendMessage("Nur für Spieler!"); return true; }
Player target = args.length >= 2 ? Bukkit.getPlayer(args[1]) : player;
if (target == null) { player.sendMessage(MessageUtil.error("Spieler §e" + args[1] + " §cnicht gefunden!")); return true; }
StatsManager.PlayerStats s = plugin.getStatsManager().getStats(target.getUniqueId());
player.sendMessage(MessageUtil.header("Statistiken: " + target.getName()));
player.sendMessage("§7 ⚽ Tore: §e" + s.goals);
player.sendMessage("§7 👟 Schüsse: §e" + s.kicks);
player.sendMessage("§7 🏆 Siege: §a" + s.wins);
player.sendMessage("§7 ❌ Niederlagen: §c" + s.losses);
player.sendMessage("§7 Unentschieden: §7" + s.draws);
player.sendMessage("§7 📊 Gespielte Spiele: §e" + s.games);
player.sendMessage("§7 📈 Siegquote: §e" + String.format("%.1f", s.getWinRate()) + "§7%");
// In-Game-Statistik anhängen wenn aktiv
Game inGame = plugin.getGameManager().getPlayerGame(target);
if (inGame != null) {
player.sendMessage("§8--- Aktuelles Spiel ---");
player.sendMessage("§7 Tore heute: §e" + inGame.getGoals().getOrDefault(target.getUniqueId(), 0));
player.sendMessage("§7 Schüsse heute: §e" + inGame.getKicks().getOrDefault(target.getUniqueId(), 0));
}
}
// ── Admin-Befehle ────────────────────────────────────────────────
case "create" -> {
if (!sender.hasPermission("fussball.admin")) { sender.sendMessage(MessageUtil.error("Keine Berechtigung!")); return true; }
if (args.length < 2) { sender.sendMessage(MessageUtil.error("Benutze: /fb create <name>")); return true; }
if (plugin.getArenaManager().arenaExists(args[1])) { sender.sendMessage(MessageUtil.error("Arena §e" + args[1] + " §cexistiert bereits!")); return true; }
plugin.getArenaManager().createArena(args[1]);
sender.sendMessage(MessageUtil.success("Arena §e" + args[1] + " §aerstellt! Richte sie mit §e/fb setup §aein."));
}
case "delete" -> {
if (!sender.hasPermission("fussball.admin")) { sender.sendMessage(MessageUtil.error("Keine Berechtigung!")); return true; }
if (args.length < 2) { sender.sendMessage(MessageUtil.error("Benutze: /fb delete <arena>")); return true; }
sender.sendMessage(plugin.getArenaManager().deleteArena(args[1])
? MessageUtil.success("Arena §e" + args[1] + " §agelöscht!") : MessageUtil.error("Arena nicht gefunden!"));
}
case "setup" -> {
if (!sender.hasPermission("fussball.admin")) { sender.sendMessage(MessageUtil.error("Keine Berechtigung!")); return true; }
if (!(sender instanceof Player player)) { sender.sendMessage("Nur für Spieler!"); return true; }
if (args.length < 3) { sendSetupHelp(player); return true; }
handleSetup(player, args);
}
case "stop" -> {
if (!sender.hasPermission("fussball.admin")) { sender.sendMessage(MessageUtil.error("Keine Berechtigung!")); return true; }
if (args.length < 2) { sender.sendMessage(MessageUtil.error("Benutze: /fb stop <arena>")); return true; }
Game game = plugin.getGameManager().getGame(args[1]);
if (game == null) { sender.sendMessage(MessageUtil.error("Kein aktives Spiel in §e" + args[1] + "§c!")); return true; }
game.endGame(null);
sender.sendMessage(MessageUtil.success("Spiel in §e" + args[1] + " §aberendet."));
}
case "top" -> {
if (args.length < 2) {
sender.sendMessage(MessageUtil.error("Benutze: /fussball top goals|wins|kicks"));
return true;
}
switch (args[1].toLowerCase()) {
case "goals" -> {
sender.sendMessage(MessageUtil.header("🏆 Top Torschützen"));
var list = plugin.getStatsManager().getTopScorers(10);
if (list.isEmpty()) { sender.sendMessage(MessageUtil.warn("Noch keine Daten.")); break; }
for (int i = 0; i < list.size(); i++) {
var e = list.get(i);
sender.sendMessage("§e#" + (i+1) + " §f" + e.getValue().name
+ " §7— §e" + e.getValue().goals + " §7Tore"
+ " §8(§7" + e.getValue().games + " Spiele§8)");
}
}
case "wins" -> {
sender.sendMessage(MessageUtil.header("🏆 Top Gewinner"));
var list = plugin.getStatsManager().getTopWins(10);
if (list.isEmpty()) { sender.sendMessage(MessageUtil.warn("Noch keine Daten.")); break; }
for (int i = 0; i < list.size(); i++) {
var e = list.get(i);
sender.sendMessage("§e#" + (i+1) + " §f" + e.getValue().name
+ " §7— §a" + e.getValue().wins + " §7Siege"
+ " §8(§7" + String.format("%.0f", e.getValue().getWinRate()) + "% WR§8)");
}
}
case "kicks" -> {
sender.sendMessage(MessageUtil.header("🏆 Top Schützen (Schüsse)"));
var list = plugin.getStatsManager().getTopScorers(10);
// Nutze getTopScorers und zeige kicks
var kickList = new java.util.ArrayList<>(plugin.getStatsManager().getTopScorers(100));
kickList.sort((a, b) -> b.getValue().kicks - a.getValue().kicks);
for (int i = 0; i < Math.min(10, kickList.size()); i++) {
var e = kickList.get(i);
sender.sendMessage("§e#" + (i+1) + " §f" + e.getValue().name
+ " §7— §e" + e.getValue().kicks + " §7Schüsse");
}
}
default -> sender.sendMessage(MessageUtil.error("Gültig: goals | wins | kicks"));
}
}
case "debug" -> {
if (!sender.hasPermission("fussball.admin")) { sender.sendMessage(MessageUtil.error("Keine Berechtigung!")); return true; }
if (!(sender instanceof Player player)) { sender.sendMessage("Nur für Spieler!"); return true; }
if (args.length < 2) { sender.sendMessage(MessageUtil.error("Benutze: /fb debug <arena>")); return true; }
Arena arena = plugin.getArenaManager().getArena(args[1]);
if (arena == null) { sender.sendMessage(MessageUtil.error("Arena nicht gefunden!")); return true; }
handleDebug(player, arena);
}
default -> sendHelp(sender);
}
return true;
}
// ── Setup-Handler ────────────────────────────────────────────────────────
private void handleSetup(Player player, String[] args) {
Arena arena = plugin.getArenaManager().getArena(args[1]);
if (arena == null) { player.sendMessage(MessageUtil.error("Arena §e" + args[1] + " §cnicht gefunden!")); return; }
switch (args[2].toLowerCase()) {
case "lobby" -> { arena.setLobby(player.getLocation()); player.sendMessage(MessageUtil.success("Lobby gesetzt: " + locStr(player.getLocation()))); }
case "redspawn" -> { arena.setRedSpawn(player.getLocation()); player.sendMessage(MessageUtil.success("Roter Spawn gesetzt: " + locStr(player.getLocation()))); }
case "bluespawn" -> { arena.setBlueSpawn(player.getLocation()); player.sendMessage(MessageUtil.success("Blauer Spawn gesetzt: " + locStr(player.getLocation()))); }
case "ballspawn" -> { arena.setBallSpawn(player.getLocation()); player.sendMessage(MessageUtil.success("Ball-Spawn gesetzt: " + locStr(player.getLocation()))); }
case "center" -> { arena.setCenter(player.getLocation()); player.sendMessage(MessageUtil.success("Mittelpunkt gesetzt: " + locStr(player.getLocation()))); }
case "redgoalmin" -> { arena.setRedGoalMin(player.getLocation()); player.sendMessage(MessageUtil.success("Rotes Tor Min gesetzt: " + locStr(player.getLocation()))); }
case "redgoalmax" -> { arena.setRedGoalMax(player.getLocation()); player.sendMessage(MessageUtil.success("Rotes Tor Max gesetzt: " + locStr(player.getLocation()))); }
case "bluegoalmin" -> { arena.setBlueGoalMin(player.getLocation()); player.sendMessage(MessageUtil.success("Blaues Tor Min gesetzt: " + locStr(player.getLocation()))); }
case "bluegoalmax" -> { arena.setBlueGoalMax(player.getLocation()); player.sendMessage(MessageUtil.success("Blaues Tor Max gesetzt: " + locStr(player.getLocation()))); }
case "fieldmin" -> { arena.setFieldMin(player.getLocation()); player.sendMessage(MessageUtil.success("Spielfeld Min gesetzt: " + locStr(player.getLocation()))); }
case "fieldmax" -> { arena.setFieldMax(player.getLocation()); player.sendMessage(MessageUtil.success("Spielfeld Max gesetzt: " + locStr(player.getLocation()))); }
case "minplayers" -> { if (args.length < 4) return; arena.setMinPlayers(Integer.parseInt(args[3])); player.sendMessage(MessageUtil.success("Min-Spieler: §e" + args[3])); }
case "maxplayers" -> { if (args.length < 4) return; arena.setMaxPlayers(Integer.parseInt(args[3])); player.sendMessage(MessageUtil.success("Max-Spieler: §e" + args[3])); }
case "duration" -> { if (args.length < 4) return; arena.setGameDuration(Integer.parseInt(args[3])); player.sendMessage(MessageUtil.success("Spieldauer: §e" + args[3] + "s")); }
case "info" -> {
player.sendMessage(MessageUtil.header("Arena: " + arena.getName()));
player.sendMessage("§7 Lobby: " + check(arena.getLobby()));
player.sendMessage("§7 Roter Spawn: " + check(arena.getRedSpawn()));
player.sendMessage("§7 Blauer Spawn: " + check(arena.getBlueSpawn()));
player.sendMessage("§7 Ball-Spawn: " + check(arena.getBallSpawn()));
player.sendMessage("§7 Mittelpunkt: " + check(arena.getCenter()));
player.sendMessage("§7 Rotes Tor: " + check(arena.getRedGoalMin(), arena.getRedGoalMax()));
player.sendMessage("§7 Blaues Tor: " + check(arena.getBlueGoalMin(), arena.getBlueGoalMax()));
player.sendMessage("§7 Spielfeld: " + check(arena.getFieldMin(), arena.getFieldMax()) + " §8(optional)");
player.sendMessage("§7 Min. Spieler: §e" + arena.getMinPlayers());
player.sendMessage("§7 Max. Spieler: §e" + arena.getMaxPlayers());
player.sendMessage("§7 Spieldauer: §e" + arena.getGameDuration() + "s");
player.sendMessage("§7 Setup komplett: " + (arena.isSetupComplete() ? "§a✔ JA" : "§c✗ NEIN"));
return;
}
default -> { sendSetupHelp(player); return; }
}
plugin.getArenaManager().saveArena(arena);
}
// ── Debug-Handler ────────────────────────────────────────────────────────
private void handleDebug(Player player, Arena arena) {
player.sendMessage(MessageUtil.header("DEBUG: " + arena.getName()));
printRegion(player, "§cROTES TOR", arena.getRedGoalMin(), arena.getRedGoalMax());
printRegion(player, "§9BLAUES TOR", arena.getBlueGoalMin(), arena.getBlueGoalMax());
printRegion(player, "§aSPIELFELD", arena.getFieldMin(), arena.getFieldMax());
Game game = plugin.getGameManager().getGame(arena.getName());
if (game != null && game.getBall() != null && game.getBall().isActive()) {
Ball ball = game.getBall();
Location bl = ball.getEntity().getLocation();
Location bh = bl.clone().add(0, 1.4, 0);
player.sendMessage("§e--- BALL ---");
player.sendMessage("§7Fuß: §f" + locStr(bl));
player.sendMessage("§7Kopf: §f" + locStr(bh));
player.sendMessage("§7RotesTor: Fuß=" + yn(arena.isInRedGoal(bl)) + " Kopf=" + yn(arena.isInRedGoal(bh)));
player.sendMessage("§7BlauesTor: Fuß=" + yn(arena.isInBlueGoal(bl)) + " Kopf=" + yn(arena.isInBlueGoal(bh)));
player.sendMessage("§7Im Feld: " + yn(arena.isInField(bl)));
player.sendMessage("§7Aus-Seite: §f" + (arena.getOutSide(bl) != null ? arena.getOutSide(bl) : "keine"));
} else {
player.sendMessage("§7(Kein aktiver Ball)");
}
player.sendMessage("§e--- DEINE POSITION ---");
player.sendMessage("§f" + locStr(player.getLocation()));
player.sendMessage("§7RotesTor: " + yn(arena.isInRedGoal(player.getLocation())));
player.sendMessage("§7BlauesTor: " + yn(arena.isInBlueGoal(player.getLocation())));
player.sendMessage("§7Im Feld: " + yn(arena.isInField(player.getLocation())));
}
// ── Hilfsmethoden ────────────────────────────────────────────────────────
private String statusDot(GameState s) {
return switch (s) {
case WAITING -> "§a●";
case STARTING -> "§e●";
case RUNNING, GOAL, HALFTIME, OVERTIME -> "§c●";
case PENALTY -> "§d●";
case ENDING -> "§7●";
};
}
private void printRegion(Player p, String label, Location min, Location max) {
p.sendMessage("§e--- " + label + " §e---");
if (min == null || max == null) { p.sendMessage("§cNICHT GESETZT"); return; }
p.sendMessage("§7Min: §f" + locStr(min) + " §7Max: §f" + locStr(max));
p.sendMessage("§7X: §f" + fmt(Math.min(min.getX(), max.getX())) + "§7─§f" + fmt(Math.max(min.getX(), max.getX())));
p.sendMessage("§7Y: §f" + fmt(Math.min(min.getY(), max.getY())) + "§7─§f" + fmt(Math.max(min.getY(), max.getY())));
p.sendMessage("§7Z: §f" + fmt(Math.min(min.getZ(), max.getZ())) + "§7─§f" + fmt(Math.max(min.getZ(), max.getZ())));
}
private void sendHelp(CommandSender s) {
s.sendMessage(MessageUtil.header("⚽ Fußball Plugin"));
s.sendMessage("§e/fb join <arena> §7- Spiel beitreten");
s.sendMessage("§e/fb leave §7- Spiel / Zuschauer verlassen");
s.sendMessage("§e/fb spectate <arena> §7- Spiel zuschauen");
s.sendMessage("§e/fb list §7- Arenen anzeigen");
s.sendMessage("§e/fb stats [spieler] §7- Statistiken anzeigen");
s.sendMessage("§e/fb top [goals|wins] §7- Bestenliste");
if (s.hasPermission("fussball.admin")) {
s.sendMessage("§c§lAdmin: §ccreate / delete / setup / stop / debug");
}
}
private void sendSetupHelp(Player p) {
p.sendMessage(MessageUtil.header("Setup-Optionen"));
p.sendMessage("§e/fb setup <arena> lobby|redspawn|bluespawn|ballspawn|center");
p.sendMessage("§e/fb setup <arena> redgoalmin|redgoalmax|bluegoalmin|bluegoalmax");
p.sendMessage("§e/fb setup <arena> fieldmin|fieldmax §8(optional Aus-Erkennung)");
p.sendMessage("§e/fb setup <arena> minplayers <n>|maxplayers <n>|duration <s>|info");
}
private String check(Location l) { return l != null ? "§a✔ " + locStr(l) : "§c✗ nicht gesetzt"; }
private String check(Location a, Location b) { return (a != null && b != null) ? "§a✔ gesetzt" : "§c✗ nicht gesetzt"; }
private String yn(boolean b) { return b ? "§aJA" : "§cNEIN"; }
private String locStr(Location l) { return fmt(l.getX()) + " / " + fmt(l.getY()) + " / " + fmt(l.getZ()); }
private String fmt(double d) { return String.format("%.1f", d); }
// ── Tab-Completion ───────────────────────────────────────────────────────
@Override
public List<String> onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) {
List<String> list = new ArrayList<>();
if (args.length == 1) {
list.addAll(List.of("join", "leave", "list", "stats", "top", "spectate"));
if (sender.hasPermission("fussball.admin")) list.addAll(List.of("create", "delete", "setup", "stop", "debug"));
} else if (args.length == 2 && List.of("join","delete","setup","stop","debug","spectate").contains(args[0].toLowerCase())) {
list.addAll(plugin.getArenaManager().getArenaNames());
} else if (args.length == 3 && args[0].equalsIgnoreCase("setup")) {
list.addAll(List.of("lobby","redspawn","bluespawn","ballspawn","center",
"redgoalmin","redgoalmax","bluegoalmin","bluegoalmax",
"fieldmin","fieldmax","minplayers","maxplayers","duration","info"));
} else if (args.length == 2 && args[0].equalsIgnoreCase("top")) {
list.addAll(List.of("goals", "wins"));
}
String input = args[args.length - 1].toLowerCase();
list.removeIf(s -> !s.toLowerCase().startsWith(input));
return list;
}
}