From 2dff68071f3a7f7b15a83f7a6fe3f3c59204acd7 Mon Sep 17 00:00:00 2001 From: stonar96 Date: Sat, 8 Oct 2022 14:20:29 +0200 Subject: [PATCH] Add non-player members --- .../bukkit/BukkitWorldConfiguration.java | 1 + .../worldguard/bukkit/WorldGuardPlugin.java | 63 +++++++++++++++ .../commands/region/RegionCommands.java | 18 +++++ .../worldguard/config/WorldConfiguration.java | 1 + .../worldguard/domains/DefaultDomain.java | 5 ++ .../com/sk89q/worldguard/domains/Domain.java | 8 ++ .../sk89q/worldguard/domains/GroupDomain.java | 5 ++ .../worldguard/domains/PlayerDomain.java | 5 ++ .../domains/registry/UnknownDomain.java | 5 ++ .../AbstractRegionOverlapAssociation.java | 62 +++++--------- .../protection/regions/ProtectedRegion.java | 80 +++++++++++++++++++ .../worldguard/domains/CustomUUIDDomain.java | 5 ++ 12 files changed, 217 insertions(+), 41 deletions(-) diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java index 936f9803f..eed50d6bb 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/BukkitWorldConfiguration.java @@ -296,6 +296,7 @@ public void loadConfiguration() { maxClaimVolume = getInt("regions.max-claim-volume", 30000); claimOnlyInsideExistingRegions = getBoolean("regions.claim-only-inside-existing-regions", false); setParentOnClaim = getString("regions.set-parent-on-claim", ""); + nonplayerBorderBypassOnClaim = getBoolean("regions.nonplayer-border-bypass-on-claim", false); boundedLocationFlags = getBoolean("regions.location-flags-only-inside-regions", false); maxRegionCountPerPlayer = getInt("regions.max-region-count-per-player.default", 7); diff --git a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java index e95d1aec1..21567dd0d 100644 --- a/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java +++ b/worldguard-bukkit/src/main/java/com/sk89q/worldguard/bukkit/WorldGuardPlugin.java @@ -64,6 +64,8 @@ import com.sk89q.worldguard.commands.GeneralCommands; import com.sk89q.worldguard.commands.ProtectionCommands; import com.sk89q.worldguard.commands.ToggleCommands; +import com.sk89q.worldguard.domains.CustomDomain; +import com.sk89q.worldguard.domains.registry.CustomDomainContext; import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry; import com.sk89q.worldguard.protection.flags.Flag; import com.sk89q.worldguard.protection.flags.Flags; @@ -93,8 +95,14 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; @@ -132,6 +140,61 @@ public static WorldGuardPlugin inst() { return inst; } + @Override + public void onLoad() { + WorldGuard.getInstance().getDomainRegistry().register("nonplayer-protection-domains", n -> new CustomDomain(n) { + private final Set nonplayerProtectionDomains = new HashSet<>(); + + @Override + public void parseInput(CustomDomainContext context) { + setDirty(true); + nonplayerProtectionDomains.addAll(Arrays.asList(context.getUserInput().split(","))); + } + + @Override + public void unmarshal(Object o) { + nonplayerProtectionDomains.clear(); + nonplayerProtectionDomains.addAll((Collection) o); + } + + @Override + public Object marshal() { + return new ArrayList<>(nonplayerProtectionDomains); + } + + @Override + public boolean contains(UUID uniqueId) { + return false; + } + + @Override + public boolean contains(String playerName) { + return false; + } + + @Override + public boolean containsNonplayer(String nonplayerProtectionDomain) { + return nonplayerProtectionDomains.contains(nonplayerProtectionDomain); + } + + @Override + public int size() { + return nonplayerProtectionDomains.size(); + } + + @Override + public void clear() { + setDirty(true); + nonplayerProtectionDomains.clear(); + } + + @Override + public String toString() { + return " " + nonplayerProtectionDomains; + } + }); + } + /** * Called on plugin enable. */ diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommands.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommands.java index 104184955..21bef1408 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommands.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommands.java @@ -53,6 +53,9 @@ import com.sk89q.worldguard.commands.task.RegionRemover; import com.sk89q.worldguard.config.ConfigurationManager; import com.sk89q.worldguard.config.WorldConfiguration; +import com.sk89q.worldguard.domains.CustomDomain; +import com.sk89q.worldguard.domains.registry.CustomDomainContext; +import com.sk89q.worldguard.domains.registry.InvalidDomainFormat; import com.sk89q.worldguard.internal.permission.RegionPermissionModel; import com.sk89q.worldguard.protection.ApplicableRegionSet; import com.sk89q.worldguard.protection.FlagValueCalculator; @@ -83,7 +86,9 @@ import com.sk89q.worldguard.util.logging.LoggerToChatHandler; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.concurrent.Callable; import java.util.logging.Level; @@ -330,6 +335,19 @@ public void claim(CommandContext args, Actor sender) throws CommandException { } } + if (wcfg.nonplayerBorderBypassOnClaim) { + CustomDomain customDomain = WorldGuard.getInstance().getDomainRegistry().createDomain("nonplayer-protection-domains"); + + try { + customDomain.parseInput(CustomDomainContext.create().setInput(player.getUniqueId().toString()).build()); + } catch (InvalidDomainFormat e) { + throw new CommandException(e.getMessage()); + } + + region.getOwners().addCustomDomain(customDomain); + region.setFlag(Flags.NONPLAYER_PROTECTION_DOMAINS, new HashSet<>(Arrays.asList(player.getUniqueId().toString()))); + } + region.getOwners().addPlayer(player); manager.addRegion(region); player.print(TextComponent.of(String.format("A new region has been claimed named '%s'.", id))); diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java b/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java index 33a92339c..dfdcf8e5a 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/config/WorldConfiguration.java @@ -130,6 +130,7 @@ public abstract class WorldConfiguration { public int maxClaimVolume; public boolean claimOnlyInsideExistingRegions; public String setParentOnClaim; + public boolean nonplayerBorderBypassOnClaim; public int maxRegionCountPerPlayer; public boolean antiWolfDumbness; public boolean signChestProtection; diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/DefaultDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/DefaultDomain.java index d14604920..37cf55ec1 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/DefaultDomain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/DefaultDomain.java @@ -324,6 +324,11 @@ public boolean contains(String playerName) { return playerDomain.contains(playerName); } + @Override + public boolean containsNonplayer(String nonplayerProtectionDomain) { + return customDomains.stream().anyMatch(d -> d.containsNonplayer(nonplayerProtectionDomain)); + } + @Override public int size() { return groupDomain.size() + playerDomain.size() + customDomains.size(); diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/Domain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/Domain.java index 8c3235aba..24ce6e3fc 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/Domain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/Domain.java @@ -58,6 +58,14 @@ public interface Domain { @Deprecated boolean contains(String playerName); + /** + * Returns true if a domain contains a non-player. + * + * @param nonplayerProtectionDomain the non-player protection domain to check + * @return whether this domain contains {@code nonplayerProtectionDomain} + */ + boolean containsNonplayer(String nonplayerProtectionDomain); + /** * Get the number of entries. * diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/GroupDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/GroupDomain.java index 83d6d9c3f..277ef863a 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/GroupDomain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/GroupDomain.java @@ -120,6 +120,11 @@ public boolean contains(String playerName) { return false; // GroupDomains can't contain player names. } + @Override + public boolean containsNonplayer(String nonplayerProtectionDomain) { + return false; // GroupDomains can't contain non-players. + } + @Override public int size() { return groups.size(); diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/PlayerDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/PlayerDomain.java index 084946219..cba554b15 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/PlayerDomain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/PlayerDomain.java @@ -184,6 +184,11 @@ public boolean contains(String playerName) { return names.contains(playerName.trim().toLowerCase()); } + @Override + public boolean containsNonplayer(String nonplayerProtectionDomain) { + return false; // PlayerDomains can't contain non-players. + } + @Override public int size() { return names.size() + uniqueIds.size(); diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/UnknownDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/UnknownDomain.java index 2d093ca0d..d6b82e515 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/UnknownDomain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/UnknownDomain.java @@ -58,6 +58,11 @@ public boolean contains(String playerName) { return false; } + @Override + public boolean containsNonplayer(String nonplayerProtectionDomain) { + return false; + } + @Override public int size() { return 0; diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/association/AbstractRegionOverlapAssociation.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/association/AbstractRegionOverlapAssociation.java index 0cbd78fe0..c4b1823a0 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/association/AbstractRegionOverlapAssociation.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/association/AbstractRegionOverlapAssociation.java @@ -22,13 +22,9 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.sk89q.worldguard.domains.Association; -import com.sk89q.worldguard.protection.FlagValueCalculator; -import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import javax.annotation.Nullable; -import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -64,39 +60,22 @@ protected void calcMaxPriority() { this.maxPriorityRegions = bestRegions; } - private boolean checkNonplayerProtectionDomains(Iterable source, Collection domains) { - if (source == null || domains == null || domains.isEmpty()) { - return false; - } - - for (ProtectedRegion region : source) { - // Potential endless recurrence? No, because there is no region group flag. - Set regionDomains = FlagValueCalculator.getEffectiveFlagOf(region, Flags.NONPLAYER_PROTECTION_DOMAINS, this); - - if (regionDomains == null || regionDomains.isEmpty()) { - continue; - } - - if (!Collections.disjoint(regionDomains, domains)) { - return true; - } - } - - return false; - } - @Override public Association getAssociation(List regions) { checkNotNull(source); + boolean member = false; + for (ProtectedRegion region : regions) { - while (region != null) { - if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty())) { + ProtectedRegion current = region; + + while (current != null) { + if ((current.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty())) { return Association.OWNER; } - if (source.contains(region)) { + if (source.contains(current)) { if (useMaxPriorityAssociation) { - int priority = region.getPriority(); + int priority = current.getPriority(); if (priority == maxPriority) { return Association.OWNER; } @@ -105,23 +84,24 @@ public Association getAssociation(List regions) { } } - Set source; + current = current.getParent(); + } - if (useMaxPriorityAssociation) { - source = maxPriorityRegions; - } else { - source = this.source; - } + Set source; - // Potential endless recurrence? No, because there is no region group flag. - if (checkNonplayerProtectionDomains(source, FlagValueCalculator.getEffectiveFlagOf(region, Flags.NONPLAYER_PROTECTION_DOMAINS, this))) { - return Association.OWNER; - } + if (useMaxPriorityAssociation) { + source = maxPriorityRegions; + } else { + source = this.source; + } - region = region.getParent(); + if (source.stream().anyMatch(region::isOwner)) { + return Association.OWNER; + } else if (!member && source.stream().anyMatch(region::isMember)) { + member = true; } } - return Association.NON_MEMBER; + return member ? Association.MEMBER : Association.NON_MEMBER; } } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedRegion.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedRegion.java index 76a527ccc..3cf2200fd 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedRegion.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/regions/ProtectedRegion.java @@ -26,7 +26,9 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.domains.DefaultDomain; +import com.sk89q.worldguard.protection.FlagValueCalculator; import com.sk89q.worldguard.protection.flags.Flag; +import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.util.ChangeTracked; import com.sk89q.worldguard.util.Normal; @@ -35,6 +37,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.regex.Pattern; @@ -325,6 +328,36 @@ public boolean isOwner(String playerName) { return false; } + /** + * Checks whether a region is an owner of this region or any of its parents. + * + * @param region region to check + * @return whether an owner + */ + public boolean isOwner(ProtectedRegion region) { + checkNotNull(region); + Set nonplayerProtectionDomains = FlagValueCalculator.getEffectiveFlagOf(region, Flags.NONPLAYER_PROTECTION_DOMAINS, null); + + if (nonplayerProtectionDomains == null) { + return false; + } + + if (nonplayerProtectionDomains.stream().anyMatch(owners::containsNonplayer)) { + return true; + } + + ProtectedRegion curParent = getParent(); + while (curParent != null) { + if (nonplayerProtectionDomains.stream().anyMatch(curParent.getOwners()::containsNonplayer)) { + return true; + } + + curParent = curParent.getParent(); + } + + return false; + } + /** * Checks whether a player is a member OR OWNER of the region * or any of its parents. @@ -374,6 +407,23 @@ public boolean isMember(String playerName) { return false; } + /** + * Checks whether a region is a member OR OWNER of this region + * or any of its parents. + * + * @param region region to check + * @return whether an owner or member + */ + public boolean isMember(ProtectedRegion region) { + checkNotNull(region); + + if (isOwner(region)) { + return true; + } + + return isMemberOnly(region); + } + /** * Checks whether a player is a member of the region or any of its parents. * @@ -399,6 +449,36 @@ public boolean isMemberOnly(LocalPlayer player) { return false; } + /** + * Checks whether a region is a member of this region or any of its parents. + * + * @param region region to check + * @return whether an member + */ + public boolean isMemberOnly(ProtectedRegion region) { + checkNotNull(region); + Set nonplayerProtectionDomains = FlagValueCalculator.getEffectiveFlagOf(region, Flags.NONPLAYER_PROTECTION_DOMAINS, null); + + if (nonplayerProtectionDomains == null) { + return false; + } + + if (nonplayerProtectionDomains.stream().anyMatch(members::containsNonplayer)) { + return true; + } + + ProtectedRegion curParent = getParent(); + while (curParent != null) { + if (nonplayerProtectionDomains.stream().anyMatch(curParent.getMembers()::containsNonplayer)) { + return true; + } + + curParent = curParent.getParent(); + } + + return false; + } + /** * Get a flag's value. * diff --git a/worldguard-core/src/test/java/com/sk89q/worldguard/domains/CustomUUIDDomain.java b/worldguard-core/src/test/java/com/sk89q/worldguard/domains/CustomUUIDDomain.java index 1f9dfd7bf..525a5c0c6 100644 --- a/worldguard-core/src/test/java/com/sk89q/worldguard/domains/CustomUUIDDomain.java +++ b/worldguard-core/src/test/java/com/sk89q/worldguard/domains/CustomUUIDDomain.java @@ -57,6 +57,11 @@ public boolean contains(String playerName) { return false; } + @Override + public boolean containsNonplayer(String nonplayerProtectionDomain) { + return false; + } + @Override public void clear() { test = null;