From cd83c0404b8a9fefc40280ef66dd3733e6b4b83e Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Thu, 11 Jan 2024 23:50:13 +0100 Subject: [PATCH] Fixes #5 and implements #4 Only clears items when exiting a clear region Tracks when a player enters one or more clear regions, through a custom event Tracks when a player leaves one or more clear regions, through a custom event Uses the tracker's region info to check if a player is in a clear region where possible Excludes boats with player passengers from the vehicle move event, and requires that vehicles are in the clear region, not outside it Tracks player clear regions when a player joins or changes world Reduces a lot of code clutter and redundancy in WorldGuardListener --- .../clearonworldguard/ClearOnWorldGuard.java | 2 + .../event/EnterClearRegionEvent.java | 55 ++++++++++ .../event/ExitClearRegionEvent.java | 55 ++++++++++ .../listener/ClearRegionListener.java | 54 +++++++++ .../listener/EntityListener.java | 15 ++- .../listener/PlayerListener.java | 59 ++++++++-- .../listener/WorldGuardListener.java | 103 ++++++++++-------- .../manager/PlayerRegionTracker.java | 77 +++++++++++++ 8 files changed, 361 insertions(+), 59 deletions(-) create mode 100644 src/main/java/net/knarcraft/clearonworldguard/event/EnterClearRegionEvent.java create mode 100644 src/main/java/net/knarcraft/clearonworldguard/event/ExitClearRegionEvent.java create mode 100644 src/main/java/net/knarcraft/clearonworldguard/listener/ClearRegionListener.java create mode 100644 src/main/java/net/knarcraft/clearonworldguard/manager/PlayerRegionTracker.java diff --git a/src/main/java/net/knarcraft/clearonworldguard/ClearOnWorldGuard.java b/src/main/java/net/knarcraft/clearonworldguard/ClearOnWorldGuard.java index 2e9ce3e..9448e81 100644 --- a/src/main/java/net/knarcraft/clearonworldguard/ClearOnWorldGuard.java +++ b/src/main/java/net/knarcraft/clearonworldguard/ClearOnWorldGuard.java @@ -2,6 +2,7 @@ package net.knarcraft.clearonworldguard; import net.knarcraft.clearonworldguard.config.Configuration; import net.knarcraft.clearonworldguard.listener.BlockListener; +import net.knarcraft.clearonworldguard.listener.ClearRegionListener; import net.knarcraft.clearonworldguard.listener.EntityListener; import net.knarcraft.clearonworldguard.listener.PlayerListener; import org.bukkit.Bukkit; @@ -33,6 +34,7 @@ public final class ClearOnWorldGuard extends JavaPlugin { Bukkit.getPluginManager().registerEvents(new PlayerListener(configuration), this); Bukkit.getPluginManager().registerEvents(new EntityListener(configuration), this); Bukkit.getPluginManager().registerEvents(new BlockListener(configuration), this); + Bukkit.getPluginManager().registerEvents(new ClearRegionListener(configuration), this); this.debugMode = configuration.debugEnabled(); } diff --git a/src/main/java/net/knarcraft/clearonworldguard/event/EnterClearRegionEvent.java b/src/main/java/net/knarcraft/clearonworldguard/event/EnterClearRegionEvent.java new file mode 100644 index 0000000..6ca8239 --- /dev/null +++ b/src/main/java/net/knarcraft/clearonworldguard/event/EnterClearRegionEvent.java @@ -0,0 +1,55 @@ +package net.knarcraft.clearonworldguard.event; + +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +/** + * An event triggered when a player enters a clear region + */ +public class EnterClearRegionEvent extends PlayerEvent { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + private final Set regionEntered; + + /** + * Instantiates a new clear region enter event + * + * @param who

The player involved in the event

+ * @param regionsEntered

The region the player entered

+ */ + public EnterClearRegionEvent(@NotNull Player who, @NotNull Set regionsEntered) { + super(who); + this.regionEntered = regionsEntered; + } + + /** + * Gets the clear regions the player entered + * + * @return

The clear regions the player entered

+ */ + public Set getRegionsEntered() { + return this.regionEntered; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + /** + * Gets registers handlers for this event + * + * @return

Registered handlers for this event

+ */ + @SuppressWarnings("unused") + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + +} diff --git a/src/main/java/net/knarcraft/clearonworldguard/event/ExitClearRegionEvent.java b/src/main/java/net/knarcraft/clearonworldguard/event/ExitClearRegionEvent.java new file mode 100644 index 0000000..37491da --- /dev/null +++ b/src/main/java/net/knarcraft/clearonworldguard/event/ExitClearRegionEvent.java @@ -0,0 +1,55 @@ +package net.knarcraft.clearonworldguard.event; + +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +/** + * An event triggered when a player leaves a clear region + */ +public class ExitClearRegionEvent extends PlayerEvent { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + private final Set regionsExited; + + /** + * Instantiates a new clear region exit event + * + * @param who

The player involved in the event

+ * @param regionsExited

The region the player exited from

+ */ + public ExitClearRegionEvent(@NotNull Player who, @NotNull Set regionsExited) { + super(who); + this.regionsExited = regionsExited; + } + + /** + * Gets the clear region the player exited from + * + * @return

The region the player left

+ */ + public Set getRegionsExited() { + return this.regionsExited; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + /** + * Gets registers handlers for this event + * + * @return

Registered handlers for this event

+ */ + @SuppressWarnings("unused") + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + +} diff --git a/src/main/java/net/knarcraft/clearonworldguard/listener/ClearRegionListener.java b/src/main/java/net/knarcraft/clearonworldguard/listener/ClearRegionListener.java new file mode 100644 index 0000000..ddb1136 --- /dev/null +++ b/src/main/java/net/knarcraft/clearonworldguard/listener/ClearRegionListener.java @@ -0,0 +1,54 @@ +package net.knarcraft.clearonworldguard.listener; + +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import net.knarcraft.clearonworldguard.ClearOnWorldGuard; +import net.knarcraft.clearonworldguard.config.Configuration; +import net.knarcraft.clearonworldguard.event.EnterClearRegionEvent; +import net.knarcraft.clearonworldguard.event.ExitClearRegionEvent; +import net.knarcraft.clearonworldguard.manager.PlayerRegionTracker; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.jetbrains.annotations.NotNull; + +import java.util.Set; + +/** + * A listener for clear region entry and exit + */ +public class ClearRegionListener extends WorldGuardListener { + + /** + * Instantiates a new WorldGuard listener + * + * @param configuration

The configuration to get regions and settings from

+ */ + public ClearRegionListener(@NotNull Configuration configuration) { + super(configuration); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onClearRegionEnter(@NotNull EnterClearRegionEvent event) { + Player player = event.getPlayer(); + Set regionsEntered = event.getRegionsEntered(); + for (ProtectedRegion region : regionsEntered) { + PlayerRegionTracker.addRegion(player, region); + } + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onClearRegionExit(@NotNull ExitClearRegionEvent event) { + Player player = event.getPlayer(); + Set regionsExited = event.getRegionsExited(); + for (ProtectedRegion region : regionsExited) { + PlayerRegionTracker.removeRegion(player, region); + } + + // Clear inventory, since the player left a clear region + if (!regionsExited.isEmpty()) { + ClearOnWorldGuard.logDebugMessage("Cleared items and vehicles of player " + player); + clearInventoriesAndRemoveRecursively(player); + } + } + +} diff --git a/src/main/java/net/knarcraft/clearonworldguard/listener/EntityListener.java b/src/main/java/net/knarcraft/clearonworldguard/listener/EntityListener.java index 02a8a40..6b99e27 100644 --- a/src/main/java/net/knarcraft/clearonworldguard/listener/EntityListener.java +++ b/src/main/java/net/knarcraft/clearonworldguard/listener/EntityListener.java @@ -2,8 +2,10 @@ package net.knarcraft.clearonworldguard.listener; import net.knarcraft.clearonworldguard.ClearOnWorldGuard; import net.knarcraft.clearonworldguard.config.Configuration; +import net.knarcraft.clearonworldguard.manager.PlayerRegionTracker; import net.knarcraft.clearonworldguard.property.Permission; import org.bukkit.Location; +import org.bukkit.entity.Boat; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -100,7 +102,7 @@ public class EntityListener extends WorldGuardListener { return; } - if ((isInClearRegion(event.getEntity()) || isInClearRegion(player)) && + if ((isInClearRegion(event.getEntity()) || PlayerRegionTracker.isInClearRegion(player)) && !player.hasPermission(Permission.BYPASS_ENTITY_INTERACTION.toString())) { ClearOnWorldGuard.logDebugMessage("Prevented entity " + event.getEntity() + " from being damaged"); event.setCancelled(true); @@ -145,7 +147,16 @@ public class EntityListener extends WorldGuardListener { Vehicle vehicle = event.getVehicle(); - if (isInDifferentClearRegions(event.getFrom(), event.getTo())) { + // Player passengers are handled by the PlayerMoveEvent + if (vehicle instanceof Boat) { + for (Entity passenger : vehicle.getPassengers()) { + if (passenger instanceof Player) { + return; + } + } + } + + if (isInClearRegion(event.getFrom()) && isInDifferentClearRegions(event.getFrom(), event.getTo())) { ClearOnWorldGuard.logDebugMessage("Destroyed vehicle " + vehicle + " crossing a clear region border"); clearInventoriesAndRemoveRecursively(vehicle); } diff --git a/src/main/java/net/knarcraft/clearonworldguard/listener/PlayerListener.java b/src/main/java/net/knarcraft/clearonworldguard/listener/PlayerListener.java index ccdb1a6..0bce4db 100644 --- a/src/main/java/net/knarcraft/clearonworldguard/listener/PlayerListener.java +++ b/src/main/java/net/knarcraft/clearonworldguard/listener/PlayerListener.java @@ -1,8 +1,13 @@ package net.knarcraft.clearonworldguard.listener; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; import net.knarcraft.clearonworldguard.ClearOnWorldGuard; import net.knarcraft.clearonworldguard.config.Configuration; +import net.knarcraft.clearonworldguard.event.EnterClearRegionEvent; +import net.knarcraft.clearonworldguard.event.ExitClearRegionEvent; +import net.knarcraft.clearonworldguard.manager.PlayerRegionTracker; import net.knarcraft.clearonworldguard.property.Permission; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; @@ -13,9 +18,11 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.block.Action; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.entity.PlayerLeashEntityEvent; +import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerDropItemEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.ItemStack; @@ -23,6 +30,8 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.SpawnEggMeta; import org.jetbrains.annotations.NotNull; +import java.util.Set; + /** * Listeners for player events */ @@ -40,7 +49,7 @@ public class PlayerListener extends WorldGuardListener { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onLeash(@NotNull PlayerLeashEntityEvent event) { // Prevent leashing of entities while in a clear region - if (isInClearRegion(event.getPlayer()) && + if (PlayerRegionTracker.isInClearRegion(event.getPlayer()) && !event.getPlayer().hasPermission(Permission.BYPASS_ENTITY_INTERACTION.toString())) { ClearOnWorldGuard.logDebugMessage("Prevented " + event.getEntity() + " from being leashed by " + event.getPlayer()); @@ -56,12 +65,19 @@ public class PlayerListener extends WorldGuardListener { return; } Player player = event.getPlayer(); + updateClearRegions(player, from, to); + } - // Prevent player from smuggling items in a chest boat or similar - if (isInDifferentClearRegions(from, to)) { - ClearOnWorldGuard.logDebugMessage("Cleared items and vehicles of player " + player); - clearInventoriesAndRemoveRecursively(player); - } + @EventHandler(priority = EventPriority.MONITOR) + public void onJoin(@NotNull PlayerJoinEvent event) { + // Update clear regions of the player + PlayerRegionTracker.replaceRegions(event.getPlayer(), getRegions(event.getPlayer().getLocation())); + } + + @EventHandler(priority = EventPriority.MONITOR) + public void onWorldChange(@NotNull PlayerChangedWorldEvent event) { + // Update clear regions of the player + PlayerRegionTracker.replaceRegions(event.getPlayer(), getRegions(event.getPlayer().getLocation())); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @@ -72,13 +88,36 @@ public class PlayerListener extends WorldGuardListener { if (toLocation == null || fromLocation.equals(toLocation)) { return; } - clearIfClearRegionChange(fromLocation, toLocation, event.getPlayer()); + + ClearOnWorldGuard.logDebugMessage("Detected teleporting player " + event.getPlayer()); + updateClearRegions(event.getPlayer(), fromLocation, toLocation); + } + + /** + * Triggers any necessary events in order to change a player's clear regions + * + * @param player

The player that moved

+ * @param from

The location the player moved from

+ * @param to

The location the player moved to

+ */ + private void updateClearRegions(@NotNull Player player, @NotNull Location from, @NotNull Location to) { + Set regionsEntered = getRegionsEntered(from, to); + if (!regionsEntered.isEmpty()) { + Bukkit.getPluginManager().callEvent(new EnterClearRegionEvent(player, regionsEntered)); + } + + Set regionsLeft = getRegionsExited(from, to); + // Only trigger on the regions the player has entered + regionsLeft.removeIf(region -> !PlayerRegionTracker.getClearRegions(player).contains(region)); + if (!regionsLeft.isEmpty()) { + Bukkit.getPluginManager().callEvent(new ExitClearRegionEvent(player, regionsLeft)); + } } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onItemDrop(@NotNull PlayerDropItemEvent event) { // Prevent a player from dropping an item while inside a clear region - if (isInClearRegion(event.getPlayer())) { + if (PlayerRegionTracker.isInClearRegion(event.getPlayer())) { ClearOnWorldGuard.logDebugMessage("Prevented player " + event.getPlayer() + " from dropping an item"); event.setCancelled(true); } @@ -87,7 +126,7 @@ public class PlayerListener extends WorldGuardListener { @EventHandler(priority = EventPriority.HIGHEST) public void onPlayerDeath(@NotNull PlayerDeathEvent event) { // Prevent deaths in clear regions from causing items to be kept or dropped - if (isInClearRegion(event.getEntity())) { + if (PlayerRegionTracker.isInClearRegion(event.getEntity())) { ClearOnWorldGuard.logDebugMessage("Prevented player " + event.getEntity() + " from dropping or keeping " + "items on death"); event.setKeepInventory(false); @@ -136,7 +175,7 @@ public class PlayerListener extends WorldGuardListener { } // Prevent entity interaction, such as trading or putting chests on donkeys - if ((isInClearRegion(event.getPlayer()) || isInClearRegion(event.getRightClicked())) && + if ((PlayerRegionTracker.isInClearRegion(event.getPlayer()) || isInClearRegion(event.getRightClicked())) && !event.getPlayer().hasPermission(Permission.BYPASS_ENTITY_INTERACTION.toString())) { ClearOnWorldGuard.logDebugMessage("Prevented player " + event.getPlayer() + " from interacting with entity " + event.getRightClicked()); diff --git a/src/main/java/net/knarcraft/clearonworldguard/listener/WorldGuardListener.java b/src/main/java/net/knarcraft/clearonworldguard/listener/WorldGuardListener.java index f4a4ec1..d91af18 100644 --- a/src/main/java/net/knarcraft/clearonworldguard/listener/WorldGuardListener.java +++ b/src/main/java/net/knarcraft/clearonworldguard/listener/WorldGuardListener.java @@ -1,7 +1,6 @@ package net.knarcraft.clearonworldguard.listener; import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldguard.protection.ApplicableRegionSet; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import net.knarcraft.clearonworldguard.ClearOnWorldGuard; import net.knarcraft.clearonworldguard.config.Configuration; @@ -89,21 +88,6 @@ public abstract class WorldGuardListener implements Listener { } } - /** - * Clears the given player's inventory if they are leaving or entering a clear region - * - * @param fromLocation

The location the player moved or teleported from

- * @param toLocation

The location the player moved or teleported to

- * @param player

The player that's moving

- */ - protected void clearIfClearRegionChange(@NotNull Location fromLocation, @NotNull Location toLocation, - @NotNull Player player) { - if (isInDifferentClearRegions(fromLocation, toLocation)) { - ClearOnWorldGuard.logDebugMessage("Cleared inventory of player " + player); - player.getInventory().clear(); - } - } - /** * Checks whether the given locations are in different clear regions * @@ -115,23 +99,47 @@ public abstract class WorldGuardListener implements Listener { * @return

True if the two locations are in different clear regions

*/ protected boolean isInDifferentClearRegions(@NotNull Location location1, @NotNull Location location2) { - World fromWorld = location1.getWorld(); - if (fromWorld == null) { - ClearOnWorldGuard.logger().log(Level.WARNING, "Unable to check region change, as location " + - location1 + " has no world."); - return false; - } - - ApplicableRegionSet setFrom = configuration.getRegionQuery().getApplicableRegions(BukkitAdapter.adapt(location1)); - ApplicableRegionSet setTo = configuration.getRegionQuery().getApplicableRegions(BukkitAdapter.adapt(location2)); - - Set fromRegions = getOccupiedClearRegions(fromWorld, setFrom.getRegions()); - Set toRegions = getOccupiedClearRegions(fromWorld, setTo.getRegions()); + Set fromRegions = getOccupiedClearRegions(location1); + Set toRegions = getOccupiedClearRegions(location2); // If the player is in one or more clear regions, clear unless the clear regions are the same return (!fromRegions.isEmpty() || !toRegions.isEmpty()) && !fromRegions.equals(toRegions); } + /** + * Gets the regions a player has newly entered + * + * @param location1

The first location to check

+ * @param location2

The second location to check

+ * @return

A list of all regions location2 is in, that location1 isn't in, or null if a world is null

+ */ + protected @NotNull Set getRegionsEntered(@NotNull Location location1, @NotNull Location location2) { + Set fromRegions = getOccupiedClearRegions(location1); + Set toRegions = getOccupiedClearRegions(location2); + toRegions.removeAll(fromRegions); + + ClearOnWorldGuard.logDebugMessage("Calculated entered regions to: " + toRegions); + + return toRegions; + } + + /** + * Gets the regions a player has newly exited + * + * @param location1

The first location to check

+ * @param location2

The second location to check

+ * @return

A list of all regions location1 is in, that location2 isn't in, or null if a world is null

+ */ + protected @NotNull Set getRegionsExited(@NotNull Location location1, @NotNull Location location2) { + Set fromRegions = getOccupiedClearRegions(location1); + Set toRegions = getOccupiedClearRegions(location2); + fromRegions.removeAll(toRegions); + + ClearOnWorldGuard.logDebugMessage("Calculated exited regions to: " + fromRegions); + + return fromRegions; + } + /** * Checks whether the given block is in a clear region * @@ -159,36 +167,37 @@ public abstract class WorldGuardListener implements Listener { * @return

True if the location is in a clear region

*/ protected boolean isInClearRegion(@NotNull Location location) { + return !getOccupiedClearRegions(location).isEmpty(); + } + + /** + * Gets all regions set as clear regions the given location currently occupies + * + * @param location

The location to get clear regions for

+ * @return

All clear regions the location occupies

+ */ + private @NotNull Set getOccupiedClearRegions(@NotNull Location location) { World playerWorld = location.getWorld(); if (playerWorld == null) { ClearOnWorldGuard.logger().log(Level.WARNING, "Unable to check region change, as location " + location + " has no world."); - return false; + return new HashSet<>(); } - ApplicableRegionSet setFrom = configuration.getRegionQuery().getApplicableRegions(BukkitAdapter.adapt(location)); - Set fromRegions = getOccupiedClearRegions(playerWorld, setFrom.getRegions()); - return !fromRegions.isEmpty(); + Set regions = new HashSet<>(getRegions(location)); + Set clearRegions = configuration.getProtectedRegions(playerWorld); + regions.removeIf(region -> !clearRegions.contains(region)); + return regions; } /** - * Gets all regions set as clear regions the player currently occupies + * Gets all regions at the given location * - * @param playerWorld

The world the player is currently in

- * @param playerRegions

The regions the player is in or will be in

- * @return

All clear regions found in playerRegions

+ * @param location

The location to get regions for

+ * @return

All regions at the location

*/ - private Set getOccupiedClearRegions(@NotNull World playerWorld, - @NotNull Set playerRegions) { - Set possibleRegions = configuration.getProtectedRegions(playerWorld); - Set result = new HashSet<>(); - for (ProtectedRegion region : playerRegions) { - if (possibleRegions.contains(region)) { - result.add(region); - } - } - - return result; + protected Set getRegions(@NotNull Location location) { + return configuration.getRegionQuery().getApplicableRegions(BukkitAdapter.adapt(location)).getRegions(); } } diff --git a/src/main/java/net/knarcraft/clearonworldguard/manager/PlayerRegionTracker.java b/src/main/java/net/knarcraft/clearonworldguard/manager/PlayerRegionTracker.java new file mode 100644 index 0000000..bba5708 --- /dev/null +++ b/src/main/java/net/knarcraft/clearonworldguard/manager/PlayerRegionTracker.java @@ -0,0 +1,77 @@ +package net.knarcraft.clearonworldguard.manager; + +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * A tracker that keeps track of every player's current clear region + */ +public final class PlayerRegionTracker { + + private static final Map> currentPlayerRegions = new HashMap<>(); + + private PlayerRegionTracker() { + + } + + /** + * Replaces the current clear regions of the given player + * + * @param player

The player to add to

+ * @param regions

The regions to add

+ */ + public static void replaceRegions(@NotNull Player player, @NotNull Set regions) { + currentPlayerRegions.put(player, new HashSet<>(regions)); + } + + /** + * Adds the given clear region to the given player + * + * @param player

The player to add to

+ * @param region

The region to add

+ */ + public static void addRegion(@NotNull Player player, @NotNull ProtectedRegion region) { + currentPlayerRegions.putIfAbsent(player, new HashSet<>()); + currentPlayerRegions.get(player).add(region); + } + + /** + * Removes the given clear region from the given player + * + * @param player

The player to remove from

+ * @param region

The region to remove

+ */ + public static void removeRegion(@NotNull Player player, @NotNull ProtectedRegion region) { + currentPlayerRegions.putIfAbsent(player, new HashSet<>()); + currentPlayerRegions.get(player).remove(region); + } + + /** + * Checks whether the given player is in any clear region + * + * @param player

The player to check

+ * @return

True if the player is in any clear region

+ */ + public static boolean isInClearRegion(@NotNull Player player) { + currentPlayerRegions.putIfAbsent(player, new HashSet<>()); + return !currentPlayerRegions.get(player).isEmpty(); + } + + /** + * Gets a player's current clear regions + * + * @param player

The player to get for

+ * @return

The player's current clear regions

+ */ + public static @NotNull Set getClearRegions(@NotNull Player player) { + currentPlayerRegions.putIfAbsent(player, new HashSet<>()); + return currentPlayerRegions.get(player); + } + +}