Prevents more shenanigans

Prevents players from leashing entities in clear regions
Removes all entities riding, being ridden by and leashed to a player when moving across clear region borders
Adds bypass permissions for mob spawning and entity interaction
Adds a debug option
Splits listeners into three classes
Prevents more shenanigans I've forgotten
This commit is contained in:
Kristian Knarvik 2024-01-10 18:56:35 +01:00
parent 487e2682c3
commit 282cc50df6
10 changed files with 931 additions and 510 deletions

View File

@ -1,9 +1,15 @@
package net.knarcraft.clearonworldguard; package net.knarcraft.clearonworldguard;
import net.knarcraft.clearonworldguard.config.Configuration;
import net.knarcraft.clearonworldguard.listener.BlockListener;
import net.knarcraft.clearonworldguard.listener.EntityListener;
import net.knarcraft.clearonworldguard.listener.PlayerListener;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
@ -13,16 +19,21 @@ import java.util.logging.Logger;
public final class ClearOnWorldGuard extends JavaPlugin { public final class ClearOnWorldGuard extends JavaPlugin {
private static ClearOnWorldGuard instance; private static ClearOnWorldGuard instance;
private boolean debugMode;
@Override @Override
public void onEnable() { public void onEnable() {
instance = this; instance = this;
this.saveDefaultConfig(); this.saveDefaultConfig();
this.reloadConfig(); this.reloadConfig();
FileConfiguration configuration = this.getConfig(); FileConfiguration fileConfiguration = this.getConfig();
// Register the WorldGuard listener // Register the WorldGuard listener
Bukkit.getPluginManager().registerEvents(new WorldGuardListener(configuration), this); Configuration configuration = new Configuration(fileConfiguration);
Bukkit.getPluginManager().registerEvents(new PlayerListener(configuration), this);
Bukkit.getPluginManager().registerEvents(new EntityListener(configuration), this);
Bukkit.getPluginManager().registerEvents(new BlockListener(configuration), this);
this.debugMode = configuration.debugEnabled();
} }
/** /**
@ -34,4 +45,26 @@ public final class ClearOnWorldGuard extends JavaPlugin {
return instance.getLogger(); return instance.getLogger();
} }
/**
* Logs a debug message
*
* @param message <p>The message to debug</p>
*/
public static void logDebugMessage(@NotNull String message) {
if (instance.debugMode) {
logger().log(Level.INFO, message);
} else {
logger().log(Level.FINEST, message);
}
}
/**
* Gets an instance of this plugin
*
* @return <p>An instance of this plugin</p>
*/
public static ClearOnWorldGuard getInstance() {
return instance;
}
} }

View File

@ -1,506 +0,0 @@
package net.knarcraft.clearonworldguard;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockDispenseArmorEvent;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.block.BlockExpEvent;
import org.bukkit.event.block.BlockFormEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.TNTPrimeEvent;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SpawnEggMeta;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
/**
* A listener that listens to players entering and leaving WorldGuard regions
*/
public class WorldGuardListener implements Listener {
private final RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer();
private final RegionQuery query = regionContainer.createQuery();
private final Map<World, Set<ProtectedRegion>> protectedRegions = new HashMap<>();
/**
* Instantiates a new WorldGuard listener
*/
public WorldGuardListener(@NotNull FileConfiguration configuration) {
ConfigurationSection worldsSection = configuration.getConfigurationSection("clearRegions");
if (worldsSection == null) {
ClearOnWorldGuard.logger().log(Level.WARNING, "Unable to find clearRegions sections in the " +
"configuration file!");
return;
}
Set<String> worlds = worldsSection.getKeys(false);
for (String worldId : worlds) {
// Parse every world identifier
World world;
try {
UUID worldUUID = UUID.fromString(worldId);
world = Bukkit.getWorld(worldUUID);
} catch (IllegalArgumentException exception) {
world = Bukkit.getWorld(worldId);
}
if (world == null) {
ClearOnWorldGuard.logger().log(Level.WARNING, "The specified world: \"" + worldId + "\" is invalid.");
continue;
}
loadRegions(world, worldsSection, worldId);
}
}
/**
* Loads clear regions for a world
*
* @param world <p>The world to load regions for</p>
* @param worldsSection <p>The configuration section listing all worlds and regions</p>
* @param worldId <p>The user-specified identifier for the currently processed world</p>
*/
private void loadRegions(@NotNull World world, @NotNull ConfigurationSection worldsSection, @NotNull String worldId) {
// Get a region manager for the world
RegionManager regionManager = regionContainer.get(BukkitAdapter.adapt(world));
if (regionManager == null) {
ClearOnWorldGuard.logger().log(Level.WARNING, "Unable to get region manager for world: " +
world.getName());
return;
}
Set<ProtectedRegion> regions = new HashSet<>();
List<String> regionNames = worldsSection.getStringList(worldId);
for (String regionName : regionNames) {
// Register the region if it's valid
ProtectedRegion region = regionManager.getRegion(regionName);
if (region == null) {
ClearOnWorldGuard.logger().log(Level.WARNING, "Region name " + regionName + " is invalid");
} else {
regions.add(region);
}
}
protectedRegions.put(world, regions);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onMove(@NotNull PlayerMoveEvent event) {
if (event.getTo() == null || event.getFrom().getWorld() == null) {
return;
}
clearIfClearRegionChange(event.getFrom(), event.getTo(), event.getPlayer());
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onTeleport(@NotNull PlayerTeleportEvent event) {
Location fromLocation = event.getFrom();
Location toLocation = event.getTo();
if (toLocation == null || fromLocation.equals(toLocation)) {
return;
}
clearIfClearRegionChange(fromLocation, toLocation, event.getPlayer());
}
@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())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onXpBottle(@NotNull ProjectileLaunchEvent event) {
// Prevent a player from using an XP bottle in a clear region
if (isInClearRegion(event.getEntity())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onTNT(@NotNull TNTPrimeEvent event) {
// Prevent TNT from being primed in a clear region, or by a player in a clear region
Entity primingEntity = event.getPrimingEntity();
if (primingEntity != null && isInClearRegion(primingEntity)) {
event.setCancelled(true);
return;
}
Block primingBlock = event.getPrimingBlock();
if (primingBlock != null && isInClearRegion(primingBlock)) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockPlace(@NotNull BlockPlaceEvent event) {
// Prevent placing a block outside a clear region
if (isInDifferentClearRegions(event.getPlayer().getLocation(), event.getBlockPlaced().getLocation())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockBreak(@NotNull BlockBreakEvent event) {
// Prevent breaking a block outside a clear region, while in the clear region
if (isInDifferentClearRegions(event.getPlayer().getLocation(), event.getBlock().getLocation())) {
event.setCancelled(true);
return;
}
// Prevent item drops when the item is destroyed
if (isInClearRegion(event.getBlock())) {
event.setDropItems(false);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onExplosionPrime(@NotNull ExplosionPrimeEvent event) {
Location location = event.getEntity().getLocation();
float radius = event.getRadius();
if (isInClearRegion(location) ||
isInClearRegion(location.clone().add(radius, radius, radius)) ||
isInClearRegion(location.clone().add(-radius, radius, radius)) ||
isInClearRegion(location.clone().add(-radius, radius, -radius)) ||
isInClearRegion(location.clone().add(radius, radius, -radius)) ||
isInClearRegion(location.clone().add(radius, -radius, radius)) ||
isInClearRegion(location.clone().add(-radius, -radius, radius)) ||
isInClearRegion(location.clone().add(-radius, -radius, -radius)) ||
isInClearRegion(location.clone().add(radius, -radius, -radius))) {
event.setCancelled(true);
event.getEntity().remove();
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityExplode(@NotNull EntityExplodeEvent event) {
// Prevent explosions in clear regions
if (isInClearRegion(event.getEntity())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityChangeBlock(@NotNull EntityChangeBlockEvent event) {
// Prevent entities from changing blocks in clear regions
if (isInClearRegion(event.getBlock())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onCreatureSpawn(@NotNull CreatureSpawnEvent event) {
// Prevent creatures from spawning
if (isInClearRegion(event.getLocation()) && event.getEntityType() != EntityType.ARMOR_STAND) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockItemDrop(@NotNull BlockDropItemEvent event) {
// Block item drops for indirectly destroyed items
if (isInClearRegion(event.getBlock())) {
event.getItems().clear();
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockXP(@NotNull BlockExpEvent event) {
// Prevent dropping XP in clear regions
if (isInClearRegion(event.getBlock())) {
event.setExpToDrop(0);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityDamage(@NotNull EntityDamageEvent event) {
// Prevent entity damage in clear regions
if (isInClearRegion(event.getEntity())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onDeath(@NotNull EntityDeathEvent event) {
// Prevent mob loot and XP
if (isInClearRegion(event.getEntity())) {
event.setDroppedExp(0);
event.getDrops().clear();
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onDispense(@NotNull BlockDispenseEvent event) {
// Prevent dispensers from dispensing and droppers from dropping
if (isInClearRegion(event.getBlock())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onArmorDispense(@NotNull BlockDispenseArmorEvent event) {
// Prevent dispensers from dispensing armors in clear regions
if (isInClearRegion(event.getBlock())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBurn(@NotNull BlockBurnEvent event) {
// Prevent blocks from burning in clear areas
Block block = event.getBlock();
if (isInClearRegion(block)) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onIgnite(@NotNull BlockIgniteEvent event) {
// Prevent ignition in clear areas, unless done by flint and steel
Block block = event.getBlock();
if (isInClearRegion(block) && event.getCause() != BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onDeath(@NotNull PlayerDeathEvent event) {
// Prevent deaths in clear regions from causing items to be kept or dropped
if (isInClearRegion(event.getEntity())) {
event.setKeepInventory(false);
event.setKeepLevel(true);
event.getEntity().getInventory().clear();
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onItemPickup(@NotNull EntityPickupItemEvent event) {
// Prevent item pickup in clear regions
if (!(event.getEntity() instanceof Player player)) {
return;
}
if (isInClearRegion(player)) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockSpread(@NotNull BlockSpreadEvent event) {
// Prevent block spread in clear regions
if (isInClearRegion(event.getSource())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockForm(@NotNull BlockFormEvent event) {
// Prevent block forming in clear regions
if (isInClearRegion(event.getBlock())) {
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPistonExtend(@NotNull BlockPistonExtendEvent event) {
// Prevent pistons from pushing blocks across the clear region border
Block piston = event.getBlock();
List<Block> blocks = event.getBlocks();
for (Block block : blocks) {
if (isInDifferentClearRegions(piston.getLocation(), block.getLocation())) {
event.setCancelled(true);
return;
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPistonRetract(@NotNull BlockPistonRetractEvent event) {
// Prevent pistons from pulling blocks across the clear region border
Block piston = event.getBlock();
List<Block> blocks = event.getBlocks();
for (Block block : blocks) {
if (isInDifferentClearRegions(piston.getLocation(), block.getLocation())) {
event.setCancelled(true);
return;
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onInteract(@NotNull PlayerInteractEvent event) {
// Prevent interacting with blocks outside the clear region, such as chests
Block clicked = event.getClickedBlock();
if (clicked != null && isInDifferentClearRegions(event.getPlayer().getLocation(), clicked.getLocation())) {
event.setCancelled(true);
return;
}
// Block changing the creature in a spawner
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && clicked != null && clicked.getType() == Material.SPAWNER &&
isInClearRegion(clicked)) {
event.setCancelled(true);
return;
}
// Block usage of spawn eggs
ItemStack item = event.getItem();
if (item != null && isInClearRegion(event.getPlayer()) && item.hasItemMeta()) {
ItemMeta meta = event.getItem().getItemMeta();
if (meta instanceof SpawnEggMeta) {
event.setCancelled(true);
}
}
}
/**
* Clears the given player's inventory if they are leaving or entering a clear region
*
* @param fromLocation <p>The location the player moved or teleported from</p>
* @param toLocation <p>The location the player moved or teleported to</p>
* @param player <p>The player that's moving</p>
*/
private void clearIfClearRegionChange(@NotNull Location fromLocation, @NotNull Location toLocation,
@NotNull Player player) {
if (isInDifferentClearRegions(fromLocation, toLocation)) {
player.getInventory().clear();
}
}
/**
* Checks whether the given locations are in different clear regions
*
* <p>If location1 is in a clear region and location2 is not, or if location1 is in a different clear region than
* region2, or if region 1 is in an additional clear region, this will return true.</p>
*
* @param location1 <p>The first location to check</p>
* @param location2 <p>The second location to check</p>
* @return <p>True if the two locations are in different clear regions</p>
*/
private 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 = query.getApplicableRegions(BukkitAdapter.adapt(location1));
ApplicableRegionSet setTo = query.getApplicableRegions(BukkitAdapter.adapt(location2));
Set<ProtectedRegion> fromRegions = getOccupiedClearRegions(fromWorld, setFrom.getRegions());
Set<ProtectedRegion> toRegions = getOccupiedClearRegions(fromWorld, setTo.getRegions());
// 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);
}
/**
* Checks whether the given block is in a clear region
*
* @param entity <p>The entity to check</p>
* @return <p>True if the block is in a clear region</p>
*/
private boolean isInClearRegion(@NotNull Entity entity) {
return isInClearRegion(entity.getLocation());
}
/**
* Checks whether the given block is in a clear region
*
* @param block <p>The block to check</p>
* @return <p>True if the block is in a clear region</p>
*/
private boolean isInClearRegion(@NotNull Block block) {
return isInClearRegion(block.getLocation());
}
/**
* Checks whether the given location is in a clear region
*
* @param location <p>The location to check</p>
* @return <p>True if the location is in a clear region</p>
*/
private boolean isInClearRegion(@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;
}
ApplicableRegionSet setFrom = query.getApplicableRegions(BukkitAdapter.adapt(location));
Set<ProtectedRegion> fromRegions = getOccupiedClearRegions(playerWorld, setFrom.getRegions());
return !fromRegions.isEmpty();
}
/**
* Gets all regions set as clear regions the player currently occupies
*
* @param playerWorld <p>The world the player is currently in</p>
* @param playerRegions <p>The regions the player is in or will be in</p>
* @return <p>All clear regions found in playerRegions</p>
*/
private Set<ProtectedRegion> getOccupiedClearRegions(@NotNull World playerWorld,
@NotNull Set<ProtectedRegion> playerRegions) {
Set<ProtectedRegion> possibleRegions = protectedRegions.get(playerWorld);
Set<ProtectedRegion> result = new HashSet<>();
for (ProtectedRegion region : playerRegions) {
if (possibleRegions.contains(region)) {
result.add(region);
}
}
return result;
}
}

View File

@ -0,0 +1,124 @@
package net.knarcraft.clearonworldguard.config;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import net.knarcraft.clearonworldguard.ClearOnWorldGuard;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
/**
* A configuration that keeps track of loaded clear regions
*/
public class Configuration {
private final RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer();
private final RegionQuery regionQuery = regionContainer.createQuery();
private final Map<World, Set<ProtectedRegion>> protectedRegions = new HashMap<>();
private final boolean debugEnabled;
/**
* Instantiates a new configuration
*
* @param configuration <p>The file configuration to read</p>
*/
public Configuration(@NotNull FileConfiguration configuration) {
debugEnabled = Boolean.parseBoolean(configuration.getString("debug"));
ConfigurationSection worldsSection = configuration.getConfigurationSection("clearRegions");
if (worldsSection == null) {
ClearOnWorldGuard.logger().log(Level.WARNING, "Unable to find clearRegions sections in the " +
"configuration file!");
return;
}
Set<String> worlds = worldsSection.getKeys(false);
for (String worldId : worlds) {
// Parse every world identifier
World world;
try {
UUID worldUUID = UUID.fromString(worldId);
world = Bukkit.getWorld(worldUUID);
} catch (IllegalArgumentException exception) {
world = Bukkit.getWorld(worldId);
}
if (world == null) {
ClearOnWorldGuard.logger().log(Level.WARNING, "The specified world: \"" + worldId + "\" is invalid.");
continue;
}
loadRegions(world, worldsSection, worldId);
}
}
/**
* Loads clear regions for a world
*
* @param world <p>The world to load regions for</p>
* @param worldsSection <p>The configuration section listing all worlds and regions</p>
* @param worldId <p>The user-specified identifier for the currently processed world</p>
*/
private void loadRegions(@NotNull World world, @NotNull ConfigurationSection worldsSection, @NotNull String worldId) {
// Get a region manager for the world
RegionManager regionManager = regionContainer.get(BukkitAdapter.adapt(world));
if (regionManager == null) {
ClearOnWorldGuard.logger().log(Level.WARNING, "Unable to get region manager for world: " +
world.getName());
return;
}
Set<ProtectedRegion> regions = new HashSet<>();
List<String> regionNames = worldsSection.getStringList(worldId);
for (String regionName : regionNames) {
// Register the region if it's valid
ProtectedRegion region = regionManager.getRegion(regionName);
if (region == null) {
ClearOnWorldGuard.logger().log(Level.WARNING, "Region name " + regionName + " is invalid");
} else {
regions.add(region);
}
}
protectedRegions.put(world, regions);
}
/**
* Gets all protected regions for the given world
*
* @return <p>All protected regions for the given world</p>
*/
public @NotNull Set<ProtectedRegion> getProtectedRegions(@NotNull World world) {
return this.protectedRegions.get(world);
}
/**
* Gets a region query
*
* @return <p>A region query</p>
*/
public @NotNull RegionQuery getRegionQuery() {
return regionQuery;
}
/**
* Gets whether debug mode is enabled
*
* @return <p>True if debug mode is enabled</p>
*/
public boolean debugEnabled() {
return this.debugEnabled;
}
}

View File

@ -0,0 +1,183 @@
package net.knarcraft.clearonworldguard.listener;
import net.knarcraft.clearonworldguard.ClearOnWorldGuard;
import net.knarcraft.clearonworldguard.config.Configuration;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockDispenseArmorEvent;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.block.BlockDropItemEvent;
import org.bukkit.event.block.BlockExpEvent;
import org.bukkit.event.block.BlockFormEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.BlockSpreadEvent;
import org.bukkit.event.block.TNTPrimeEvent;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Listeners for block events
*/
public class BlockListener extends WorldGuardListener {
/**
* Instantiates a new WorldGuard listener
*
* @param configuration <p>The configuration to get regions and settings from</p>
*/
public BlockListener(@NotNull Configuration configuration) {
super(configuration);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockItemDrop(@NotNull BlockDropItemEvent event) {
// Block item drops for indirectly destroyed items
if (isInClearRegion(event.getBlock())) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + event.getBlock() + " from dropping as an item");
event.getItems().clear();
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onBlockXP(@NotNull BlockExpEvent event) {
// Prevent dropping XP in clear regions
if (isInClearRegion(event.getBlock())) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + event.getBlock() + " from dropping any XP");
event.setExpToDrop(0);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onDispense(@NotNull BlockDispenseEvent event) {
// Prevent dispensers from dispensing and droppers from dropping
if (isInClearRegion(event.getBlock())) {
ClearOnWorldGuard.logDebugMessage("Prevented dispenser " + event.getBlock() + " from dispensing");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onArmorDispense(@NotNull BlockDispenseArmorEvent event) {
// Prevent dispensers from dispensing armors in clear regions
if (isInClearRegion(event.getBlock())) {
ClearOnWorldGuard.logDebugMessage("Prevented armor from dispensing from " + event.getBlock());
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBurn(@NotNull BlockBurnEvent event) {
// Prevent blocks from burning in clear areas
Block block = event.getBlock();
if (isInClearRegion(block)) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + event.getBlock() + " from burning");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onIgnite(@NotNull BlockIgniteEvent event) {
// Prevent ignition in clear areas, unless done by flint and steel
Block block = event.getBlock();
if (isInClearRegion(block) && event.getCause() != BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + event.getBlock() + " from igniting");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockSpread(@NotNull BlockSpreadEvent event) {
// Prevent block spread in clear regions
if (isInClearRegion(event.getSource())) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + event.getBlock() + " from spreading");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockForm(@NotNull BlockFormEvent event) {
// Prevent block forming in clear regions
if (isInClearRegion(event.getBlock())) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + event.getBlock() + " from forming");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPistonExtend(@NotNull BlockPistonExtendEvent event) {
// Prevent pistons from pushing blocks across the clear region border
Block piston = event.getBlock();
List<Block> blocks = event.getBlocks();
for (Block block : blocks) {
if (isInDifferentClearRegions(piston.getLocation(), block.getLocation())) {
ClearOnWorldGuard.logDebugMessage("Prevented piston " + piston + " from extending");
event.setCancelled(true);
return;
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onPistonRetract(@NotNull BlockPistonRetractEvent event) {
// Prevent pistons from pulling blocks across the clear region border
Block piston = event.getBlock();
List<Block> blocks = event.getBlocks();
for (Block block : blocks) {
if (isInDifferentClearRegions(piston.getLocation(), block.getLocation())) {
ClearOnWorldGuard.logDebugMessage("Prevented piston " + piston + " from retracting");
event.setCancelled(true);
return;
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockPlace(@NotNull BlockPlaceEvent event) {
// Prevent placing a block outside a clear region
if (isInDifferentClearRegions(event.getPlayer().getLocation(), event.getBlockPlaced().getLocation())) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + event.getBlock() + " from being placed");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onBlockBreak(@NotNull BlockBreakEvent event) {
// Prevent breaking a block outside a clear region, while in the clear region
Block block = event.getBlock();
if (isInDifferentClearRegions(event.getPlayer().getLocation(), block.getLocation())) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + block + " from being broken");
event.setCancelled(true);
return;
}
// Prevent item drops when the item is destroyed
if (isInClearRegion(block)) {
ClearOnWorldGuard.logDebugMessage("Prevented block " + block + " from dropping items");
event.setDropItems(false);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onTNT(@NotNull TNTPrimeEvent event) {
// Prevent TNT from being primed in a clear region, or by a player in a clear region
Entity primingEntity = event.getPrimingEntity();
Block block = event.getBlock();
Block primingBlock = event.getPrimingBlock();
if ((primingEntity != null && isInClearRegion(primingEntity)) || isInClearRegion(block) ||
(primingBlock != null && isInClearRegion(primingBlock))) {
ClearOnWorldGuard.logDebugMessage("Prevented TNT " + event.getBlock() + " from being primed by entity " +
primingEntity + " or block " + primingBlock);
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,192 @@
package net.knarcraft.clearonworldguard.listener;
import net.knarcraft.clearonworldguard.ClearOnWorldGuard;
import net.knarcraft.clearonworldguard.config.Configuration;
import net.knarcraft.clearonworldguard.property.Permission;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.event.vehicle.VehicleDestroyEvent;
import org.bukkit.event.vehicle.VehicleMoveEvent;
import org.jetbrains.annotations.NotNull;
import org.spigotmc.event.entity.EntityMountEvent;
/**
* Listeners for entity events
*/
public class EntityListener extends WorldGuardListener {
/**
* Instantiates a new WorldGuard listener
*
* @param configuration <p>The configuration to get regions and settings from</p>
*/
public EntityListener(@NotNull Configuration configuration) {
super(configuration);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityExplode(@NotNull EntityExplodeEvent event) {
// Prevent explosions in clear regions
if (isInClearRegion(event.getEntity())) {
ClearOnWorldGuard.logDebugMessage("Prevented entity " + event.getEntity() + " from exploding");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityMount(@NotNull EntityMountEvent event) {
// Prevent entity mounting in clear regions
Entity entity = event.getEntity();
Entity mount = event.getMount();
// Don't restrict NPCs
if (entity instanceof Player player && player.hasMetadata("NPC")) {
return;
}
if ((isInClearRegion(entity) || isInClearRegion(mount)) &&
!entity.hasPermission(Permission.BYPASS_ENTITY_INTERACTION.toString())) {
ClearOnWorldGuard.logDebugMessage("Prevented entity " + entity + " from mounting " + mount);
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityChangeBlock(@NotNull EntityChangeBlockEvent event) {
// Prevent entities from changing blocks in clear regions
if (isInClearRegion(event.getBlock())) {
ClearOnWorldGuard.logDebugMessage("Prevented entity " + event.getEntity() + " from changing the block " +
event.getBlock());
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onCreatureSpawn(@NotNull CreatureSpawnEvent event) {
// Prevent creatures from spawning, unless it's intentional
CreatureSpawnEvent.SpawnReason spawnReason = event.getSpawnReason();
if (isInClearRegion(event.getLocation()) && (event.getEntityType() != EntityType.ARMOR_STAND &&
spawnReason != CreatureSpawnEvent.SpawnReason.COMMAND) &&
spawnReason != CreatureSpawnEvent.SpawnReason.SPAWNER_EGG
) {
if (spawnReason != CreatureSpawnEvent.SpawnReason.NATURAL &&
spawnReason != CreatureSpawnEvent.SpawnReason.BEEHIVE) {
ClearOnWorldGuard.logDebugMessage("Prevented creature " + event.getEntity() + " from spawning with " +
"spawn reason " + event.getSpawnReason());
}
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityDamage(@NotNull EntityDamageByEntityEvent event) {
// Prevent entity damage from players in clear regions
if (!(event.getDamager() instanceof Player player)) {
return;
}
if ((isInClearRegion(event.getEntity()) || isInClearRegion(player)) &&
!player.hasPermission(Permission.BYPASS_ENTITY_INTERACTION.toString())) {
ClearOnWorldGuard.logDebugMessage("Prevented entity " + event.getEntity() + " from being damaged");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityDeath(@NotNull EntityDeathEvent event) {
// Prevent mob loot and XP
if (isInClearRegion(event.getEntity())) {
ClearOnWorldGuard.logDebugMessage("Prevented entity " + event.getEntity() + " from dropping items");
event.setDroppedExp(0);
event.getDrops().clear();
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onItemPickup(@NotNull EntityPickupItemEvent event) {
// Prevent item pickup in clear regions
if (isInClearRegion(event.getEntity())) {
ClearOnWorldGuard.logDebugMessage("Prevented entity " + event.getEntity() + " from picking up an item");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onVehicleDestroy(@NotNull VehicleDestroyEvent event) {
// Prevent destroyed vehicles from dropping as items
if (isInClearRegion(event.getVehicle())) {
ClearOnWorldGuard.logDebugMessage("Prevented vehicle " + event.getVehicle() + " from dropping as an item");
event.setCancelled(true);
clearInventoriesAndRemoveRecursively(event.getVehicle());
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onVehicleMove(@NotNull VehicleMoveEvent event) {
// Prevent chest minecarts or similar from leaving the clear region
if (event.getFrom().equals(event.getTo())) {
return;
}
Vehicle vehicle = event.getVehicle();
if (isInDifferentClearRegions(event.getFrom(), event.getTo())) {
ClearOnWorldGuard.logDebugMessage("Destroyed vehicle " + vehicle + " crossing a clear region border");
clearInventoriesAndRemoveRecursively(vehicle);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onProjectileLaunch(@NotNull ProjectileLaunchEvent event) {
// Prevent a player from using an XP bottle in a clear region
if (isInClearRegion(event.getEntity())) {
ClearOnWorldGuard.logDebugMessage("Prevented projectile " + event.getEntity());
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onExplosionPrime(@NotNull ExplosionPrimeEvent event) {
// Prevent explosion from priming if any exploded blocks are in a clear region
Location location = event.getEntity().getLocation();
float radius = event.getRadius();
if (isInClearRegion(location) ||
isInClearRegion(location.clone().add(radius, radius, radius)) ||
isInClearRegion(location.clone().add(-radius, radius, radius)) ||
isInClearRegion(location.clone().add(-radius, radius, -radius)) ||
isInClearRegion(location.clone().add(radius, radius, -radius)) ||
isInClearRegion(location.clone().add(radius, -radius, radius)) ||
isInClearRegion(location.clone().add(-radius, -radius, radius)) ||
isInClearRegion(location.clone().add(-radius, -radius, -radius)) ||
isInClearRegion(location.clone().add(radius, -radius, -radius))) {
ClearOnWorldGuard.logDebugMessage("Prevented " + event.getEntity() + " from being primed");
event.setCancelled(true);
event.getEntity().remove();
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onCombust(@NotNull EntityCombustEvent event) {
// Prevent entities in clear regions from being put on fire
if (isInClearRegion(event.getEntity())) {
ClearOnWorldGuard.logDebugMessage("Prevented " + event.getEntity() + " from combusting");
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,147 @@
package net.knarcraft.clearonworldguard.listener;
import net.knarcraft.clearonworldguard.ClearOnWorldGuard;
import net.knarcraft.clearonworldguard.config.Configuration;
import net.knarcraft.clearonworldguard.property.Permission;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
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.PlayerDropItemEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SpawnEggMeta;
import org.jetbrains.annotations.NotNull;
/**
* Listeners for player events
*/
public class PlayerListener extends WorldGuardListener {
/**
* Instantiates a new WorldGuard listener
*
* @param configuration <p>The configuration to get regions and settings from</p>
*/
public PlayerListener(@NotNull Configuration configuration) {
super(configuration);
}
@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()) &&
!event.getPlayer().hasPermission(Permission.BYPASS_ENTITY_INTERACTION.toString())) {
ClearOnWorldGuard.logDebugMessage("Prevented " + event.getEntity() + " from being leashed by " +
event.getPlayer());
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onMove(@NotNull PlayerMoveEvent event) {
Location from = event.getFrom();
Location to = event.getTo();
if (to == null || from.getWorld() == null) {
return;
}
Player player = event.getPlayer();
// 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, ignoreCancelled = true)
public void onTeleport(@NotNull PlayerTeleportEvent event) {
Location fromLocation = event.getFrom();
Location toLocation = event.getTo();
if (toLocation == null || fromLocation.equals(toLocation)) {
return;
}
clearIfClearRegionChange(fromLocation, toLocation, event.getPlayer());
}
@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())) {
ClearOnWorldGuard.logDebugMessage("Prevented player " + event.getPlayer() + " from dropping an item");
event.setCancelled(true);
}
}
@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())) {
ClearOnWorldGuard.logDebugMessage("Prevented player " + event.getEntity() + " from dropping or keeping " +
"items on death");
event.setKeepInventory(false);
event.setKeepLevel(true);
event.getEntity().getInventory().clear();
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onInteract(@NotNull PlayerInteractEvent event) {
// Prevent interacting with blocks outside the clear region, such as chests
Player player = event.getPlayer();
Block clicked = event.getClickedBlock();
if (clicked != null && isInDifferentClearRegions(player.getLocation(), clicked.getLocation())) {
ClearOnWorldGuard.logDebugMessage("Prevented player " + player + " from interacting across a clear" +
" region border");
event.setCancelled(true);
return;
}
// Block changing the creature in a spawner
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && clicked != null && clicked.getType() == Material.SPAWNER &&
isInClearRegion(clicked) && !player.hasPermission(Permission.BYPASS_MOB_SPAWNING.toString())) {
ClearOnWorldGuard.logDebugMessage("Prevented player " + player + " from interacting with mob spawner " +
clicked);
event.setCancelled(true);
return;
}
// Block usage of spawn eggs
ItemStack item = event.getItem();
if (item != null && isInClearRegion(player) && item.hasItemMeta()) {
ItemMeta meta = event.getItem().getItemMeta();
if (meta instanceof SpawnEggMeta && !player.hasPermission(Permission.BYPASS_MOB_SPAWNING.toString())) {
ClearOnWorldGuard.logDebugMessage("Prevented player " + player + " from using the spawn egg " + item);
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onEntityInteract(@NotNull PlayerInteractEntityEvent event) {
// Allow interactions with human NPCs
if (event.getRightClicked() instanceof HumanEntity && !(event.getRightClicked() instanceof Player)) {
return;
}
// Prevent entity interaction, such as trading or putting chests on donkeys
if ((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());
event.setCancelled(true);
}
}
}

View File

@ -0,0 +1,194 @@
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;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Creature;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.inventory.InventoryHolder;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.logging.Level;
/**
* A listener that listens to players entering and leaving WorldGuard regions
*/
public abstract class WorldGuardListener implements Listener {
private final Configuration configuration;
/**
* Instantiates a new WorldGuard listener
*
* @param configuration <p>The configuration to get regions and settings from</p>
*/
public WorldGuardListener(@NotNull Configuration configuration) {
this.configuration = configuration;
}
/**
* Recursively clears and removes entities connected together
*
* @param startEntity <p>The entity to start with</p>
*/
protected void clearInventoriesAndRemoveRecursively(@NotNull Entity startEntity) {
List<Entity> processed = new ArrayList<>();
Queue<Entity> queue = new LinkedList<>();
queue.add(startEntity);
while (!queue.isEmpty()) {
Entity entity = queue.remove();
// Prevent duplicate processing
if (processed.contains(entity)) {
continue;
}
// Queue the entity's vehicle
if (entity.isInsideVehicle()) {
queue.add(entity.getVehicle());
}
// Queue the entity's passengers
queue.addAll(entity.getPassengers());
// Add any nearby creatures leashed to the entity
Collection<Entity> nearbyEntities = entity.getWorld().getNearbyEntities(entity.getLocation(), 10, 10, 10);
for (Entity nearby : nearbyEntities) {
if (nearby instanceof Creature creature && creature.isLeashed() && creature.getLeashHolder().equals(entity)) {
queue.add(nearby);
}
}
// Clear inventory if necessary
if (entity instanceof InventoryHolder inventoryHolder) {
inventoryHolder.getInventory().clear();
}
processed.add(entity);
}
// Eject and remove every entity
for (Entity entity : processed) {
if (!(entity instanceof Player)) {
entity.eject();
entity.remove();
}
}
}
/**
* Clears the given player's inventory if they are leaving or entering a clear region
*
* @param fromLocation <p>The location the player moved or teleported from</p>
* @param toLocation <p>The location the player moved or teleported to</p>
* @param player <p>The player that's moving</p>
*/
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
*
* <p>If location1 is in a clear region and location2 is not, or if location1 is in a different clear region than
* region2, or if region 1 is in an additional clear region, this will return true.</p>
*
* @param location1 <p>The first location to check</p>
* @param location2 <p>The second location to check</p>
* @return <p>True if the two locations are in different clear regions</p>
*/
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<ProtectedRegion> fromRegions = getOccupiedClearRegions(fromWorld, setFrom.getRegions());
Set<ProtectedRegion> toRegions = getOccupiedClearRegions(fromWorld, setTo.getRegions());
// 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);
}
/**
* Checks whether the given block is in a clear region
*
* @param entity <p>The entity to check</p>
* @return <p>True if the block is in a clear region</p>
*/
protected boolean isInClearRegion(@NotNull Entity entity) {
return isInClearRegion(entity.getLocation());
}
/**
* Checks whether the given block is in a clear region
*
* @param block <p>The block to check</p>
* @return <p>True if the block is in a clear region</p>
*/
protected boolean isInClearRegion(@NotNull Block block) {
return isInClearRegion(block.getLocation());
}
/**
* Checks whether the given location is in a clear region
*
* @param location <p>The location to check</p>
* @return <p>True if the location is in a clear region</p>
*/
protected boolean isInClearRegion(@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;
}
ApplicableRegionSet setFrom = configuration.getRegionQuery().getApplicableRegions(BukkitAdapter.adapt(location));
Set<ProtectedRegion> fromRegions = getOccupiedClearRegions(playerWorld, setFrom.getRegions());
return !fromRegions.isEmpty();
}
/**
* Gets all regions set as clear regions the player currently occupies
*
* @param playerWorld <p>The world the player is currently in</p>
* @param playerRegions <p>The regions the player is in or will be in</p>
* @return <p>All clear regions found in playerRegions</p>
*/
private Set<ProtectedRegion> getOccupiedClearRegions(@NotNull World playerWorld,
@NotNull Set<ProtectedRegion> playerRegions) {
Set<ProtectedRegion> possibleRegions = configuration.getProtectedRegions(playerWorld);
Set<ProtectedRegion> result = new HashSet<>();
for (ProtectedRegion region : playerRegions) {
if (possibleRegions.contains(region)) {
result.add(region);
}
}
return result;
}
}

View File

@ -0,0 +1,37 @@
package net.knarcraft.clearonworldguard.property;
import org.jetbrains.annotations.NotNull;
/**
* A representation of manually checked permissions
*/
public enum Permission {
/**
* The permission for bypassing entity interaction restrictions
*/
BYPASS_ENTITY_INTERACTION("clearonworldguard.bypass.entityinteraction"),
/**
* The permission for bypassing mob spawning restrictions
*/
BYPASS_MOB_SPAWNING("clearonworldguard.bypass.mobspawning"),
;
private final String permissionString;
/**
* Instantiates a new permission
*
* @param permissionString <p>The permission string this represents</p>
*/
Permission(@NotNull String permissionString) {
this.permissionString = permissionString;
}
@Override
public String toString() {
return permissionString;
}
}

View File

@ -4,4 +4,7 @@ clearRegions:
# the square parentheses. # the square parentheses.
world: [ ] world: [ ]
world_nether: [ ] world_nether: [ ]
world_the_end: [ ] world_the_end: [ ]
# Whether to enable debug mode, which spams debug messages at log level INFO, rather than log level FINEST
debug: false

View File

@ -3,4 +3,18 @@ version: '${project.version}'
main: net.knarcraft.clearonworldguard.ClearOnWorldGuard main: net.knarcraft.clearonworldguard.ClearOnWorldGuard
api-version: '1.20' api-version: '1.20'
description: A custom KnarCraft plugin description: A custom KnarCraft plugin
depend: [ WorldGuard ] depend: [ WorldGuard ]
permissions:
clearonworldguard.bypass.*:
default: false
description: Gives all bypass permissions
children:
- clearonworldguard.bypass.mobspawning
- clearonworldguard.bypass.entityinteraction
clearonworldguard.bypass.mobspawning:
default: false
description: Allows a player to spawn mobs in clear regions
clearonworldguard.bypass.entityinteraction:
default: false
description: Allows a player to interact with mobs in a clear region