From e7870d49978737060c6c3dae9e393978d7800cd8 Mon Sep 17 00:00:00 2001
From: stonar96
Date: Fri, 7 Apr 2023 19:32:57 +0200
Subject: [PATCH] Add testBuild API to ARS and clean up flag querying
---
.../protection/AbstractRegionSet.java | 28 --
.../protection/ApplicableRegionSet.java | 132 +-----
.../protection/DefaultFlagQuery.java | 50 +++
.../protection/FailedLoadRegionSet.java | 34 +-
.../worldguard/protection/FlagQuery.java | 282 +++++++++++++
.../protection/FlagValueCalculator.java | 151 +------
.../protection/PermissiveRegionSet.java | 44 +-
.../protection/RegionResultSet.java | 26 +-
.../protection/regions/RegionQuery.java | 382 ++++--------------
9 files changed, 439 insertions(+), 690 deletions(-)
create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/protection/DefaultFlagQuery.java
create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/protection/FlagQuery.java
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/AbstractRegionSet.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/AbstractRegionSet.java
index ea78e6854..98c7341f5 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/AbstractRegionSet.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/AbstractRegionSet.java
@@ -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;
- }
-
}
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/ApplicableRegionSet.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/ApplicableRegionSet.java
index 845931d08..c4dcbd28a 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/ApplicableRegionSet.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/ApplicableRegionSet.java
@@ -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 @@
* An instance of this can be created using the spatial query methods
* available on {@link RegionManager}.
*/
-public interface ApplicableRegionSet extends Iterable {
+public interface ApplicableRegionSet extends FlagQuery, Iterable {
/**
* Return whether this region set is a virtual set. A virtual set
@@ -61,127 +52,6 @@ public interface ApplicableRegionSet extends Iterable {
*/
boolean isVirtual();
- /**
- * Test whether the (effective) value for a list of state flags equals
- * {@code ALLOW}.
- *
- * {@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.
- *
- * @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.
- *
- * {@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.
- *
- * @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.
- *
- * 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}.
- *
- * {@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.
- *
- * @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 queryValue(@Nullable RegionAssociable subject, Flag 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.
- *
- * 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.
- *
- * @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 queryMapValue(@Nullable RegionAssociable subject, MapFlag 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.
- *
- * 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.
- *
- * @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 queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, @Nullable Flag 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.
- *
- * {@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.
- *
- * @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
- */
- Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag);
-
/**
* Test whether a player is an owner of all regions in this set.
*
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/DefaultFlagQuery.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/DefaultFlagQuery.java
new file mode 100644
index 000000000..7f4aecaa4
--- /dev/null
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/DefaultFlagQuery.java
@@ -0,0 +1,50 @@
+/*
+ * WorldGuard, a suite of tools for Minecraft
+ * Copyright (C) sk89q
+ * 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 .
+ */
+
+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 queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, @Nullable Flag fallback) {
+ Map defaultVal = flag.getDefault();
+ return defaultVal != null ? defaultVal.get(key) : fallback != null ? fallback.getDefault() : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ default Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag, boolean acceptOne) {
+ V fallback = flag.getDefault();
+ return fallback != null ? ImmutableList.of(fallback) : (Collection) ImmutableList.of();
+ }
+
+}
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FailedLoadRegionSet.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FailedLoadRegionSet.java
index 71b99e059..6f47ddfbe 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FailedLoadRegionSet.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FailedLoadRegionSet.java
@@ -24,7 +24,6 @@
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 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 boolean isVirtual() {
}
@SuppressWarnings("unchecked")
- @Nullable
@Override
- public V queryValue(@Nullable RegionAssociable subject, Flag 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 queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key) {
- return queryMapValue(subject, flag, key, null);
- }
-
- @Nullable
- @Override
- public V queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, @Nullable Flag fallback) {
- Map defaultVal = flag.getDefault();
- return defaultVal != null ? defaultVal.get(key) : fallback != null ? fallback.getDefault() : null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag) {
+ public Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag, boolean acceptOne) {
if (flag == Flags.BUILD) {
return (Collection) ImmutableList.of(State.DENY);
} else if (flag == Flags.DENY_MESSAGE) {
return (Collection) denyMessageCollection;
}
- V fallback = flag.getDefault();
- return fallback != null ? ImmutableList.of(fallback) : (Collection) ImmutableList.of();
+ return DefaultFlagQuery.super.queryAllValues(subject, flag, acceptOne);
}
@Override
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FlagQuery.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FlagQuery.java
new file mode 100644
index 000000000..dc42c359c
--- /dev/null
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FlagQuery.java
@@ -0,0 +1,282 @@
+/*
+ * WorldGuard, a suite of tools for Minecraft
+ * Copyright (C) sk89q
+ * 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 .
+ */
+
+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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * This method does not check the region bypass permission. That must
+ * be done by the calling code.
+ *
+ * @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.
+ *
+ * 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.
+ *
+ * This method does include parameters for a {@link MapFlag}.
+ *
+ * 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.
+ *
+ * This method does not check the region bypass permission. That must
+ * be done by the calling code.
+ *
+ * @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 boolean testBuild(RegionAssociable subject, MapFlag 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}.
+ *
+ * {@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.
+ *
+ * @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.
+ *
+ * {@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.
+ *
+ * @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.
+ *
+ * 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}.
+ *
+ * {@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.
+ *
+ * @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 queryValue(@Nullable RegionAssociable subject, Flag flag) {
+ Collection 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.
+ *
+ * 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.
+ *
+ * @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 queryMapValue(@Nullable RegionAssociable subject, MapFlag 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.
+ *
+ * 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.
+ *
+ * @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 queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, @Nullable Flag 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.
+ *
+ * {@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.
+ *
+ * @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 Collection queryAllValues(@Nullable RegionAssociable subject, Flag 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.
+ *
+ * {@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.
+ *
+ * @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
+ */
+ Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag, boolean acceptOne);
+
+}
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FlagValueCalculator.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FlagValueCalculator.java
index c6cdc189b..f27288a30 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FlagValueCalculator.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/FlagValueCalculator.java
@@ -24,8 +24,8 @@
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 @@
* value of a flag is far from trivial. This class abstracts away the
* difficult with a number of methods for performing these calculations.
*/
-public class FlagValueCalculator {
+public class FlagValueCalculator implements FlagQuery {
@Nullable
private final ProtectedRegion globalRegion;
@@ -148,107 +148,28 @@ public Result getMembership(RegionAssociable subject) {
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}.
- *
- * 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.
- *
- * @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}.
*
* This method is the same as
* {@link #queryState(RegionAssociable, StateFlag...)}.
*
- * @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.
- *
- * 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}.
- *
- * 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.
- *
- * @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 queryValue(@Nullable RegionAssociable subject, Flag flag) {
- Collection 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.
- *
- * 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.
- *
- * @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}
- */
+ @Override
@Nullable
- public V queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, Flag fallback) {
+ public V queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, @Nullable Flag fallback) {
checkNotNull(flag);
checkNotNull(key);
@@ -297,27 +218,27 @@ public V queryMapValue(@Nullable RegionAssociable subject, MapFlag
}
@Nullable
- public V getEffectiveMapValue(ProtectedRegion region, MapFlag mapFlag, K key, RegionAssociable subject) {
- return getEffectiveMapValueOf(region, mapFlag, key, subject);
+ public V getEffectiveMapValue(ProtectedRegion region, MapFlag flag, K key, RegionAssociable subject) {
+ return getEffectiveMapValueOf(region, flag, key, subject);
}
@Nullable
- public static V getEffectiveMapValueOf(ProtectedRegion region, MapFlag mapFlag, K key, RegionAssociable subject) {
+ public static V getEffectiveMapValueOf(ProtectedRegion region, MapFlag flag, K key, RegionAssociable subject) {
List seen = new ArrayList<>();
ProtectedRegion current = region;
while (current != null) {
seen.add(current);
- Map mapValue = current.getFlag(mapFlag);
+ Map 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 static V getEffectiveMapValueOf(ProtectedRegion region, MapFlagA 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.
- *
- * @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 Collection queryAllValues(@Nullable RegionAssociable subject, Flag 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.
- *
- * 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.
- *
- * @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 Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag, boolean acceptOne) {
+ @Override
+ public Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag, boolean acceptOne) {
checkNotNull(flag);
// Can't use this optimization with flags that have a conflict resolution strategy
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/PermissiveRegionSet.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/PermissiveRegionSet.java
index bf800e5b8..3d61e2ee9 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/PermissiveRegionSet.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/PermissiveRegionSet.java
@@ -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 boolean isVirtual() {
return true;
}
- @SuppressWarnings("unchecked")
- @Nullable
- @Override
- public V queryValue(@Nullable RegionAssociable subject, Flag flag) {
- if (flag == Flags.BUILD) {
- return (V) State.DENY;
- }
- return flag.getDefault();
- }
-
- @Nullable
- @Override
- public V queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key) {
- return queryMapValue(subject, flag, key, null);
- }
-
- @Nullable
- @Override
- public V queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, @Nullable Flag fallback) {
- Map defaultVal = flag.getDefault();
- return defaultVal != null ? defaultVal.get(key) : fallback != null ? fallback.getDefault() : null;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag) {
- if (flag == Flags.BUILD) {
- return (Collection) ImmutableList.of(State.DENY);
- }
- V fallback = flag.getDefault();
- return fallback != null ? ImmutableList.of(fallback) : (Collection) ImmutableList.of();
- }
-
@Override
public boolean isOwnerOfAll(LocalPlayer player) {
return true;
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/RegionResultSet.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/RegionResultSet.java
index f4346ddf0..6925c80ba 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/RegionResultSet.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/RegionResultSet.java
@@ -24,8 +24,6 @@
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 boolean isVirtual() {
}
@Override
- @Nullable
- public State queryState(@Nullable RegionAssociable subject, StateFlag... flags) {
- return flagValueCalculator.queryState(subject, flags);
- }
-
- @Override
- @Nullable
- public V queryValue(@Nullable RegionAssociable subject, Flag flag) {
- return flagValueCalculator.queryValue(subject, flag);
- }
-
- @Override
- public Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag) {
- return flagValueCalculator.queryAllValues(subject, flag);
- }
-
- @Override
- @Nullable
- public V queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key) {
- return flagValueCalculator.queryMapValue(subject, flag, key, null);
+ public Collection queryAllValues(@Nullable RegionAssociable subject, Flag flag, boolean acceptOne) {
+ return flagValueCalculator.queryAllValues(subject, flag, acceptOne);
}
@Override
@Nullable
- public V queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, Flag fallback) {
+ public V queryMapValue(@Nullable RegionAssociable subject, MapFlag flag, K key, @Nullable Flag fallback) {
return flagValueCalculator.queryMapValue(subject, flag, key, fallback);
}
diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/regions/RegionQuery.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/regions/RegionQuery.java
index 2ee030c1e..558bbf77f 100644
--- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/regions/RegionQuery.java
+++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/regions/RegionQuery.java
@@ -34,9 +34,7 @@
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 ApplicableRegionSet getApplicableRegions(Location location, QueryOption o
}
/**
- * 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...)}
*
- * 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.
- *
- * 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.
- *
- * This method does not check the region bypass permission. That must
- * be done by the calling code.
- *
- * @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.
- *
- * 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.
- *
- * 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.
- *
- * This method does not check the region bypass permission. That must
- * be done by the calling code.
- *
- * @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.
- *
- * 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.
- *
- * This method does include parameters for a {@link MapFlag}.
- *
- * 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.
- *
- * This method does not check the region bypass permission. That must
- * be done by the calling code.
- *
- * @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 boolean testBuild(Location location, RegionAssociable associable, MapFlag 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 boolean testBuild(Location location, RegionAssociable subject, MapFlag 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...)}
*
- * {@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.
- *
- * This method does not check the region bypass permission. That must
- * be done by the calling code.
- *
- * @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}.
- *
- * {@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.
- *
- * This method does not check the region bypass permission. That must
- * be done by the calling code.
- *
- * @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.
- *
- * {@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.
+ * Convenience method for
+ * {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryState(RegionAssociable, StateFlag...)
+ * .queryState(RegionAssociable, StateFlag...)}
*
- * @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 player, StateFlag... flags) {
- return getApplicableRegions(location).queryState(player, flags);
+ public State queryState(Location location, @Nullable LocalPlayer 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.
- *
- * {@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.
- *
- * @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...)
+ * Convenience method for
+ * {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryState(RegionAssociable, StateFlag...)
+ * .queryState(RegionAssociable, StateFlag...)}
*/
@Nullable
- public State queryState(Location location, @Nullable RegionAssociable associable, StateFlag... flags) {
- return getApplicableRegions(location).queryState(associable, flags);
+ public State queryState(Location location, @Nullable RegionAssociable subject, StateFlag... flags) {
+ return getApplicableRegions(location).queryState(subject, 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.
- *
- * 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}.
+ * Convenience method for
+ * {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryValue(RegionAssociable, Flag)
+ * .queryValue(RegionAssociable, Flag)}
*
- * {@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.
- *
- * @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)
+ * @deprecated use {@link #queryValue(Location, RegionAssociable, Flag)} instead, will be removed in WorldGuard 8
*/
+ @Deprecated(forRemoval = true)
@Nullable
- public V queryValue(Location location, @Nullable LocalPlayer player, Flag flag) {
- return getApplicableRegions(location).queryValue(player, flag);
+ public V queryValue(Location location, @Nullable LocalPlayer subject, Flag 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.
- *
- * 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}.
- *
- * {@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.
- *
- * @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)
+ * Convenience method for
+ * {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryValue(RegionAssociable, Flag)
+ * .queryValue(RegionAssociable, Flag)}
*/
@Nullable
- public V queryValue(Location location, @Nullable RegionAssociable associable, Flag flag) {
- return getApplicableRegions(location).queryValue(associable, flag);
+ public V queryValue(Location location, @Nullable RegionAssociable subject, Flag flag) {
+ return getApplicableRegions(location).queryValue(subject, 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.
- *
- * 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.
- *
- * @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 queryMapValue(Location location, @Nullable RegionAssociable subject, MapFlag flag, K key) {
@@ -425,73 +237,43 @@ public V queryMapValue(Location location, @Nullable RegionAssociable subj
}
/**
- * 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.
- *
- * 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.
- *
- * It's possible to provide a fallback flag for the case when the key doesn't
- * exist in the {@link MapFlag}.
- *
- * @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 queryMapValue(Location location, @Nullable RegionAssociable subject, MapFlag flag, K key, Flag fallback) {
+ public V queryMapValue(Location location, @Nullable RegionAssociable subject, MapFlag flag, K key, @Nullable Flag 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)}
*
- * {@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.
- *
- * @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 Collection queryAllValues(Location location, @Nullable LocalPlayer player, Flag flag) {
- return getApplicableRegions(location).queryAllValues(player, flag);
+ @Deprecated(forRemoval = true)
+ public Collection queryAllValues(Location location, @Nullable LocalPlayer subject, Flag 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.
- *
- * {@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.
- *
- * @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 Collection queryAllValues(Location location, @Nullable RegionAssociable subject, Flag flag) {
+ return getApplicableRegions(location).queryAllValues(subject, flag);
+ }
+
+ /**
+ * Convenience method for
+ * {@link #getApplicableRegions(Location)}{@link ApplicableRegionSet#queryAllValues(RegionAssociable, Flag, boolean)
+ * .queryAllValues(RegionAssociable, Flag, boolean)}
*/
- public Collection queryAllValues(Location location, @Nullable RegionAssociable associable, Flag flag) {
- return getApplicableRegions(location).queryAllValues(associable, flag);
+ public Collection queryAllValues(Location location, @Nullable RegionAssociable subject, Flag flag, boolean acceptOne) {
+ return getApplicableRegions(location).queryAllValues(subject, flag, acceptOne);
}
/**