Update from Git Manager GUI

This commit is contained in:
2026-02-27 15:11:33 +01:00
parent fbf4ab16b0
commit b15396ba16
4 changed files with 121 additions and 13 deletions

View File

@@ -15,6 +15,8 @@ public class Arena implements ConfigurationSerializable {
private Location fieldMin, fieldMax; private Location fieldMin, fieldMax;
// Strafräume optional manuell gesetzt; sonst auto-berechnet aus Tor + config // Strafräume optional manuell gesetzt; sonst auto-berechnet aus Tor + config
private Location redPenaltyMin, redPenaltyMax, bluePenaltyMin, bluePenaltyMax; private Location redPenaltyMin, redPenaltyMax, bluePenaltyMin, bluePenaltyMax;
// Elfmeter-Punkte (optional sonst wird ballSpawn genutzt)
private Location redPenaltySpot, bluePenaltySpot;
private int minPlayers, maxPlayers, gameDuration; private int minPlayers, maxPlayers, gameDuration;
/** /**
@@ -255,6 +257,8 @@ public class Arena implements ConfigurationSerializable {
if (redPenaltyMax != null) map.put("redPenaltyMax", serLoc(redPenaltyMax)); if (redPenaltyMax != null) map.put("redPenaltyMax", serLoc(redPenaltyMax));
if (bluePenaltyMin != null) map.put("bluePenaltyMin", serLoc(bluePenaltyMin)); if (bluePenaltyMin != null) map.put("bluePenaltyMin", serLoc(bluePenaltyMin));
if (bluePenaltyMax != null) map.put("bluePenaltyMax", serLoc(bluePenaltyMax)); if (bluePenaltyMax != null) map.put("bluePenaltyMax", serLoc(bluePenaltyMax));
if (redPenaltySpot != null) map.put("redPenaltySpot", serLoc(redPenaltySpot));
if (bluePenaltySpot != null) map.put("bluePenaltySpot", serLoc(bluePenaltySpot));
return map; return map;
} }
@@ -283,6 +287,8 @@ public class Arena implements ConfigurationSerializable {
if (map.containsKey("redPenaltyMax")) a.redPenaltyMax = desLoc(map.get("redPenaltyMax")); if (map.containsKey("redPenaltyMax")) a.redPenaltyMax = desLoc(map.get("redPenaltyMax"));
if (map.containsKey("bluePenaltyMin")) a.bluePenaltyMin = desLoc(map.get("bluePenaltyMin")); if (map.containsKey("bluePenaltyMin")) a.bluePenaltyMin = desLoc(map.get("bluePenaltyMin"));
if (map.containsKey("bluePenaltyMax")) a.bluePenaltyMax = desLoc(map.get("bluePenaltyMax")); if (map.containsKey("bluePenaltyMax")) a.bluePenaltyMax = desLoc(map.get("bluePenaltyMax"));
if (map.containsKey("redPenaltySpot")) a.redPenaltySpot = desLoc(map.get("redPenaltySpot"));
if (map.containsKey("bluePenaltySpot")) a.bluePenaltySpot = desLoc(map.get("bluePenaltySpot"));
return a; return a;
} }
@@ -338,7 +344,25 @@ public class Arena implements ConfigurationSerializable {
public void setBluePenaltyMin(Location l) { this.bluePenaltyMin = l; } public void setBluePenaltyMin(Location l) { this.bluePenaltyMin = l; }
public Location getBluePenaltyMax() { return bluePenaltyMax; } public Location getBluePenaltyMax() { return bluePenaltyMax; }
public void setBluePenaltyMax(Location l) { this.bluePenaltyMax = l; } public void setBluePenaltyMax(Location l) { this.bluePenaltyMax = l; }
public boolean hasManualpPenaltyAreas() { return redPenaltyMin != null && redPenaltyMax != null
// ── Elfmeter-Punkte ──────────────────────────────────────────────────────
public Location getRedPenaltySpot() { return redPenaltySpot; }
public void setRedPenaltySpot(Location l) { this.redPenaltySpot = l; }
public Location getBluePenaltySpot() { return bluePenaltySpot; }
public void setBluePenaltySpot(Location l) { this.bluePenaltySpot = l; }
/**
* Gibt den Elfmeter-Punkt für ein Team zurück.
* Falls nicht gesetzt, wird ballSpawn als Fallback verwendet.
*/
public Location getPenaltySpot(de.fussball.plugin.game.Team team) {
if (team == de.fussball.plugin.game.Team.RED) {
return redPenaltySpot != null ? redPenaltySpot : ballSpawn;
} else {
return bluePenaltySpot != null ? bluePenaltySpot : ballSpawn;
}
}
public boolean hasManualPenaltyAreas() { return redPenaltyMin != null && redPenaltyMax != null
&& bluePenaltyMin != null && bluePenaltyMax != null; } && bluePenaltyMin != null && bluePenaltyMax != null; }
public int getMinPlayers() { return minPlayers; } public int getMinPlayers() { return minPlayers; }
public void setMinPlayers(int n) { this.minPlayers = n; } public void setMinPlayers(int n) { this.minPlayers = n; }

View File

@@ -133,6 +133,22 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
sender.sendMessage(MessageUtil.success("Spiel in §e" + args[1] + " §aberendet.")); sender.sendMessage(MessageUtil.success("Spiel in §e" + args[1] + " §aberendet."));
} }
// ── Torwart manuell zuweisen ─────────────────────────────────────────
case "setgk" -> {
if (!sender.hasPermission("fussball.admin")) { sender.sendMessage(MessageUtil.error("Keine Berechtigung!")); return true; }
// Nutzung: /fb setgk <arena> <spieler>
if (args.length < 3) { sender.sendMessage(MessageUtil.error("Benutze: /fb setgk <arena> <spieler>")); return true; }
Game gkGame = plugin.getGameManager().getGame(args[1]);
if (gkGame == null) { sender.sendMessage(MessageUtil.error("Kein aktives Spiel in §e" + args[1] + "§c!")); return true; }
Player target = Bukkit.getPlayerExact(args[2]);
if (target == null) { sender.sendMessage(MessageUtil.error("Spieler §e" + args[2] + " §cnicht online!")); return true; }
if (!gkGame.isInGame(target)) { sender.sendMessage(MessageUtil.error("§e" + args[2] + " §cist nicht in diesem Spiel!")); return true; }
if (!gkGame.setGoalkeeper(target)) {
sender.sendMessage(MessageUtil.error("Konnte Torwart nicht zuweisen Spieler hat kein Team?"));
} else {
sender.sendMessage(MessageUtil.success("§e" + target.getName() + " §aist jetzt Torwart!"));
}
}
case "top" -> { case "top" -> {
if (args.length < 2) { if (args.length < 2) {
sender.sendMessage(MessageUtil.error("Benutze: /fussball top goals|wins|kicks")); sender.sendMessage(MessageUtil.error("Benutze: /fussball top goals|wins|kicks"));
@@ -163,8 +179,6 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
} }
case "kicks" -> { case "kicks" -> {
sender.sendMessage(MessageUtil.header("🏆 Top Schützen (Schüsse)")); 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)); var kickList = new java.util.ArrayList<>(plugin.getStatsManager().getTopScorers(100));
kickList.sort((a, b) -> b.getValue().kicks - a.getValue().kicks); kickList.sort((a, b) -> b.getValue().kicks - a.getValue().kicks);
for (int i = 0; i < Math.min(10, kickList.size()); i++) { for (int i = 0; i < Math.min(10, kickList.size()); i++) {
@@ -213,6 +227,8 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
case "redpenaltymax" -> { arena.setRedPenaltyMax(player.getLocation()); player.sendMessage(MessageUtil.success("Roter Strafraum Max gesetzt: " + locStr(player.getLocation()))); } case "redpenaltymax" -> { arena.setRedPenaltyMax(player.getLocation()); player.sendMessage(MessageUtil.success("Roter Strafraum Max gesetzt: " + locStr(player.getLocation()))); }
case "bluepenaltymin" -> { arena.setBluePenaltyMin(player.getLocation()); player.sendMessage(MessageUtil.success("Blauer Strafraum Min gesetzt: "+ locStr(player.getLocation()))); } case "bluepenaltymin" -> { arena.setBluePenaltyMin(player.getLocation()); player.sendMessage(MessageUtil.success("Blauer Strafraum Min gesetzt: "+ locStr(player.getLocation()))); }
case "bluepenaltymax" -> { arena.setBluePenaltyMax(player.getLocation()); player.sendMessage(MessageUtil.success("Blauer Strafraum Max gesetzt: "+ locStr(player.getLocation()))); } case "bluepenaltymax" -> { arena.setBluePenaltyMax(player.getLocation()); player.sendMessage(MessageUtil.success("Blauer Strafraum Max gesetzt: "+ locStr(player.getLocation()))); }
case "redpenaltyspot" -> { arena.setRedPenaltySpot(player.getLocation()); player.sendMessage(MessageUtil.success("Roter Elfmeter-Punkt gesetzt: " + locStr(player.getLocation()))); }
case "bluepenaltyspot" -> { arena.setBluePenaltySpot(player.getLocation()); player.sendMessage(MessageUtil.success("Blauer Elfmeter-Punkt 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 "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 "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 "duration" -> { if (args.length < 4) return; arena.setGameDuration(Integer.parseInt(args[3])); player.sendMessage(MessageUtil.success("Spieldauer: §e" + args[3] + "s")); }
@@ -230,6 +246,8 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
+ " §8(optional sonst auto-berechnet)"); + " §8(optional sonst auto-berechnet)");
player.sendMessage("§7 Blauer Strafraum: " + check(arena.getBluePenaltyMin(), arena.getBluePenaltyMax()) player.sendMessage("§7 Blauer Strafraum: " + check(arena.getBluePenaltyMin(), arena.getBluePenaltyMax())
+ " §8(optional sonst auto-berechnet)"); + " §8(optional sonst auto-berechnet)");
player.sendMessage("§7 Roter Elfmeter-Punkt: " + check(arena.getRedPenaltySpot()) + " §8(optional sonst ball-spawn)");
player.sendMessage("§7 Blauer Elfmeter-Punkt: " + check(arena.getBluePenaltySpot()) + " §8(optional sonst ball-spawn)");
player.sendMessage("§7 Min. Spieler: §e" + arena.getMinPlayers()); player.sendMessage("§7 Min. Spieler: §e" + arena.getMinPlayers());
player.sendMessage("§7 Max. Spieler: §e" + arena.getMaxPlayers()); player.sendMessage("§7 Max. Spieler: §e" + arena.getMaxPlayers());
player.sendMessage("§7 Spieldauer: §e" + arena.getGameDuration() + "s"); player.sendMessage("§7 Spieldauer: §e" + arena.getGameDuration() + "s");
@@ -327,14 +345,24 @@ public class FussballCommand implements CommandExecutor, TabCompleter {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
if (args.length == 1) { if (args.length == 1) {
list.addAll(List.of("join", "leave", "list", "stats", "top", "spectate")); list.addAll(List.of("join", "leave", "list", "stats", "top", "spectate"));
if (sender.hasPermission("fussball.admin")) list.addAll(List.of("create", "delete", "setup", "stop", "debug")); if (sender.hasPermission("fussball.admin")) list.addAll(List.of("create", "delete", "setup", "stop", "setgk", "debug"));
} else if (args.length == 2 && List.of("join","delete","setup","stop","debug","spectate").contains(args[0].toLowerCase())) { } else if (args.length == 2 && List.of("join","delete","setup","stop","setgk","debug","spectate").contains(args[0].toLowerCase())) {
list.addAll(plugin.getArenaManager().getArenaNames()); list.addAll(plugin.getArenaManager().getArenaNames());
} else if (args.length == 3 && args[0].equalsIgnoreCase("setgk")) {
// Spielernamen aus dem aktiven Spiel vorschlagen
Game gkGame = plugin.getGameManager().getGame(args[1]);
if (gkGame != null) {
for (UUID uuid : gkGame.getAllPlayers()) {
Player p = Bukkit.getPlayer(uuid);
if (p != null) list.add(p.getName());
}
}
} else if (args.length == 3 && args[0].equalsIgnoreCase("setup")) { } else if (args.length == 3 && args[0].equalsIgnoreCase("setup")) {
list.addAll(List.of("lobby","redspawn","bluespawn","ballspawn","center", list.addAll(List.of("lobby","redspawn","bluespawn","ballspawn","center",
"redgoalmin","redgoalmax","bluegoalmin","bluegoalmax", "redgoalmin","redgoalmax","bluegoalmin","bluegoalmax",
"fieldmin","fieldmax", "fieldmin","fieldmax",
"redpenaltymin","redpenaltymax","bluepenaltymin","bluepenaltymax", "redpenaltymin","redpenaltymax","bluepenaltymin","bluepenaltymax",
"redpenaltyspot","bluepenaltyspot",
"minplayers","maxplayers","duration","info")); "minplayers","maxplayers","duration","info"));
} else if (args.length == 2 && args[0].equalsIgnoreCase("top")) { } else if (args.length == 2 && args[0].equalsIgnoreCase("top")) {
list.addAll(List.of("goals", "wins")); list.addAll(List.of("goals", "wins"));

View File

@@ -411,6 +411,9 @@ public class Game {
for (UUID uuid : blueTeam) { Player p = Bukkit.getPlayer(uuid); if (p != null) { p.teleport(arena.getBlueSpawn()); p.sendTitle("§6§lVERLÄNGERUNG!", "§710 Minuten extra!", 10, 60, 10); } } for (UUID uuid : blueTeam) { Player p = Bukkit.getPlayer(uuid); if (p != null) { p.teleport(arena.getBlueSpawn()); p.sendTitle("§6§lVERLÄNGERUNG!", "§710 Minuten extra!", 10, 60, 10); } }
if (bossBar != null) { bossBar.setColor(BarColor.YELLOW); bossBar.setTitle("§6VERLÄNGERUNG §c" + redScore + " §7: §9" + blueScore); } if (bossBar != null) { bossBar.setColor(BarColor.YELLOW); bossBar.setTitle("§6VERLÄNGERUNG §c" + redScore + " §7: §9" + blueScore); }
scoreboard.updateAll(); scoreboard.updateAll();
// Neuen Game-Loop für die Verlängerung starten
startGameLoop();
} }
// ════════════════════════════════════════════════════════════════════════ // ════════════════════════════════════════════════════════════════════════
@@ -475,18 +478,18 @@ public class Game {
for (UUID uuid : redTeam) { Player p = Bukkit.getPlayer(uuid); if (p != null && !p.equals(shooter)) p.teleport(arena.getRedSpawn()); } for (UUID uuid : redTeam) { Player p = Bukkit.getPlayer(uuid); if (p != null && !p.equals(shooter)) p.teleport(arena.getRedSpawn()); }
for (UUID uuid : blueTeam) { Player p = Bukkit.getPlayer(uuid); if (p != null && !p.equals(shooter)) p.teleport(arena.getBlueSpawn()); } for (UUID uuid : blueTeam) { Player p = Bukkit.getPlayer(uuid); if (p != null && !p.equals(shooter)) p.teleport(arena.getBlueSpawn()); }
// Ball aufstellen // Ball aufstellen am Elfmeter-Punkt des schießenden Teams (Fallback: ballSpawn)
if (ball != null) ball.remove(); if (ball != null) ball.remove();
// KORREKTUR: Hier muss 'this' übergeben werden Location penaltySpot = arena.getPenaltySpot(penaltyTurn);
ball = new Ball(this, plugin, arena.getBallSpawn()); ball = new Ball(this, plugin, penaltySpot);
spawnCooldown = 0; // Elfmeter sofort spielbar spawnCooldown = 0; // Elfmeter sofort spielbar
new BukkitRunnable() { new BukkitRunnable() {
public void run() { ball.spawn(); lastBallLocation = arena.getBallSpawn().clone(); } public void run() { ball.spawn(); lastBallLocation = penaltySpot.clone(); }
}.runTaskLater(plugin, 2L); }.runTaskLater(plugin, 2L);
// Schützen vorbereiten // Schützen vorbereiten
if (shooter != null) { if (shooter != null) {
shooter.teleport(arena.getBallSpawn()); shooter.teleport(penaltySpot);
shooter.sendTitle(teamColor + "Du schießt!", "§7Du hast §e15 Sekunden§7!", 10, 40, 10); shooter.sendTitle(teamColor + "Du schießt!", "§7Du hast §e15 Sekunden§7!", 10, 40, 10);
shooter.sendMessage(MessageUtil.info("§eDu schießt den Elfmeter! Tritt auf den Ball!")); shooter.sendMessage(MessageUtil.info("§eDu schießt den Elfmeter! Tritt auf den Ball!"));
} else { } else {
@@ -525,7 +528,7 @@ public class Game {
broadcastAll(c + "⚽ TREFFER! §7(" + penaltyRedGoals + ":" + penaltyBlueGoals + ")"); broadcastAll(c + "⚽ TREFFER! §7(" + penaltyRedGoals + ":" + penaltyBlueGoals + ")");
for (UUID uuid : allPlayers) { for (UUID uuid : allPlayers) {
Player p = Bukkit.getPlayer(uuid); Player p = Bukkit.getPlayer(uuid);
if (p != null) { spawnFirework(arena.getBallSpawn(), penaltyTurn); p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_BLAST, 2f, 1f); } if (p != null) { spawnFirework(arena.getPenaltySpot(penaltyTurn), penaltyTurn); p.playSound(p.getLocation(), Sound.ENTITY_FIREWORK_ROCKET_BLAST, 2f, 1f); }
} }
scoreboard.updateAll(); scoreboard.updateAll();
advancePenaltyTurn(); advancePenaltyTurn();
@@ -1043,6 +1046,60 @@ public class Game {
return uuid.equals(redGoalkeeper) || uuid.equals(blueGoalkeeper); return uuid.equals(redGoalkeeper) || uuid.equals(blueGoalkeeper);
} }
/**
* Weist einem Spieler manuell die Torwart-Rolle zu.
* Der bisherige Torwart des Teams verliert seine TW-Rüstung und erhält normale Team-Rüstung.
* @return false wenn der Spieler nicht im entsprechenden Team ist
*/
public boolean setGoalkeeper(Player newGk) {
Team team = getTeam(newGk);
if (team == null) return false;
// Bisherigen TW zurücksetzen
UUID oldGkUuid = (team == Team.RED) ? redGoalkeeper : blueGoalkeeper;
if (oldGkUuid != null && !oldGkUuid.equals(newGk.getUniqueId())) {
Player oldGk = Bukkit.getPlayer(oldGkUuid);
if (oldGk != null) {
applyTeamArmor(oldGk, team);
oldGk.sendMessage(MessageUtil.info("§7Du bist nicht mehr Torwart."));
}
}
// Neuen TW setzen
if (team == Team.RED) redGoalkeeper = newGk.getUniqueId();
else blueGoalkeeper = newGk.getUniqueId();
applyGoalkeeperArmor(newGk, team);
newGk.sendMessage(Messages.get("goalkeeper-assigned"));
broadcastAll(MessageUtil.info("§6" + newGk.getName() + " §7ist jetzt Torwart (" + team.getColorCode() + team.getDisplayName() + "§7)."));
return true;
}
/** Gibt dem Spieler normale Team-Lederrüstung (ohne TW-Sonderlook) */
private void applyTeamArmor(Player player, Team team) {
org.bukkit.Color c = team == Team.RED
? org.bukkit.Color.fromRGB(180, 0, 0)
: org.bukkit.Color.fromRGB(0, 0, 200);
for (int slot = 0; slot < 4; slot++) {
Material mat = switch (slot) {
case 0 -> Material.LEATHER_BOOTS;
case 1 -> Material.LEATHER_LEGGINGS;
case 2 -> Material.LEATHER_CHESTPLATE;
default -> Material.LEATHER_HELMET;
};
ItemStack item = new ItemStack(mat);
if (item.getItemMeta() instanceof org.bukkit.inventory.meta.LeatherArmorMeta meta) {
meta.setColor(c);
item.setItemMeta(meta);
}
switch (slot) {
case 0 -> player.getInventory().setBoots(item);
case 1 -> player.getInventory().setLeggings(item);
case 2 -> player.getInventory().setChestplate(item);
case 3 -> player.getInventory().setHelmet(item);
}
}
}
public boolean isInOwnHalf(Player player) { public boolean isInOwnHalf(Player player) {
if (arena.getFieldDirection() == null) return true; if (arena.getFieldDirection() == null) return true;
double playerAxis = arena.getAxisValue(player.getLocation()); double playerAxis = arena.getAxisValue(player.getLocation());
@@ -1400,7 +1457,7 @@ public class Game {
throwInTeam = null; throwInTeam = null;
// Persistente Statistiken speichern // Persistente Statistiken speichern
boolean draw = (winner == null || redScore == blueScore) && state != GameState.PENALTY; boolean draw = winner == null || redScore == blueScore;
Map<UUID, String> names = new HashMap<>(); Map<UUID, String> names = new HashMap<>();
for (UUID uuid : allPlayers) { Player p = Bukkit.getPlayer(uuid); if (p != null) names.put(uuid, p.getName()); } for (UUID uuid : allPlayers) { Player p = Bukkit.getPlayer(uuid); if (p != null) names.put(uuid, p.getName()); }
plugin.getStatsManager().flushKicks(kicks, names); plugin.getStatsManager().flushKicks(kicks, names);

View File

@@ -20,7 +20,6 @@ import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.UUID;
/** /**
* Verwaltet Ball-Interaktionen: * Verwaltet Ball-Interaktionen: