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); } /**