Improved queryMapValue to return defaultValue instead of null

This commit is contained in:
JOO200 2020-10-18 17:55:50 +02:00 committed by wizjany
parent 88c91ce3fc
commit 89c6a33b90
2 changed files with 90 additions and 4 deletions

View File

@ -268,7 +268,7 @@ public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V>
if (effectiveValue != null) { if (effectiveValue != null) {
minimumPriority = getPriority(region); minimumPriority = getPriority(region);
consideredValues.put(region, effectiveValue); consideredValues.put(region, effectiveValue);
} else { } else if (fallback != null) {
effectiveValue = getEffectiveFlag(region, fallback, subject); effectiveValue = getEffectiveFlag(region, fallback, subject);
if (effectiveValue != null) { if (effectiveValue != null) {
minimumPriority = getPriority(region); minimumPriority = getPriority(region);
@ -278,9 +278,17 @@ public <V, K> V queryMapValue(@Nullable RegionAssociable subject, MapFlag<K, V>
addParents(ignoredParents, region); 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 @Nullable

View File

@ -173,6 +173,56 @@ public boolean testBuild(Location location, RegionAssociable associable, StateFl
queryState(location, associable, flag))); 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.
*
* <p>Use this method when checking flags that are related to build
* protection. For example, lighting fire in a region should not be
* permitted unless the player is a member of the region or the
* LIGHTER flag allows it. However, the LIGHTER flag should be able
* to allow lighting fires even if BUILD is set to DENY.</p>
*
* <p>This method does include parameters for a {@link MapFlag}.</p>
*
* <p>How this method works (BUILD can be overridden by other flags but
* not the other way around) is inconsistent, but it's required for
* legacy reasons.</p>
*
* <p>This method does not check the region bypass permission. That must
* be done by the calling code.</p>
*
* @param location the location
* @param associable an optional associable
* @param mapFlag the MapFlag
* @param key the key for the MapFlag
* @param fallback the fallback flag for MapFlag
* @param flag the flags
* @return true if the result was {@code ALLOW}
* @see RegionResultSet#queryValue(RegionAssociable, Flag)
*/
public <K> boolean testBuild(Location location, RegionAssociable associable, MapFlag<K, State> mapFlag, K key,
@Nullable StateFlag fallback, StateFlag... flag) {
if (mapFlag == null)
return testBuild(location, associable, flag);
if (flag.length == 0) {
return StateFlag.test(StateFlag.combine(
StateFlag.denyToNone(queryState(location, associable, Flags.BUILD)),
queryMapValue(location, associable, mapFlag, key, fallback)
));
}
return StateFlag.test(StateFlag.combine(
StateFlag.denyToNone(queryState(location, associable, Flags.BUILD)),
queryMapValue(location, associable, mapFlag, key, fallback),
queryState(location, associable, flag)
));
}
/** /**
* Test whether the (effective) value for a list of state flags equals * Test whether the (effective) value for a list of state flags equals
* {@code ALLOW}. * {@code ALLOW}.
@ -345,6 +395,34 @@ public <V, K> V queryMapValue(Location location, @Nullable RegionAssociable subj
return getApplicableRegions(location).queryMapValue(subject, flag, key); 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.
*
* <p>A subject can be provided that is used to determine whether the value
* of a flag on a particular region should be used. For example, if a
* flag's region group is set to {@link RegionGroup#MEMBERS} and the given
* subject is not a member, then the region would be skipped when
* querying that flag. If {@code null} is provided for the subject, then
* only flags that use {@link RegionGroup#ALL},
* {@link RegionGroup#NON_MEMBERS}, etc. will apply.</p>
*
* <p>It's possible to provide a fallback flag for the case when the key doesn't
* exist in the {@link MapFlag}.</p>
*
* @param subject an optional subject, which would be used to determine the region group to apply
* @param flag the flag of type {@link MapFlag}
* @param key the key for the map flag
* @param fallback the fallback flag
* @return a value, which could be {@code null}
*/
@Nullable
public <V, K> V queryMapValue(Location location, @Nullable RegionAssociable subject, MapFlag<K, V> flag, K key, Flag<V> fallback) {
return getApplicableRegions(location).queryMapValue(subject, flag, key, fallback);
}
/** /**
* Get the effective values for a flag, returning a collection of all * 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, * values. It is up to the caller to determine which value, if any,