Add testBuild API to ARS and clean up flag querying
This commit is contained in:
parent
b67fd01ebd
commit
e7870d4997
|
@ -19,34 +19,6 @@
|
|||
|
||||
package com.sk89q.worldguard.protection;
|
||||
|
||||
import static com.sk89q.worldguard.protection.flags.StateFlag.test;
|
||||
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public abstract class AbstractRegionSet implements ApplicableRegionSet {
|
||||
|
||||
@Override
|
||||
public boolean testState(@Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
return test(queryState(subject, flags));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public State queryState(@Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
State value = null;
|
||||
|
||||
for (StateFlag flag : flags) {
|
||||
value = StateFlag.combine(value, queryValue(subject, flag));
|
||||
if (value == State.DENY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,18 +20,9 @@
|
|||
package com.sk89q.worldguard.protection;
|
||||
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.MapFlag;
|
||||
import com.sk89q.worldguard.protection.flags.RegionGroup;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -41,7 +32,7 @@ import java.util.Set;
|
|||
* <p>An instance of this can be created using the spatial query methods
|
||||
* available on {@link RegionManager}.</p>
|
||||
*/
|
||||
public interface ApplicableRegionSet extends Iterable<ProtectedRegion> {
|
||||
public interface ApplicableRegionSet extends FlagQuery, Iterable<ProtectedRegion> {
|
||||
|
||||
/**
|
||||
* Return whether this region set is a virtual set. A virtual set
|
||||
|
@ -61,127 +52,6 @@ public interface ApplicableRegionSet extends Iterable<ProtectedRegion> {
|
|||
*/
|
||||
boolean isVirtual();
|
||||
|
||||
/**
|
||||
* Test whether the (effective) value for a list of state flags equals
|
||||
* {@code ALLOW}.
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* @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(RegionAssociable, StateFlag...)
|
||||
*/
|
||||
boolean testState(@Nullable RegionAssociable subject, StateFlag... flags);
|
||||
|
||||
/**
|
||||
* Get the (effective) value for a list of state flags. The rules of
|
||||
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
|
||||
* and {@code ALLOW} overrides {@code NONE}. One flag may override another.
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* @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
|
||||
State queryState(@Nullable RegionAssociable subject, StateFlag... flags);
|
||||
|
||||
/**
|
||||
* Get the effective value for a flag. If there are multiple values
|
||||
* (for example, multiple overlapping regions with
|
||||
* the same priority may have the same flag set), then the selected
|
||||
* (or "winning") value will depend on the flag type.
|
||||
*
|
||||
* <p>Only some flag types actually have a strategy for picking the
|
||||
* "best value." For most types, the actual value that is chosen to be
|
||||
* returned is undefined (it could be any value). As of writing, the only
|
||||
* type of flag that actually has a strategy for picking a value is the
|
||||
* {@link StateFlag}.</p>
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @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
|
||||
<V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag);
|
||||
|
||||
/**
|
||||
* Get the effective value for a key in a {@link MapFlag}. If there are multiple values
|
||||
* (for example, if there are multiple regions with the same priority
|
||||
* but with different farewell messages set, there would be multiple
|
||||
* completing values), then the selected (or "winning") value will be undefined.
|
||||
*
|
||||
* <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
|
||||
* 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 subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag of type {@link MapFlag}
|
||||
* @param key the key for the map flag
|
||||
* @return a value, which could be {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
<V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key);
|
||||
|
||||
/**
|
||||
* Get the effective value for a key in a {@link MapFlag}. If there are multiple values
|
||||
* (for example, if there are multiple regions with the same priority
|
||||
* but with different farewell messages set, there would be multiple
|
||||
* completing values), then the selected (or "winning") value will be undefined.
|
||||
*
|
||||
* <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
|
||||
* 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 subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag of type {@link MapFlag}
|
||||
* @param key the key for the map flag
|
||||
* @return a value, which could be {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
<V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, @Nullable Flag<V> fallback);
|
||||
|
||||
/**
|
||||
* Get the effective values for a flag, returning a collection of all
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
<V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag);
|
||||
|
||||
/**
|
||||
* Test whether a player is an owner of all regions in this set.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.MapFlag;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link FlagQuery}, returning flag default values.
|
||||
*/
|
||||
public interface DefaultFlagQuery extends FlagQuery {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
default <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, @Nullable Flag<V> fallback) {
|
||||
Map<K, V> defaultVal = flag.getDefault();
|
||||
return defaultVal != null ? defaultVal.get(key) : fallback != null ? fallback.getDefault() : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
default <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne) {
|
||||
V fallback = flag.getDefault();
|
||||
return fallback != null ? ImmutableList.of(fallback) : (Collection<V>) ImmutableList.of();
|
||||
}
|
||||
|
||||
}
|
|
@ -24,7 +24,6 @@ import com.sk89q.worldguard.LocalPlayer;
|
|||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.MapFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
|
@ -32,14 +31,13 @@ import javax.annotation.Nullable;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A region set that is to be used when region data has failed. Operations
|
||||
* are blocked.
|
||||
*/
|
||||
public class FailedLoadRegionSet extends AbstractRegionSet {
|
||||
public class FailedLoadRegionSet extends AbstractRegionSet implements DefaultFlagQuery {
|
||||
|
||||
private static final FailedLoadRegionSet INSTANCE = new FailedLoadRegionSet();
|
||||
|
||||
|
@ -56,40 +54,14 @@ public class FailedLoadRegionSet extends AbstractRegionSet {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
if (flag == Flags.BUILD) {
|
||||
return (V) State.DENY;
|
||||
} else if (flag == Flags.DENY_MESSAGE) {
|
||||
return (V) denyMessage;
|
||||
}
|
||||
return flag.getDefault();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key) {
|
||||
return queryMapValue(subject, flag, key, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, @Nullable Flag<V> fallback) {
|
||||
Map<K, V> defaultVal = flag.getDefault();
|
||||
return defaultVal != null ? defaultVal.get(key) : fallback != null ? fallback.getDefault() : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne) {
|
||||
if (flag == Flags.BUILD) {
|
||||
return (Collection<V>) ImmutableList.of(State.DENY);
|
||||
} else if (flag == Flags.DENY_MESSAGE) {
|
||||
return (Collection<V>) denyMessageCollection;
|
||||
}
|
||||
V fallback = flag.getDefault();
|
||||
return fallback != null ? ImmutableList.of(fallback) : (Collection<V>) ImmutableList.of();
|
||||
return DefaultFlagQuery.super.queryAllValues(subject, flag, acceptOne);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import static com.sk89q.worldguard.protection.flags.StateFlag.combine;
|
||||
import static com.sk89q.worldguard.protection.flags.StateFlag.denyToNone;
|
||||
import static com.sk89q.worldguard.protection.flags.StateFlag.test;
|
||||
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.MapFlag;
|
||||
import com.sk89q.worldguard.protection.flags.RegionGroup;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Common methods for querying flags.
|
||||
*/
|
||||
public interface FlagQuery {
|
||||
|
||||
/**
|
||||
* Returns true if the BUILD flag allows the action, but it
|
||||
* can be overridden by a list of other flags. The BUILD flag will not
|
||||
* override the other flags, but the other flags can override BUILD. If
|
||||
* neither BUILD or any of the flags permit the action, then false will
|
||||
* be returned.
|
||||
*
|
||||
* <p>Use this method when checking flags that are related to build
|
||||
* protection. For example, lighting fire in a region should not be
|
||||
* permitted unless the player is a member of the region or the
|
||||
* LIGHTER flag allows it. However, the LIGHTER flag should be able
|
||||
* to allow lighting fires even if BUILD is set to DENY.</p>
|
||||
*
|
||||
* <p>How this method works (BUILD can be overridden by other flags but
|
||||
* not the other way around) is inconsistent, but it's required for
|
||||
* legacy reasons.</p>
|
||||
*
|
||||
* <p>This method does not check the region bypass permission. That must
|
||||
* be done by the calling code.</p>
|
||||
*
|
||||
* @param subject the subject
|
||||
* @param flags the flags
|
||||
* @return true if the result was {@code ALLOW}
|
||||
*/
|
||||
default boolean testBuild(RegionAssociable subject, StateFlag... flags) {
|
||||
if (flags.length == 0) {
|
||||
return testState(subject, Flags.BUILD);
|
||||
}
|
||||
|
||||
return test(
|
||||
denyToNone(queryState(subject, Flags.BUILD)),
|
||||
queryState(subject, flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the BUILD flag allows the action, but it
|
||||
* can be overridden by a list of other flags. The BUILD flag will not
|
||||
* override the other flags, but the other flags can override BUILD. If
|
||||
* neither BUILD or any of the flags permit the action, then false will
|
||||
* be returned.
|
||||
*
|
||||
* <p>Use this method when checking flags that are related to build
|
||||
* protection. For example, lighting fire in a region should not be
|
||||
* permitted unless the player is a member of the region or the
|
||||
* LIGHTER flag allows it. However, the LIGHTER flag should be able
|
||||
* to allow lighting fires even if BUILD is set to DENY.</p>
|
||||
*
|
||||
* <p>This method does include parameters for a {@link MapFlag}.</p>
|
||||
*
|
||||
* <p>How this method works (BUILD can be overridden by other flags but
|
||||
* not the other way around) is inconsistent, but it's required for
|
||||
* legacy reasons.</p>
|
||||
*
|
||||
* <p>This method does not check the region bypass permission. That must
|
||||
* be done by the calling code.</p>
|
||||
*
|
||||
* @param subject the subject
|
||||
* @param flag the MapFlag
|
||||
* @param key the key for the MapFlag
|
||||
* @param fallback the fallback flag for MapFlag
|
||||
* @param flags the flags
|
||||
* @return true if the result was {@code ALLOW}
|
||||
*/
|
||||
default <K> boolean testBuild(RegionAssociable subject, MapFlag<K, State> flag, K key,
|
||||
@Nullable StateFlag fallback, StateFlag... flags) {
|
||||
if (flag == null)
|
||||
return testBuild(subject, flags);
|
||||
|
||||
if (flags.length == 0) {
|
||||
return test(
|
||||
denyToNone(queryState(subject, Flags.BUILD)),
|
||||
queryMapValue(subject, flag, key, fallback)
|
||||
);
|
||||
}
|
||||
|
||||
return test(
|
||||
denyToNone(queryState(subject, Flags.BUILD)),
|
||||
queryMapValue(subject, flag, key, fallback),
|
||||
queryState(subject, flags)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the (effective) value for a list of state flags equals
|
||||
* {@code ALLOW}.
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* @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}
|
||||
*/
|
||||
default boolean testState(@Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
return test(queryState(subject, flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the (effective) value for a list of state flags. The rules of
|
||||
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
|
||||
* and {@code ALLOW} overrides {@code NONE}. One flag may override another.
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* @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
|
||||
default State queryState(@Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
State value = null;
|
||||
|
||||
for (StateFlag flag : flags) {
|
||||
value = combine(value, queryValue(subject, flag));
|
||||
if (value == State.DENY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a flag. If there are multiple values
|
||||
* (for example, multiple overlapping regions with
|
||||
* the same priority may have the same flag set), then the selected
|
||||
* (or "winning") value will depend on the flag type.
|
||||
*
|
||||
* <p>Only some flag types actually have a strategy for picking the
|
||||
* "best value." For most types, the actual value that is chosen to be
|
||||
* returned is undefined (it could be any value). As of writing, the only
|
||||
* type of flag that actually has a strategy for picking a value is the
|
||||
* {@link StateFlag}.</p>
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @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
|
||||
default <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
Collection<V> values = queryAllValues(subject, flag, true);
|
||||
return flag.chooseValue(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a key in a {@link MapFlag}. If there are multiple values
|
||||
* (for example, if there are multiple regions with the same priority
|
||||
* but with different farewell messages set, there would be multiple
|
||||
* completing values), then the selected (or "winning") value will be undefined.
|
||||
*
|
||||
* <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
|
||||
* 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 subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag of type {@link MapFlag}
|
||||
* @param key the key for the map flag
|
||||
* @return a value, which could be {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
default <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key) {
|
||||
return queryMapValue(subject, flag, key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a key in a {@link MapFlag}. If there are multiple values
|
||||
* (for example, if there are multiple regions with the same priority
|
||||
* but with different farewell messages set, there would be multiple
|
||||
* completing values), then the selected (or "winning") value will be undefined.
|
||||
*
|
||||
* <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
|
||||
* 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 subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag of type {@link MapFlag}
|
||||
* @param key the key for the map flag
|
||||
* @return a value, which could be {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
<V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, @Nullable Flag<V> fallback);
|
||||
|
||||
/**
|
||||
* Get the effective values for a flag, returning a collection of all
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
default <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
return queryAllValues(subject, flag, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective values for a flag, returning a collection of all
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
*
|
||||
* <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 subject argument is required if the
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @param acceptOne if possible, return only one value if it doesn't matter
|
||||
* @return a collection of values
|
||||
*/
|
||||
<V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne);
|
||||
|
||||
}
|
|
@ -24,8 +24,8 @@ import com.google.common.collect.Iterables;
|
|||
import com.google.common.collect.Sets;
|
||||
import com.sk89q.worldguard.domains.Association;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.MapFlag;
|
||||
import com.sk89q.worldguard.protection.flags.RegionGroup;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
|
@ -56,7 +56,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
* value of a flag is far from trivial. This class abstracts away the
|
||||
* difficult with a number of methods for performing these calculations.</p>
|
||||
*/
|
||||
public class FlagValueCalculator {
|
||||
public class FlagValueCalculator implements FlagQuery {
|
||||
|
||||
@Nullable
|
||||
private final ProtectedRegion globalRegion;
|
||||
|
@ -148,107 +148,28 @@ public class FlagValueCalculator {
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the effective value for a list of state flags. The rules of
|
||||
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
|
||||
* and {@code ALLOW} overrides {@code NONE}.
|
||||
*
|
||||
* <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
|
||||
* 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 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 RegionAssociable subject, StateFlag... flags) {
|
||||
State value = null;
|
||||
|
||||
for (StateFlag flag : flags) {
|
||||
value = StateFlag.combine(value, queryValue(subject, flag));
|
||||
if (value == State.DENY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a list of state flags. The rules of
|
||||
* Get the (effective) value for a state flag. The rules of
|
||||
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
|
||||
* and {@code ALLOW} overrides {@code NONE}.
|
||||
*
|
||||
* <p>This method is the same as
|
||||
* {@link #queryState(RegionAssociable, StateFlag...)}.</p>
|
||||
*
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param subject an optional subject, which would be used to determine the region groups that apply
|
||||
* @param flag a flag to check
|
||||
* @return a state
|
||||
* @deprecated use {@link #queryState(RegionAssociable, StateFlag...)} instead, will be removed in WorldGuard 8
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@Nullable
|
||||
public State queryState(@Nullable RegionAssociable subject, StateFlag flag) {
|
||||
return queryValue(subject, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a flag. If there are multiple values
|
||||
* (for example, if there are multiple regions with the same priority
|
||||
* but with different farewell messages set, there would be multiple
|
||||
* completing values), then the selected (or "winning") value will depend
|
||||
* on the flag type.
|
||||
*
|
||||
* <p>Only some flag types actually have a strategy for picking the
|
||||
* "best value." For most types, the actual value that is chosen to be
|
||||
* returned is undefined (it could be any value). As of writing, the only
|
||||
* type of flag that can consistently return the same 'best' value is
|
||||
* {@link StateFlag}.</p>
|
||||
*
|
||||
* <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
|
||||
* 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 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}
|
||||
*/
|
||||
@Override
|
||||
@Nullable
|
||||
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
Collection<V> values = queryAllValues(subject, flag, true);
|
||||
return flag.chooseValue(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a key in a {@link MapFlag}. If there are multiple values
|
||||
* (for example, if there are multiple regions with the same priority
|
||||
* but with different farewell messages set, there would be multiple
|
||||
* completing values), then the selected (or "winning") value will be undefined.
|
||||
*
|
||||
* <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
|
||||
* 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 subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag of type {@link MapFlag}
|
||||
* @param key the key for the map flag
|
||||
* @return a value, which could be {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, Flag<V> fallback) {
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, @Nullable Flag<V> fallback) {
|
||||
checkNotNull(flag);
|
||||
checkNotNull(key);
|
||||
|
||||
|
@ -297,27 +218,27 @@ public class FlagValueCalculator {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public <V, K> V getEffectiveMapValue(ProtectedRegion region, MapFlag<K, V> mapFlag, K key, RegionAssociable subject) {
|
||||
return getEffectiveMapValueOf(region, mapFlag, key, subject);
|
||||
public <V, K> V getEffectiveMapValue(ProtectedRegion region, MapFlag<K, V> flag, K key, RegionAssociable subject) {
|
||||
return getEffectiveMapValueOf(region, flag, key, subject);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <V, K> V getEffectiveMapValueOf(ProtectedRegion region, MapFlag<K, V> mapFlag, K key, RegionAssociable subject) {
|
||||
public static <V, K> V getEffectiveMapValueOf(ProtectedRegion region, MapFlag<K, V> flag, K key, RegionAssociable subject) {
|
||||
List<ProtectedRegion> seen = new ArrayList<>();
|
||||
ProtectedRegion current = region;
|
||||
|
||||
while (current != null) {
|
||||
seen.add(current);
|
||||
|
||||
Map<K, V> mapValue = current.getFlag(mapFlag);
|
||||
Map<K, V> mapValue = current.getFlag(flag);
|
||||
|
||||
if (mapValue != null && mapValue.containsKey(key)) {
|
||||
boolean use = true;
|
||||
|
||||
if (mapFlag.getRegionGroupFlag() != null) {
|
||||
RegionGroup group = current.getFlag(mapFlag.getRegionGroupFlag());
|
||||
if (flag.getRegionGroupFlag() != null) {
|
||||
RegionGroup group = current.getFlag(flag.getRegionGroupFlag());
|
||||
if (group == null) {
|
||||
group = mapFlag.getRegionGroupFlag().getDefault();
|
||||
group = flag.getRegionGroupFlag().getDefault();
|
||||
}
|
||||
|
||||
if (group == null) {
|
||||
|
@ -339,47 +260,9 @@ public class FlagValueCalculator {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective values for a flag, returning a collection of all
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
*
|
||||
* <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
|
||||
* 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 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 RegionAssociable subject, Flag<V> flag) {
|
||||
return queryAllValues(subject, flag, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective values for a flag, returning a collection of all
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
*
|
||||
* <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
|
||||
* 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 subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag
|
||||
* @param acceptOne if possible, return only one value if it doesn't matter
|
||||
* @return a collection of values
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne) {
|
||||
@Override
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne) {
|
||||
checkNotNull(flag);
|
||||
|
||||
// Can't use this optimization with flags that have a conflict resolution strategy
|
||||
|
|
|
@ -19,27 +19,18 @@
|
|||
|
||||
package com.sk89q.worldguard.protection;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.sk89q.worldguard.LocalPlayer;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.MapFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A virtual region result set that is highly permissive, considering everyone
|
||||
* a member. Returned flag values are default values (when available).
|
||||
*/
|
||||
public class PermissiveRegionSet extends AbstractRegionSet {
|
||||
public class PermissiveRegionSet extends AbstractRegionSet implements DefaultFlagQuery {
|
||||
|
||||
private static final PermissiveRegionSet INSTANCE = new PermissiveRegionSet();
|
||||
|
||||
|
@ -51,39 +42,6 @@ public class PermissiveRegionSet extends AbstractRegionSet {
|
|||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
@Override
|
||||
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
if (flag == Flags.BUILD) {
|
||||
return (V) State.DENY;
|
||||
}
|
||||
return flag.getDefault();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key) {
|
||||
return queryMapValue(subject, flag, key, null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, @Nullable Flag<V> fallback) {
|
||||
Map<K, V> defaultVal = flag.getDefault();
|
||||
return defaultVal != null ? defaultVal.get(key) : fallback != null ? fallback.getDefault() : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
if (flag == Flags.BUILD) {
|
||||
return (Collection<V>) ImmutableList.of(State.DENY);
|
||||
}
|
||||
V fallback = flag.getDefault();
|
||||
return fallback != null ? ImmutableList.of(fallback) : (Collection<V>) ImmutableList.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOwnerOfAll(LocalPlayer player) {
|
||||
return true;
|
||||
|
|
|
@ -24,8 +24,6 @@ import com.sk89q.worldguard.LocalPlayer;
|
|||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.MapFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
|
||||
import com.sk89q.worldguard.protection.util.NormativeOrders;
|
||||
|
||||
|
@ -98,31 +96,13 @@ public class RegionResultSet extends AbstractRegionSet {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public State queryState(@Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
return flagValueCalculator.queryState(subject, flags);
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne) {
|
||||
return flagValueCalculator.queryAllValues(subject, flag, acceptOne);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <V> V queryValue(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
return flagValueCalculator.queryValue(subject, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> Collection<V> queryAllValues(@Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
return flagValueCalculator.queryAllValues(subject, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key) {
|
||||
return flagValueCalculator.queryMapValue(subject, flag, key, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, Flag<V> fallback) {
|
||||
public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, @Nullable Flag<V> fallback) {
|
||||
return flagValueCalculator.queryMapValue(subject, flag, key, fallback);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,7 @@ import com.sk89q.worldguard.protection.PermissiveRegionSet;
|
|||
import com.sk89q.worldguard.protection.RegionResultSet;
|
||||
import com.sk89q.worldguard.protection.association.RegionAssociable;
|
||||
import com.sk89q.worldguard.protection.flags.Flag;
|
||||
import com.sk89q.worldguard.protection.flags.Flags;
|
||||
import com.sk89q.worldguard.protection.flags.MapFlag;
|
||||
import com.sk89q.worldguard.protection.flags.RegionGroup;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag;
|
||||
import com.sk89q.worldguard.protection.flags.StateFlag.State;
|
||||
import com.sk89q.worldguard.protection.managers.RegionManager;
|
||||
|
@ -131,293 +129,107 @@ public class RegionQuery {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns true if the BUILD flag allows the action in the location, but it
|
||||
* can be overridden by a list of other flags. The BUILD flag will not
|
||||
* override the other flags, but the other flags can override BUILD. If
|
||||
* neither BUILD or any of the flags permit the action, then false will
|
||||
* be returned.
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#testBuild(RegionAssociable, StateFlag...)
|
||||
* .testBuild(RegionAssociable, StateFlag...)}
|
||||
*
|
||||
* <p>Use this method when checking flags that are related to build
|
||||
* protection. For example, lighting fire in a region should not be
|
||||
* permitted unless the player is a member of the region or the
|
||||
* LIGHTER flag allows it. However, the LIGHTER flag should be able
|
||||
* to allow lighting fires even if BUILD is set to DENY.</p>
|
||||
*
|
||||
* <p>How this method works (BUILD can be overridden by other flags but
|
||||
* not the other way around) is inconsistent, but it's required for
|
||||
* legacy reasons.</p>
|
||||
*
|
||||
* <p>This method does not check the region bypass permission. That must
|
||||
* be done by the calling code.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @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 RegionResultSet#queryValue(RegionAssociable, Flag)
|
||||
* @deprecated use {@link #testBuild(Location, RegionAssociable, StateFlag...)} instead, will be removed in WorldGuard 8
|
||||
*/
|
||||
public boolean testBuild(Location location, LocalPlayer player, StateFlag... flag) {
|
||||
if (flag.length == 0) {
|
||||
return testState(location, player, Flags.BUILD);
|
||||
}
|
||||
|
||||
return StateFlag.test(StateFlag.combine(
|
||||
StateFlag.denyToNone(queryState(location, player, Flags.BUILD)),
|
||||
queryState(location, player, flag)));
|
||||
@Deprecated(forRemoval = true)
|
||||
public boolean testBuild(Location location, LocalPlayer subject, StateFlag... flags) {
|
||||
return getApplicableRegions(location).testBuild(subject, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the BUILD flag allows the action in the location, but it
|
||||
* can be overridden by a list of other flags. The BUILD flag will not
|
||||
* override the other flags, but the other flags can override BUILD. If
|
||||
* neither BUILD or any of the flags permit the action, then false will
|
||||
* be returned.
|
||||
*
|
||||
* <p>Use this method when checking flags that are related to build
|
||||
* protection. For example, lighting fire in a region should not be
|
||||
* permitted unless the player is a member of the region or the
|
||||
* LIGHTER flag allows it. However, the LIGHTER flag should be able
|
||||
* to allow lighting fires even if BUILD is set to DENY.</p>
|
||||
*
|
||||
* <p>How this method works (BUILD can be overridden by other flags but
|
||||
* not the other way around) is inconsistent, but it's required for
|
||||
* legacy reasons.</p>
|
||||
*
|
||||
* <p>This method does not check the region bypass permission. That must
|
||||
* be done by the calling code.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @param associable an optional associable
|
||||
* @param flag the flag
|
||||
* @return true if the result was {@code ALLOW}
|
||||
* @see RegionResultSet#queryValue(RegionAssociable, Flag)
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#testBuild(RegionAssociable, StateFlag...)
|
||||
* .testBuild(RegionAssociable, StateFlag...)}
|
||||
*/
|
||||
public boolean testBuild(Location location, RegionAssociable associable, StateFlag... flag) {
|
||||
if (flag.length == 0) {
|
||||
return testState(location, associable, Flags.BUILD);
|
||||
}
|
||||
|
||||
return StateFlag.test(StateFlag.combine(
|
||||
StateFlag.denyToNone(queryState(location, associable, Flags.BUILD)),
|
||||
queryState(location, associable, flag)));
|
||||
public boolean testBuild(Location location, RegionAssociable subject, StateFlag... flags) {
|
||||
return getApplicableRegions(location).testBuild(subject, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the BUILD flag allows the action in the location, but it
|
||||
* can be overridden by a list of other flags. The BUILD flag will not
|
||||
* override the other flags, but the other flags can override BUILD. If
|
||||
* neither BUILD or any of the flags permit the action, then false will
|
||||
* be returned.
|
||||
*
|
||||
* <p>Use this method when checking flags that are related to build
|
||||
* protection. For example, lighting fire in a region should not be
|
||||
* permitted unless the player is a member of the region or the
|
||||
* LIGHTER flag allows it. However, the LIGHTER flag should be able
|
||||
* to allow lighting fires even if BUILD is set to DENY.</p>
|
||||
*
|
||||
* <p>This method does include parameters for a {@link MapFlag}.</p>
|
||||
*
|
||||
* <p>How this method works (BUILD can be overridden by other flags but
|
||||
* not the other way around) is inconsistent, but it's required for
|
||||
* legacy reasons.</p>
|
||||
*
|
||||
* <p>This method does not check the region bypass permission. That must
|
||||
* be done by the calling code.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @param associable an optional associable
|
||||
* @param mapFlag the MapFlag
|
||||
* @param key the key for the MapFlag
|
||||
* @param fallback the fallback flag for MapFlag
|
||||
* @param flag the flags
|
||||
* @return true if the result was {@code ALLOW}
|
||||
* @see RegionResultSet#queryValue(RegionAssociable, Flag)
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#testBuild(RegionAssociable, MapFlag, Object, StateFlag, StateFlag...)
|
||||
* .testBuild(RegionAssociable, MapFlag, Object, StateFlag, StateFlag...)}
|
||||
*/
|
||||
public <K> boolean testBuild(Location location, RegionAssociable associable, MapFlag<K, State> mapFlag, K key,
|
||||
@Nullable StateFlag fallback, StateFlag... flag) {
|
||||
if (mapFlag == null)
|
||||
return testBuild(location, associable, flag);
|
||||
|
||||
if (flag.length == 0) {
|
||||
return StateFlag.test(StateFlag.combine(
|
||||
StateFlag.denyToNone(queryState(location, associable, Flags.BUILD)),
|
||||
queryMapValue(location, associable, mapFlag, key, fallback)
|
||||
));
|
||||
}
|
||||
|
||||
return StateFlag.test(StateFlag.combine(
|
||||
StateFlag.denyToNone(queryState(location, associable, Flags.BUILD)),
|
||||
queryMapValue(location, associable, mapFlag, key, fallback),
|
||||
queryState(location, associable, flag)
|
||||
));
|
||||
public <K> boolean testBuild(Location location, RegionAssociable subject, MapFlag<K, State> flag, K key,
|
||||
@Nullable StateFlag fallback, StateFlag... flags) {
|
||||
return getApplicableRegions(location).testBuild(subject, flag, key, fallback, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the (effective) value for a list of state flags equals
|
||||
* {@code ALLOW}.
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#testState(RegionAssociable, StateFlag...)
|
||||
* .testState(RegionAssociable, StateFlag...)}
|
||||
*
|
||||
* <p>{@code player} 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
|
||||
* {@link Flags#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* <p>This method does not check the region bypass permission. That must
|
||||
* be done by the calling code.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @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 RegionResultSet#queryValue(RegionAssociable, Flag)
|
||||
* @deprecated use {@link #testState(Location, RegionAssociable, StateFlag...)} instead, will be removed in WorldGuard 8
|
||||
*/
|
||||
public boolean testState(Location location, @Nullable LocalPlayer player, StateFlag... flag) {
|
||||
return StateFlag.test(queryState(location, player, flag));
|
||||
@Deprecated(forRemoval = true)
|
||||
public boolean testState(Location location, @Nullable LocalPlayer subject, StateFlag... flags) {
|
||||
return getApplicableRegions(location).testState(subject, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* 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
|
||||
* {@link Flags#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* <p>This method does not check the region bypass permission. That must
|
||||
* be done by the calling code.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @param associable an optional associable
|
||||
* @param flag the flag
|
||||
* @return true if the result was {@code ALLOW}
|
||||
* @see RegionResultSet#queryValue(RegionAssociable, Flag)
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#testState(RegionAssociable, StateFlag...)
|
||||
* .testState(RegionAssociable, StateFlag...)}
|
||||
*/
|
||||
public boolean testState(Location location, @Nullable RegionAssociable associable, StateFlag... flag) {
|
||||
return StateFlag.test(queryState(location, associable, flag));
|
||||
public boolean testState(Location location, @Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
return getApplicableRegions(location).testState(subject, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the (effective) value for a list of state flags. The rules of
|
||||
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
|
||||
* and {@code ALLOW} overrides {@code NONE}. One flag may override another.
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryState(RegionAssociable, StateFlag...)
|
||||
* .queryState(RegionAssociable, StateFlag...)}
|
||||
*
|
||||
* <p>{@code player} 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
|
||||
* {@link Flags#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @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 RegionResultSet#queryState(RegionAssociable, StateFlag...)
|
||||
* @deprecated use {@link #queryState(Location, RegionAssociable, StateFlag...)} instead, will be removed in WorldGuard 8
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@Nullable
|
||||
public State queryState(Location location, @Nullable LocalPlayer subject, StateFlag... flags) {
|
||||
return getApplicableRegions(location).queryState(subject, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryState(RegionAssociable, StateFlag...)
|
||||
* .queryState(RegionAssociable, StateFlag...)}
|
||||
*/
|
||||
@Nullable
|
||||
public State queryState(Location location, @Nullable LocalPlayer player, StateFlag... flags) {
|
||||
return getApplicableRegions(location).queryState(player, flags);
|
||||
public State queryState(Location location, @Nullable RegionAssociable subject, StateFlag... flags) {
|
||||
return getApplicableRegions(location).queryState(subject, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the (effective) value for a list of state flags. The rules of
|
||||
* states is observed here; that is, {@code DENY} overrides {@code ALLOW},
|
||||
* and {@code ALLOW} overrides {@code NONE}. One flag may override another.
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryValue(RegionAssociable, Flag)
|
||||
* .queryValue(RegionAssociable, Flag)}
|
||||
*
|
||||
* <p>{@code player} 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
|
||||
* {@link Flags#BUILD} flag is in the list of flags.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @param associable an optional associable
|
||||
* @param flags a list of flags to check
|
||||
* @return a state
|
||||
* @see RegionResultSet#queryState(RegionAssociable, StateFlag...)
|
||||
* @deprecated use {@link #queryValue(Location, RegionAssociable, Flag)} instead, will be removed in WorldGuard 8
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@Nullable
|
||||
public <V> V queryValue(Location location, @Nullable LocalPlayer subject, Flag<V> flag) {
|
||||
return getApplicableRegions(location).queryValue(subject, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryValue(RegionAssociable, Flag)
|
||||
* .queryValue(RegionAssociable, Flag)}
|
||||
*/
|
||||
@Nullable
|
||||
public State queryState(Location location, @Nullable RegionAssociable associable, StateFlag... flags) {
|
||||
return getApplicableRegions(location).queryState(associable, flags);
|
||||
public <V> V queryValue(Location location, @Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
return getApplicableRegions(location).queryValue(subject, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a flag. If there are multiple values
|
||||
* (for example, multiple overlapping regions with
|
||||
* the same priority may have the same flag set), then the selected
|
||||
* (or "winning") value will depend on the flag type.
|
||||
*
|
||||
* <p>Only some flag types actually have a strategy for picking the
|
||||
* "best value." For most types, the actual value that is chosen to be
|
||||
* returned is undefined (it could be any value). As of writing, the only
|
||||
* 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,
|
||||
* 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
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @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 RegionResultSet#queryValue(RegionAssociable, Flag)
|
||||
*/
|
||||
@Nullable
|
||||
public <V> V queryValue(Location location, @Nullable LocalPlayer player, Flag<V> flag) {
|
||||
return getApplicableRegions(location).queryValue(player, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a flag. If there are multiple values
|
||||
* (for example, multiple overlapping regions with
|
||||
* the same priority may have the same flag set), then the selected
|
||||
* (or "winning") value will depend on the flag type.
|
||||
*
|
||||
* <p>Only some flag types actually have a strategy for picking the
|
||||
* "best value." For most types, the actual value that is chosen to be
|
||||
* returned is undefined (it could be any value). As of writing, the only
|
||||
* 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,
|
||||
* 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
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @param associable an optional associable
|
||||
* @param flag the flag
|
||||
* @return a value, which could be {@code null}
|
||||
* @see RegionResultSet#queryValue(RegionAssociable, Flag)
|
||||
*/
|
||||
@Nullable
|
||||
public <V> V queryValue(Location location, @Nullable RegionAssociable associable, Flag<V> flag) {
|
||||
return getApplicableRegions(location).queryValue(associable, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a key in a {@link MapFlag}. If there are multiple values
|
||||
* (for example, if there are multiple regions with the same priority
|
||||
* but with different farewell messages set, there would be multiple
|
||||
* completing values), then the selected (or "winning") value will be undefined.
|
||||
*
|
||||
* <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
|
||||
* 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 subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag of type {@link MapFlag}
|
||||
* @param key the key for the map flag
|
||||
* @return a value, which could be {@code null}
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryMapValue(RegionAssociable, MapFlag, Object)
|
||||
* .queryMapValue(RegionAssociable, MapFlag, Object)}
|
||||
*/
|
||||
@Nullable
|
||||
public <V, K> V queryMapValue(Location location, @Nullable RegionAssociable subject, MapFlag<K, V> flag, K key) {
|
||||
|
@ -425,73 +237,43 @@ public class RegionQuery {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the effective value for a key in a {@link MapFlag}. If there are multiple values
|
||||
* (for example, if there are multiple regions with the same priority
|
||||
* but with different farewell messages set, there would be multiple
|
||||
* completing values), then the selected (or "winning") value will be undefined.
|
||||
*
|
||||
* <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
|
||||
* 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>
|
||||
*
|
||||
* <p>It's possible to provide a fallback flag for the case when the key doesn't
|
||||
* exist in the {@link MapFlag}.</p>
|
||||
*
|
||||
* @param subject an optional subject, which would be used to determine the region group to apply
|
||||
* @param flag the flag of type {@link MapFlag}
|
||||
* @param key the key for the map flag
|
||||
* @param fallback the fallback flag
|
||||
* @return a value, which could be {@code null}
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryMapValue(RegionAssociable, MapFlag, Object, Flag)
|
||||
* .queryMapValue(RegionAssociable, MapFlag, Object, Flag)}
|
||||
*/
|
||||
@Nullable
|
||||
public <V, K> V queryMapValue(Location location, @Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, Flag<V> fallback) {
|
||||
public <V, K> V queryMapValue(Location location, @Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, @Nullable Flag<V> fallback) {
|
||||
return getApplicableRegions(location).queryMapValue(subject, flag, key, fallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective values for a flag, returning a collection of all
|
||||
* values. It is up to the caller to determine which value, if any,
|
||||
* from the collection will be used.
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryAllValues(RegionAssociable, Flag)
|
||||
* .queryAllValues(RegionAssociable, Flag)}
|
||||
*
|
||||
* <p>{@code player} 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
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @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 RegionResultSet#queryAllValues(RegionAssociable, Flag)
|
||||
* @deprecated use {@link #queryAllValues(Location, RegionAssociable, Flag)} instead, will be removed in WorldGuard 8
|
||||
*/
|
||||
public <V> Collection<V> queryAllValues(Location location, @Nullable LocalPlayer player, Flag<V> flag) {
|
||||
return getApplicableRegions(location).queryAllValues(player, flag);
|
||||
@Deprecated(forRemoval = true)
|
||||
public <V> Collection<V> queryAllValues(Location location, @Nullable LocalPlayer subject, Flag<V> flag) {
|
||||
return getApplicableRegions(location).queryAllValues(subject, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the effective values for a flag, returning a collection of all
|
||||
* 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,
|
||||
* 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
|
||||
* {@link Flags#BUILD} flag is the flag being queried.</p>
|
||||
*
|
||||
* @param location the location
|
||||
* @param associable an optional associable
|
||||
* @param flag the flag
|
||||
* @return a collection of values
|
||||
* @see RegionResultSet#queryAllValues(RegionAssociable, Flag)
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryAllValues(RegionAssociable, Flag)
|
||||
* .queryAllValues(RegionAssociable, Flag)}
|
||||
*/
|
||||
public <V> Collection<V> queryAllValues(Location location, @Nullable RegionAssociable associable, Flag<V> flag) {
|
||||
return getApplicableRegions(location).queryAllValues(associable, flag);
|
||||
public <V> Collection<V> queryAllValues(Location location, @Nullable RegionAssociable subject, Flag<V> flag) {
|
||||
return getApplicableRegions(location).queryAllValues(subject, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for
|
||||
* {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryAllValues(RegionAssociable, Flag, boolean)
|
||||
* .queryAllValues(RegionAssociable, Flag, boolean)}
|
||||
*/
|
||||
public <V> Collection<V> queryAllValues(Location location, @Nullable RegionAssociable subject, Flag<V> flag, boolean acceptOne) {
|
||||
return getApplicableRegions(location).queryAllValues(subject, flag, acceptOne);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue