From 30c691d33e42eabea03f11c329166400c9db27eb Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 27 Mar 2022 17:43:29 +0100 Subject: [PATCH] Implement hidden observers for series --- src/main/java/rip/bolt/ingame/Ingame.java | 1 + .../ingame/api/definitions/BoltMatch.java | 13 +++ .../bolt/ingame/api/definitions/Series.java | 33 +++++++ .../bolt/ingame/events/BoltMatchEvent.java | 17 ++++ .../events/BoltMatchStatusChangeEvent.java | 38 ++++++++ .../rip/bolt/ingame/ranked/PlayerWatcher.java | 2 +- .../rip/bolt/ingame/ranked/RankedManager.java | 22 ++++- .../bolt/ingame/ranked/SpectatorManager.java | 90 +++++++++++++++++++ 8 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 src/main/java/rip/bolt/ingame/api/definitions/Series.java create mode 100644 src/main/java/rip/bolt/ingame/events/BoltMatchEvent.java create mode 100644 src/main/java/rip/bolt/ingame/events/BoltMatchStatusChangeEvent.java create mode 100644 src/main/java/rip/bolt/ingame/ranked/SpectatorManager.java diff --git a/src/main/java/rip/bolt/ingame/Ingame.java b/src/main/java/rip/bolt/ingame/Ingame.java index 3419573..f50f910 100644 --- a/src/main/java/rip/bolt/ingame/Ingame.java +++ b/src/main/java/rip/bolt/ingame/Ingame.java @@ -44,6 +44,7 @@ public void onEnable() { Bukkit.getPluginManager().registerEvents(rankedManager.getPlayerWatcher(), this); Bukkit.getPluginManager().registerEvents(rankedManager.getRankManager(), this); Bukkit.getPluginManager().registerEvents(rankedManager.getRequeueManager(), this); + Bukkit.getPluginManager().registerEvents(rankedManager.getSpectatorManager(), this); BasicBukkitCommandGraph g = new BasicBukkitCommandGraph(new CommandModule()); DispatcherNode node = g.getRootDispatcherNode(); diff --git a/src/main/java/rip/bolt/ingame/api/definitions/BoltMatch.java b/src/main/java/rip/bolt/ingame/api/definitions/BoltMatch.java index 95554a3..359afb3 100644 --- a/src/main/java/rip/bolt/ingame/api/definitions/BoltMatch.java +++ b/src/main/java/rip/bolt/ingame/api/definitions/BoltMatch.java @@ -11,6 +11,8 @@ public class BoltMatch { private String id; + private Series series; + private BoltPGMMap map; private List teams; @@ -35,6 +37,14 @@ public void setId(String id) { this.id = id; } + public Series getSeries() { + return series; + } + + public void setSeries(Series series) { + this.series = series; + } + public BoltPGMMap getMap() { return map; } @@ -100,6 +110,9 @@ public String toString() { .append("Match ID: ") .append(getId()) .append("\n") + .append("Series: ") + .append(getSeries()) + .append("\n") .append("Map: ") .append(getMap().getName()) .append("\n") diff --git a/src/main/java/rip/bolt/ingame/api/definitions/Series.java b/src/main/java/rip/bolt/ingame/api/definitions/Series.java new file mode 100644 index 0000000..3b49903 --- /dev/null +++ b/src/main/java/rip/bolt/ingame/api/definitions/Series.java @@ -0,0 +1,33 @@ +package rip.bolt.ingame.api.definitions; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class Series { + + private String name; + private Boolean hideObservers = false; + + public Series() {} + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean getHideObservers() { + return hideObservers; + } + + public void setHideObservers(boolean hideObservers) { + this.hideObservers = hideObservers; + } + + @Override + public String toString() { + return "Series{" + "name='" + name + '\'' + ", hideObservers=" + hideObservers + '}'; + } +} diff --git a/src/main/java/rip/bolt/ingame/events/BoltMatchEvent.java b/src/main/java/rip/bolt/ingame/events/BoltMatchEvent.java new file mode 100644 index 0000000..fc0ef15 --- /dev/null +++ b/src/main/java/rip/bolt/ingame/events/BoltMatchEvent.java @@ -0,0 +1,17 @@ +package rip.bolt.ingame.events; + +import org.bukkit.event.Event; +import rip.bolt.ingame.api.definitions.BoltMatch; + +abstract class BoltMatchEvent extends Event { + + private final BoltMatch boltMatch; + + public BoltMatchEvent(BoltMatch boltMatch) { + this.boltMatch = boltMatch; + } + + public BoltMatch getBoltMatch() { + return boltMatch; + } +} diff --git a/src/main/java/rip/bolt/ingame/events/BoltMatchStatusChangeEvent.java b/src/main/java/rip/bolt/ingame/events/BoltMatchStatusChangeEvent.java new file mode 100644 index 0000000..69f1ad1 --- /dev/null +++ b/src/main/java/rip/bolt/ingame/events/BoltMatchStatusChangeEvent.java @@ -0,0 +1,38 @@ +package rip.bolt.ingame.events; + +import javax.annotation.Nullable; +import org.bukkit.event.HandlerList; +import rip.bolt.ingame.api.definitions.BoltMatch; +import rip.bolt.ingame.ranked.MatchStatus; + +public class BoltMatchStatusChangeEvent extends BoltMatchEvent { + + private static final HandlerList handlers = new HandlerList(); + + @Nullable private final MatchStatus oldStatus; + private final MatchStatus newStatus; + + public BoltMatchStatusChangeEvent( + BoltMatch boltMatch, @Nullable MatchStatus oldStatus, MatchStatus newStatus) { + super(boltMatch); + this.oldStatus = oldStatus; + this.newStatus = newStatus; + } + + public @Nullable MatchStatus getOldStatus() { + return oldStatus; + } + + public MatchStatus getNewStatus() { + return newStatus; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/rip/bolt/ingame/ranked/PlayerWatcher.java b/src/main/java/rip/bolt/ingame/ranked/PlayerWatcher.java index b01be15..32f7cc0 100644 --- a/src/main/java/rip/bolt/ingame/ranked/PlayerWatcher.java +++ b/src/main/java/rip/bolt/ingame/ranked/PlayerWatcher.java @@ -161,7 +161,7 @@ private void playerAbandoned(UUID player) { () -> Ingame.get().getApiManager().postPlayerPunishment(new Punishment(player))); } - private boolean isPlaying(UUID uuid) { + public boolean isPlaying(UUID uuid) { return players.containsKey(uuid); } diff --git a/src/main/java/rip/bolt/ingame/ranked/RankedManager.java b/src/main/java/rip/bolt/ingame/ranked/RankedManager.java index ac754d3..6a032f5 100644 --- a/src/main/java/rip/bolt/ingame/ranked/RankedManager.java +++ b/src/main/java/rip/bolt/ingame/ranked/RankedManager.java @@ -26,6 +26,7 @@ import rip.bolt.ingame.api.definitions.BoltMatch; import rip.bolt.ingame.api.definitions.Team; import rip.bolt.ingame.config.AppData; +import rip.bolt.ingame.events.BoltMatchStatusChangeEvent; import rip.bolt.ingame.utils.PGMMapUtils; import tc.oc.pgm.api.PGM; import tc.oc.pgm.api.match.Match; @@ -41,6 +42,7 @@ public class RankedManager implements Listener { private final RequeueManager requeueManager; private final RankManager rankManager; private final StatsManager statsManager; + private final SpectatorManager spectatorManager; private final TabManager tabManager; private final MatchSearch poll; @@ -55,7 +57,9 @@ public RankedManager(Plugin plugin) { requeueManager = new RequeueManager(); rankManager = new RankManager(this); statsManager = new StatsManager(this); + spectatorManager = new SpectatorManager(playerWatcher); tabManager = new TabManager(plugin); + MatchPreloader.create(); poll = new MatchSearch(this::setupMatch); @@ -105,6 +109,11 @@ public void setupMatch(BoltMatch match) { cycleTime = Duration.ofSeconds(5); format.addRound(ranked); + Ingame.get() + .getServer() + .getPluginManager() + .callEvent(new BoltMatchStatusChangeEvent(match, null, MatchStatus.CREATED)); + Bukkit.broadcastMessage(ChatColor.YELLOW + "A new match is starting on this server!"); Tournament.get() .getTournamentManager() @@ -221,7 +230,10 @@ public void postMatchStatus(Match match, MatchStatus status) { public BoltMatch transition( Match match, BoltMatch boltMatch, MatchStatus newStatus, Instant transitionAt) { - if (boltMatch == null || !boltMatch.getStatus().canTransitionTo(newStatus)) return null; + if (boltMatch == null) return null; + + MatchStatus oldStatus = boltMatch.getStatus(); + if (!oldStatus.canTransitionTo(newStatus)) return null; switch (newStatus) { case LOADED: @@ -249,7 +261,15 @@ public BoltMatch transition( } boltMatch.setStatus(newStatus); + Ingame.get() + .getServer() + .getPluginManager() + .callEvent(new BoltMatchStatusChangeEvent(boltMatch, oldStatus, newStatus)); return boltMatch; } + + public SpectatorManager getSpectatorManager() { + return spectatorManager; + } } diff --git a/src/main/java/rip/bolt/ingame/ranked/SpectatorManager.java b/src/main/java/rip/bolt/ingame/ranked/SpectatorManager.java new file mode 100644 index 0000000..1ea9104 --- /dev/null +++ b/src/main/java/rip/bolt/ingame/ranked/SpectatorManager.java @@ -0,0 +1,90 @@ +package rip.bolt.ingame.ranked; + +import java.util.HashMap; +import java.util.Objects; +import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.permissions.PermissionAttachment; +import rip.bolt.ingame.Ingame; +import rip.bolt.ingame.events.BoltMatchStatusChangeEvent; +import tc.oc.pgm.api.PGM; +import tc.oc.pgm.api.player.MatchPlayer; +import tc.oc.pgm.api.player.VanishManager; +import tc.oc.pgm.events.PlayerJoinMatchEvent; + +public class SpectatorManager implements Listener { + + private static final String SPECTATE_VANISH = "events.spectate.vanish"; + private static final String PGM_VANISH = "pgm.vanish"; + + private final VanishManager vanishManager; + private final PlayerWatcher watcher; + + private final HashMap permissions = new HashMap<>(); + + public SpectatorManager(PlayerWatcher playerWatcher) { + this.watcher = playerWatcher; + vanishManager = PGM.get().getVanishManager(); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onBoltMatchStateChange(BoltMatchStatusChangeEvent event) { + if (Objects.equals(event.getNewStatus(), MatchStatus.CREATED)) { + Bukkit.getOnlinePlayers().forEach(this::updatePlayer); + } + } + + @EventHandler(priority = EventPriority.NORMAL) + public void onPlayerJoinEvent(PlayerJoinMatchEvent event) { + updatePlayer(event.getPlayer().getBukkit()); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerQuitEvent event) { + PermissionAttachment attachment = permissions.remove(event.getPlayer().getUniqueId()); + if (attachment != null) attachment.remove(); + } + + private void updatePlayer(Player player) { + if (Ingame.get().getRankedManager().getMatch() == null) return; + + boolean hidden = Ingame.get().getRankedManager().getMatch().getSeries().getHideObservers(); + boolean playing = watcher.isPlaying(player.getUniqueId()); + + // Allow people who can vanish to remain in current state + if (!playing && player.hasPermission(PGM_VANISH)) return; + + if (!hidden || playing) { + unvanish(player); + } else { + vanish(player); + } + } + + private void vanish(Player player) { + permissions.computeIfAbsent( + player.getUniqueId(), uuid -> player.addAttachment(Ingame.get(), SPECTATE_VANISH, true)); + + // Set vanish if not already + if (vanishManager.isVanished(player.getUniqueId())) return; + + MatchPlayer matchPlayer = PGM.get().getMatchManager().getPlayer(player); + vanishManager.setVanished(matchPlayer, true, true); + } + + private void unvanish(Player player) { + PermissionAttachment attachment = permissions.remove(player.getUniqueId()); + if (attachment != null) attachment.remove(); + + // Remove vanish if not already + if (!vanishManager.isVanished(player.getUniqueId())) return; + + MatchPlayer matchPlayer = PGM.get().getMatchManager().getPlayer(player); + vanishManager.setVanished(matchPlayer, false, true); + } +}