From d07e81288a8e78cc36c66c519daf123c745d3459 Mon Sep 17 00:00:00 2001 From: sk89q Date: Fri, 15 Aug 2014 14:16:05 -0700 Subject: [PATCH] Make the state flag test use a Predicate for membership testing. --- .../protection/ApplicableRegionSet.java | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/sk89q/worldguard/protection/ApplicableRegionSet.java b/src/main/java/com/sk89q/worldguard/protection/ApplicableRegionSet.java index 650e59ba..45efba92 100644 --- a/src/main/java/com/sk89q/worldguard/protection/ApplicableRegionSet.java +++ b/src/main/java/com/sk89q/worldguard/protection/ApplicableRegionSet.java @@ -19,13 +19,14 @@ package com.sk89q.worldguard.protection; +import com.google.common.base.Predicate; import com.sk89q.worldguard.LocalPlayer; 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.flags.StateFlag.*; import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedRegion; @@ -93,7 +94,7 @@ public ApplicableRegionSet(SortedSet applicable, @Nullable Prot */ public boolean canBuild(LocalPlayer player) { checkNotNull(player); - return test(calculateState(DefaultFlag.BUILD, player, null)); + return test(calculateState(DefaultFlag.BUILD, new RegionMemberTest(player), null)); } /** @@ -184,13 +185,24 @@ public boolean isMemberOfAll(LocalPlayer player) { * value of a flag {@link StateFlag#getDefault()}. * * @param flag the flag to check - * @param player the player, or null to not check owners and members + * @param membershipTest null to perform a "wilderness check" or a predicate + * returns true if a the subject is a member of the + * region passed * @param groupPlayer a player to use for the group flag check * @return the allow/deny state for the flag */ - private State calculateState(StateFlag flag, @Nullable LocalPlayer player, @Nullable LocalPlayer groupPlayer) { + private State calculateState(StateFlag flag, @Nullable Predicate membershipTest, @Nullable LocalPlayer groupPlayer) { checkNotNull(flag); + // This method works in two modes: + // + // 1) Membership mode (if membershipTest != null): + // a) Regions in this set -> Check membership + Check region flags + // a) No regions -> Use global region + default value + // 1) Flag mode: + // a) Regions in this set -> Use global region + default value + // a) No regions -> Use global region + default value + int minimumPriority = Integer.MIN_VALUE; boolean regionsThatCountExistHere = false; // We can't do a application.isEmpty() because // PASSTHROUGH regions have to be skipped @@ -237,7 +249,7 @@ private State calculateState(StateFlag flag, @Nullable LocalPlayer player, @Null // If PASSTHROUGH is set and we are checking to see if a player // is a member, then skip this region - if (player != null && getStateFlagIncludingParents(region, DefaultFlag.PASSTHROUGH) == State.ALLOW) { + if (membershipTest != null && getStateFlagIncludingParents(region, DefaultFlag.PASSTHROUGH) == State.ALLOW) { continue; } @@ -269,11 +281,11 @@ private State calculateState(StateFlag flag, @Nullable LocalPlayer player, @Null minimumPriority = region.getPriority(); } else { - if (player != null) { + if (membershipTest != null) { minimumPriority = region.getPriority(); if (!hasCleared.contains(region)) { - if (!region.isMember(player)) { + if (!membershipTest.apply(region)) { needsClear.add(region); } else { // Need to clear all parents @@ -284,13 +296,13 @@ private State calculateState(StateFlag flag, @Nullable LocalPlayer player, @Null } } - if (player != null) { + if (membershipTest != null) { State fallback; if (regionsThatCountExistHere) { fallback = allowOrNone(needsClear.isEmpty()); } else { - fallback = getDefault(flag, player); + fallback = getDefault(flag, membershipTest); } return combine(state, fallback); @@ -300,7 +312,7 @@ private State calculateState(StateFlag flag, @Nullable LocalPlayer player, @Null } @Nullable - private State getDefault(StateFlag flag, @Nullable LocalPlayer player) { + private State getDefault(StateFlag flag, @Nullable Predicate membershipTest) { boolean allowed = flag.getDefault(); // Handle defaults @@ -310,15 +322,15 @@ private State getDefault(StateFlag flag, @Nullable LocalPlayer player) { // The global region has this flag set if (globalState != null) { // Build flag is very special - if (player != null && globalRegion.hasMembersOrOwners()) { - allowed = globalRegion.isMember(player) && (globalState == State.ALLOW); + if (membershipTest != null && globalRegion.hasMembersOrOwners()) { + allowed = membershipTest.apply(globalRegion) && (globalState == State.ALLOW); } else { allowed = (globalState == State.ALLOW); } } else { // Build flag is very special - if (player != null && globalRegion.hasMembersOrOwners()) { - allowed = globalRegion.isMember(player); + if (membershipTest != null && globalRegion.hasMembersOrOwners()) { + allowed = membershipTest.apply(globalRegion); } } } @@ -487,4 +499,20 @@ public static ApplicableRegionSet getEmpty() { return EMPTY; } + /** + * Returns true if a player is a member (or owner) of a region. + */ + private static class RegionMemberTest implements Predicate { + private final LocalPlayer player; + + private RegionMemberTest(LocalPlayer player) { + this.player = checkNotNull(player); + } + + @Override + public boolean apply(ProtectedRegion region) { + return region.isMember(player); + } + } + }