Flag Calculation¶
To check flags, an instance of ApplicableRegionSet (which contains a list of regions) must have been retrieved. That is documented in Spatial Queries.
Querying Flags¶
One issue with query flags given a list of regions is that there may be several regions with the same flag assigned (and with different values). If priorities and child inheritance are properly configured, then there might only be one “effective” value, but otherwise there will be several.
Getting All Values¶
queryAllValues(RegionAssociable, Flag) can be used to get all the values that have been set for a flag. Flags can be obtained from Flags.
Getting One Value¶
queryValue(RegionAssociable, Flag) can be used to get one value. Depending on the flag type, this may be the first value found, or it may be a “best” value. As of writing, only StateFlags will actually pick a “best” value.
The returned value may be null if the flag is not set on any regions.
Getting StateFlag Values¶
If you are trying to query a StateFlag (a flag with allow/deny), there are additional methods that you can use. They allow you to specify multiple state flags for automatic combination (remember, “deny” overrides “allow”).
queryState(RegionAssociable, StateFlag...)takes one or more flags and returns an allow, deny, or nulltestState(RegionAssociable, StateFlag...)does the same thing, but returns true if it’s allow
You can still use queryValue, but you can only specify one flag at a time.
Flags With No Player¶
If you are trying to lookup a flag that doesn’t use a player (for example, the creeper-explosion flag), then you can use null for the RegionAssociable.
Hint
You can also pass in null for flags that do use a player, but then flag region groups will not work correctly.
Also via RegionQuery¶
The methods described on this page are also conveniently available directly on instances of RegionQuery.
In addition, you can use testBuild and so on as a shortcut to testState(..., Flags.BUILD, your flags).
Non-Player Actors¶
Instead of passing in a player, you can instead pass in a (non-LocalPlayer) RegionAssociable. This object is used to determine whether to use rules for owners, members, or non-members should be used.
However, let’s first consider what happens with players. Given a player part of the build team, who has been made an owner of both spawn’s region and the “builder’s club,” the association returned should be OWNER, as illustrated below:
List<ProtectedRegion> regions = Arrays.asList(spawnRegion, buildersClub);
builderPlayer.getAssociation(regions) == Association.OWNER;
As you may be aware, you cannot add entities or blocks as members to a region, so it can’t work the same way. To do that, a special RegionAssociable is used for blocks and entities: it takes a list of source regions to determine whether the source regions should be considered a “member” of the target location. This is illustrated below.
Set deepInside = newHashSet(spawn, mall);
Set inside = newHashSet(spawn);
Set outside = newHashSet(); // Empty set
// outside -> inside = considered as "non-member"
new RegionOverlapAssociation(outside).getAssociation(inside) == NON_MEMBER
// inside -> inside = considered as "member"
new RegionOverlapAssociation(inside).getAssociation(inside) == OWNER
// inside -> deepInside = considered as "member"
// Note that by default building is blocked in this case.
// The association must be at least "member" for all regions individually.
new RegionOverlapAssociation(inside).getAssociation(deepInside) == OWNER
// inside -> outside = considered as "non-member"
new RegionOverlapAssociation(inside).getAssociation(outside) == NON_MEMBER
// deepInside -> inside = considered as "member"
new RegionOverlapAssociation(deepInside).getAssociation(inside) == OWNER
Note that the nonplayer-protection-domains flag and region inheritance can override this behavior. The various test... and query... methods will handle this for you.
To summarize:
Player (
LocalPlayer) objects already implementRegionAssociableFor entities and blocks, WorldGuard uses the regions where the block or entity is (
RegionOverlapAssociation)
There is also:
ConstantAssociationuses a pre-set type of association (new ConstantAssociation(Association.MEMBER)orAssociables.constant(Association.MEMBER))DelayedRegionOverlapAssociationwhich works likeRegionOverlapAssociation, but doesn’t do the spatial query for regions at the source until it is needed