From fdd6d94102f48b9be8cf95f18f3fb8291b90a71e Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Mon, 22 Apr 2024 14:52:19 +0200 Subject: [PATCH] Makes levers clicked in parkour arenas turn off When a lever is clicked while inside a parkour arena, that lever is saved. Once the last player leaves, or the last player restarts, the saved levers are turned off. --- .../arena/AbstractArenaPlayerRegistry.java | 40 ++++++++++---- .../net/knarcraft/minigames/arena/Arena.java | 25 +++++---- .../minigames/arena/ArenaPlayerRegistry.java | 20 +++++-- .../arena/PlayerVisibilityManager.java | 2 +- .../minigames/arena/dropper/DropperArena.java | 4 +- .../minigames/arena/parkour/ParkourArena.java | 2 +- .../parkour/ParkourArenaPlayerRegistry.java | 2 +- .../arena/parkour/ParkourArenaSession.java | 53 ++++++++++++++++++- .../net/knarcraft/minigames/gui/ArenaGUI.java | 21 ++++++-- .../minigames/listener/InteractListener.java | 35 ++++++++++-- 10 files changed, 168 insertions(+), 36 deletions(-) diff --git a/src/main/java/net/knarcraft/minigames/arena/AbstractArenaPlayerRegistry.java b/src/main/java/net/knarcraft/minigames/arena/AbstractArenaPlayerRegistry.java index 8e2c4d8..55cb140 100644 --- a/src/main/java/net/knarcraft/minigames/arena/AbstractArenaPlayerRegistry.java +++ b/src/main/java/net/knarcraft/minigames/arena/AbstractArenaPlayerRegistry.java @@ -19,7 +19,8 @@ import java.util.logging.Level; */ public abstract class AbstractArenaPlayerRegistry implements ArenaPlayerRegistry { - private final Map arenaPlayers = new HashMap<>(); + private final Map> arenaPlayers = new HashMap<>(); + private final Map arenaSessions = new HashMap<>(); private final Map entryStates = new HashMap<>(); /** @@ -30,19 +31,25 @@ public abstract class AbstractArenaPlayerRegistry implements Ar } @Override - public @NotNull Set getPlayingPlayers() { - return arenaPlayers.keySet(); + @NotNull + public Set getPlayingPlayers() { + return arenaSessions.keySet(); } @Override - public @Nullable PlayerEntryState getEntryState(@NotNull UUID playerId) { + @Nullable + public PlayerEntryState getEntryState(@NotNull UUID playerId) { return this.entryStates.get(playerId); } @Override public void registerPlayer(@NotNull UUID playerId, @NotNull ArenaSession arenaSession) { - this.arenaPlayers.put(playerId, arenaSession); + this.arenaSessions.put(playerId, arenaSession); this.entryStates.put(playerId, arenaSession.getEntryState()); + + this.arenaPlayers.putIfAbsent(arenaSession.getArena(), new HashSet<>()); + this.arenaPlayers.get(arenaSession.getArena()).add(playerId); + this.saveEntryStates(); } @@ -60,25 +67,38 @@ public abstract class AbstractArenaPlayerRegistry implements Ar this.saveEntryStates(); } - return this.arenaPlayers.remove(playerId) != null; + if (this.arenaSessions.containsKey(playerId)) { + this.arenaPlayers.get(this.arenaSessions.get(playerId).getArena()).remove(playerId); + } + return this.arenaSessions.remove(playerId) != null; } @Override public @Nullable ArenaSession getArenaSession(@NotNull UUID playerId) { - return this.arenaPlayers.getOrDefault(playerId, null); + return this.arenaSessions.getOrDefault(playerId, null); } @Override - public void removeForArena(K arena, boolean immediately) { + public void removeForArena(@NotNull K arena, boolean immediately) { Set removed = new HashSet<>(); - for (Map.Entry entry : this.arenaPlayers.entrySet()) { + for (Map.Entry entry : this.arenaSessions.entrySet()) { if (entry.getValue().getArena() == arena) { // Kick the player gracefully entry.getValue().triggerQuit(immediately, false); removed.add(entry.getKey()); } } - removed.forEach(this.arenaPlayers::remove); + removed.forEach(this.arenaSessions::remove); + } + + @Override + @NotNull + public Set getPlayingPlayers(@NotNull K arena) { + if (arenaPlayers.containsKey(arena)) { + return arenaPlayers.get(arena); + } else { + return new HashSet<>(); + } } /** diff --git a/src/main/java/net/knarcraft/minigames/arena/Arena.java b/src/main/java/net/knarcraft/minigames/arena/Arena.java index ecb4574..6a3c4ab 100644 --- a/src/main/java/net/knarcraft/minigames/arena/Arena.java +++ b/src/main/java/net/knarcraft/minigames/arena/Arena.java @@ -20,28 +20,32 @@ public interface Arena { * * @return

The name of this arena

*/ - @NotNull String getArenaName(); + @NotNull + String getArenaName(); /** * Gets the data stored for this arena * * @return

The stored data

*/ - @NotNull ArenaData getData(); + @NotNull + ArenaData getData(); /** * Gets the id of this arena * * @return

This arena's identifier

*/ - @NotNull UUID getArenaId(); + @NotNull + UUID getArenaId(); /** * Gets this arena's sanitized name * * @return

This arena's sanitized name

*/ - @NotNull String getArenaNameSanitized(); + @NotNull + String getArenaNameSanitized(); /** * Removes the data file belonging to this arena @@ -63,7 +67,7 @@ public interface Arena { * @param block

The block to check

* @return

True if standing on the block will cause a win

*/ - boolean willCauseWin(Block block); + boolean willCauseWin(@NotNull Block block); /** * Gets whether standing on the given block should cause a loss @@ -71,7 +75,7 @@ public interface Arena { * @param block

The block to check

* @return

True if standing on the block will cause a loss

*/ - boolean willCauseLoss(Block block); + boolean willCauseLoss(@NotNull Block block); /** * Gets whether the win location is a solid block @@ -85,14 +89,16 @@ public interface Arena { * * @return

This arena's spawn location

*/ - @NotNull Location getSpawnLocation(); + @NotNull + Location getSpawnLocation(); /** * Gets this arena's exit location * * @return

This arena's exit location, or null if no such location is set.

*/ - @Nullable Location getExitLocation(); + @Nullable + Location getExitLocation(); /** * Adds a reward to this arena @@ -115,6 +121,7 @@ public interface Arena { * @param rewardCondition

The condition to get the rewards for

* @return

All rewards

*/ - @NotNull Set getRewards(RewardCondition rewardCondition); + @NotNull + Set getRewards(RewardCondition rewardCondition); } diff --git a/src/main/java/net/knarcraft/minigames/arena/ArenaPlayerRegistry.java b/src/main/java/net/knarcraft/minigames/arena/ArenaPlayerRegistry.java index 20f0db2..b5a0b03 100644 --- a/src/main/java/net/knarcraft/minigames/arena/ArenaPlayerRegistry.java +++ b/src/main/java/net/knarcraft/minigames/arena/ArenaPlayerRegistry.java @@ -18,7 +18,17 @@ public interface ArenaPlayerRegistry { * * @return

The ids of the playing players

*/ - @NotNull Set getPlayingPlayers(); + @NotNull + Set getPlayingPlayers(); + + /** + * Gets all players currently playing in the given arena + * + * @param arena

The arena to check

+ * @return

All players currently in the arena

+ */ + @NotNull + Set getPlayingPlayers(@NotNull K arena); /** * Gets the current entry state for the given player @@ -26,7 +36,8 @@ public interface ArenaPlayerRegistry { * @param playerId

The id of the player to get an entry state for

* @return

The entry state of the player, or null if not found

*/ - @Nullable PlayerEntryState getEntryState(@NotNull UUID playerId); + @Nullable + PlayerEntryState getEntryState(@NotNull UUID playerId); /** * Registers that the given player has started playing the given dropper arena session @@ -50,7 +61,8 @@ public interface ArenaPlayerRegistry { * @param playerId

The id of the player to get arena for

* @return

The player's active arena session, or null if not currently playing

*/ - @Nullable ArenaSession getArenaSession(@NotNull UUID playerId); + @Nullable + ArenaSession getArenaSession(@NotNull UUID playerId); /** * Removes all active sessions for the given arena @@ -58,6 +70,6 @@ public interface ArenaPlayerRegistry { * @param arena

The arena to remove sessions for

* @param immediately

Whether to immediately teleport the player

*/ - void removeForArena(K arena, boolean immediately); + void removeForArena(@NotNull K arena, boolean immediately); } diff --git a/src/main/java/net/knarcraft/minigames/arena/PlayerVisibilityManager.java b/src/main/java/net/knarcraft/minigames/arena/PlayerVisibilityManager.java index 9e2e342..e748141 100644 --- a/src/main/java/net/knarcraft/minigames/arena/PlayerVisibilityManager.java +++ b/src/main/java/net/knarcraft/minigames/arena/PlayerVisibilityManager.java @@ -22,7 +22,7 @@ public class PlayerVisibilityManager { * * @param player

The the player to update

*/ - public void toggleHidePlayers(@NotNull ArenaPlayerRegistry playerRegistry, @NotNull Player player) { + public void toggleHidePlayers(@Nullable ArenaPlayerRegistry playerRegistry, @NotNull Player player) { if (displayingEnabledFor.contains(player.getUniqueId())) { displayingEnabledFor.remove(player.getUniqueId()); // Make all other players hidden diff --git a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java index 2e659b8..32d245e 100644 --- a/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java +++ b/src/main/java/net/knarcraft/minigames/arena/dropper/DropperArena.java @@ -243,12 +243,12 @@ public class DropperArena implements Arena { } @Override - public boolean willCauseWin(Block block) { + public boolean willCauseWin(@NotNull Block block) { return block.getType() == winBlockType; } @Override - public boolean willCauseLoss(Block block) { + public boolean willCauseLoss(@NotNull Block block) { return !dropperConfiguration.getBlockWhitelist().contains(block.getType()); } diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java index b97d712..74a432f 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArena.java @@ -340,7 +340,7 @@ public class ParkourArena implements Arena { } @Override - public boolean willCauseLoss(Block block) { + public boolean willCauseLoss(@NotNull Block block) { return this.getKillPlaneBlocks().contains(block.getType()) || this.getObstacleBlocks().contains(block.getType()); } diff --git a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaPlayerRegistry.java b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaPlayerRegistry.java index f863e18..3cc6cf9 100644 --- a/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaPlayerRegistry.java +++ b/src/main/java/net/knarcraft/minigames/arena/parkour/ParkourArenaPlayerRegistry.java @@ -11,5 +11,5 @@ public class ParkourArenaPlayerRegistry extends AbstractArenaPlayerRegistry> changedLevers = new HashMap<>(); private final @NotNull ParkourArena arena; private final @NotNull Player player; private final @NotNull ParkourArenaGameMode gameMode; - private Location reachedCheckpoint = null; + private @Nullable Location reachedCheckpoint = null; /** * Instantiates a new parkour arena session @@ -65,6 +74,16 @@ public class ParkourArenaSession extends AbstractArenaSession { this.reachedCheckpoint = location; } + /** + * Registers a lever change + * + * @param block

The block of the lever

+ */ + public void registerChangedLever(@NotNull Block block) { + changedLevers.putIfAbsent(this.arena, new HashSet<>()); + changedLevers.get(this.arena).add(block); + } + /** * Gets the checkpoint currently registered as the player's spawn location * @@ -132,6 +151,9 @@ public class ParkourArenaSession extends AbstractArenaSession { @Override public void reset() { this.reachedCheckpoint = null; + if (MiniGames.getInstance().getParkourArenaPlayerRegistry().getPlayingPlayers(this.arena).size() == 1) { + resetLevers(); + } super.reset(); } @@ -154,4 +176,33 @@ public class ParkourArenaSession extends AbstractArenaSession { }; } + @Override + public void triggerQuit(boolean immediately, boolean removeSession) { + super.triggerQuit(immediately, removeSession); + + if (MiniGames.getInstance().getParkourArenaPlayerRegistry().getPlayingPlayers(this.arena).isEmpty()) { + resetLevers(); + } + } + + /** + * Resets all levers if the arena is empty + */ + private void resetLevers() { + // Make a copy in case new player join while the levers are resetting + Set changed = changedLevers.remove(this.arena); + if (changed == null || changed.isEmpty()) { + return; + } + + // Reset all levers toggled by players in the arena + for (Block block : changed) { + BlockData blockData = block.getBlockData(); + if (blockData instanceof Powerable powerable) { + powerable.setPowered(false); + block.setBlockData(blockData); + } + } + } + } diff --git a/src/main/java/net/knarcraft/minigames/gui/ArenaGUI.java b/src/main/java/net/knarcraft/minigames/gui/ArenaGUI.java index 0983f37..67a2956 100644 --- a/src/main/java/net/knarcraft/minigames/gui/ArenaGUI.java +++ b/src/main/java/net/knarcraft/minigames/gui/ArenaGUI.java @@ -17,6 +17,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -32,7 +33,7 @@ public abstract class ArenaGUI extends AbstractGUI { * @param inventorySize

The size of the GUI's inventory

* @param inventoryName

The name of the inventory

*/ - public ArenaGUI(int inventorySize, String inventoryName) { + public ArenaGUI(int inventorySize, @NotNull String inventoryName) { super(inventorySize, inventoryName, null); } @@ -79,6 +80,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

A player toggle item

*/ + @NotNull protected ItemStack getTogglePlayersItemDisabled() { GUIItemFactory togglePlayersItemFactory = new SimpleGUIItemFactory(Material.PLAYER_HEAD); List loreLines = getLoreLines(); @@ -95,7 +97,8 @@ public abstract class ArenaGUI extends AbstractGUI { * @param player

The player to get the item for

* @return

A player toggle item

*/ - protected ItemStack getTogglePlayersItemEnabled(Player player) { + @NotNull + protected ItemStack getTogglePlayersItemEnabled(@NotNull Player player) { if (GeyserHelper.isGeyserPlayer(player)) { return getTogglePlayersItemEnabledBedrock(); } else { @@ -108,6 +111,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

A player toggle item

*/ + @NotNull protected ItemStack getTogglePlayersItemEnabledJava() { PlayerHeadGUIItemFactory togglePlayersItemFactory = new PlayerHeadGUIItemFactory(); togglePlayersItemFactory.useSkin("c10591e6909e6a281b371836e462d67a2c78fa0952e910f32b41a26c48c1757c"); @@ -119,6 +123,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

A player toggle item

*/ + @NotNull protected ItemStack getTogglePlayersItemEnabledBedrock() { return setTogglePlayersItemData(new SimpleGUIItemFactory(Material.SKELETON_SKULL)); } @@ -129,6 +134,7 @@ public abstract class ArenaGUI extends AbstractGUI { * @param itemFactory

The factory to apply the data to

* @return

The finished item, with the data applied

*/ + @NotNull protected ItemStack setTogglePlayersItemData(@NotNull GUIItemFactory itemFactory) { List loreLines = getLoreLines(); loreLines.add(ChatColor.GRAY + "Use this item to enable the visibility"); @@ -143,6 +149,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

A give up item

*/ + @NotNull protected ItemStack getGiveUpItem() { GUIItemFactory giveUpItemFactory = new SimpleGUIItemFactory(Material.RESPAWN_ANCHOR); List loreLines = getLoreLines(); @@ -158,6 +165,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

A leave item

*/ + @NotNull protected ItemStack getLeaveItem() { GUIItemFactory leaveItemFactory = new SimpleGUIItemFactory(Material.BARRIER); List loreLines = getLoreLines(); @@ -172,6 +180,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

An arraylist with one blank line

*/ + @NotNull protected List getLoreLines() { List loreLines = new ArrayList<>(); loreLines.add(""); @@ -184,7 +193,7 @@ public abstract class ArenaGUI extends AbstractGUI { * @param inventorySlot

The inventory slot the action should be added to

* @param action

The action to register

*/ - protected void setAnyClickAction(int inventorySlot, GUIAction action) { + protected void setAnyClickAction(int inventorySlot, @NotNull GUIAction action) { setClickAction(inventorySlot, ClickType.LEFT, action); setClickAction(inventorySlot, ClickType.RIGHT, action); } @@ -194,6 +203,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

The leave action

*/ + @NotNull public static GUIAction getLeaveAction() { return (player) -> { ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId()); @@ -208,6 +218,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

The action for triggering a session restart

*/ + @NotNull public static GUIAction getRestartAction() { return (player -> { ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId()); @@ -224,7 +235,8 @@ public abstract class ArenaGUI extends AbstractGUI { * @param inventorySlot

The inventory slot to replace when toggling

* @return

The action for triggering player visibility

*/ - public GUIAction getTogglePlayersAction(ArenaPlayerRegistry playerRegistry, int inventorySlot) { + @NotNull + public GUIAction getTogglePlayersAction(@Nullable ArenaPlayerRegistry playerRegistry, int inventorySlot) { return (player) -> { PlayerVisibilityManager visibilityManager = MiniGames.getInstance().getPlayerVisibilityManager(); visibilityManager.toggleHidePlayers(playerRegistry, player); @@ -241,6 +253,7 @@ public abstract class ArenaGUI extends AbstractGUI { * * @return

The give up action

*/ + @NotNull public static GUIAction getGiveUpAction() { return (player) -> { ArenaSession session = MiniGames.getInstance().getSession(player.getUniqueId()); diff --git a/src/main/java/net/knarcraft/minigames/listener/InteractListener.java b/src/main/java/net/knarcraft/minigames/listener/InteractListener.java index c16b95b..ba730f1 100644 --- a/src/main/java/net/knarcraft/minigames/listener/InteractListener.java +++ b/src/main/java/net/knarcraft/minigames/listener/InteractListener.java @@ -1,17 +1,25 @@ package net.knarcraft.minigames.listener; import net.knarcraft.minigames.MiniGames; +import net.knarcraft.minigames.arena.ArenaPlayerRegistry; +import net.knarcraft.minigames.arena.parkour.ParkourArena; +import net.knarcraft.minigames.arena.parkour.ParkourArenaSession; import net.knarcraft.minigames.gui.ArenaGUI; import net.knarcraft.minigames.gui.ParkourGUI; import net.knarcraft.minigames.property.PersistentDataKey; import net.knarcraft.minigames.util.GUIHelper; import org.bukkit.NamespacedKey; +import org.bukkit.block.Block; +import org.bukkit.block.data.type.Switch; +import org.bukkit.event.Event; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; /** * A listener that listens for player interactions @@ -19,7 +27,26 @@ import org.bukkit.persistence.PersistentDataType; public class InteractListener implements Listener { @EventHandler - public void menuInteractListener(PlayerInteractEvent event) { + public void menuInteractListener(@NotNull PlayerInteractEvent event) { + handleMenuClick(event); + + Block clicked = event.getClickedBlock(); + if (event.useInteractedBlock() != Event.Result.DENY && event.getAction() == Action.RIGHT_CLICK_BLOCK && + clicked != null && clicked.getBlockData() instanceof Switch) { + ArenaPlayerRegistry playerRegistry = MiniGames.getInstance().getParkourArenaPlayerRegistry(); + ParkourArenaSession arenaSession = (ParkourArenaSession) playerRegistry.getArenaSession(event.getPlayer().getUniqueId()); + if (arenaSession != null) { + arenaSession.registerChangedLever(clicked); + } + } + } + + /** + * Handles clicking of the menu item + * + * @param event

The triggered player interact event

+ */ + private void handleMenuClick(@NotNull PlayerInteractEvent event) { ItemStack item = event.getItem(); if (item == null || !item.hasItemMeta()) { return; @@ -33,7 +60,8 @@ public class InteractListener implements Listener { PersistentDataKey.MENU_ITEM.getKeyName()), PersistentDataType.INTEGER); if (persistentData != null && persistentData == PersistentDataKey.MENU_ITEM.getDataValue()) { - event.setCancelled(true); + event.setUseItemInHand(Event.Result.DENY); + event.setUseInteractedBlock(Event.Result.DENY); GUIHelper.openGUI(event.getPlayer()); return; } @@ -41,7 +69,8 @@ public class InteractListener implements Listener { persistentData = meta.getPersistentDataContainer().get(new NamespacedKey(MiniGames.getInstance(), PersistentDataKey.LEAVE_ITEM.getKeyName()), PersistentDataType.INTEGER); if (persistentData != null) { - event.setCancelled(true); + event.setUseItemInHand(Event.Result.DENY); + event.setUseInteractedBlock(Event.Result.DENY); if (persistentData == PersistentDataKey.LEAVE_ITEM.getDataValue()) { ArenaGUI.getLeaveAction().run(event.getPlayer()); } else if (persistentData == PersistentDataKey.GIVE_UP_ITEM.getDataValue()) {