diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/SetFlag.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/SetFlag.java index 408420ec..de334327 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/SetFlag.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/SetFlag.java @@ -20,18 +20,25 @@ package com.sk89q.worldguard.protection.flags; import com.google.common.collect.Sets; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Stores a set of types. */ public class SetFlag extends Flag> { + private static final Pattern ANY_MODIFIER = Pattern.compile("^(add|sub|subtract|rem|remove) (.*)$"); + private static final Pattern REMOVE_MODIFIERS = Pattern.compile("^(sub|subtract|rem|remove) (.*)$"); + private Flag subFlag; public SetFlag(String name, RegionGroup defaultGroup, Flag subFlag) { @@ -60,10 +67,32 @@ public class SetFlag extends Flag> { return Sets.newHashSet(); } else { Set items = Sets.newHashSet(); + boolean subtractive = false; + + // If the input starts with particular keywords, attempt to load the existing values, + // and make this a modification, instead of an overwrite. + Matcher keywordMatcher = ANY_MODIFIER.matcher(input); + if (keywordMatcher.matches()) { + ProtectedRegion region = Objects.requireNonNull((ProtectedRegion) context.get("region")); + + Set existingValue = region.getFlag(this); + if (existingValue != null) { + items.addAll(existingValue); + } + + subtractive = REMOVE_MODIFIERS.matcher(input).matches(); + input = keywordMatcher.group(2); + } for (String str : input.split(",")) { FlagContext copy = context.copyWith(null, str, null); - items.add(subFlag.parseInput(copy)); + + T subFlagValue = subFlag.parseInput(copy); + if (subtractive) { + items.remove(subFlagValue); + } else { + items.add(subFlagValue); + } } return items;