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:
parent
487e2682c3
commit
282cc50df6
@ -1,9 +1,15 @@
|
||||
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.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
@ -13,16 +19,21 @@ import java.util.logging.Logger;
|
||||
public final class ClearOnWorldGuard extends JavaPlugin {
|
||||
|
||||
private static ClearOnWorldGuard instance;
|
||||
private boolean debugMode;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
instance = this;
|
||||
this.saveDefaultConfig();
|
||||
this.reloadConfig();
|
||||
FileConfiguration configuration = this.getConfig();
|
||||
FileConfiguration fileConfiguration = this.getConfig();
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -5,3 +5,6 @@ clearRegions:
|
||||
world: [ ]
|
||||
world_nether: [ ]
|
||||
world_the_end: [ ]
|
||||
|
||||
# Whether to enable debug mode, which spams debug messages at log level INFO, rather than log level FINEST
|
||||
debug: false
|
@ -4,3 +4,17 @@ main: net.knarcraft.clearonworldguard.ClearOnWorldGuard
|
||||
api-version: '1.20'
|
||||
description: A custom KnarCraft plugin
|
||||
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
|
Loading…
Reference in New Issue
Block a user