From 832c82568402e6119ecd8c05622ec4c15059763f Mon Sep 17 00:00:00 2001 From: JOO200 Date: Sun, 18 Oct 2020 17:55:50 +0200 Subject: [PATCH] Improved queryMapValue to return defaultValue instead of null --- .../protection/FlagValueCalculator.java | 16 +++- .../protection/regions/RegionQuery.java | 78 +++++++++++++++++++ 2 files changed, 90 insertions(+), 4 deletions(-) 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 4f58e9c52..b30de0cc7 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 @@ -268,7 +268,7 @@ public V queryMapValue(@Nullable RegionAssociable subject, MapFlag if (effectiveValue != null) { minimumPriority = getPriority(region); consideredValues.put(region, effectiveValue); - } else { + } else if (fallback != null) { effectiveValue = getEffectiveFlag(region, fallback, subject); if (effectiveValue != null) { minimumPriority = getPriority(region); @@ -278,9 +278,17 @@ public V queryMapValue(@Nullable RegionAssociable subject, MapFlag addParents(ignoredParents, region); } - V finalValue = flag.getValueFlag().chooseValue(consideredValues.values()); - if (finalValue == null) return fallback.chooseValue(fallbackValues.values()); - return finalValue; + + + if (consideredValues.isEmpty()) { + if (fallback != null && !fallbackValues.isEmpty()) { + return fallback.chooseValue(fallbackValues.values()); + } + V defaultValue = flag.getValueFlag().getDefault(); + return defaultValue != null ? defaultValue : fallback != null ? fallback.getDefault() : null; + } + + return flag.getValueFlag().chooseValue(consideredValues.values()); } @Nullable 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 a3f24492b..03a41a0f7 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 @@ -173,6 +173,56 @@ public boolean testBuild(Location location, RegionAssociable associable, StateFl queryState(location, associable, flag))); } + /** + * 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) + */ + 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) + )); + } + /** * Test whether the (effective) value for a list of state flags equals * {@code ALLOW}. @@ -345,6 +395,34 @@ public V queryMapValue(Location location, @Nullable RegionAssociable subj return getApplicableRegions(location).queryMapValue(subject, flag, 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.

+ * + *

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} + */ + @Nullable + public V queryMapValue(Location location, @Nullable RegionAssociable subject, MapFlag flag, K key, 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,