From ecf813c809e1235549a6a4651cc4b35f63ef99bd Mon Sep 17 00:00:00 2001 From: Lixfel Date: Fri, 21 Jan 2022 19:57:24 +0100 Subject: [PATCH] WIP Fightserverportale --- pom.xml | 1 + .../lobby/{servers => }/Fightserver.java | 95 +++++++++------ .../lobby/command/HologramCommand.java | 6 +- .../steamwar/lobby/command/PortalCommand.java | 46 +++----- .../steamwar/lobby/display/Displayable.java | 6 +- src/de/steamwar/lobby/display/Hologram.java | 51 +++++--- src/de/steamwar/lobby/display/NPC.java | 110 ++++++++++++++++++ .../steamwar/lobby/listener/Fightservers.java | 2 +- src/de/steamwar/lobby/listener/Join.java | 3 +- src/de/steamwar/lobby/listener/Portals.java | 2 +- src/de/steamwar/lobby/listener/Protocol.java | 44 ------- .../lobby/portal/FightserverPortal.java | 80 +++++++++++-- src/de/steamwar/lobby/portal/Portal.java | 2 +- .../steamwar/lobby/portal/TeleportPortal.java | 4 + src/de/steamwar/lobby/servers/Observable.java | 50 -------- 15 files changed, 318 insertions(+), 184 deletions(-) rename src/de/steamwar/lobby/{servers => }/Fightserver.java (58%) create mode 100644 src/de/steamwar/lobby/display/NPC.java delete mode 100644 src/de/steamwar/lobby/listener/Protocol.java delete mode 100644 src/de/steamwar/lobby/servers/Observable.java diff --git a/pom.xml b/pom.xml index 1b9e391..f18c8e7 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,7 @@ 8 8 + -Xlint diff --git a/src/de/steamwar/lobby/servers/Fightserver.java b/src/de/steamwar/lobby/Fightserver.java similarity index 58% rename from src/de/steamwar/lobby/servers/Fightserver.java rename to src/de/steamwar/lobby/Fightserver.java index 3c3d468..85a869a 100644 --- a/src/de/steamwar/lobby/servers/Fightserver.java +++ b/src/de/steamwar/lobby/Fightserver.java @@ -17,10 +17,11 @@ * along with this program. If not, see . */ -package de.steamwar.lobby.servers; +package de.steamwar.lobby; import com.google.common.io.ByteArrayDataInput; import de.steamwar.comms.packets.FightInfoPacket; +import de.steamwar.lobby.portal.FightserverPortal; import java.time.Instant; import java.time.temporal.ChronoUnit; @@ -29,42 +30,8 @@ import java.util.function.Consumer; public class Fightserver { - private static final List> listeners = new ArrayList<>(); - - public static void registerListener(Consumer listener) { - listeners.add(listener); - } - private static final Map servers = new HashMap<>(); - private Instant lastUpdate; - private final String serverName; - private final String gameMode; - private final Observable> bluePlayers = new Observable<>(); - private final Observable> redPlayers = new Observable<>(); - private final Observable playerCount = new Observable<>(); - - private Fightserver(FightInfoPacket fightInfo) { - serverName = fightInfo.getServerName(); - gameMode = fightInfo.getGameMode(); - - update(fightInfo); - listeners.forEach(listener -> listener.accept(this)); - - servers.put(serverName, this); - } - - private void update(FightInfoPacket fightInfo) { - bluePlayers.update(new HashSet<>(fightInfo.getBluePlayers())); - redPlayers.update(new HashSet<>(fightInfo.getRedPlayers())); - playerCount.update(fightInfo.getBluePlayers().size() + fightInfo.getRedPlayers().size() + fightInfo.getSpectators().size()); - lastUpdate = Instant.now(); - } - - private void remove() { - - } - public static void newFightInfo(ByteArrayDataInput in) { FightInfoPacket fightInfo = new FightInfoPacket(in); Fightserver server = servers.get(fightInfo.getServerName()); @@ -87,4 +54,62 @@ public class Fightserver { } } } + + private final List portals = new ArrayList<>(); + + private FightInfoPacket fightInfo; + private Instant lastUpdate; + + private Fightserver(FightInfoPacket fightInfo) { + this.fightInfo = fightInfo; + + update(fightInfo); + + setupPortal(getGameMode().toLowerCase()); + setupPortal("all"); + + servers.put(getServerName(), this); + } + + private void setupPortal(String gameMode) { + FightserverPortal portal = FightserverPortal.findFree(gameMode); + if(portal == null) + return; + + portals.add(portal); + portal.setServer(this); + } + + public String getGameMode() { + return fightInfo.getGameMode(); + } + + public String getServerName() { + return fightInfo.getServerName(); + } + + public FightInfoPacket current() { + return fightInfo; + } + + private void update(FightInfoPacket fightInfo) { + FightInfoPacket old = this.fightInfo; + this.fightInfo = fightInfo; + lastUpdate = Instant.now(); + + update(old.getBluePlayers(), fightInfo.getBluePlayers(), FightserverPortal::updateBluePlayers); + update(old.getRedPlayers(), fightInfo.getRedPlayers(), FightserverPortal::updateRedPlayers); + update(old.getCountdown(), fightInfo.getCountdown(), FightserverPortal::updateText); + update(old.getFightState(), fightInfo.getFightState(), FightserverPortal::updateText); + } + + private void update(T old, T current, Consumer observer) { + if(!old.equals(current)) + portals.forEach(observer); + } + + private void remove() { + portals.forEach(portal -> portal.setServer(null)); + portals.clear(); + } } diff --git a/src/de/steamwar/lobby/command/HologramCommand.java b/src/de/steamwar/lobby/command/HologramCommand.java index fb38db4..15832b0 100644 --- a/src/de/steamwar/lobby/command/HologramCommand.java +++ b/src/de/steamwar/lobby/command/HologramCommand.java @@ -57,7 +57,11 @@ public class HologramCommand extends SWCommand { public void portalDelete(Player player, String id) { if (PortalCommand.noPermissions(player)) return; - Hologram.getHologram(id).delete(); + Hologram hologram = Hologram.getHologram(id); + if (hologram == null) + return; + + hologram.delete(); LobbySystem.config().save(); } } diff --git a/src/de/steamwar/lobby/command/PortalCommand.java b/src/de/steamwar/lobby/command/PortalCommand.java index 989a516..c8c6942 100644 --- a/src/de/steamwar/lobby/command/PortalCommand.java +++ b/src/de/steamwar/lobby/command/PortalCommand.java @@ -52,44 +52,33 @@ public class PortalCommand extends SWCommand { @Register({"create", "command"}) public void portalAddCommand(Player player, String portalName, String... command) { if (noPermissions(player)) return; - Tuple tuple = getSelection(player); - if (tuple == null) { - LobbySystem.getMessage().send("PORTAL_NO_WORLDEDIT_SELECTION", player); - return; - } + PortalLocations tuple = getSelection(player); + if (tuple == null) return; new Portal(portalName, tuple.k, tuple.v, portal -> new CommandPortal(String.join(" ", command))); } - @Register({"create", "fightserver"}) - public void portalAddFightserver(Player player, String portalName, String group, String target) { + @Register({"create", "fight"}) + public void portalAddFightserver(Player player, String portalName, String gamemode, int order, String target) { if (noPermissions(player)) return; - Tuple tuple = getSelection(player); - if (tuple == null) { - LobbySystem.getMessage().send("PORTAL_NO_WORLDEDIT_SELECTION", player); - return; - } - new Portal(portalName, tuple.k, tuple.v, portal -> new FightserverPortal(portal, group, target)); + PortalLocations tuple = getSelection(player); + if (tuple == null) return; + new Portal(portalName, tuple.k, tuple.v, portal -> new FightserverPortal(portal, gamemode.toLowerCase(), order, target)); } @Register({"create", "teleport"}) public void portalAddTeleport(Player player, String portalName, String portalDestination) { if (noPermissions(player)) return; - Tuple tuple = getSelection(player); - if (tuple == null) { - LobbySystem.getMessage().send("PORTAL_NO_WORLDEDIT_SELECTION", player); - return; - } + PortalLocations tuple = getSelection(player); + if (tuple == null) return; new Portal(portalName, tuple.k, tuple.v, portal -> new TeleportPortal(portal, portalDestination)); } @Register({"create", "stack"}) public void portalAddStack(Player player, String portalName, String portalDestination, String... command) { if (noPermissions(player)) return; - Tuple tuple = getSelection(player); - if (tuple == null) { - LobbySystem.getMessage().send("PORTAL_NO_WORLDEDIT_SELECTION", player); - return; - } + PortalLocations tuple = getSelection(player); + if (tuple == null) return; + new Portal(portalName, tuple.k, tuple.v, portal -> new StackPortal(portal, portalDestination, String.join(" ", command))); } @@ -115,12 +104,12 @@ public class PortalCommand extends SWCommand { } @Data - private static class Tuple { - private final K k; - private final V v; + private static class PortalLocations { + private final Location k; + private final Location v; } - private Tuple getSelection(Player player) { + private PortalLocations getSelection(Player player) { RegionSelector regionSelector = WorldEdit.getInstance() .getSessionManager() .get(BukkitAdapter.adapt(player)) @@ -128,8 +117,9 @@ public class PortalCommand extends SWCommand { try { CuboidRegion region = (CuboidRegion)regionSelector.getRegion(); - return new Tuple<>(adapt(player.getWorld(), region.getPos1()), adapt(player.getWorld(), region.getPos2())); + return new PortalLocations(adapt(player.getWorld(), region.getPos1()), adapt(player.getWorld(), region.getPos2())); } catch (IncompleteRegionException e) { + LobbySystem.getMessage().send("PORTAL_NO_WORLDEDIT_SELECTION", player); return null; } } diff --git a/src/de/steamwar/lobby/display/Displayable.java b/src/de/steamwar/lobby/display/Displayable.java index 52ab923..b84ca97 100644 --- a/src/de/steamwar/lobby/display/Displayable.java +++ b/src/de/steamwar/lobby/display/Displayable.java @@ -51,6 +51,10 @@ public class Displayable extends BasicListener { Bukkit.getOnlinePlayers().forEach(player -> checkLocation(player, player.getLocation())); } + public Set getVisitors() { + return visible; + } + @EventHandler public void onJoin(PlayerJoinEvent e) { checkLocation(e.getPlayer(), e.getPlayer().getLocation()); @@ -63,7 +67,7 @@ public class Displayable extends BasicListener { private void checkLocation(Player player, Location at) { boolean shown = visible.contains(player); - int viewDistance = player.getClientViewDistance(); + int viewDistance = player.getClientViewDistance() / 2; boolean see = Math.abs(chunkX - posToChunk(at.getX())) < viewDistance && Math.abs(chunkZ - posToChunk(at.getZ())) < viewDistance; if(!shown && see) { diff --git a/src/de/steamwar/lobby/display/Hologram.java b/src/de/steamwar/lobby/display/Hologram.java index 537eafb..c032d18 100644 --- a/src/de/steamwar/lobby/display/Hologram.java +++ b/src/de/steamwar/lobby/display/Hologram.java @@ -20,7 +20,7 @@ package de.steamwar.lobby.display; import com.comphenix.tinyprotocol.Reflection; -import de.steamwar.lobby.listener.Protocol; +import com.comphenix.tinyprotocol.TinyProtocol; import org.bukkit.Location; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.entity.Player; @@ -80,9 +80,19 @@ public class Hologram implements ConfigurationSerializable { private static final Class destroyPacket = Reflection.getClass("{nms}.PacketPlayOutEntityDestroy"); private static final Reflection.ConstructorInvoker destoryPacketConstructor = Reflection.getConstructor(destroyPacket); private static final Reflection.FieldAccessor destroyIds = Reflection.getField(destroyPacket, int[].class, 0); + public static Object destroyPacket(int entityId) { + Object destroy = destoryPacketConstructor.invoke(); + destroyIds.set(destroy, new int[]{entityId}); + return destroy; + } + + private static int entityIds = -1; + public static int createEntityId() { + return entityIds--; + } private static final Map holograms = new HashMap<>(); - private static int entityIds = -1; + private static final Random random = new Random(); public static List getHolograms() { @@ -94,11 +104,15 @@ public class Hologram implements ConfigurationSerializable { private final Displayable display; private final int entityId; + private final Object spawnLiving; + private Object metadata; private final Object destroy; + private final String id; private final Location location; - private final String text; + + private String text; public Hologram(Map map) { this((String) map.get("id"), (Location) map.get("location"), (String) map.get("text")); @@ -108,7 +122,7 @@ public class Hologram implements ConfigurationSerializable { this.id = id; this.location = location; this.text = text; - entityId = entityIds--; + entityId = createEntityId(); spawnLiving = spawnLivingPacketConstructor.invoke(); spawnLivingEntityId.set(spawnLiving, entityId); @@ -118,8 +132,9 @@ public class Hologram implements ConfigurationSerializable { spawnLivingEntityY.set(spawnLiving, location.getY()); spawnLivingEntityZ.set(spawnLiving, location.getZ()); - destroy = destoryPacketConstructor.invoke(); - destroyIds.set(destroy, new int[]{entityId}); + constructMetadataPacket(); + + destroy = destroyPacket(entityId); display = new Displayable(location, this::show, this::hide); @@ -127,22 +142,32 @@ public class Hologram implements ConfigurationSerializable { holograms.put(id, this); } - private void show(Player player) { - Protocol.getTinyProtocol().sendPacket(player, spawnLiving); + public void updateText(String text) { + this.text = text; + constructMetadataPacket(); + for(Player player : display.getVisitors()) { + TinyProtocol.instance.sendPacket(player, metadata); + } + } - Object packet = metadataConstructor.invoke(); - metadataEntity.set(packet, entityId); + private void constructMetadataPacket() { + metadata = metadataConstructor.invoke(); + metadataEntity.set(metadata, entityId); List watchers = new ArrayList<>(); watchers.add(itemConstructor.invoke(invisibleWatcher, (byte) 0x20)); watchers.add(itemConstructor.invoke(nameWatcher, Optional.of(chatComponentTextConstructor.invoke(text)))); watchers.add(itemConstructor.invoke(nameVisibleWatcher, true)); watchers.add(itemConstructor.invoke(sizeWatcher, (byte) 0x10)); - metadataMetadata.set(packet, watchers); - Protocol.getTinyProtocol().sendPacket(player, packet); + metadataMetadata.set(metadata, watchers); + } + + private void show(Player player) { + TinyProtocol.instance.sendPacket(player, spawnLiving); + TinyProtocol.instance.sendPacket(player, metadata); } private void hide(Player player) { - Protocol.getTinyProtocol().sendPacket(player, destroy); + TinyProtocol.instance.sendPacket(player, destroy); } @Override diff --git a/src/de/steamwar/lobby/display/NPC.java b/src/de/steamwar/lobby/display/NPC.java new file mode 100644 index 0000000..5fc53c5 --- /dev/null +++ b/src/de/steamwar/lobby/display/NPC.java @@ -0,0 +1,110 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2021 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.display; + +import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import com.mojang.authlib.GameProfile; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +public class NPC { + private static final Class playerInfoPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPlayerInfo"); + private static final Reflection.ConstructorInvoker playerInfoConstructor = Reflection.getConstructor(playerInfoPacket); + private static final Class playerInfoActionClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPlayerInfo$EnumPlayerInfoAction"); + private static final Object addPlayer = playerInfoActionClass.getEnumConstants()[0]; + private static final Reflection.FieldAccessor playerInfoAction = Reflection.getField(playerInfoPacket, playerInfoActionClass, 0); + private static final Object removePlayer = playerInfoActionClass.getEnumConstants()[4]; + private static final Reflection.FieldAccessor playerInfoData = Reflection.getField(playerInfoPacket, List.class, 0); + private static final Class playerInfoDataClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPlayerInfo$PlayerInfoData"); + private static final Class enumGamemode = Reflection.getClass("{nms.world.level}.EnumGamemode"); + private static final Object creative = enumGamemode.getEnumConstants()[2]; + private static final Class iChatBaseComponent = Reflection.getClass("{nms.network.chat}.IChatBaseComponent"); + private static final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClass, playerInfoPacket, GameProfile.class, int.class, enumGamemode, iChatBaseComponent); + private static Object playerInfoPacket(Object action, GameProfile profile) { + Object packet = playerInfoConstructor.invoke(); + playerInfoAction.set(packet, action); + playerInfoData.set(packet, Collections.singletonList(playerInfoDataConstructor.invoke(packet, profile, 0, creative, null))); + return packet; + } + + private static final Class namedSpawnPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutNamedEntitySpawn"); + private static final Reflection.ConstructorInvoker namedSpawnConstructor = Reflection.getConstructor(namedSpawnPacket); + private static final Reflection.FieldAccessor namedSpawnEntity = Reflection.getField(namedSpawnPacket, int.class, 0); + private static final Reflection.FieldAccessor namedSpawnUUID = Reflection.getField(namedSpawnPacket, UUID.class, 0); + private static final Reflection.FieldAccessor namedSpawnX = Reflection.getField(namedSpawnPacket, double.class, 0); + private static final Reflection.FieldAccessor namedSpawnY = Reflection.getField(namedSpawnPacket, double.class, 1); + private static final Reflection.FieldAccessor namedSpawnZ = Reflection.getField(namedSpawnPacket, double.class, 2); + private static final Reflection.FieldAccessor namedSpawnYaw = Reflection.getField(namedSpawnPacket, byte.class, 0); + private static final Reflection.FieldAccessor namedSpawnPitch = Reflection.getField(namedSpawnPacket, byte.class, 1); + + private final Displayable display; + + private final int entityId; + private final UUID uuid; + private final String name; + private final Location location; + + private final Object addPlayerInfo; + private final Object namedSpawn; + private final Object removePlayerInfo; + private final Object destroy; + + public NPC(Location location, UUID uuid, String name) { + this.entityId = Hologram.createEntityId(); + this.uuid = uuid; + this.name = name; + this.location = location; + + GameProfile profile = new GameProfile(uuid, name); + addPlayerInfo = playerInfoPacket(addPlayer, profile); + removePlayerInfo = playerInfoPacket(removePlayer, profile); + destroy = Hologram.destroyPacket(entityId); + + namedSpawn = namedSpawnConstructor.invoke(); + namedSpawnEntity.set(namedSpawn, entityId); + namedSpawnUUID.set(namedSpawn, uuid); + namedSpawnX.set(namedSpawn, location.getX()); + namedSpawnY.set(namedSpawn, location.getY()); + namedSpawnZ.set(namedSpawn, location.getZ()); + namedSpawnYaw.set(namedSpawn, (byte)(int)(location.getYaw() * 256.0 / 360.0)); + namedSpawnPitch.set(namedSpawn, (byte)(int)(location.getPitch() * 256.0 / 360.0)); + + display = new Displayable(location, this::show, this::hide); + } + + private void show(Player player) { + TinyProtocol.instance.sendPacket(player, addPlayerInfo); + TinyProtocol.instance.sendPacket(player, namedSpawn); + } + + private void hide(Player player) { + TinyProtocol.instance.sendPacket(player, removePlayerInfo); + TinyProtocol.instance.sendPacket(player, destroy); + } + + public void delete() { + display.delete(); + } +} diff --git a/src/de/steamwar/lobby/listener/Fightservers.java b/src/de/steamwar/lobby/listener/Fightservers.java index 2352952..30d6857 100644 --- a/src/de/steamwar/lobby/listener/Fightservers.java +++ b/src/de/steamwar/lobby/listener/Fightservers.java @@ -22,7 +22,7 @@ package de.steamwar.lobby.listener; import de.steamwar.comms.BungeeReceiver; import de.steamwar.comms.PacketIdManager; import de.steamwar.lobby.LobbySystem; -import de.steamwar.lobby.servers.Fightserver; +import de.steamwar.lobby.Fightserver; import org.bukkit.Bukkit; public class Fightservers { diff --git a/src/de/steamwar/lobby/listener/Join.java b/src/de/steamwar/lobby/listener/Join.java index 799c913..9321c1d 100644 --- a/src/de/steamwar/lobby/listener/Join.java +++ b/src/de/steamwar/lobby/listener/Join.java @@ -19,6 +19,7 @@ package de.steamwar.lobby.listener; +import de.steamwar.comms.packets.ImALobbyPacket; import org.bukkit.GameMode; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -33,6 +34,6 @@ public class Join extends BasicListener { player.setGameMode(GameMode.ADVENTURE); player.setWalkSpeed(0.5f); - //new ImALobbyPacket().send(player); + new ImALobbyPacket().send(player); } } diff --git a/src/de/steamwar/lobby/listener/Portals.java b/src/de/steamwar/lobby/listener/Portals.java index 7416c7e..576d17d 100644 --- a/src/de/steamwar/lobby/listener/Portals.java +++ b/src/de/steamwar/lobby/listener/Portals.java @@ -51,7 +51,7 @@ public class Portals extends BasicListener { Location to = e.getTo(); assert to != null; - Portal portal = Portal.getPortal(e.getPlayer(), from, to); + Portal portal = Portal.getPortal(from, to); if (portal == null) return; diff --git a/src/de/steamwar/lobby/listener/Protocol.java b/src/de/steamwar/lobby/listener/Protocol.java deleted file mode 100644 index 8655cea..0000000 --- a/src/de/steamwar/lobby/listener/Protocol.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 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.listener; - -import com.comphenix.tinyprotocol.TinyProtocol; -import de.steamwar.lobby.LobbySystem; -import io.netty.channel.Channel; -import org.bukkit.entity.Player; - -public class Protocol { - - private static final TinyProtocol tinyProtocol = new TinyProtocol(LobbySystem.getPlugin()) { - @Override - public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { - return super.onPacketOutAsync(receiver, channel, packet); - } - - @Override - public Object onPacketInAsync(Player sender, Channel channel, Object packet) { - return super.onPacketInAsync(sender, channel, packet); - } - }; - - public static TinyProtocol getTinyProtocol() { - return tinyProtocol; - } -} diff --git a/src/de/steamwar/lobby/portal/FightserverPortal.java b/src/de/steamwar/lobby/portal/FightserverPortal.java index fba1459..2968175 100644 --- a/src/de/steamwar/lobby/portal/FightserverPortal.java +++ b/src/de/steamwar/lobby/portal/FightserverPortal.java @@ -19,37 +19,93 @@ package de.steamwar.lobby.portal; +import de.steamwar.comms.packets.FightInfoPacket; +import de.steamwar.lobby.display.Hologram; +import de.steamwar.lobby.Fightserver; import org.bukkit.Location; import org.bukkit.entity.Player; +import org.bukkit.util.Vector; -import java.util.Map; +import java.util.*; -public class FightserverPortal implements PortalHandler { +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 group; + private final String gamemode; + private final int order; private final String target; + private final Hologram hologram; + private Fightserver server = null; private PortalHandler handler = new DummyPortal(); public FightserverPortal(Map section, Portal portal) { this.portal = portal; - this.group = (String) section.get("group"); + this.gamemode = (String) section.get("group"); this.target = (String) section.get("target"); + this.order = (int) section.get("order"); + hologram = new Hologram(null, portal.getPos1().clone().add(portal.getOrientation().clone().divide(new Vector(2, 2, 2))), ""); init(); } - public FightserverPortal(Portal portal, String group, String target) { + public FightserverPortal(Portal portal, String gamemode, int order, String target) { this.portal = portal; - this.group = group; + this.gamemode = gamemode; + this.order = order; this.target = target; + hologram = new Hologram(null, portal.getPos1().clone().add(portal.getOrientation().clone().divide(new Vector(2, 2, 2))), ""); init(); } + 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("Neuen Kampf starten"); + return; + } + + FightInfoPacket info = server.current(); + hologram.updateText(server.getServerName() + " " + info.getFightState() + " " + (info.getCountdown() / 60) + ":" + (info.getCountdown() % 60)); + } + + public void updateBluePlayers() { + + } + + public void updateRedPlayers() { + + } + private void init() { - setHandler(new TeleportPortal(portal, target)); + updateText(); + + List list = portals.computeIfAbsent(gamemode, mode -> new ArrayList<>()); + list.add(this); + list.sort(null); } private void setHandler(PortalHandler handler) { @@ -64,7 +120,8 @@ public class FightserverPortal implements PortalHandler { @Override public void serialize(Map map) { - map.put("group", group); + map.put("group", gamemode); + map.put("order", order); map.put("target", target); } @@ -75,6 +132,13 @@ public class FightserverPortal implements PortalHandler { @Override public void delete() { + portals.get(gamemode).remove(this); + hologram.delete(); handler.delete(); } + + @Override + public int compareTo(FightserverPortal other) { + return other.order - order; + } } diff --git a/src/de/steamwar/lobby/portal/Portal.java b/src/de/steamwar/lobby/portal/Portal.java index 91479c6..26c537a 100644 --- a/src/de/steamwar/lobby/portal/Portal.java +++ b/src/de/steamwar/lobby/portal/Portal.java @@ -41,7 +41,7 @@ public class Portal implements PortalHandler, ConfigurationSerializable { return portals.keySet(); } - public static Portal getPortal(Player player, Location from, Location to) { + public static Portal getPortal(Location from, Location to) { Vector movement = to.toVector().subtract(from.toVector()); for(Portal portal : portals.values()) { diff --git a/src/de/steamwar/lobby/portal/TeleportPortal.java b/src/de/steamwar/lobby/portal/TeleportPortal.java index 5355b2a..2f52ae6 100644 --- a/src/de/steamwar/lobby/portal/TeleportPortal.java +++ b/src/de/steamwar/lobby/portal/TeleportPortal.java @@ -65,6 +65,10 @@ public class TeleportPortal implements PortalHandler { } private void teleport(Player player, Location from, Location to, Portal target) { + if(target == null) { + player.sendMessage("teleport " + portal.getId() + " -> UNKNOWN"); + return; + } player.sendMessage("teleport " + portal.getId() + " -> " + target.getId()); Vector ownOrientation = portal.getOrientation().clone(); diff --git a/src/de/steamwar/lobby/servers/Observable.java b/src/de/steamwar/lobby/servers/Observable.java deleted file mode 100644 index 314070a..0000000 --- a/src/de/steamwar/lobby/servers/Observable.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 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.servers; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; - -public class Observable { - - private final List> observers = new ArrayList<>(); - - private T value; - - public Observable() { - value = null; - } - - public Observable(T initial) { - value = initial; - } - - public void register(Consumer observer) { - observers.add(observer); - } - - public void update(T value) { - if(!value.equals(this.value)) { - this.value = value; - observers.forEach(observer -> observer.accept(value)); - } - } -}