mirror of
https://github.com/EngineHub/WorldGuard.git
synced 2024-12-17 22:57:39 +01:00
Implement Associables to handle non-player region membership checks.
This commit is contained in:
parent
ff3fa759d1
commit
41fb8a0722
@ -20,10 +20,13 @@
|
||||
package com.sk89q.worldguard;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class LocalPlayer {
|
||||
public abstract class LocalPlayer implements RegionAssociable {
|
||||
|
||||
/**
|
||||
* Get this player's name.
|
||||
@ -90,6 +93,17 @@ public abstract class LocalPlayer {
|
||||
*/
|
||||
public abstract boolean hasPermission(String perm);
|
||||
|
||||
@Override
|
||||
public Association getAssociation(ProtectedRegion region) {
|
||||
if (region.isOwner(this)) {
|
||||
return Association.OWNER;
|
||||
} else if (region.isMember(this)) {
|
||||
return Association.MEMBER;
|
||||
} else {
|
||||
return Association.NON_MEMBER;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof LocalPlayer && ((LocalPlayer) obj).getName().equals(getName());
|
||||
|
@ -22,6 +22,7 @@
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.GlobalRegionManager;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
@ -108,26 +109,46 @@ public ApplicableRegionSet getApplicableRegions(Location location) {
|
||||
* @param player the player
|
||||
* @param flags zero or more flags
|
||||
* @return true if permission is granted
|
||||
* @see ApplicableRegionSet#testBuild(LocalPlayer, StateFlag...)
|
||||
* @see ApplicableRegionSet#testBuild(RegionAssociable, StateFlag...)
|
||||
*/
|
||||
public boolean testBuild(Location location, Player player, StateFlag... flags) {
|
||||
checkNotNull(location);
|
||||
checkNotNull(player);
|
||||
checkNotNull(flags);
|
||||
|
||||
World world = location.getWorld();
|
||||
WorldConfiguration worldConfig = config.get(world);
|
||||
|
||||
if (!worldConfig.useRegions) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.hasPermission("worldguard.region.bypass." + world.getName())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
LocalPlayer localPlayer = plugin.wrapPlayer(player);
|
||||
return getApplicableRegions(location).testBuild(localPlayer, flags);
|
||||
return testBuild(location, localPlayer, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the given flags evaluate to {@code ALLOW}, implicitly also
|
||||
* considering the {@link DefaultFlag#BUILD} flag.
|
||||
*
|
||||
* <p>This method is equivalent to calling
|
||||
* {@link #testState(Location, Player, StateFlag...)} with
|
||||
* {@code flags} plus the {@code BUILD} flag.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @param subject the subject
|
||||
* @param flags zero or more flags
|
||||
* @return true if permission is granted
|
||||
* @see ApplicableRegionSet#testBuild(RegionAssociable, StateFlag...)
|
||||
*/
|
||||
public boolean testBuild(Location location, RegionAssociable subject, StateFlag... flags) {
|
||||
checkNotNull(location);
|
||||
checkNotNull(subject);
|
||||
checkNotNull(flags);
|
||||
|
||||
World world = location.getWorld();
|
||||
WorldConfiguration worldConfig = config.get(world);
|
||||
|
||||
return !worldConfig.useRegions || getApplicableRegions(location).testBuild(subject, flags);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,7 +165,7 @@ public boolean testBuild(Location location, Player player, StateFlag... flags) {
|
||||
* @param player an optional player, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @return true if the result was {@code ALLOW}
|
||||
* @see ApplicableRegionSet#queryValue(LocalPlayer, Flag)
|
||||
* @see ApplicableRegionSet#queryValue(RegionAssociable, Flag)
|
||||
*/
|
||||
public boolean testState(Location location, @Nullable Player player, StateFlag... flag) {
|
||||
return StateFlag.test(queryState(location, player, flag));
|
||||
@ -165,7 +186,7 @@ public boolean testState(Location location, @Nullable Player player, StateFlag..
|
||||
* @param player an optional player, which would be used to determine the region groups that apply
|
||||
* @param flags a list of flags to check
|
||||
* @return a state
|
||||
* @see ApplicableRegionSet#queryState(LocalPlayer, StateFlag...)
|
||||
* @see ApplicableRegionSet#queryState(RegionAssociable, StateFlag...)
|
||||
*/
|
||||
@Nullable
|
||||
public State queryState(Location location, @Nullable Player player, StateFlag... flags) {
|
||||
@ -195,7 +216,7 @@ public State queryState(Location location, @Nullable Player player, StateFlag...
|
||||
* @param player an optional player, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @return a value, which could be {@code null}
|
||||
* @see ApplicableRegionSet#queryValue(LocalPlayer, Flag)
|
||||
* @see ApplicableRegionSet#queryValue(RegionAssociable, Flag)
|
||||
*/
|
||||
@Nullable
|
||||
public <V> V queryValue(Location location, @Nullable Player player, Flag<V> flag) {
|
||||
@ -218,7 +239,7 @@ public <V> V queryValue(Location location, @Nullable Player player, Flag<V> flag
|
||||
* @param player an optional player, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @return a collection of values
|
||||
* @see ApplicableRegionSet#queryAllValues(LocalPlayer, Flag)
|
||||
* @see ApplicableRegionSet#queryAllValues(RegionAssociable, Flag)
|
||||
*/
|
||||
public <V> Collection<V> queryAllValues(Location location, @Nullable Player player, Flag<V> flag) {
|
||||
LocalPlayer localPlayer = player != null ? plugin.wrapPlayer(player) : null;
|
||||
|
@ -71,6 +71,15 @@ public boolean isKnown() {
|
||||
return !causes.isEmpty();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object getRootCause() {
|
||||
if (!causes.isEmpty()) {
|
||||
return causes.get(0);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Player getPlayerRootCause() {
|
||||
for (Object object : causes) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.listener;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.cause.Cause;
|
||||
import com.sk89q.worldguard.bukkit.event.block.BreakBlockEvent;
|
||||
@ -28,6 +29,7 @@
|
||||
import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent;
|
||||
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
|
||||
import com.sk89q.worldguard.bukkit.event.inventory.UseItemEvent;
|
||||
import com.sk89q.worldguard.bukkit.util.BlockStateAsBlockFunction;
|
||||
import com.sk89q.worldguard.bukkit.util.Blocks;
|
||||
import com.sk89q.worldguard.bukkit.util.Events;
|
||||
import com.sk89q.worldguard.bukkit.util.Materials;
|
||||
@ -40,6 +42,7 @@
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.FallingBlock;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.ThrownPotion;
|
||||
@ -84,11 +87,14 @@
|
||||
import org.bukkit.event.player.PlayerUnleashEntityEvent;
|
||||
import org.bukkit.event.vehicle.VehicleDamageEvent;
|
||||
import org.bukkit.event.vehicle.VehicleDestroyEvent;
|
||||
import org.bukkit.event.world.StructureGrowEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.Dispenser;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
import static com.sk89q.worldguard.bukkit.cause.Cause.create;
|
||||
import static com.sk89q.worldguard.bukkit.util.Materials.isBlockModifiedOnClick;
|
||||
@ -138,6 +144,12 @@ public void onBlockBurn(BlockBurnEvent event) {
|
||||
Events.fireToCancel(event, new UseBlockEvent(event, Cause.unknown(), event.getBlock()));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onStructureGrowEvent(StructureGrowEvent event) {
|
||||
List<Block> blockList = Lists.transform(event.getBlocks(), new BlockStateAsBlockFunction());
|
||||
Events.fireBulkEventToCancel(event, new PlaceBlockEvent(event, create(event.getPlayer()), event.getLocation().getWorld(), blockList, Material.AIR));
|
||||
}
|
||||
|
||||
// TODO: Handle EntityCreatePortalEvent?
|
||||
|
||||
@EventHandler
|
||||
@ -162,9 +174,20 @@ public void onEntityChangeBlock(EntityChangeBlockEvent event) {
|
||||
Events.fireToCancel(event, new BreakBlockEvent(event, create(entity), event.getBlock()));
|
||||
}
|
||||
} else {
|
||||
boolean wasCancelled = event.isCancelled();
|
||||
Cause cause = create(entity);
|
||||
|
||||
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, event.getBlock().getLocation(), to));
|
||||
|
||||
if (event.isCancelled() && !wasCancelled && entity instanceof FallingBlock) {
|
||||
FallingBlock fallingBlock = (FallingBlock) entity;
|
||||
ItemStack itemStack = new ItemStack(fallingBlock.getMaterial(), 1, fallingBlock.getBlockData());
|
||||
Item item = block.getWorld().dropItem(fallingBlock.getLocation(), itemStack);
|
||||
item.setVelocity(new Vector());
|
||||
if (Events.fireAndTestCancel(new SpawnEntityEvent(event, create(block, entity), item))) {
|
||||
item.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -331,23 +354,21 @@ public void onPlayerBucketFill(PlayerBucketFillEvent event) {
|
||||
|
||||
@EventHandler
|
||||
public void onBlockFromTo(BlockFromToEvent event) {
|
||||
if (ABSTRACT_FROM_TO_EVENTS) {
|
||||
Block from = event.getBlock();
|
||||
Block to = event.getToBlock();
|
||||
Block from = event.getBlock();
|
||||
Block to = event.getToBlock();
|
||||
|
||||
// Liquids pass this event when flowing to solid blocks
|
||||
if (to.getType().isSolid() && Materials.isLiquid(from.getType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cause cause = create(from);
|
||||
|
||||
if (from.getType() != Material.AIR) {
|
||||
Events.fireToCancel(event, new BreakBlockEvent(event, cause, to));
|
||||
}
|
||||
|
||||
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, to.getLocation(), from.getType()));
|
||||
// Liquids pass this event when flowing to solid blocks
|
||||
if (to.getType().isSolid() && Materials.isLiquid(from.getType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cause cause = create(from);
|
||||
|
||||
if (from.getType() != Material.AIR) {
|
||||
Events.fireToCancel(event, new BreakBlockEvent(event, cause, to));
|
||||
}
|
||||
|
||||
Events.fireToCancel(event, new PlaceBlockEvent(event, cause, to.getLocation(), from.getType()));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
|
@ -33,12 +33,17 @@
|
||||
import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent;
|
||||
import com.sk89q.worldguard.bukkit.util.Entities;
|
||||
import com.sk89q.worldguard.bukkit.util.Materials;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.ApplicableRegionSet;
|
||||
import com.sk89q.worldguard.protection.association.Associables;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.association.RegionOverlapAssociation;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Creeper;
|
||||
import org.bukkit.entity.EnderDragon;
|
||||
import org.bukkit.entity.Entity;
|
||||
@ -65,11 +70,15 @@ public RegionProtectionListener(WorldGuardPlugin plugin) {
|
||||
/**
|
||||
* Tell a sender that s/he cannot do something 'here'.
|
||||
*
|
||||
* @param sender the sender
|
||||
* @param cause the cause
|
||||
* @param subject the subject that the sender was blocked from touching
|
||||
*/
|
||||
private void tellErrorMessage(CommandSender sender, Object subject) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + "Sorry, but you are not allowed to do that here.");
|
||||
private void tellErrorMessage(Cause cause, Object subject) {
|
||||
Object rootCause = cause.getRootCause();
|
||||
|
||||
if (rootCause instanceof Player) {
|
||||
((Player) rootCause).sendMessage(ChatColor.DARK_RED + "Sorry, but you are not allowed to do that here.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,6 +107,24 @@ public boolean apply(@Nullable Location location) {
|
||||
};
|
||||
}
|
||||
|
||||
private RegionAssociable createRegionAssociable(Cause cause) {
|
||||
Object rootCause = cause.getRootCause();
|
||||
|
||||
if (rootCause instanceof Player) {
|
||||
return getPlugin().wrapPlayer((Player) rootCause);
|
||||
} else if (rootCause instanceof Entity) {
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
ApplicableRegionSet source = query.getApplicableRegions(((Entity) rootCause).getLocation());
|
||||
return new RegionOverlapAssociation(source.getRegions());
|
||||
} else if (rootCause instanceof Block) {
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
ApplicableRegionSet source = query.getApplicableRegions(((Block) rootCause).getLocation());
|
||||
return new RegionOverlapAssociation(source.getRegions());
|
||||
} else {
|
||||
return Associables.constant(Association.NON_MEMBER);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPlaceBlock(final PlaceBlockEvent event) {
|
||||
if (isWhitelisted(event.getCause())) {
|
||||
@ -105,36 +132,30 @@ public void onPlaceBlock(final PlaceBlockEvent event) {
|
||||
}
|
||||
|
||||
final Material type = event.getEffectiveMaterial();
|
||||
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
final RegionAssociable associable = createRegionAssociable(event.getCause());
|
||||
|
||||
final Player player;
|
||||
event.filterBlocks(new Predicate<Location>() {
|
||||
@Override
|
||||
public boolean apply(Location target) {
|
||||
boolean canPlace;
|
||||
|
||||
if ((player = event.getCause().getPlayerRootCause()) != null) {
|
||||
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
// Flint and steel, fire charge
|
||||
if (type == Material.FIRE) {
|
||||
canPlace = query.testBuild(target, associable, DefaultFlag.LIGHTER);
|
||||
|
||||
event.filterBlocks(new Predicate<Location>() {
|
||||
@Override
|
||||
public boolean apply(Location target) {
|
||||
boolean canPlace;
|
||||
|
||||
// Flint and steel, fire charge
|
||||
if (type == Material.FIRE) {
|
||||
canPlace = query.testBuild(target, player, DefaultFlag.LIGHTER);
|
||||
|
||||
} else {
|
||||
canPlace = query.testBuild(target, player);
|
||||
}
|
||||
|
||||
if (!canPlace) {
|
||||
tellErrorMessage(player, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
canPlace = query.testBuild(target, associable);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (!canPlace) {
|
||||
tellErrorMessage(event.getCause(), target);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
@ -143,37 +164,13 @@ public void onBreakBlock(final BreakBlockEvent event) {
|
||||
return; // Whitelisted cause
|
||||
}
|
||||
|
||||
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
ConfigurationManager globalConfig = getPlugin().getGlobalStateManager();
|
||||
WorldConfiguration config = globalConfig.get(event.getWorld());
|
||||
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
|
||||
final Player player;
|
||||
final Entity entity;
|
||||
|
||||
// ====================================================================
|
||||
// Player caused
|
||||
// ====================================================================
|
||||
|
||||
if ((player = event.getCause().getPlayerRootCause()) != null) {
|
||||
event.filterBlocks(new Predicate<Location>() {
|
||||
@Override
|
||||
public boolean apply(Location target) {
|
||||
boolean canBreak = query.testBuild(target, player);
|
||||
|
||||
if (!canBreak) {
|
||||
tellErrorMessage(player, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// ====================================================================
|
||||
// Entity caused
|
||||
// ====================================================================
|
||||
|
||||
} else if ((entity = event.getCause().getEntityRootCause()) != null) {
|
||||
// TODO: Move this to another event handler
|
||||
Entity entity;
|
||||
if ((entity = event.getCause().getEntityRootCause()) != null) {
|
||||
// Creeper
|
||||
if (entity instanceof Creeper) {
|
||||
event.filterBlocks(createStateTest(query, DefaultFlag.CREEPER_EXPLOSION), config.explosionFlagCancellation);
|
||||
@ -187,8 +184,24 @@ public boolean apply(Location target) {
|
||||
event.filterBlocks(createStateTest(query, DefaultFlag.TNT), config.explosionFlagCancellation);
|
||||
|
||||
}
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
final RegionAssociable associable = createRegionAssociable(event.getCause());
|
||||
|
||||
event.filterBlocks(new Predicate<Location>() {
|
||||
@Override
|
||||
public boolean apply(Location target) {
|
||||
boolean canBreak = query.testBuild(target, associable);
|
||||
|
||||
if (!canBreak) {
|
||||
tellErrorMessage(event.getCause(), target);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,45 +212,39 @@ public void onUseBlock(final UseBlockEvent event) {
|
||||
}
|
||||
|
||||
final Material type = event.getEffectiveMaterial();
|
||||
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
final RegionAssociable associable = createRegionAssociable(event.getCause());
|
||||
|
||||
final Player player;
|
||||
event.filterBlocks(new Predicate<Location>() {
|
||||
@Override
|
||||
public boolean apply(Location target) {
|
||||
boolean canUse;
|
||||
|
||||
if ((player = event.getCause().getPlayerRootCause()) != null) {
|
||||
final RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
// Inventory blocks (CHEST_ACCESS)
|
||||
if (Materials.isInventoryBlock(type)) {
|
||||
canUse = query.testBuild(target, associable, DefaultFlag.USE, DefaultFlag.CHEST_ACCESS);
|
||||
|
||||
event.filterBlocks(new Predicate<Location>() {
|
||||
@Override
|
||||
public boolean apply(Location target) {
|
||||
boolean canUse;
|
||||
// Beds (SLEEP)
|
||||
} else if (type == Material.BED) {
|
||||
canUse = query.testBuild(target, associable, DefaultFlag.USE, DefaultFlag.SLEEP);
|
||||
|
||||
// Inventory blocks (CHEST_ACCESS)
|
||||
if (Materials.isInventoryBlock(type)) {
|
||||
canUse = query.testBuild(target, player, DefaultFlag.USE, DefaultFlag.CHEST_ACCESS);
|
||||
// TNT (TNT)
|
||||
} else if (type == Material.TNT) {
|
||||
canUse = query.testBuild(target, associable, DefaultFlag.TNT);
|
||||
|
||||
// Beds (SLEEP)
|
||||
} else if (type == Material.BED) {
|
||||
canUse = query.testBuild(target, player, DefaultFlag.USE, DefaultFlag.SLEEP);
|
||||
|
||||
// TNT (TNT)
|
||||
} else if (type == Material.TNT) {
|
||||
canUse = query.testBuild(target, player, DefaultFlag.TNT);
|
||||
|
||||
// Everything else
|
||||
} else {
|
||||
canUse = query.testBuild(target, player, DefaultFlag.USE);
|
||||
}
|
||||
|
||||
if (!canUse) {
|
||||
tellErrorMessage(player, target);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Everything else
|
||||
} else {
|
||||
canUse = query.testBuild(target, associable, DefaultFlag.USE);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
if (!canUse) {
|
||||
tellErrorMessage(event.getCause(), target);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
@ -249,23 +256,19 @@ public void onSpawnEntity(SpawnEntityEvent event) {
|
||||
Location target = event.getTarget();
|
||||
EntityType type = event.getEffectiveType();
|
||||
|
||||
Player player;
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
RegionAssociable associable = createRegionAssociable(event.getCause());
|
||||
|
||||
if ((player = event.getCause().getPlayerRootCause()) != null) {
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
boolean canSpawn;
|
||||
boolean canSpawn;
|
||||
|
||||
if (Entities.isVehicle(type)) {
|
||||
canSpawn = query.testBuild(target, player, DefaultFlag.PLACE_VEHICLE);
|
||||
} else {
|
||||
canSpawn = query.testBuild(target, player);
|
||||
}
|
||||
|
||||
if (!canSpawn) {
|
||||
tellErrorMessage(player, target);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
if (Entities.isVehicle(type)) {
|
||||
canSpawn = query.testBuild(target, associable, DefaultFlag.PLACE_VEHICLE);
|
||||
} else {
|
||||
canSpawn = query.testBuild(target, associable);
|
||||
}
|
||||
|
||||
if (!canSpawn) {
|
||||
tellErrorMessage(event.getCause(), target);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@ -278,24 +281,19 @@ public void onDestroyEntity(DestroyEntityEvent event) {
|
||||
|
||||
Location target = event.getTarget();
|
||||
EntityType type = event.getEntity().getType();
|
||||
RegionAssociable associable = createRegionAssociable(event.getCause());
|
||||
|
||||
Player player;
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
boolean canDestroy;
|
||||
|
||||
if ((player = event.getCause().getPlayerRootCause()) != null) {
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
boolean canDestroy;
|
||||
|
||||
if (Entities.isVehicle(type)) {
|
||||
canDestroy = query.testBuild(target, player, DefaultFlag.DESTROY_VEHICLE);
|
||||
} else {
|
||||
canDestroy = query.testBuild(target, player);
|
||||
}
|
||||
|
||||
if (!canDestroy) {
|
||||
tellErrorMessage(player, target);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
if (Entities.isVehicle(type)) {
|
||||
canDestroy = query.testBuild(target, associable, DefaultFlag.DESTROY_VEHICLE);
|
||||
} else {
|
||||
canDestroy = query.testBuild(target, associable);
|
||||
}
|
||||
|
||||
if (!canDestroy) {
|
||||
tellErrorMessage(event.getCause(), target);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@ -307,18 +305,13 @@ public void onUseEntity(UseEntityEvent event) {
|
||||
}
|
||||
|
||||
Location target = event.getTarget();
|
||||
RegionAssociable associable = createRegionAssociable(event.getCause());
|
||||
|
||||
Player player;
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
boolean canUse = query.testBuild(target, associable, DefaultFlag.USE);
|
||||
|
||||
if ((player = event.getCause().getPlayerRootCause()) != null) {
|
||||
RegionQuery query = getPlugin().getRegionContainer().createQuery();
|
||||
boolean canUse = query.testBuild(target, player, DefaultFlag.USE);
|
||||
|
||||
if (!canUse) {
|
||||
tellErrorMessage(player, target);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
} else {
|
||||
if (!canUse) {
|
||||
tellErrorMessage(event.getCause(), target);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.bukkit.util;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class BlockStateAsBlockFunction implements Function<BlockState, Block> {
|
||||
|
||||
@Override
|
||||
public Block apply(@Nullable BlockState blockState) {
|
||||
return blockState != null ? blockState.getBlock() : null;
|
||||
}
|
||||
|
||||
}
|
31
src/main/java/com/sk89q/worldguard/domains/Association.java
Normal file
31
src/main/java/com/sk89q/worldguard/domains/Association.java
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.domains;
|
||||
|
||||
/**
|
||||
* Indicates the level of membership.
|
||||
*/
|
||||
public enum Association {
|
||||
|
||||
OWNER,
|
||||
MEMBER,
|
||||
NON_MEMBER
|
||||
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.RegionGroup;
|
||||
@ -34,6 +35,7 @@
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
@ -88,11 +90,11 @@ public ApplicableRegionSet(SortedSet<ProtectedRegion> applicable, @Nullable Prot
|
||||
* <p>If there are several relevant flags (i.e. in addition to
|
||||
* {@code BUILD}, such as {@link DefaultFlag#SLEEP} when the target
|
||||
* object is a bed), then
|
||||
* {@link #testBuild(LocalPlayer, StateFlag...)} should be used.</p>
|
||||
* {@link #testBuild(RegionAssociable, StateFlag...)} should be used.</p>
|
||||
*
|
||||
* @param player the player to check
|
||||
* @return true if permitted
|
||||
* @deprecated use {@link #testBuild(LocalPlayer, StateFlag...)}
|
||||
* @deprecated use {@link #testBuild(RegionAssociable, StateFlag...)}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean canBuild(LocalPlayer player) {
|
||||
@ -105,36 +107,36 @@ public boolean canBuild(LocalPlayer player) {
|
||||
* considering the {@link DefaultFlag#BUILD} flag.
|
||||
*
|
||||
* <p>This method is equivalent to calling
|
||||
* {@link #testState(LocalPlayer, StateFlag...)} with {@code flags} plus
|
||||
* {@link #testState(RegionAssociable, StateFlag...)} with {@code flags} plus
|
||||
* the {@code BUILD} flag.</p>
|
||||
*
|
||||
* @param player the player
|
||||
* @param subject the subject
|
||||
* @param flags zero or more flags
|
||||
* @return true if permission is granted
|
||||
* @see #queryState(LocalPlayer, StateFlag...)
|
||||
* @see #queryState(RegionAssociable, StateFlag...)
|
||||
*/
|
||||
public boolean testBuild(LocalPlayer player, StateFlag... flags) {
|
||||
checkNotNull(player);
|
||||
return test(flagValueCalculator.queryState(player, ObjectArrays.concat(flags, DefaultFlag.BUILD)));
|
||||
public boolean testBuild(RegionAssociable subject, StateFlag... flags) {
|
||||
checkNotNull(subject);
|
||||
return test(flagValueCalculator.queryState(subject, ObjectArrays.concat(flags, DefaultFlag.BUILD)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the (effective) value for a list of state flags equals
|
||||
* {@code ALLOW}.
|
||||
*
|
||||
* <p>{@code player} can be non-null to satisfy region group requirements,
|
||||
* <p>{@code subject} can be non-null to satisfy region group requirements,
|
||||
* otherwise it will be assumed that the caller that is not a member of any
|
||||
* regions. (Flags on a region can be changed so that they only apply
|
||||
* to certain users.) The player argument is required if the
|
||||
* to certain users.) The subject argument is required if the
|
||||
* {@link DefaultFlag#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* @param player an optional player, which would be used to determine the region groups that apply
|
||||
* @param subject an optional subject, which would be used to determine the region groups that apply
|
||||
* @param flags a list of flags to check
|
||||
* @return true if the result was {@code ALLOW}
|
||||
* @see #queryState(LocalPlayer, StateFlag...)
|
||||
* @see #queryState(RegionAssociable, StateFlag...)
|
||||
*/
|
||||
public boolean testState(@Nullable LocalPlayer player, StateFlag... flags) {
|
||||
return test(flagValueCalculator.queryState(player, flags));
|
||||
public boolean testState(@Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
return test(flagValueCalculator.queryState(subject, flags));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,19 +144,19 @@ public boolean testState(@Nullable LocalPlayer player, StateFlag... flags) {
|
||||
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
|
||||
* and {@code ALLOW} overrides {@code NONE}. One flag may override another.
|
||||
*
|
||||
* <p>{@code player} can be non-null to satisfy region group requirements,
|
||||
* <p>{@code subject} can be non-null to satisfy region group requirements,
|
||||
* otherwise it will be assumed that the caller that is not a member of any
|
||||
* regions. (Flags on a region can be changed so that they only apply
|
||||
* to certain users.) The player argument is required if the
|
||||
* to certain users.) The subject argument is required if the
|
||||
* {@link DefaultFlag#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* @param player an optional player, which would be used to determine the region groups that apply
|
||||
* @param subject an optional subject, which would be used to determine the region groups that apply
|
||||
* @param flags a list of flags to check
|
||||
* @return a state
|
||||
*/
|
||||
@Nullable
|
||||
public State queryState(@Nullable LocalPlayer player, StateFlag... flags) {
|
||||
return flagValueCalculator.queryState(player, flags);
|
||||
public State queryState(@Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
return flagValueCalculator.queryState(subject, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,19 +171,19 @@ public State queryState(@Nullable LocalPlayer player, StateFlag... flags) {
|
||||
* type of flag that actually has a strategy for picking a value is the
|
||||
* {@link StateFlag}.</p>
|
||||
*
|
||||
* <p>{@code player} can be non-null to satisfy region group requirements,
|
||||
* <p>{@code subject} can be non-null to satisfy region group requirements,
|
||||
* otherwise it will be assumed that the caller that is not a member of any
|
||||
* regions. (Flags on a region can be changed so that they only apply
|
||||
* to certain users.) The player argument is required if the
|
||||
* to certain users.) The subject argument is required if the
|
||||
* {@link DefaultFlag#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @param player an optional player, which would be used to determine the region group to apply
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @return a value, which could be {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
public <V> V queryValue(@Nullable LocalPlayer player, Flag<V> flag) {
|
||||
return flagValueCalculator.queryValue(player, flag);
|
||||
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
return flagValueCalculator.queryValue(subject, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,18 +191,18 @@ public <V> V queryValue(@Nullable LocalPlayer player, Flag<V> flag) {
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
*
|
||||
* <p>{@code player} can be non-null to satisfy region group requirements,
|
||||
* <p>{@code subject} can be non-null to satisfy region group requirements,
|
||||
* otherwise it will be assumed that the caller that is not a member of any
|
||||
* regions. (Flags on a region can be changed so that they only apply
|
||||
* to certain users.) The player argument is required if the
|
||||
* to certain users.) The subject argument is required if the
|
||||
* {@link DefaultFlag#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @param player an optional player, which would be used to determine the region group to apply
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @return a collection of values
|
||||
*/
|
||||
public <V> Collection<V> queryAllValues(@Nullable LocalPlayer player, Flag<V> flag) {
|
||||
return flagValueCalculator.queryAllValues(player, flag);
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
return flagValueCalculator.queryAllValues(subject, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,7 +226,7 @@ public boolean canConstruct(LocalPlayer player) {
|
||||
* @param flag flag to check
|
||||
* @return whether it is allowed
|
||||
* @throws IllegalArgumentException if the build flag is given
|
||||
* @deprecated use {@link #queryState(LocalPlayer, StateFlag...)} instead
|
||||
* @deprecated use {@link #queryState(RegionAssociable, StateFlag...)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean allows(StateFlag flag) {
|
||||
@ -244,7 +246,7 @@ public boolean allows(StateFlag flag) {
|
||||
* @param player player (used by some flags)
|
||||
* @return whether the state is allows for it
|
||||
* @throws IllegalArgumentException if the build flag is given
|
||||
* @deprecated use {@link #queryState(LocalPlayer, StateFlag...)} instead
|
||||
* @deprecated use {@link #queryState(RegionAssociable, StateFlag...)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean allows(StateFlag flag, @Nullable LocalPlayer player) {
|
||||
@ -299,7 +301,7 @@ public boolean isMemberOfAll(LocalPlayer player) {
|
||||
*
|
||||
* @param flag the flag to check
|
||||
* @return value of the flag, which may be null
|
||||
* @deprecated Use {@link #queryValue(LocalPlayer, Flag)} instead. There
|
||||
* @deprecated Use {@link #queryValue(RegionAssociable, Flag)} instead. There
|
||||
* is no difference in functionality.
|
||||
*/
|
||||
@Deprecated
|
||||
@ -316,7 +318,7 @@ public <T extends Flag<V>, V> V getFlag(T flag) {
|
||||
* @param groupPlayer player to check {@link RegionGroup}s against
|
||||
* @return value of the flag, which may be null
|
||||
* @throws IllegalArgumentException if a StateFlag is given
|
||||
* @deprecated Use {@link #queryValue(LocalPlayer, Flag)} instead. There
|
||||
* @deprecated Use {@link #queryValue(RegionAssociable, Flag)} instead. There
|
||||
* is no difference in functionality.
|
||||
*/
|
||||
@Deprecated
|
||||
@ -334,6 +336,15 @@ public int size() {
|
||||
return applicable.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an immutable set of regions that are included in this set.
|
||||
*
|
||||
* @return a set of regions
|
||||
*/
|
||||
public Set<ProtectedRegion> getRegions() {
|
||||
return Collections.unmodifiableSet(applicable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ProtectedRegion> iterator() {
|
||||
return applicable.iterator();
|
||||
|
@ -21,11 +21,11 @@
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.DefaultFlag;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.RegionGroup;
|
||||
import com.sk89q.worldguard.protection.flags.RegionGroupFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
@ -84,9 +84,9 @@ private Iterable<ProtectedRegion> getApplicable() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the membership status of the given player, indicating
|
||||
* Return the membership status of the given subject, indicating
|
||||
* whether there are no (counted) regions in the list of regions,
|
||||
* whether the player is a member of all regions, or whether
|
||||
* whether the subject is a member of all regions, or whether
|
||||
* the region is not a member of all regions.
|
||||
*
|
||||
* <p>A region is "counted" if it doesn't have the
|
||||
@ -97,20 +97,20 @@ private Iterable<ProtectedRegion> getApplicable() {
|
||||
* <p>This method is mostly for internal use. It's not particularly
|
||||
* useful.</p>
|
||||
*
|
||||
* @param player the player
|
||||
* @param subject the subject
|
||||
* @return the membership result
|
||||
*/
|
||||
public Result getMembership(LocalPlayer player) {
|
||||
checkNotNull(player);
|
||||
public Result getMembership(RegionAssociable subject) {
|
||||
checkNotNull(subject);
|
||||
|
||||
int minimumPriority = Integer.MIN_VALUE;
|
||||
boolean foundApplicableRegion = false;
|
||||
|
||||
// Say there are two regions in one location: CHILD and PARENT (CHILD
|
||||
// is a child of PARENT). If there are two overlapping regions in WG, a
|
||||
// player has to be a member of /both/ (or flags permit) in order to
|
||||
// subject has to be a member of /both/ (or flags permit) in order to
|
||||
// build in that location. However, inheritance is supposed
|
||||
// to allow building if the player is a member of just CHILD. That
|
||||
// to allow building if the subject is a member of just CHILD. That
|
||||
// presents a problem.
|
||||
//
|
||||
// To rectify this, we keep two sets. When we iterate over the list of
|
||||
@ -145,7 +145,7 @@ public Result getMembership(LocalPlayer player) {
|
||||
}
|
||||
|
||||
// If PASSTHROUGH is set, ignore this region
|
||||
if (getEffectiveFlag(region, DefaultFlag.PASSTHROUGH, player) == State.ALLOW) {
|
||||
if (getEffectiveFlag(region, DefaultFlag.PASSTHROUGH, subject) == State.ALLOW) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ public Result getMembership(LocalPlayer player) {
|
||||
foundApplicableRegion = true;
|
||||
|
||||
if (!hasCleared.contains(region)) {
|
||||
if (!region.isMember(player)) {
|
||||
if (!RegionGroup.MEMBERS.contains(subject.getAssociation(region))) {
|
||||
needsClear.add(region);
|
||||
} else {
|
||||
// Need to clear all parents
|
||||
@ -175,24 +175,24 @@ public Result getMembership(LocalPlayer player) {
|
||||
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
|
||||
* and {@code ALLOW} overrides {@code NONE}.
|
||||
*
|
||||
* <p>A player can be provided that is used to determine whether the value
|
||||
* <p>A subject can be provided that is used to determine whether the value
|
||||
* of a flag on a particular region should be used. For example, if a
|
||||
* flag's region group is set to {@link RegionGroup#MEMBERS} and the given
|
||||
* player is not a member, then the region would be skipped when
|
||||
* querying that flag. If {@code null} is provided for the player, then
|
||||
* subject is not a member, then the region would be skipped when
|
||||
* querying that flag. If {@code null} is provided for the subject, then
|
||||
* only flags that use {@link RegionGroup#ALL},
|
||||
* {@link RegionGroup#NON_MEMBERS}, etc. will apply.</p>
|
||||
*
|
||||
* @param player an optional player, which would be used to determine the region group to apply
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flags a list of flags to check
|
||||
* @return a state
|
||||
*/
|
||||
@Nullable
|
||||
public State queryState(@Nullable LocalPlayer player, StateFlag... flags) {
|
||||
public State queryState(@Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
State value = null;
|
||||
|
||||
for (StateFlag flag : flags) {
|
||||
value = StateFlag.combine(value, queryValue(player, flag));
|
||||
value = StateFlag.combine(value, queryValue(subject, flag));
|
||||
if (value == State.DENY) {
|
||||
break;
|
||||
}
|
||||
@ -214,21 +214,21 @@ public State queryState(@Nullable LocalPlayer player, StateFlag... flags) {
|
||||
* type of flag that can consistently return the same 'best' value is
|
||||
* {@link StateFlag}.</p>
|
||||
*
|
||||
* <p>A player can be provided that is used to determine whether the value
|
||||
* <p>A subject can be provided that is used to determine whether the value
|
||||
* of a flag on a particular region should be used. For example, if a
|
||||
* flag's region group is set to {@link RegionGroup#MEMBERS} and the given
|
||||
* player is not a member, then the region would be skipped when
|
||||
* querying that flag. If {@code null} is provided for the player, then
|
||||
* subject is not a member, then the region would be skipped when
|
||||
* querying that flag. If {@code null} is provided for the subject, then
|
||||
* only flags that use {@link RegionGroup#ALL},
|
||||
* {@link RegionGroup#NON_MEMBERS}, etc. will apply.</p>
|
||||
*
|
||||
* @param player an optional player, which would be used to determine the region group to apply
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @return a value, which could be {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
public <V> V queryValue(@Nullable LocalPlayer player, Flag<V> flag) {
|
||||
Collection<V> values = queryAllValues(player, flag);
|
||||
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
Collection<V> values = queryAllValues(subject, flag);
|
||||
return flag.chooseValue(values);
|
||||
}
|
||||
|
||||
@ -237,20 +237,20 @@ public <V> V queryValue(@Nullable LocalPlayer player, Flag<V> flag) {
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
*
|
||||
* <p>A player can be provided that is used to determine whether the value
|
||||
* <p>A subject can be provided that is used to determine whether the value
|
||||
* of a flag on a particular region should be used. For example, if a
|
||||
* flag's region group is set to {@link RegionGroup#MEMBERS} and the given
|
||||
* player is not a member, then the region would be skipped when
|
||||
* querying that flag. If {@code null} is provided for the player, then
|
||||
* subject is not a member, then the region would be skipped when
|
||||
* querying that flag. If {@code null} is provided for the subject, then
|
||||
* only flags that use {@link RegionGroup#ALL},
|
||||
* {@link RegionGroup#NON_MEMBERS}, etc. will apply.</p>
|
||||
*
|
||||
* @param player an optional player, which would be used to determine the region group to apply
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @return a collection of values
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V> Collection<V> queryAllValues(@Nullable LocalPlayer player, Flag<V> flag) {
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
checkNotNull(flag);
|
||||
|
||||
int minimumPriority = Integer.MIN_VALUE;
|
||||
@ -295,7 +295,7 @@ public <V> Collection<V> queryAllValues(@Nullable LocalPlayer player, Flag<V> fl
|
||||
break;
|
||||
}
|
||||
|
||||
V value = getEffectiveFlag(region, flag, player);
|
||||
V value = getEffectiveFlag(region, flag, subject);
|
||||
|
||||
if (value != null) {
|
||||
if (!ignoredRegions.contains(region)) {
|
||||
@ -314,11 +314,11 @@ public <V> Collection<V> queryAllValues(@Nullable LocalPlayer player, Flag<V> fl
|
||||
}
|
||||
|
||||
if (flag == DefaultFlag.BUILD && consideredValues.isEmpty()) {
|
||||
if (player == null) {
|
||||
throw new NullPointerException("The BUILD flag is handled in a special fashion and requires a non-null player parameter");
|
||||
if (subject == null) {
|
||||
throw new NullPointerException("The BUILD flag is handled in a special fashion and requires a non-null subject parameter");
|
||||
}
|
||||
|
||||
switch (getMembership(player)) {
|
||||
switch (getMembership(subject)) {
|
||||
case FAIL:
|
||||
return ImmutableList.of();
|
||||
case SUCCESS:
|
||||
@ -359,10 +359,11 @@ public int getPriority(final ProtectedRegion region) {
|
||||
*
|
||||
* @param region the region
|
||||
* @param flag the flag
|
||||
* @param subject an subject object
|
||||
* @return the value
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <V> V getEffectiveFlag(final ProtectedRegion region, Flag<V> flag, @Nullable LocalPlayer player) {
|
||||
public <V> V getEffectiveFlag(final ProtectedRegion region, Flag<V> flag, @Nullable RegionAssociable subject) {
|
||||
if (region == globalRegion) {
|
||||
if (flag == DefaultFlag.PASSTHROUGH) {
|
||||
// Has members/owners -> the global region acts like
|
||||
@ -393,7 +394,9 @@ public <V> V getEffectiveFlag(final ProtectedRegion region, Flag<V> flag, @Nulla
|
||||
group = flag.getRegionGroupFlag().getDefault();
|
||||
}
|
||||
|
||||
if (!RegionGroupFlag.isMember(region, group, player)) {
|
||||
if (subject == null) {
|
||||
use = group.contains(Association.NON_MEMBER);
|
||||
} else if (!group.contains(subject.getAssociation(region))) {
|
||||
use = false;
|
||||
}
|
||||
}
|
||||
@ -448,7 +451,7 @@ private void ignoreValuesOfParents(Map<ProtectedRegion, ?> needsClear, Set<Prote
|
||||
|
||||
/**
|
||||
* Describes the membership result from
|
||||
* {@link #getMembership(LocalPlayer)}.
|
||||
* {@link #getMembership(RegionAssociable)}.
|
||||
*/
|
||||
public static enum Result {
|
||||
/**
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.association;
|
||||
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Utility methods to deal with associables.
|
||||
*/
|
||||
public final class Associables {
|
||||
|
||||
private static final RegionAssociable OWNER_ASSOCIABLE = new ConstantAssociation(Association.OWNER);
|
||||
private static final RegionAssociable MEMBER_ASSOCIABLE = new ConstantAssociation(Association.MEMBER);
|
||||
private static final RegionAssociable NON_MEMBER_ASSOCIABLE = new ConstantAssociation(Association.NON_MEMBER);
|
||||
|
||||
private Associables() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an instance that always returns the same association.
|
||||
*
|
||||
* @param association the association
|
||||
* @return the instance
|
||||
*/
|
||||
public static RegionAssociable constant(Association association) {
|
||||
checkNotNull(association);
|
||||
switch (association) {
|
||||
case OWNER:
|
||||
return OWNER_ASSOCIABLE;
|
||||
case MEMBER:
|
||||
return MEMBER_ASSOCIABLE;
|
||||
case NON_MEMBER:
|
||||
return NON_MEMBER_ASSOCIABLE;
|
||||
default:
|
||||
return new ConstantAssociation(association);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.association;
|
||||
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
class ConstantAssociation implements RegionAssociable {
|
||||
|
||||
private final Association association;
|
||||
|
||||
ConstantAssociation(Association association) {
|
||||
this.association = association;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Association getAssociation(ProtectedRegion region) {
|
||||
return association;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.association;
|
||||
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
/**
|
||||
* An object that can have membership in a region.
|
||||
*/
|
||||
public interface RegionAssociable {
|
||||
|
||||
/**
|
||||
* Get the most specific association level for the input region.
|
||||
*
|
||||
* @param region the input region
|
||||
* @return the most specific membership level
|
||||
*/
|
||||
Association getAssociation(ProtectedRegion region);
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.protection.association;
|
||||
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Determines that the association to a region is {@code OWNER} if the input
|
||||
* region is in a set of source regions.
|
||||
*/
|
||||
public class RegionOverlapAssociation implements RegionAssociable {
|
||||
|
||||
private final Set<ProtectedRegion> source;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param source set of regions that input regions must be contained within
|
||||
*/
|
||||
public RegionOverlapAssociation(Set<ProtectedRegion> source) {
|
||||
checkNotNull(source);
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Association getAssociation(ProtectedRegion region) {
|
||||
if (source.contains(region)) {
|
||||
return Association.OWNER;
|
||||
} else {
|
||||
return Association.NON_MEMBER;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -19,14 +19,40 @@
|
||||
|
||||
package com.sk89q.worldguard.protection.flags;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A grouping of region membership types
|
||||
* A grouping of region membership types.
|
||||
*/
|
||||
public enum RegionGroup {
|
||||
MEMBERS,
|
||||
OWNERS,
|
||||
NON_MEMBERS,
|
||||
NON_OWNERS,
|
||||
ALL,
|
||||
NONE
|
||||
|
||||
MEMBERS(Association.MEMBER, Association.OWNER),
|
||||
OWNERS(Association.OWNER),
|
||||
NON_MEMBERS(Association.NON_MEMBER),
|
||||
NON_OWNERS(Association.MEMBER, Association.NON_MEMBER),
|
||||
ALL(Association.OWNER, Association.MEMBER, Association.NON_MEMBER),
|
||||
NONE();
|
||||
|
||||
private final Set<Association> contained;
|
||||
|
||||
RegionGroup(Association... association) {
|
||||
this.contained = ImmutableSet.copyOf(association);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether this group contains the given membership status.
|
||||
*
|
||||
* @param association membership status
|
||||
* @return true if contained
|
||||
*/
|
||||
public boolean contains(Association association) {
|
||||
checkNotNull(association);
|
||||
return contained.contains(association);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user