/* * This file is a part of the SteamWar software. * * Copyright (C) 2025 SteamWar.de-Serverteam * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package de.steamwar.lobby.portal; import de.steamwar.lobby.Fightserver; import de.steamwar.lobby.LobbySystem; import de.steamwar.lobby.display.Hologram; import de.steamwar.lobby.display.NPC; import de.steamwar.network.packets.common.FightInfoPacket; import de.steamwar.sql.SteamwarUser; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.util.Vector; import java.util.*; import java.util.logging.Level; import java.util.stream.Collectors; public class FightserverPortal implements PortalHandler, Comparable { private static final Map> portals = new HashMap<>(); public static FightserverPortal findFree(String gamemode) { List list = portals.getOrDefault(gamemode, Collections.emptyList()); for (FightserverPortal portal : list) { if (portal.server == null) return portal; } return null; } private final Portal portal; private final String gamemode; private final int order; private final String target; private final List bluePlayers; private final List redPlayers; private Fightserver server = null; private PortalHandler handler = new DummyPortal(); private final Hologram hologram; private final List blueNPCs = new ArrayList<>(); private final List redNPCs = new ArrayList<>(); public FightserverPortal(Map section, Portal portal) { this( portal, (String) section.get("group"), (int) section.get("order"), (String) section.get("target"), (List) section.getOrDefault("bluePlayers", new ArrayList<>()), (List) section.getOrDefault("redPlayers", new ArrayList<>()) ); } public FightserverPortal(Portal portal, String gamemode, int order, String target, List bluePlayers, List redPlayers) { this.portal = portal; this.gamemode = gamemode; this.order = order; this.target = target; this.bluePlayers = bluePlayers; this.redPlayers = redPlayers; hologram = new Hologram(null, portal.denormalize(new Vector(0.5, 0.5, 0.5)).toLocation(portal.getPos1().getWorld()), "", false); setServer(null); List list = portals.computeIfAbsent(gamemode, mode -> new ArrayList<>()); list.add(this); list.sort(null); } public void setServer(Fightserver server) { this.server = server; if (server == null) { setHandler(new TeleportPortal(portal, target)); } else { setHandler(new CommandPortal("arena " + server.getServerName())); } updateText(); updateBluePlayers(); updateRedPlayers(); } public void updateText() { if (server == null) { hologram.updateText("§7Neuen Kampf starten"); return; } FightInfoPacket info = server.current(); if (fightStateCountdown(info.getFightState())) { hologram.updateText(String.format("§7%s §e%s §7%d§8:§7%02d", server.getServerName(), fightStateMapper(info.getFightState()), info.getCountdown() / 60, info.getCountdown() % 60)); } else { hologram.updateText(String.format("§7%s §e%s", server.getServerName(), fightStateMapper(info.getFightState()))); } } public void updateBluePlayers() { updateNPCs(bluePlayers, blueNPCs, server != null ? server.current().getBluePlayers() : Collections.emptyList()); } public void updateRedPlayers() { updateNPCs(redPlayers, redNPCs, server != null ? server.current().getRedPlayers() : Collections.emptyList()); } private void updateNPCs(List locations, List npcs, List players) { List remainingPlayers = players.stream().map(SteamwarUser::byId).collect(Collectors.toList()); List remainingLocations = new ArrayList<>(locations); npcs.removeIf(npc -> { SteamwarUser user = SteamwarUser.get(npc.getUuid()); if (remainingPlayers.contains(user)) { remainingPlayers.remove(user); remainingLocations.remove(npc.getLocation()); return false; } else { npc.delete(); return true; } }); for (SteamwarUser user : remainingPlayers) { if (remainingLocations.isEmpty()) break; npcs.add(new NPC(remainingLocations.remove(0), user.getUUID(), user.getUserName())); } } public void addBlue(Location location) { bluePlayers.add(location); LobbySystem.config().save(); } public void addRed(Location location) { redPlayers.add(location); LobbySystem.config().save(); } public void removeBlue(int i) { bluePlayers.remove(i); LobbySystem.config().save(); } public void removeRed(int i) { redPlayers.remove(i); LobbySystem.config().save(); } private void setHandler(PortalHandler handler) { handler.delete(); this.handler = handler; } @Override public void handle(Player player, Location from, Location to) { handler.handle(player, from, to); } @Override public void serialize(Map map) { map.put("group", gamemode); map.put("order", order); map.put("target", target); map.put("bluePlayers", bluePlayers); map.put("redPlayers", redPlayers); } @Override public PortalType type() { return PortalType.FIGHTSERVER; } @Override public void delete() { portals.get(gamemode).remove(this); hologram.delete(); blueNPCs.forEach(NPC::delete); redNPCs.forEach(NPC::delete); handler.delete(); } @Override public int compareTo(FightserverPortal other) { return order - other.order; } private boolean fightStateCountdown(String state) { switch (state) { case "waiting": case "PRE_LEADER_SETUP": case "end": case "SPECTATE": return false; default: return true; } } private String fightStateMapper(String state) { switch (state) { case "waiting": case "PRE_LEADER_SETUP": return "Warten auf Spieler"; case "PRE_SCHEM_SETUP": return "Schemauswahl"; case "POST_SCHEM_SETUP": case "generating_tower": return "Vorbereitung"; case "PRE_RUNNING": return "Kampfbeginn in"; case "fighting": case "RUNNING": case "running": return "Kampf läuft"; case "end": case "SPECTATE": return "Zuschauerphase"; default: LobbySystem.getInstance().getLogger().log(Level.SEVERE, "Unknown FightState " + state + " encountered"); return "Programmierfehler"; } } @Override public String toString() { return "Fightserver"; } }