From 40317394991d09dd10e7e2d8a4c6701f6c5d54b3 Mon Sep 17 00:00:00 2001 From: JOO200 Date: Wed, 29 Dec 2021 21:20:54 +0100 Subject: [PATCH 01/11] Add Api Domains to add custom domains --- .../worldguard/bukkit/WorldGuardPlugin.java | 2 + .../java/com/sk89q/worldguard/WorldGuard.java | 13 ++ .../sk89q/worldguard/domains/ApiDomain.java | 69 ++++++++ .../worldguard/domains/DefaultDomain.java | 42 ++++- .../registry/DomainConflictException.java | 26 +++ .../domains/registry/DomainRegistry.java | 91 +++++++++++ .../registry/SimpleDomainRegistry.java | 150 ++++++++++++++++++ .../domains/registry/UnknownDomain.java | 67 ++++++++ .../managers/storage/file/YamlRegionFile.java | 16 ++ 9 files changed, 472 insertions(+), 4 deletions(-) create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/domains/ApiDomain.java create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainConflictException.java create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/UnknownDomain.java 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 e0f83634a..e95d1aec1 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,7 @@ import com.sk89q.worldguard.commands.GeneralCommands; import com.sk89q.worldguard.commands.ProtectionCommands; import com.sk89q.worldguard.commands.ToggleCommands; +import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry; import com.sk89q.worldguard.protection.flags.Flag; import com.sk89q.worldguard.protection.flags.Flags; import com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry; @@ -211,6 +212,7 @@ public void onEnable() { }); ((SimpleFlagRegistry) WorldGuard.getInstance().getFlagRegistry()).setInitialized(true); + ((SimpleDomainRegistry) WorldGuard.getInstance().getDomainRegistry()).setInitialized(true); // Enable metrics final Metrics metrics = new Metrics(this, BSTATS_PLUGIN_ID); // bStats plugin id diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/WorldGuard.java b/worldguard-core/src/main/java/com/sk89q/worldguard/WorldGuard.java index 637eee7bd..cc287c6c3 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/WorldGuard.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/WorldGuard.java @@ -24,6 +24,8 @@ import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import com.sk89q.minecraft.util.commands.CommandException; +import com.sk89q.worldguard.domains.registry.DomainRegistry; +import com.sk89q.worldguard.domains.registry.SimpleDomainRegistry; import com.sk89q.worldguard.util.profile.cache.HashMapCache; import com.sk89q.worldguard.util.profile.cache.ProfileCache; import com.sk89q.worldguard.util.profile.cache.SQLiteCache; @@ -55,6 +57,7 @@ public final class WorldGuard { private WorldGuardPlatform platform; private final SimpleFlagRegistry flagRegistry = new SimpleFlagRegistry(); + private final SimpleDomainRegistry domainRegistry = new SimpleDomainRegistry(); private final Supervisor supervisor = new SimpleSupervisor(); private ProfileCache profileCache; private ProfileService profileService; @@ -116,6 +119,16 @@ public FlagRegistry getFlagRegistry() { return this.flagRegistry; } + + /** + * Get the domain registry. + * + * @return the domain registry + */ + public DomainRegistry getDomainRegistry() { + return this.domainRegistry; + } + /** * Get the supervisor. * diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/ApiDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/ApiDomain.java new file mode 100644 index 000000000..49e7ddddf --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/ApiDomain.java @@ -0,0 +1,69 @@ +/* + * 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.domains; + +import com.sk89q.worldguard.LocalPlayer; + +import java.util.regex.Pattern; + +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class ApiDomain implements Domain { + private static final Pattern VALID_NAME = Pattern.compile("^[:A-Za-z0-9\\-]{1,40}$"); + + private String name; + + public ApiDomain(String name) { + this.name = name; + } + + /** + * Get the name of the domain resolver. + * + * @return The name of the domain + */ + public String getName() { + return name; + } + + /** + * Convert the current Domain to a storable foramt + * + * @return The marshalled type + */ + public abstract Object marshal(); + + /** + * Test whether a flag name is valid. + * + * @param name The flag name + * @return Whether the name is valid + */ + public static boolean isValidName(String name) { + checkNotNull(name, "name"); + return VALID_NAME.matcher(name).matches(); + } + + + @Override + public boolean contains(LocalPlayer player) { + return contains(player.getUniqueId()); + } +} 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 3030a9c10..601b1fbae 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 @@ -22,8 +22,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.sk89q.worldguard.util.profile.Profile; -import com.sk89q.worldguard.util.profile.cache.ProfileCache; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; @@ -31,9 +29,14 @@ import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.util.ChangeTracked; +import com.sk89q.worldguard.util.profile.Profile; +import com.sk89q.worldguard.util.profile.cache.ProfileCache; import javax.annotation.Nullable; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -50,6 +53,8 @@ public class DefaultDomain implements Domain, ChangeTracked { private PlayerDomain playerDomain = new PlayerDomain(); private GroupDomain groupDomain = new GroupDomain(); + private Set apiDomains = new HashSet<>(); + /** * Create a new domain. */ @@ -104,6 +109,35 @@ public void setGroupDomain(GroupDomain groupDomain) { this.groupDomain = new GroupDomain(groupDomain); } + /** + * Add new api domains + * + * @param apiDomain a domain + */ + public void addApiDomain(ApiDomain apiDomain) { + checkNotNull(apiDomain); + this.apiDomains.add(apiDomain); + } + + /** + * Set the api domains to a specified value + * + * @param apiDomains the domains + */ + public void setApiDomains(Collection apiDomains) { + checkNotNull(apiDomains); + this.apiDomains = new HashSet<>(apiDomains); + } + + /** + * Get all api domains + * + * @return a unmodifiable copy of the domains + */ + public Set getApiDomains() { + return Collections.unmodifiableSet(this.apiDomains); + } + /** * Add the given player to the domain, identified by the player's name. * @@ -242,12 +276,12 @@ public Set getGroups() { @Override public boolean contains(LocalPlayer player) { - return playerDomain.contains(player) || groupDomain.contains(player); + return playerDomain.contains(player) || groupDomain.contains(player) || apiDomains.stream().anyMatch(d -> d.contains(player)); } @Override public boolean contains(UUID uniqueId) { - return playerDomain.contains(uniqueId); + return playerDomain.contains(uniqueId) || apiDomains.stream().anyMatch(d -> d.contains(uniqueId)); } @Override diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainConflictException.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainConflictException.java new file mode 100644 index 000000000..4ab7e933b --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainConflictException.java @@ -0,0 +1,26 @@ +/* + * 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.domains.registry; + +public class DomainConflictException extends RuntimeException { + public DomainConflictException(String message) { + super(message); + } +} diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java new file mode 100644 index 000000000..bad155147 --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java @@ -0,0 +1,91 @@ +/* + * 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.domains.registry; + +import com.sk89q.worldguard.domains.ApiDomain; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.Map; + +public interface DomainRegistry extends Iterable> { + abstract static class Factory { + public abstract T create(String name, Object values); + } + + /** + * Register a new Domain + * + *

There may be an appropiate time to register domains. if domains are + * registered outside this time, then an exception may be thrown.

+ * + * @param domain The domain + * @throws DomainConflictException Thrown when already an existing domain exists with the same name + * @throws IllegalStateException If it is not the right time to register new domains + */ + void register(String name, Factory domain) throws DomainConflictException; + + /** + * Register a collection of domains. + * + *

There may be an appropriate time to register domains. If domains are + * registered outside this time, then an exception may be thrown.

+ * + *

If there is a domain conflict, then an error will be logged but + * no exception will be thrown.

+ * + * @param flags a collection of flags + * @throws IllegalStateException If it is not the right time to register new flags + */ + void registerAll(Map> domains); + + /** + * Get the domain by its name. + * + * @param name The name + * @return The domain, if it has been registered + */ + @Nullable + Factory get(String name); + + /** + * Get all domains + * + * @return All domains + */ + List> getAll(); + + /** + * Unmarshal a raw map of values into a list of domains with their + * unmarshalled values. + * + * @param rawValues The raw values map + * @param createUnknown Whether "just in time" domains should be created for unknown domains + * @return The unmarshalled domain list + */ + List unmarshal(Map rawValues, boolean createUnknown); + + /** + * Get the number of registered domains. + * + * @return The number of registered domains + */ + int size(); +} diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java new file mode 100644 index 000000000..11a8ebaf5 --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java @@ -0,0 +1,150 @@ +/* + * 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.domains.registry; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterators; +import com.google.common.collect.Maps; +import com.sk89q.worldguard.domains.ApiDomain; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentMap; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.google.common.base.Preconditions.checkNotNull; + +public class SimpleDomainRegistry implements DomainRegistry { + private static final Logger log = Logger.getLogger(SimpleDomainRegistry.class.getCanonicalName()); + + private final Object lock = new Object(); + private final ConcurrentMap> domains = Maps.newConcurrentMap(); + private boolean initialized = false; + + public boolean isInitialized() { + return initialized; + } + + public void setInitialized(boolean initialized) { + this.initialized = initialized; + } + + @Override + public void register(String name, Factory domain) throws DomainConflictException { + synchronized (lock) { + if (initialized) { + throw new IllegalStateException("New flags cannot be registered at this time"); + } + + forceRegister(name, domain); + } + } + + @Override + public void registerAll(Map> domains) { + synchronized (lock) { + for (Map.Entry> entry : domains.entrySet()) { + try { + register(entry.getKey(), entry.getValue()); + } catch (DomainConflictException e) { + log.log(Level.WARNING, e.getMessage()); + } + } + } + } + + private > T forceRegister(String name, T domain) throws DomainConflictException { + checkNotNull(domain, "domain"); + checkNotNull(name, "name"); + + synchronized (lock) { + if (domains.containsKey(name)) { + throw new DomainConflictException("A domain already exists by the name " + name); + } + + domains.put(name, domain); + } + + return domain; + } + + @Nullable + @Override + public Factory get(String name) { + checkNotNull(name, "name"); + return domains.get(name.toLowerCase()); + } + + @Override + public List> getAll() { + return ImmutableList.copyOf(domains.values()); + } + + private ApiDomain getOrCreate(String name, Object value, boolean createUnknown) { + Factory domain = get(name); + + if (domain != null) { + return domain.create(name, value); + } + + synchronized (lock) { + domain = get(name); // Load again because the previous load was not synchronized + if (domain != null) { + return domain.create(name, value); + } + if (createUnknown) { + Factory unknownFactory = forceRegister(name, UnknownDomain.FACTORY); + return unknownFactory.create(name, value); + } + } + return null; + } + + public List unmarshal(Map rawValues, boolean createUnknown) { + checkNotNull(rawValues, "rawValues"); + + List domainList = new ArrayList<>(); + + for (Map.Entry entry : rawValues.entrySet()) { + try { + ApiDomain domain = getOrCreate(entry.getKey(), entry.getValue(), createUnknown); + domainList.add(domain); + } catch (Throwable e) { + log.log(Level.WARNING, "Failed to unmarshal domain for " + entry.getKey(), e); + } + } + return domainList; + } + + @Override + public int size() { + return domains.size(); + } + + @Override + public Iterator> iterator() { + return Iterators.unmodifiableIterator(domains.values().iterator()); + } +} 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 new file mode 100644 index 000000000..551f5c657 --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/UnknownDomain.java @@ -0,0 +1,67 @@ +/* + * 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.domains.registry; + +import com.sk89q.worldguard.domains.ApiDomain; + +import javax.annotation.Nullable; +import java.util.UUID; + +public class UnknownDomain extends ApiDomain { + public static DomainRegistry.Factory FACTORY = new DomainRegistry.Factory() { + @Override + public UnknownDomain create(String name, Object values) { + return new UnknownDomain(name, values); + } + }; + + Object o; + + public UnknownDomain(String name, Object values) { + super(name); + this.o = values; + } + + + @Override + public Object marshal() { + return o; + } + + @Override + public boolean contains(UUID uniqueId) { + return false; + } + + @Override + public boolean contains(String playerName) { + return false; + } + + @Override + public int size() { + return 0; + } + + @Override + public void clear() { + o = null; + } +} diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java index 9aebc5ac7..1d9187412 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java @@ -27,6 +27,8 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.domains.ApiDomain; import com.sk89q.worldguard.domains.DefaultDomain; import com.sk89q.worldguard.protection.flags.FlagUtil; import com.sk89q.worldguard.protection.flags.registry.FlagRegistry; @@ -284,6 +286,12 @@ private DefaultDomain parseDomain(YAMLNode node) { } } + YAMLNode apiDomains = node.getNode("api"); + if (apiDomains != null) { + List parsedDomains = WorldGuard.getInstance().getDomainRegistry().unmarshal(apiDomains.getMap(), true); + domain.setApiDomains(parsedDomains); + } + return domain; } @@ -304,6 +312,14 @@ private Map getDomainData(DefaultDomain domain) { setDomainData(domainData, "unique-ids", domain.getUniqueIds()); setDomainData(domainData, "groups", domain.getGroups()); + if (!domain.getApiDomains().isEmpty()) { + Map values = new HashMap<>(); + for (ApiDomain apiDomain : domain.getApiDomains()) { + values.put(apiDomain.getName(), apiDomain.marshal()); + } + domainData.put("api", values); + } + return domainData; } From 3b7c6fb9e1031424d08b2395b9a48ae94b2bc20a Mon Sep 17 00:00:00 2001 From: JOO200 Date: Thu, 30 Dec 2021 20:38:36 +0100 Subject: [PATCH 02/11] Improved api usage for CustomDomains --- .../domains/registry/DomainFactory.java | 28 +++++++++++++++++++ .../domains/registry/DomainRegistry.java | 15 ++++------ .../registry/SimpleDomainRegistry.java | 20 ++++++------- .../domains/registry/UnknownDomain.java | 7 +---- 4 files changed, 45 insertions(+), 25 deletions(-) create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainFactory.java diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainFactory.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainFactory.java new file mode 100644 index 000000000..7fff6f661 --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainFactory.java @@ -0,0 +1,28 @@ +/* + * 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.domains.registry; + +import com.sk89q.worldguard.domains.ApiDomain; + +@FunctionalInterface +public interface DomainFactory { + T create(String name, Object values); +} diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java index bad155147..ead7a7801 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java @@ -25,10 +25,7 @@ import java.util.List; import java.util.Map; -public interface DomainRegistry extends Iterable> { - abstract static class Factory { - public abstract T create(String name, Object values); - } +public interface DomainRegistry extends Iterable> { /** * Register a new Domain @@ -40,7 +37,7 @@ abstract static class Factory { * @throws DomainConflictException Thrown when already an existing domain exists with the same name * @throws IllegalStateException If it is not the right time to register new domains */ - void register(String name, Factory domain) throws DomainConflictException; + void register(String name, DomainFactory domain) throws DomainConflictException; /** * Register a collection of domains. @@ -51,10 +48,10 @@ abstract static class Factory { *

If there is a domain conflict, then an error will be logged but * no exception will be thrown.

* - * @param flags a collection of flags + * @param domains a collection of domain factories * @throws IllegalStateException If it is not the right time to register new flags */ - void registerAll(Map> domains); + void registerAll(Map> domains); /** * Get the domain by its name. @@ -63,14 +60,14 @@ abstract static class Factory { * @return The domain, if it has been registered */ @Nullable - Factory get(String name); + DomainFactory get(String name); /** * Get all domains * * @return All domains */ - List> getAll(); + List> getAll(); /** * Unmarshal a raw map of values into a list of domains with their diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java index 11a8ebaf5..9e6f56ce8 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java @@ -40,7 +40,7 @@ public class SimpleDomainRegistry implements DomainRegistry { private static final Logger log = Logger.getLogger(SimpleDomainRegistry.class.getCanonicalName()); private final Object lock = new Object(); - private final ConcurrentMap> domains = Maps.newConcurrentMap(); + private final ConcurrentMap> domains = Maps.newConcurrentMap(); private boolean initialized = false; public boolean isInitialized() { @@ -52,7 +52,7 @@ public void setInitialized(boolean initialized) { } @Override - public void register(String name, Factory domain) throws DomainConflictException { + public void register(String name, DomainFactory domain) throws DomainConflictException { synchronized (lock) { if (initialized) { throw new IllegalStateException("New flags cannot be registered at this time"); @@ -63,9 +63,9 @@ public void register(String name, Factory domain) throws DomainConflictExcept } @Override - public void registerAll(Map> domains) { + public void registerAll(Map> domains) { synchronized (lock) { - for (Map.Entry> entry : domains.entrySet()) { + for (Map.Entry> entry : domains.entrySet()) { try { register(entry.getKey(), entry.getValue()); } catch (DomainConflictException e) { @@ -75,7 +75,7 @@ public void registerAll(Map> domains) { } } - private > T forceRegister(String name, T domain) throws DomainConflictException { + private > T forceRegister(String name, T domain) throws DomainConflictException { checkNotNull(domain, "domain"); checkNotNull(name, "name"); @@ -92,18 +92,18 @@ private > T forceRegister(String name, T domain) throws Dom @Nullable @Override - public Factory get(String name) { + public DomainFactory get(String name) { checkNotNull(name, "name"); return domains.get(name.toLowerCase()); } @Override - public List> getAll() { + public List> getAll() { return ImmutableList.copyOf(domains.values()); } private ApiDomain getOrCreate(String name, Object value, boolean createUnknown) { - Factory domain = get(name); + DomainFactory domain = get(name); if (domain != null) { return domain.create(name, value); @@ -115,7 +115,7 @@ private ApiDomain getOrCreate(String name, Object value, boolean createUnknown) return domain.create(name, value); } if (createUnknown) { - Factory unknownFactory = forceRegister(name, UnknownDomain.FACTORY); + DomainFactory unknownFactory = forceRegister(name, UnknownDomain.FACTORY); return unknownFactory.create(name, value); } } @@ -144,7 +144,7 @@ public int size() { } @Override - public Iterator> iterator() { + public Iterator> iterator() { return Iterators.unmodifiableIterator(domains.values().iterator()); } } 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 551f5c657..fd2d431a4 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 @@ -25,12 +25,7 @@ import java.util.UUID; public class UnknownDomain extends ApiDomain { - public static DomainRegistry.Factory FACTORY = new DomainRegistry.Factory() { - @Override - public UnknownDomain create(String name, Object values) { - return new UnknownDomain(name, values); - } - }; + public static DomainFactory FACTORY = UnknownDomain::new; Object o; From 65a0cfad438c714101c321e67629008abf3f807f Mon Sep 17 00:00:00 2001 From: JOO200 Date: Sat, 1 Jan 2022 16:19:50 +0100 Subject: [PATCH 03/11] Renamed ApiDomain to CustomDomain, added commands to modify CustomDomains --- .../commands/CommandInputContext.java | 112 ++++++++++++ .../commands/region/MemberCommands.java | 162 +++++++++++++++++- .../commands/region/RegionCommandsBase.java | 15 +- .../{ApiDomain.java => CustomDomain.java} | 27 ++- .../worldguard/domains/DefaultDomain.java | 103 ++++++++--- .../domains/registry/CustomDomainContext.java | 93 ++++++++++ .../domains/registry/DomainFactory.java | 6 +- .../domains/registry/DomainRegistry.java | 8 +- .../domains/registry/InvalidDomainFormat.java | 28 +++ .../registry/SimpleDomainRegistry.java | 39 +++-- .../domains/registry/UnknownDomain.java | 38 +++- .../permission/RegionPermissionModel.java | 20 +++ .../protection/flags/FlagContext.java | 88 +--------- .../managers/storage/file/YamlRegionFile.java | 12 +- .../protection/util/DomainInputResolver.java | 2 +- 15 files changed, 603 insertions(+), 150 deletions(-) create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java rename worldguard-core/src/main/java/com/sk89q/worldguard/domains/{ApiDomain.java => CustomDomain.java} (68%) create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/CustomDomainContext.java create mode 100644 worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/InvalidDomainFormat.java diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java new file mode 100644 index 000000000..5aab831c4 --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java @@ -0,0 +1,112 @@ +/* + * 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.commands; + +import com.google.common.collect.Maps; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.protection.flags.FlagContext; +import com.sk89q.worldguard.protection.flags.InvalidFlagFormat; + +import javax.annotation.Nullable; +import java.util.Map; + +public class CommandInputContext { + protected final Actor sender; + protected final String input; + + protected Map context; + + protected CommandInputContext(Actor sender, String input, Map values) { + this.sender = sender; + this.input = input; + this.context = values; + } + + public void put(String name, Object value) { + context.put(name, value); + } + + public Actor getSender() { + return sender; + } + + public String getUserInput() { + return input; + } + + /** + * Gets the CommandSender as a player. + * + * @return Player + * @throws InvalidFlagFormat if the sender is not a player + */ + public LocalPlayer getPlayerSender() throws InvalidFlagFormat { + if (sender.isPlayer() && sender instanceof LocalPlayer) { + return (LocalPlayer) sender; + } else { + throw new InvalidFlagFormat("Not a player"); + } + } + + public Integer getUserInputAsInt() throws InvalidFlagFormat { + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { + throw new InvalidFlagFormat("Not a number: " + input); + } + } + + public Double getUserInputAsDouble() throws InvalidFlagFormat { + try { + return Double.parseDouble(input); + } catch (NumberFormatException e) { + throw new InvalidFlagFormat("Not a number: " + input); + } + } + + /** + * Get an object from the context by key name. + * May return null if the object does not exist in the context. + * + * @param name key name of the object + * @return the object matching the key, or null + */ + @Nullable + public Object get(String name) { + return get(name, null); + } + + /** + * Get an object from the context by key name. + * Will only return null if + * a) you provide null as the default + * b) the key has explicity been set to null + * + * @param name key name of the object + * @return the object matching the key + */ + @Nullable + public Object get(String name, Object defaultValue) { + Object obj; + return (((obj = context.get(name)) != null) || context.containsKey(name) + ? obj : defaultValue); + } +} diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java index e41eb1b93..292683481 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java @@ -25,16 +25,30 @@ import com.sk89q.minecraft.util.commands.CommandPermissionsException; import com.sk89q.worldedit.command.util.AsyncCommandBuilder; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldedit.util.auth.AuthorizationException; +import com.sk89q.worldedit.util.formatting.component.ErrorFormat; +import com.sk89q.worldedit.util.formatting.component.SubtleFormat; +import com.sk89q.worldedit.util.formatting.text.Component; +import com.sk89q.worldedit.util.formatting.text.TextComponent; +import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; +import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; +import com.sk89q.worldedit.util.formatting.text.format.TextColor; import com.sk89q.worldedit.world.World; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.domains.CustomDomain; import com.sk89q.worldguard.domains.DefaultDomain; +import com.sk89q.worldguard.domains.registry.DomainFactory; +import com.sk89q.worldguard.domains.registry.DomainRegistry; +import com.sk89q.worldguard.domains.registry.InvalidDomainFormat; +import com.sk89q.worldguard.internal.permission.RegionPermissionModel; import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import com.sk89q.worldguard.protection.util.DomainInputResolver; import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map; import java.util.concurrent.Callable; public class MemberCommands extends RegionCommandsBase { @@ -229,4 +243,150 @@ public void removeOwner(CommandContext args, Actor sender) throws CommandExcepti .onFailure("Failed to remove owners", worldGuard.getExceptionConverter()) .buildAndExec(worldGuard.getExecutorService()); } + + + /** + * Modify a custom domain for owner. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"ownerdomain"}, + usage = " [-w world] [value]", + flags = "w:", + desc = "Set flags", + min = 2) + public void ownerDomain(CommandContext args, Actor sender) throws CommandException { + domain(args, sender, true); + } + + /** + * Modify a custom domain for member. + * + * @param args the arguments + * @param sender the sender + * @throws CommandException any error + */ + @Command(aliases = {"memberdomain"}, + usage = " [-w world] [value]", + flags = "w:", + desc = "Set flags", + min = 2) + public void onMemberDomain(CommandContext args, Actor sender) throws CommandException { + domain(args, sender, false); + } + + private void domain(CommandContext args, Actor sender, boolean isOwner) throws CommandException { + warnAboutSaveFailures(sender); + + World world = checkWorld(args, sender, 'w'); // Get the world + String domainName = args.getString(1); + String value = args.argsLength() >= 3 ? args.getJoinedStrings(2) : null; + DomainRegistry domainRegistry = WorldGuard.getInstance().getDomainRegistry(); + RegionPermissionModel permModel = getPermissionModel(sender); + + // Lookup the existing region + RegionManager manager = checkRegionManager(world); + ProtectedRegion existing = checkExistingRegion(manager, args.getString(0), true); + + // Check permissions + if (!permModel.mayModifyCustomDomain(existing, isOwner, domainName)) { + throw new CommandPermissionsException(); + } + String regionId = existing.getId(); + + DomainFactory domainFactory = domainRegistry.get(domainName); + + // We didn't find the domain, so let's print a list of domains that the user + // can use, and do nothing afterwards + if (domainFactory == null) { + AsyncCommandBuilder.wrap(new DomainListBuilder(domainRegistry, permModel, existing, world, + regionId, sender, domainName, isOwner), sender) + .registerWithSupervisor(WorldGuard.getInstance().getSupervisor(), "Domain list for invalid domain command.") + .onSuccess((Component) null, sender::print) + .onFailure((Component) null, WorldGuard.getInstance().getExceptionConverter()) + .buildAndExec(WorldGuard.getInstance().getExecutorService()); + return; + } + + DefaultDomain usedDomain = isOwner ? existing.getOwners() : existing.getMembers(); + + // Set the flag value if a value was set + if (value != null) { + // Set the flag if [value] was given even if [-g group] was given as well + try { + CustomDomain customDomain = domainFactory.create(domainName); + setDomain(existing, usedDomain, customDomain, sender, value); + } catch (InvalidDomainFormat e) { + throw new CommandException(e.getMessage()); + } + // No value? Clear the flag, if -g isn't specified + } else { + usedDomain.removeCustomDomain(domainName); + } + + RegionPrintoutBuilder printout = new RegionPrintoutBuilder(world.getName(), existing, null, sender); + printout.append(SubtleFormat.wrap("(Current domains: ")); + printout.appendDomain(); + printout.append(SubtleFormat.wrap(")")); + printout.send(sender); + checkSpawnOverlap(sender, world, existing); + + } + + private static class DomainListBuilder implements Callable { + private final DomainRegistry domainRegistry; + private final RegionPermissionModel permModel; + private final ProtectedRegion existing; + private final World world; + private final String regionId; + private final Actor sender; + private final boolean isOwner; + private final String domainName; + + DomainListBuilder(DomainRegistry domainRegistry, RegionPermissionModel permModel, ProtectedRegion existing, + World world, String regionId, Actor sender, String domainName, boolean isOwner) { + this.domainRegistry = domainRegistry; + this.permModel = permModel; + this.existing = existing; + this.world = world; + this.regionId = regionId; + this.sender = sender; + this.domainName = domainName; + this.isOwner = isOwner; + } + + @Override + public Component call() { + ArrayList domainList = new ArrayList<>(); + + // Need to build a list + for (Map.Entry> domainEntry : domainRegistry.getAll().entrySet()) { + if (!permModel.mayModifyCustomDomain(existing, isOwner, domainEntry.getKey())) { + continue; + } + domainList.add(domainEntry.getKey()); + } + Collections.sort(domainList); + + final TextComponent.Builder builder = TextComponent.builder("Available domains: "); + + final HoverEvent clickToSet = HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to set")); + for (int i = 0; i < domainList.size(); i++) { + String flag = domainList.get(i); + + builder.append(TextComponent.of(flag, i % 2 == 0 ? TextColor.GRAY : TextColor.WHITE) + .hoverEvent(clickToSet).clickEvent(ClickEvent.of(ClickEvent.Action.SUGGEST_COMMAND, + "/rg " + (isOwner ? "ownerdomains" : "memberdomains") +" -w \"" + world.getName() + "\" " + regionId + " " + flag + " "))); + if (i < domainList.size() + 1) { + builder.append(TextComponent.of(", ")); + } + } + + return ErrorFormat.wrap("Unknown domain specified: " + domainName) + .append(TextComponent.newline()) + .append(builder.build()); + } + } } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommandsBase.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommandsBase.java index 7d2ca5a82..fa74e839b 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommandsBase.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommandsBase.java @@ -32,18 +32,19 @@ import com.sk89q.worldedit.regions.Polygonal2DRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.RegionSelector; -import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; -import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector; import com.sk89q.worldedit.util.formatting.component.ErrorFormat; import com.sk89q.worldedit.util.formatting.component.SubtleFormat; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; import com.sk89q.worldedit.util.formatting.text.event.HoverEvent; import com.sk89q.worldedit.util.formatting.text.format.TextColor; -import com.sk89q.worldedit.util.formatting.text.format.TextDecoration; import com.sk89q.worldedit.world.World; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.domains.CustomDomain; +import com.sk89q.worldguard.domains.DefaultDomain; +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.flags.Flag; @@ -426,4 +427,12 @@ protected static V setFlag(ProtectedRegion region, Flag flag, Actor sende return val; } + /** + * Utility method to set a custom domain + */ + protected static void setDomain(ProtectedRegion region, DefaultDomain target, CustomDomain domain, Actor sender, String value) throws InvalidDomainFormat { + domain.parseInput(CustomDomainContext.create().setSender(sender).setInput(value).setObject("region", region).build()); + target.addCustomDomain(domain); + } + } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/ApiDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java similarity index 68% rename from worldguard-core/src/main/java/com/sk89q/worldguard/domains/ApiDomain.java rename to worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java index 49e7ddddf..b48678083 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/ApiDomain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java @@ -20,17 +20,20 @@ package com.sk89q.worldguard.domains; import com.sk89q.worldguard.LocalPlayer; +import com.sk89q.worldguard.domains.registry.CustomDomainContext; +import com.sk89q.worldguard.domains.registry.InvalidDomainFormat; +import com.sk89q.worldguard.util.ChangeTracked; import java.util.regex.Pattern; import static com.google.common.base.Preconditions.checkNotNull; -public abstract class ApiDomain implements Domain { - private static final Pattern VALID_NAME = Pattern.compile("^[:A-Za-z0-9\\-]{1,40}$"); +public abstract class CustomDomain implements Domain, ChangeTracked { + private static final Pattern VALID_NAME = Pattern.compile("^[A-Za-z0-9\\-]{1,40}$"); - private String name; + private final String name; - public ApiDomain(String name) { + public CustomDomain(String name) { this.name = name; } @@ -43,6 +46,22 @@ public String getName() { return name; } + /** + * Parse a given input to fill the context of the CustomDomain. + * + * @param context the {@link CustomDomainContext} + * @throws InvalidDomainFormat Raised if the input is invalid + */ + public abstract void parseInput(CustomDomainContext context) throws InvalidDomainFormat; + + /** + * Convert a raw type that was loaded (from a YAML file, for example) + * into the custom domain. + * + * @param o The object + */ + public abstract void unmarshal(Object o); + /** * Convert the current Domain to a storable foramt * 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 601b1fbae..ae44a94df 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 @@ -53,7 +53,7 @@ public class DefaultDomain implements Domain, ChangeTracked { private PlayerDomain playerDomain = new PlayerDomain(); private GroupDomain groupDomain = new GroupDomain(); - private Set apiDomains = new HashSet<>(); + private Set customDomains = new HashSet<>(); /** * Create a new domain. @@ -110,23 +110,44 @@ public void setGroupDomain(GroupDomain groupDomain) { } /** - * Add new api domains + * Add new custom domains * - * @param apiDomain a domain + * @param customDomain a domain */ - public void addApiDomain(ApiDomain apiDomain) { - checkNotNull(apiDomain); - this.apiDomains.add(apiDomain); + public void addCustomDomain(CustomDomain customDomain) { + checkNotNull(customDomain); + removeCustomDomain(customDomain.getName()); + this.customDomains.add(customDomain); + } + + /** + * Remove a custom domain matched by the name + * + * @param name the name + */ + public void removeCustomDomain(String name) { + checkNotNull(name); + this.customDomains.removeIf(d -> d.getName().equalsIgnoreCase(name)); + } + + /** + * Remove a custom domain + * + * @param customDomain a domain + */ + public void removeCustomDomain(CustomDomain customDomain) { + checkNotNull(customDomain); + this.customDomains.remove(customDomain); } /** * Set the api domains to a specified value * - * @param apiDomains the domains + * @param customDomains the domains */ - public void setApiDomains(Collection apiDomains) { - checkNotNull(apiDomains); - this.apiDomains = new HashSet<>(apiDomains); + public void setCustomDomains(Collection customDomains) { + checkNotNull(customDomains); + this.customDomains = new HashSet<>(customDomains); } /** @@ -134,8 +155,8 @@ public void setApiDomains(Collection apiDomains) { * * @return a unmodifiable copy of the domains */ - public Set getApiDomains() { - return Collections.unmodifiableSet(this.apiDomains); + public Set getCustomDomains() { + return Collections.unmodifiableSet(this.customDomains); } /** @@ -209,6 +230,9 @@ public void addAll(DefaultDomain other) { for (String group : other.getGroups()) { addGroup(group); } + for (CustomDomain domain : other.getCustomDomains()) { + addCustomDomain(domain); + } } /** @@ -227,6 +251,9 @@ public void removeAll(DefaultDomain other) { for (String group : other.getGroups()) { removeGroup(group); } + for (CustomDomain domain : other.getCustomDomains()) { + removeCustomDomain(domain); + } } /** @@ -276,12 +303,12 @@ public Set getGroups() { @Override public boolean contains(LocalPlayer player) { - return playerDomain.contains(player) || groupDomain.contains(player) || apiDomains.stream().anyMatch(d -> d.contains(player)); + return playerDomain.contains(player) || groupDomain.contains(player) || customDomains.stream().anyMatch(d -> d.contains(player)); } @Override public boolean contains(UUID uniqueId) { - return playerDomain.contains(uniqueId) || apiDomains.stream().anyMatch(d -> d.contains(uniqueId)); + return playerDomain.contains(uniqueId) || customDomains.stream().anyMatch(d -> d.contains(uniqueId)); } @Override @@ -309,7 +336,6 @@ public String toPlayersString() { } public String toPlayersString(@Nullable ProfileCache cache) { - StringBuilder str = new StringBuilder(); List output = new ArrayList<>(); for (String name : playerDomain.getPlayers()) { @@ -333,13 +359,7 @@ public String toPlayersString(@Nullable ProfileCache cache) { } output.sort(String.CASE_INSENSITIVE_ORDER); - for (Iterator it = output.iterator(); it.hasNext();) { - str.append(it.next()); - if (it.hasNext()) { - str.append(", "); - } - } - return str.toString(); + return String.join(", ", output); } public String toGroupsString() { @@ -354,6 +374,15 @@ public String toGroupsString() { return str.toString(); } + public String toCustomDomainsString() { + List output = new ArrayList<>(); + for (CustomDomain customDomain : customDomains) { + output.add(customDomain.getName() + ":" + customDomain.toString()); + } + output.sort(String.CASE_INSENSITIVE_ORDER); + return String.join(", ", output); + } + public String toUserFriendlyString() { StringBuilder str = new StringBuilder(); @@ -386,6 +415,12 @@ public String toUserFriendlyString(ProfileCache cache) { str.append(toGroupsString()); } + if (!customDomains.isEmpty()) { + if (str.length() > 0) { + str.append("; "); + } + str.append(toCustomDomainsString()); + } return str.toString(); } @@ -401,6 +436,12 @@ public Component toUserFriendlyComponent(@Nullable ProfileCache cache) { } builder.append(toGroupsComponent()); } + if (!customDomains.isEmpty()) { + if (playerDomain.size() > 0 || groupDomain.size() > 0) { + builder.append(TextComponent.of("; ")); + } + builder.append(toCustomDomainsString()); + } return builder.build(); } @@ -476,21 +517,37 @@ private Component toPlayersComponent(ProfileCache cache) { return builder.build(); } + private Component toCustomDomainsComponent(ProfileCache cache) { + final TextComponent.Builder builder = TextComponent.builder(""); + for (Iterator it = customDomains.iterator(); it.hasNext(); ) { + CustomDomain domain = it.next(); + builder.append(TextComponent.of(domain.getName() + ":", TextColor.GRAY)) + .append(TextComponent.of(domain.toString(), TextColor.GOLD)); + if (it.hasNext()) { + builder.append(TextComponent.of(", ")); + } + } + return builder.build().hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("CustomDomain"))); + } + + @Override public boolean isDirty() { - return playerDomain.isDirty() || groupDomain.isDirty(); + return playerDomain.isDirty() || groupDomain.isDirty() || customDomains.stream().anyMatch(ChangeTracked::isDirty); } @Override public void setDirty(boolean dirty) { playerDomain.setDirty(dirty); groupDomain.setDirty(dirty); + customDomains.forEach(d -> d.setDirty(dirty)); } @Override public String toString() { return "{players=" + playerDomain + ", groups=" + groupDomain + + ", custom=" + customDomains + '}'; } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/CustomDomainContext.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/CustomDomainContext.java new file mode 100644 index 000000000..e534bc483 --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/CustomDomainContext.java @@ -0,0 +1,93 @@ +/* + * 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.domains.registry; + +import com.google.common.collect.Maps; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldguard.commands.CommandInputContext; + +import javax.annotation.Nullable; +import java.util.Map; + +public final class CustomDomainContext extends CommandInputContext { + + private CustomDomainContext(Actor sender, String input, Map values) { + super(sender, input, values); + } + + + public static CustomDomainContext.CustomDomainContextBuilder create() { + return new CustomDomainContext.CustomDomainContextBuilder(); + } + + /** + * Create a copy of this FlagContext, with optional substitutions for values + * + * If any supplied variable is null, it will be ignored. + * If a map is supplied, it will override this FlagContext's values of the same key, + * but unprovided keys will not be overriden and will be returned as shallow copies. + * + * @param commandSender CommandSender for the new FlagContext to run under + * @param s String of the user input for the new FlagContext + * @param values map of values to override from the current FlagContext + * @return a copy of this FlagContext + */ + public CustomDomainContext copyWith(@Nullable Actor commandSender, @Nullable String s, @Nullable Map values) { + Map map = Maps.newHashMap(); + map.putAll(context); + if (values != null) { + map.putAll(values); + } + return new CustomDomainContext(commandSender == null ? this.sender : commandSender, s == null ? this.input : s, map); + } + + public static class CustomDomainContextBuilder { + private Actor sender; + private String input; + private Map map = Maps.newHashMap(); + + public CustomDomainContextBuilder setSender(Actor sender) { + this.sender = sender; + return this; + } + + public CustomDomainContextBuilder setInput(String input) { + this.input = input; + return this; + } + + public CustomDomainContextBuilder setObject(String key, Object value) { + this.map.put(key, value); + return this; + } + + public boolean tryAddToMap(String key, Object value) { + if (map.containsKey(key)) return false; + this.map.put(key, value); + return true; + } + + public CustomDomainContext build() { + return new CustomDomainContext(sender, input, map); + } + } + +} + diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainFactory.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainFactory.java index 7fff6f661..5d901bd3e 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainFactory.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainFactory.java @@ -20,9 +20,9 @@ package com.sk89q.worldguard.domains.registry; -import com.sk89q.worldguard.domains.ApiDomain; +import com.sk89q.worldguard.domains.CustomDomain; @FunctionalInterface -public interface DomainFactory { - T create(String name, Object values); +public interface DomainFactory { + T create(String name); } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java index ead7a7801..e05ad1780 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java @@ -19,7 +19,7 @@ package com.sk89q.worldguard.domains.registry; -import com.sk89q.worldguard.domains.ApiDomain; +import com.sk89q.worldguard.domains.CustomDomain; import javax.annotation.Nullable; import java.util.List; @@ -63,11 +63,11 @@ public interface DomainRegistry extends Iterable> { DomainFactory get(String name); /** - * Get all domains + * Get all domains keyed by the registered name * * @return All domains */ - List> getAll(); + Map> getAll(); /** * Unmarshal a raw map of values into a list of domains with their @@ -77,7 +77,7 @@ public interface DomainRegistry extends Iterable> { * @param createUnknown Whether "just in time" domains should be created for unknown domains * @return The unmarshalled domain list */ - List unmarshal(Map rawValues, boolean createUnknown); + List unmarshal(Map rawValues, boolean createUnknown); /** * Get the number of registered domains. diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/InvalidDomainFormat.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/InvalidDomainFormat.java new file mode 100644 index 000000000..83fc3fc91 --- /dev/null +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/InvalidDomainFormat.java @@ -0,0 +1,28 @@ +/* + * 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.domains.registry; + +public class InvalidDomainFormat extends Exception { + private static final long serialVersionUID = 8101615074524004172L; + + public InvalidDomainFormat(String msg) { + super(msg); + } +} diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java index 9e6f56ce8..27f14b3ca 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java @@ -19,14 +19,13 @@ package com.sk89q.worldguard.domains.registry; -import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterators; import com.google.common.collect.Maps; -import com.sk89q.worldguard.domains.ApiDomain; +import com.sk89q.worldguard.domains.CustomDomain; import javax.annotation.Nullable; import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -98,38 +97,46 @@ public DomainFactory get(String name) { } @Override - public List> getAll() { - return ImmutableList.copyOf(domains.values()); + public Map> getAll() { + return ImmutableMap.copyOf(domains); } - private ApiDomain getOrCreate(String name, Object value, boolean createUnknown) { - DomainFactory domain = get(name); + private CustomDomain getOrCreate(String name, Object value, boolean createUnknown) { + DomainFactory domainFactory = get(name); - if (domain != null) { - return domain.create(name, value); + if (domainFactory != null) { + CustomDomain customDomain = domainFactory.create(name); + if (customDomain != null) customDomain.unmarshal(value); + return customDomain; } synchronized (lock) { - domain = get(name); // Load again because the previous load was not synchronized - if (domain != null) { - return domain.create(name, value); + domainFactory = get(name); // Load again because the previous load was not synchronized + if (domainFactory != null) { + CustomDomain customDomain = domainFactory.create(name); + if (customDomain != null) customDomain.unmarshal(value); + return customDomain; } if (createUnknown) { DomainFactory unknownFactory = forceRegister(name, UnknownDomain.FACTORY); - return unknownFactory.create(name, value); + if (unknownFactory != null) { + CustomDomain customDomain = unknownFactory.create(name); + if (customDomain != null) customDomain.unmarshal(value); + return customDomain; + } } } return null; } - public List unmarshal(Map rawValues, boolean createUnknown) { + public List unmarshal(Map rawValues, boolean createUnknown) { checkNotNull(rawValues, "rawValues"); - List domainList = new ArrayList<>(); + List domainList = new ArrayList<>(); for (Map.Entry entry : rawValues.entrySet()) { try { - ApiDomain domain = getOrCreate(entry.getKey(), entry.getValue(), createUnknown); + CustomDomain domain = getOrCreate(entry.getKey(), entry.getValue(), createUnknown); domainList.add(domain); } catch (Throwable e) { log.log(Level.WARNING, "Failed to unmarshal domain for " + entry.getKey(), e); 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 fd2d431a4..1b509bc4a 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 @@ -19,21 +19,29 @@ package com.sk89q.worldguard.domains.registry; -import com.sk89q.worldguard.domains.ApiDomain; +import com.sk89q.worldguard.domains.CustomDomain; -import javax.annotation.Nullable; import java.util.UUID; -public class UnknownDomain extends ApiDomain { +public class UnknownDomain extends CustomDomain { public static DomainFactory FACTORY = UnknownDomain::new; - Object o; + private boolean isDirty = false; + private Object o; - public UnknownDomain(String name, Object values) { + public UnknownDomain(String name) { super(name); - this.o = values; } + @Override + public void parseInput(CustomDomainContext c) throws InvalidDomainFormat { + throw new InvalidDomainFormat("The plugin that registered this flag is not currently installed"); + } + + @Override + public void unmarshal(Object o) { + this.o = o; + } @Override public Object marshal() { @@ -57,6 +65,24 @@ public int size() { @Override public void clear() { + isDirty = true; o = null; } + + @Override + public void setDirty(boolean dirty) { + isDirty = dirty; + } + + @Override + public boolean isDirty() { + return isDirty; + } + + @Override + public String toString() { + return "UnknownDomain{" + + "o=" + o + + '}'; + } } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/internal/permission/RegionPermissionModel.java b/worldguard-core/src/main/java/com/sk89q/worldguard/internal/permission/RegionPermissionModel.java index 287ed972d..966801375 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/internal/permission/RegionPermissionModel.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/internal/permission/RegionPermissionModel.java @@ -27,6 +27,7 @@ import com.sk89q.worldguard.protection.flags.Flag; import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import javax.annotation.Nonnull; import javax.annotation.Nullable; /** @@ -176,6 +177,24 @@ public boolean mayRemoveMembers(ProtectedRegion region) { public boolean mayRemoveOwners(ProtectedRegion region) { return hasPatternPermission("removeowner", region); } + + /** + * Checks to see if the given sender has permission to modify a custom region + * + * @param region the region + * @param isOwnerLevel whether the domain level is owner (else member) + * @param domainName the name of the domain + * @return whether the actor has the permission + */ + public boolean mayModifyCustomDomain(ProtectedRegion region, boolean isOwnerLevel, @Nonnull String domainName) { + + String sanitizedValue = domainName.trim().toLowerCase().replaceAll("[^a-z0-9]", ""); + if (sanitizedValue.length() > 20) { + sanitizedValue = sanitizedValue.substring(0, 20); + } + + return hasPatternPermission("flag.flags." + sanitizedValue + "." + (isOwnerLevel ? "owner" : "member"), region); + } /** * Checks to see if the given sender has permission to modify the given region @@ -183,6 +202,7 @@ public boolean mayRemoveOwners(ProtectedRegion region) { * * @param perm the name of the node * @param region the region + * @return whether the actor has the permission */ private boolean hasPatternPermission(String perm, ProtectedRegion region) { if (!(getSender() instanceof Player)) { diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/FlagContext.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/FlagContext.java index a394a18fb..d5d8cda65 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/FlagContext.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/FlagContext.java @@ -21,100 +21,22 @@ import com.google.common.collect.Maps; import com.sk89q.worldedit.extension.platform.Actor; -import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.WorldGuard; - -import java.util.Map; +import com.sk89q.worldguard.commands.CommandInputContext; import javax.annotation.Nullable; +import java.util.Map; -public final class FlagContext { - - private final Actor sender; - private final String input; - - private Map context; +public final class FlagContext extends CommandInputContext { private FlagContext(Actor sender, String input, Map values) { - this.sender = sender; - this.input = input; - this.context = values; + super(sender, input, values); } - public static FlagContextBuilder create() { + public static FlagContext.FlagContextBuilder create() { return new FlagContextBuilder(); } - public void put(String name, Object value) { - context.put(name, value); - } - - public Actor getSender() { - return sender; - } - - public String getUserInput() { - return input; - } - - /** - * Gets the CommandSender as a player. - * - * @return Player - * @throws InvalidFlagFormat if the sender is not a player - */ - public LocalPlayer getPlayerSender() throws InvalidFlagFormat { - if (sender.isPlayer() && sender instanceof LocalPlayer) { - return (LocalPlayer) sender; - } else { - throw new InvalidFlagFormat("Not a player"); - } - } - - public Integer getUserInputAsInt() throws InvalidFlagFormat { - try { - return Integer.parseInt(input); - } catch (NumberFormatException e) { - throw new InvalidFlagFormat("Not a number: " + input); - } - } - - public Double getUserInputAsDouble() throws InvalidFlagFormat { - try { - return Double.parseDouble(input); - } catch (NumberFormatException e) { - throw new InvalidFlagFormat("Not a number: " + input); - } - } - - /** - * Get an object from the context by key name. - * May return null if the object does not exist in the context. - * - * @param name key name of the object - * @return the object matching the key, or null - */ - @Nullable - public Object get(String name) { - return get(name, null); - } - - /** - * Get an object from the context by key name. - * Will only return null if - * a) you provide null as the default - * b) the key has explicity been set to null - * - * @param name key name of the object - * @return the object matching the key - */ - @Nullable - public Object get(String name, Object defaultValue) { - Object obj; - return (((obj = context.get(name)) != null) || context.containsKey(name) - ? obj : defaultValue); - } - /** * Create a copy of this FlagContext, with optional substitutions for values * diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java index 1d9187412..f45ac1e0a 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java @@ -28,7 +28,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldguard.WorldGuard; -import com.sk89q.worldguard.domains.ApiDomain; +import com.sk89q.worldguard.domains.CustomDomain; import com.sk89q.worldguard.domains.DefaultDomain; import com.sk89q.worldguard.protection.flags.FlagUtil; import com.sk89q.worldguard.protection.flags.registry.FlagRegistry; @@ -288,8 +288,8 @@ private DefaultDomain parseDomain(YAMLNode node) { YAMLNode apiDomains = node.getNode("api"); if (apiDomains != null) { - List parsedDomains = WorldGuard.getInstance().getDomainRegistry().unmarshal(apiDomains.getMap(), true); - domain.setApiDomains(parsedDomains); + List parsedDomains = WorldGuard.getInstance().getDomainRegistry().unmarshal(apiDomains.getMap(), true); + domain.setCustomDomains(parsedDomains); } return domain; @@ -312,10 +312,10 @@ private Map getDomainData(DefaultDomain domain) { setDomainData(domainData, "unique-ids", domain.getUniqueIds()); setDomainData(domainData, "groups", domain.getGroups()); - if (!domain.getApiDomains().isEmpty()) { + if (!domain.getCustomDomains().isEmpty()) { Map values = new HashMap<>(); - for (ApiDomain apiDomain : domain.getApiDomains()) { - values.put(apiDomain.getName(), apiDomain.marshal()); + for (CustomDomain customDomain : domain.getCustomDomains()) { + values.put(customDomain.getName(), customDomain.marshal()); } domainData.put("api", values); } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java index 4c8a00ff8..e30856c33 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java @@ -102,7 +102,7 @@ public DefaultDomain call() throws UnresolvedNamesException { UUID uuid = parseUUID(s); if (uuid != null) { // Try to add any UUIDs given - domain.addPlayer(UUID.fromString(UUIDs.addDashes(s.replaceAll("^uuid:", "")))); + domain.addPlayer(uuid); } else { switch (locatorPolicy) { case NAME_ONLY: From b0669cc756b034dbf48f4c5290f8388baed56665 Mon Sep 17 00:00:00 2001 From: JOO200 Date: Sat, 1 Jan 2022 17:23:38 +0100 Subject: [PATCH 04/11] Fixed unformatted command output, check for valid domain name --- .../java/com/sk89q/worldguard/domains/CustomDomain.java | 8 ++++++++ .../java/com/sk89q/worldguard/domains/DefaultDomain.java | 9 +++++---- .../domains/registry/SimpleDomainRegistry.java | 4 ++++ .../protection/managers/storage/file/YamlRegionFile.java | 4 ++-- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java index b48678083..213d6d718 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java @@ -34,6 +34,9 @@ public abstract class CustomDomain implements Domain, ChangeTracked { private final String name; public CustomDomain(String name) { + if (name == null ||!isValidName(name)) { + throw new IllegalArgumentException("Invalid Domain name used."); + } this.name = name; } @@ -85,4 +88,9 @@ public static boolean isValidName(String name) { public boolean contains(LocalPlayer player) { return contains(player.getUniqueId()); } + + @Override + public int size() { + return 1; + } } 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 ae44a94df..0b7d0dc83 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 @@ -69,6 +69,7 @@ public DefaultDomain() { public DefaultDomain(DefaultDomain existing) { setPlayerDomain(existing.getPlayerDomain()); setGroupDomain(existing.getGroupDomain()); + setCustomDomains(existing.getCustomDomains()); } /** @@ -318,7 +319,7 @@ public boolean contains(String playerName) { @Override public int size() { - return groupDomain.size() + playerDomain.size(); + return groupDomain.size() + playerDomain.size() + customDomains.size(); } @Override @@ -440,7 +441,7 @@ public Component toUserFriendlyComponent(@Nullable ProfileCache cache) { if (playerDomain.size() > 0 || groupDomain.size() > 0) { builder.append(TextComponent.of("; ")); } - builder.append(toCustomDomainsString()); + builder.append(toCustomDomainsComponent()); } return builder.build(); } @@ -517,11 +518,11 @@ private Component toPlayersComponent(ProfileCache cache) { return builder.build(); } - private Component toCustomDomainsComponent(ProfileCache cache) { + private Component toCustomDomainsComponent() { final TextComponent.Builder builder = TextComponent.builder(""); for (Iterator it = customDomains.iterator(); it.hasNext(); ) { CustomDomain domain = it.next(); - builder.append(TextComponent.of(domain.getName() + ":", TextColor.GRAY)) + builder.append(TextComponent.of(domain.getName() + ":", TextColor.LIGHT_PURPLE)) .append(TextComponent.of(domain.toString(), TextColor.GOLD)); if (it.hasNext()) { builder.append(TextComponent.of(", ")); diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java index 27f14b3ca..7b0b0a8b4 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java @@ -78,6 +78,10 @@ private > T forceRegister(String name, T domain) thro checkNotNull(domain, "domain"); checkNotNull(name, "name"); + if (!CustomDomain.isValidName(name)) { + throw new IllegalArgumentException("Invalid Domain name used."); + } + synchronized (lock) { if (domains.containsKey(name)) { throw new DomainConflictException("A domain already exists by the name " + name); diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java index f45ac1e0a..531b499f6 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/managers/storage/file/YamlRegionFile.java @@ -286,7 +286,7 @@ private DefaultDomain parseDomain(YAMLNode node) { } } - YAMLNode apiDomains = node.getNode("api"); + YAMLNode apiDomains = node.getNode("custom"); if (apiDomains != null) { List parsedDomains = WorldGuard.getInstance().getDomainRegistry().unmarshal(apiDomains.getMap(), true); domain.setCustomDomains(parsedDomains); @@ -317,7 +317,7 @@ private Map getDomainData(DefaultDomain domain) { for (CustomDomain customDomain : domain.getCustomDomains()) { values.put(customDomain.getName(), customDomain.marshal()); } - domainData.put("api", values); + domainData.put("custom", values); } return domainData; From 8736185c92353643911f88e22bbcf06f4cf1b533 Mon Sep 17 00:00:00 2001 From: JOO200 Date: Sat, 1 Jan 2022 17:42:23 +0100 Subject: [PATCH 05/11] Fix for weird format --- .../com/sk89q/worldguard/commands/region/MemberCommands.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java index 292683481..33e3f8224 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java @@ -327,7 +327,8 @@ private void domain(CommandContext args, Actor sender, boolean isOwner) throws C } RegionPrintoutBuilder printout = new RegionPrintoutBuilder(world.getName(), existing, null, sender); - printout.append(SubtleFormat.wrap("(Current domains: ")); + printout.append(SubtleFormat.wrap("(Current domains:")); + printout.newline(); printout.appendDomain(); printout.append(SubtleFormat.wrap(")")); printout.send(sender); From 4f1be027c5e766514c3524f1fa0b66ee4366a35f Mon Sep 17 00:00:00 2001 From: JOO200 Date: Thu, 13 Jan 2022 21:08:39 +0100 Subject: [PATCH 06/11] Fixed dirty flags for CustomDomain, added UnitTest --- .../commands/CommandInputContext.java | 2 - .../worldguard/domains/CustomDomain.java | 11 ++++ .../worldguard/domains/DefaultDomain.java | 15 ++++- .../domains/registry/UnknownDomain.java | 2 +- .../worldguard/domains/CustomUUIDDomain.java | 64 +++++++++++++++++++ .../worldguard/domains/DefaultDomainTest.java | 6 ++ 6 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 worldguard-core/src/test/java/com/sk89q/worldguard/domains/CustomUUIDDomain.java diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java index 5aab831c4..737d062d3 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java @@ -19,10 +19,8 @@ package com.sk89q.worldguard.commands; -import com.google.common.collect.Maps; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldguard.LocalPlayer; -import com.sk89q.worldguard.protection.flags.FlagContext; import com.sk89q.worldguard.protection.flags.InvalidFlagFormat; import javax.annotation.Nullable; diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java index 213d6d718..3383a0388 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java @@ -32,6 +32,7 @@ public abstract class CustomDomain implements Domain, ChangeTracked { private static final Pattern VALID_NAME = Pattern.compile("^[A-Za-z0-9\\-]{1,40}$"); private final String name; + private boolean dirty; public CustomDomain(String name) { if (name == null ||!isValidName(name)) { @@ -93,4 +94,14 @@ public boolean contains(LocalPlayer player) { public int size() { return 1; } + + @Override + public boolean isDirty() { + return dirty; + } + + @Override + public void setDirty(boolean dirty) { + this.dirty = dirty; + } } 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 0b7d0dc83..3128076fc 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 @@ -54,6 +54,7 @@ public class DefaultDomain implements Domain, ChangeTracked { private GroupDomain groupDomain = new GroupDomain(); private Set customDomains = new HashSet<>(); + private boolean customDomainsChanged = false; /** * Create a new domain. @@ -119,6 +120,7 @@ public void addCustomDomain(CustomDomain customDomain) { checkNotNull(customDomain); removeCustomDomain(customDomain.getName()); this.customDomains.add(customDomain); + customDomainsChanged = true; } /** @@ -128,7 +130,9 @@ public void addCustomDomain(CustomDomain customDomain) { */ public void removeCustomDomain(String name) { checkNotNull(name); - this.customDomains.removeIf(d -> d.getName().equalsIgnoreCase(name)); + if (this.customDomains.removeIf(d -> d.getName().equalsIgnoreCase(name))) { + customDomainsChanged = true; + } } /** @@ -138,7 +142,9 @@ public void removeCustomDomain(String name) { */ public void removeCustomDomain(CustomDomain customDomain) { checkNotNull(customDomain); - this.customDomains.remove(customDomain); + if (this.customDomains.remove(customDomain)) { + customDomainsChanged = true; + } } /** @@ -149,6 +155,7 @@ public void removeCustomDomain(CustomDomain customDomain) { public void setCustomDomains(Collection customDomains) { checkNotNull(customDomains); this.customDomains = new HashSet<>(customDomains); + customDomainsChanged = true; } /** @@ -534,13 +541,15 @@ private Component toCustomDomainsComponent() { @Override public boolean isDirty() { - return playerDomain.isDirty() || groupDomain.isDirty() || customDomains.stream().anyMatch(ChangeTracked::isDirty); + return playerDomain.isDirty() || groupDomain.isDirty() || + customDomainsChanged || customDomains.stream().anyMatch(ChangeTracked::isDirty); } @Override public void setDirty(boolean dirty) { playerDomain.setDirty(dirty); groupDomain.setDirty(dirty); + customDomainsChanged = true; customDomains.forEach(d -> d.setDirty(dirty)); } 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 1b509bc4a..5aa83f460 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 @@ -34,7 +34,7 @@ public UnknownDomain(String name) { } @Override - public void parseInput(CustomDomainContext c) throws InvalidDomainFormat { + public void parseInput(CustomDomainContext context) throws InvalidDomainFormat { throw new InvalidDomainFormat("The plugin that registered this flag is not currently installed"); } 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 new file mode 100644 index 000000000..1f9dfd7bf --- /dev/null +++ b/worldguard-core/src/test/java/com/sk89q/worldguard/domains/CustomUUIDDomain.java @@ -0,0 +1,64 @@ +/* + * 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.domains; + +import com.sk89q.worldguard.domains.registry.CustomDomainContext; +import com.sk89q.worldguard.domains.registry.InvalidDomainFormat; + +import java.util.Objects; +import java.util.UUID; + +public class CustomUUIDDomain extends CustomDomain { + private UUID test; + + public CustomUUIDDomain(String name, UUID test) { + super(name); + this.test = test; + } + + @Override + public void parseInput(CustomDomainContext context) throws InvalidDomainFormat { + throw new InvalidDomainFormat("not supported"); + } + + @Override + public void unmarshal(Object o) { + } + + @Override + public Object marshal() { + return null; + } + + @Override + public boolean contains(UUID uniqueId) { + return Objects.equals(test, uniqueId); + } + + @Override + public boolean contains(String playerName) { + return false; + } + + @Override + public void clear() { + test = null; + } +} diff --git a/worldguard-core/src/test/java/com/sk89q/worldguard/domains/DefaultDomainTest.java b/worldguard-core/src/test/java/com/sk89q/worldguard/domains/DefaultDomainTest.java index 86586657f..fc112219d 100644 --- a/worldguard-core/src/test/java/com/sk89q/worldguard/domains/DefaultDomainTest.java +++ b/worldguard-core/src/test/java/com/sk89q/worldguard/domains/DefaultDomainTest.java @@ -112,5 +112,11 @@ public void testContains() throws Exception { assertFalse(domain.contains(player1)); assertTrue(domain.contains(player2)); assertTrue(domain.contains(player3)); + + domain = new DefaultDomain(); + domain.addCustomDomain(new CustomUUIDDomain("test", player2.getUniqueId())); + assertTrue(domain.contains(player2)); + assertFalse(domain.contains(player2.getName())); + assertFalse(domain.contains(player3)); } } \ No newline at end of file From b3ae14bfbaf43ba1c97816afd9c61e02d1377e84 Mon Sep 17 00:00:00 2001 From: JOO200 Date: Sat, 29 Jan 2022 19:42:13 +0100 Subject: [PATCH 07/11] Removed commands for custom domains. Adding/Removing custom domains are now in /rg addmember/delmember/addowner/delowner --- .../commands/region/MemberCommands.java | 108 ++---------------- .../commands/region/RegionCommands.java | 4 +- .../commands/region/RegionCommandsBase.java | 9 -- .../worldguard/commands/task/RegionAdder.java | 18 ++- .../worldguard/domains/CustomDomain.java | 3 +- .../worldguard/domains/DefaultDomain.java | 4 +- .../protection/util/DomainInputResolver.java | 52 ++++++++- .../util/WorldGuardExceptionConverter.java | 6 + 8 files changed, 89 insertions(+), 115 deletions(-) diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java index 33e3f8224..960782d8b 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java @@ -81,6 +81,8 @@ public void addMember(CommandContext args, Actor sender) throws CommandException DomainInputResolver resolver = new DomainInputResolver( WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0)); resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY); + resolver.setActor(sender); + resolver.setRegion(region); final String description = String.format("Adding members to the region '%s' on '%s'", region.getId(), world.getName()); @@ -115,7 +117,8 @@ public void addOwner(CommandContext args, Actor sender) throws CommandException DomainInputResolver resolver = new DomainInputResolver( WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0)); resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_ONLY); - + resolver.setActor(sender); + resolver.setRegion(region); final String description = String.format("Adding owners to the region '%s' on '%s'", region.getId(), world.getName()); AsyncCommandBuilder.wrap(checkedAddOwners(sender, manager, region, world, resolver), sender) @@ -188,6 +191,8 @@ public void removeMember(CommandContext args, Actor sender) throws CommandExcept DomainInputResolver resolver = new DomainInputResolver( WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0)); resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME); + resolver.setActor(sender); + resolver.setRegion(region); callable = resolver; } @@ -231,6 +236,8 @@ public void removeOwner(CommandContext args, Actor sender) throws CommandExcepti DomainInputResolver resolver = new DomainInputResolver( WorldGuard.getInstance().getProfileService(), args.getParsedPaddedSlice(1, 0)); resolver.setLocatorPolicy(args.hasFlag('n') ? UserLocatorPolicy.NAME_ONLY : UserLocatorPolicy.UUID_AND_NAME); + resolver.setActor(sender); + resolver.setRegion(region); callable = resolver; } @@ -244,98 +251,7 @@ public void removeOwner(CommandContext args, Actor sender) throws CommandExcepti .buildAndExec(worldGuard.getExecutorService()); } - - /** - * Modify a custom domain for owner. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"ownerdomain"}, - usage = " [-w world] [value]", - flags = "w:", - desc = "Set flags", - min = 2) - public void ownerDomain(CommandContext args, Actor sender) throws CommandException { - domain(args, sender, true); - } - - /** - * Modify a custom domain for member. - * - * @param args the arguments - * @param sender the sender - * @throws CommandException any error - */ - @Command(aliases = {"memberdomain"}, - usage = " [-w world] [value]", - flags = "w:", - desc = "Set flags", - min = 2) - public void onMemberDomain(CommandContext args, Actor sender) throws CommandException { - domain(args, sender, false); - } - - private void domain(CommandContext args, Actor sender, boolean isOwner) throws CommandException { - warnAboutSaveFailures(sender); - - World world = checkWorld(args, sender, 'w'); // Get the world - String domainName = args.getString(1); - String value = args.argsLength() >= 3 ? args.getJoinedStrings(2) : null; - DomainRegistry domainRegistry = WorldGuard.getInstance().getDomainRegistry(); - RegionPermissionModel permModel = getPermissionModel(sender); - - // Lookup the existing region - RegionManager manager = checkRegionManager(world); - ProtectedRegion existing = checkExistingRegion(manager, args.getString(0), true); - - // Check permissions - if (!permModel.mayModifyCustomDomain(existing, isOwner, domainName)) { - throw new CommandPermissionsException(); - } - String regionId = existing.getId(); - - DomainFactory domainFactory = domainRegistry.get(domainName); - - // We didn't find the domain, so let's print a list of domains that the user - // can use, and do nothing afterwards - if (domainFactory == null) { - AsyncCommandBuilder.wrap(new DomainListBuilder(domainRegistry, permModel, existing, world, - regionId, sender, domainName, isOwner), sender) - .registerWithSupervisor(WorldGuard.getInstance().getSupervisor(), "Domain list for invalid domain command.") - .onSuccess((Component) null, sender::print) - .onFailure((Component) null, WorldGuard.getInstance().getExceptionConverter()) - .buildAndExec(WorldGuard.getInstance().getExecutorService()); - return; - } - - DefaultDomain usedDomain = isOwner ? existing.getOwners() : existing.getMembers(); - - // Set the flag value if a value was set - if (value != null) { - // Set the flag if [value] was given even if [-g group] was given as well - try { - CustomDomain customDomain = domainFactory.create(domainName); - setDomain(existing, usedDomain, customDomain, sender, value); - } catch (InvalidDomainFormat e) { - throw new CommandException(e.getMessage()); - } - // No value? Clear the flag, if -g isn't specified - } else { - usedDomain.removeCustomDomain(domainName); - } - - RegionPrintoutBuilder printout = new RegionPrintoutBuilder(world.getName(), existing, null, sender); - printout.append(SubtleFormat.wrap("(Current domains:")); - printout.newline(); - printout.appendDomain(); - printout.append(SubtleFormat.wrap(")")); - printout.send(sender); - checkSpawnOverlap(sender, world, existing); - - } - + // TODO: Implement a list for available domains. Maybe /rg domains? or /rg addmembers/addowners/delmembers/delowners? private static class DomainListBuilder implements Callable { private final DomainRegistry domainRegistry; private final RegionPermissionModel permModel; @@ -375,11 +291,11 @@ public Component call() { final HoverEvent clickToSet = HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of("Click to set")); for (int i = 0; i < domainList.size(); i++) { - String flag = domainList.get(i); + String domainName = domainList.get(i); - builder.append(TextComponent.of(flag, i % 2 == 0 ? TextColor.GRAY : TextColor.WHITE) + builder.append(TextComponent.of(domainName, i % 2 == 0 ? TextColor.GRAY : TextColor.WHITE) .hoverEvent(clickToSet).clickEvent(ClickEvent.of(ClickEvent.Action.SUGGEST_COMMAND, - "/rg " + (isOwner ? "ownerdomains" : "memberdomains") +" -w \"" + world.getName() + "\" " + regionId + " " + flag + " "))); + "/rg " + (isOwner ? "addowner" : "addmember") +" -w \"" + world.getName() + "\" " + regionId + " " + domainName + ":"))); if (i < domainList.size() + 1) { builder.append(TextComponent.of(", ")); } 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 9299ad02b..104184955 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 @@ -160,7 +160,7 @@ public void define(CommandContext args, Actor sender) throws CommandException { region = checkRegionFromSelection(sender, id); } - RegionAdder task = new RegionAdder(manager, region); + RegionAdder task = new RegionAdder(manager, region, sender); task.addOwnersFromCommand(args, 2); final String description = String.format("Adding region '%s'", region.getId()); @@ -214,7 +214,7 @@ public void redefine(CommandContext args, Actor sender) throws CommandException region.copyFrom(existing); - RegionAdder task = new RegionAdder(manager, region); + RegionAdder task = new RegionAdder(manager, region, sender); final String description = String.format("Updating region '%s'", region.getId()); AsyncCommandBuilder.wrap(task, sender) diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommandsBase.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommandsBase.java index fa74e839b..8d728a44e 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommandsBase.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/RegionCommandsBase.java @@ -426,13 +426,4 @@ protected static V setFlag(ProtectedRegion region, Flag flag, Actor sende region.setFlag(flag, val); return val; } - - /** - * Utility method to set a custom domain - */ - protected static void setDomain(ProtectedRegion region, DefaultDomain target, CustomDomain domain, Actor sender, String value) throws InvalidDomainFormat { - domain.parseInput(CustomDomainContext.create().setSender(sender).setInput(value).setObject("region", region).build()); - target.addCustomDomain(domain); - } - } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/task/RegionAdder.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/task/RegionAdder.java index 932b85827..dc7a957da 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/task/RegionAdder.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/task/RegionAdder.java @@ -20,6 +20,7 @@ package com.sk89q.worldguard.commands.task; import com.sk89q.minecraft.util.commands.CommandContext; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.domains.DefaultDomain; import com.sk89q.worldguard.protection.managers.RegionManager; @@ -39,6 +40,7 @@ public class RegionAdder implements Callable { private final RegionManager manager; private final ProtectedRegion region; + private final Actor actor; @Nullable private String[] ownersInput; private UserLocatorPolicy locatorPolicy = UserLocatorPolicy.UUID_ONLY; @@ -46,15 +48,26 @@ public class RegionAdder implements Callable { /** * Create a new instance. * - * @param manager the manage + * @param manager the manager * @param region the region */ public RegionAdder(RegionManager manager, ProtectedRegion region) { + this(manager, region, null); + } + + /** + * Create a new instance. + * @param manager the manager + * @param region the region + * @param actor the actor + */ + public RegionAdder(RegionManager manager, ProtectedRegion region, Actor actor) { checkNotNull(manager); checkNotNull(region); this.manager = manager; this.region = region; + this.actor = actor; } /** @@ -75,6 +88,9 @@ public ProtectedRegion call() throws Exception { if (ownersInput != null) { DomainInputResolver resolver = new DomainInputResolver(WorldGuard.getInstance().getProfileService(), ownersInput); resolver.setLocatorPolicy(locatorPolicy); + resolver.setActor(actor); + resolver.setRegion(region); + DefaultDomain domain = resolver.call(); region.getOwners().addAll(domain); } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java index 3383a0388..991bef226 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/CustomDomain.java @@ -81,7 +81,8 @@ public String getName() { */ public static boolean isValidName(String name) { checkNotNull(name, "name"); - return VALID_NAME.matcher(name).matches(); + // g is already reserved by the group domain + return VALID_NAME.matcher(name).matches() && !name.equalsIgnoreCase("g"); } 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 3128076fc..d14604920 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 @@ -260,7 +260,7 @@ public void removeAll(DefaultDomain other) { removeGroup(group); } for (CustomDomain domain : other.getCustomDomains()) { - removeCustomDomain(domain); + removeCustomDomain(domain.getName()); } } @@ -549,7 +549,7 @@ public boolean isDirty() { public void setDirty(boolean dirty) { playerDomain.setDirty(dirty); groupDomain.setDirty(dirty); - customDomainsChanged = true; + customDomainsChanged = dirty; customDomains.forEach(d -> d.setDirty(dirty)); } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java index e30856c33..ed9ce6826 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java @@ -21,6 +21,13 @@ import com.google.common.base.Function; import com.google.common.base.Joiner; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.domains.CustomDomain; +import com.sk89q.worldguard.domains.registry.CustomDomainContext; +import com.sk89q.worldguard.domains.registry.DomainFactory; +import com.sk89q.worldguard.domains.registry.InvalidDomainFormat; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; import com.sk89q.worldguard.util.profile.Profile; import com.sk89q.worldguard.util.profile.resolver.ProfileService; import com.sk89q.worldguard.util.profile.util.UUIDs; @@ -43,6 +50,7 @@ public class DomainInputResolver implements Callable { private static final Pattern GROUP_PATTERN = Pattern.compile("(?i)^[G]:(.+)$"); + private static final Pattern CUSTOM_PATTERN = Pattern.compile("(?i)^([A-Za-z0-9\\-]{1,40}):(.*)$"); /** * The policy for locating users. @@ -56,6 +64,8 @@ public enum UserLocatorPolicy { private final ProfileService profileService; private final String[] input; private UserLocatorPolicy locatorPolicy = UserLocatorPolicy.UUID_ONLY; + private ProtectedRegion region; + private Actor actor; /** * Create a new instance. @@ -89,15 +99,49 @@ public void setLocatorPolicy(UserLocatorPolicy locatorPolicy) { this.locatorPolicy = locatorPolicy; } + /** + * Set the region for the Resolver + * @param region the region + */ + public void setRegion(ProtectedRegion region) { + this.region = region; + } + + /** + * Get the current region from the Resolver + * @return the region + */ + public @Nullable ProtectedRegion getRegion() { + return region; + } + + /** + * Set the actor of the Resolver + * @param actor the actor + */ + public void setActor(Actor actor) { + this.actor = actor; + } + @Override - public DefaultDomain call() throws UnresolvedNamesException { + public DefaultDomain call() throws UnresolvedNamesException, InvalidDomainFormat { DefaultDomain domain = new DefaultDomain(); List namesToQuery = new ArrayList<>(); for (String s : input) { - Matcher m = GROUP_PATTERN.matcher(s); - if (m.matches()) { - domain.addGroup(m.group(1)); + Matcher groupMatcher = GROUP_PATTERN.matcher(s); + Matcher customMatcher = CUSTOM_PATTERN.matcher(s); + if (groupMatcher.matches()) { + domain.addGroup(groupMatcher.group(1)); + } else if (customMatcher.matches()) { + String domainName = customMatcher.group(1); + DomainFactory domainFactory = WorldGuard.getInstance().getDomainRegistry().get(domainName); + if (domainFactory == null) { + throw new InvalidDomainFormat("No domain named '" + domainName + "' found."); + } + CustomDomain customDomain = domainFactory.create(domainName); + customDomain.parseInput(CustomDomainContext.create() + .setSender(actor).setInput(customMatcher.group(2)).setObject("region", region).build()); } else { UUID uuid = parseUUID(s); if (uuid != null) { diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/util/WorldGuardExceptionConverter.java b/worldguard-core/src/main/java/com/sk89q/worldguard/util/WorldGuardExceptionConverter.java index 89492df2d..f508951cd 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/util/WorldGuardExceptionConverter.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/util/WorldGuardExceptionConverter.java @@ -26,6 +26,7 @@ import com.sk89q.worldedit.util.auth.AuthorizationException; import com.sk89q.worldedit.util.formatting.component.InvalidComponentException; import com.sk89q.worldguard.WorldGuard; +import com.sk89q.worldguard.domains.registry.InvalidDomainFormat; import com.sk89q.worldguard.protection.managers.storage.StorageException; import com.sk89q.worldguard.protection.util.UnresolvedNamesException; @@ -91,6 +92,11 @@ public void convert(UnresolvedNamesException e) throws CommandException { throw newCommandException(e.getMessage(), e); } + @ExceptionMatch + public void convert(InvalidDomainFormat e) throws CommandException { + throw newCommandException(e.getMessage(), e); + } + @ExceptionMatch public void convert(AuthorizationException e) throws CommandException { throw newCommandException("You don't have permission to do that.", e); From 44f7380d7783e237f10a4a727cfb41e8a79bc9a9 Mon Sep 17 00:00:00 2001 From: JOO200 Date: Sat, 29 Jan 2022 19:55:18 +0100 Subject: [PATCH 08/11] Cleanup DomainRegistry --- .../commands/region/MemberCommands.java | 3 --- .../domains/registry/DomainRegistry.java | 6 +++++ .../registry/SimpleDomainRegistry.java | 24 ++++++++++++------- .../protection/util/DomainInputResolver.java | 5 ++-- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java index 960782d8b..1ddc48030 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/region/MemberCommands.java @@ -26,7 +26,6 @@ import com.sk89q.worldedit.command.util.AsyncCommandBuilder; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.util.formatting.component.ErrorFormat; -import com.sk89q.worldedit.util.formatting.component.SubtleFormat; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.event.ClickEvent; @@ -35,11 +34,9 @@ import com.sk89q.worldedit.world.World; import com.sk89q.worldguard.LocalPlayer; import com.sk89q.worldguard.WorldGuard; -import com.sk89q.worldguard.domains.CustomDomain; import com.sk89q.worldguard.domains.DefaultDomain; import com.sk89q.worldguard.domains.registry.DomainFactory; import com.sk89q.worldguard.domains.registry.DomainRegistry; -import com.sk89q.worldguard.domains.registry.InvalidDomainFormat; import com.sk89q.worldguard.internal.permission.RegionPermissionModel; import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedRegion; diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java index e05ad1780..8a7294b95 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java @@ -62,6 +62,12 @@ public interface DomainRegistry extends Iterable> { @Nullable DomainFactory get(String name); + /** + * Try to get a domain by its name + */ + @Nullable + CustomDomain createDomain(String name); + /** * Get all domains keyed by the registered name * diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java index 7b0b0a8b4..95f8837f7 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/SimpleDomainRegistry.java @@ -100,31 +100,37 @@ public DomainFactory get(String name) { return domains.get(name.toLowerCase()); } + @Nullable + @Override + public CustomDomain createDomain(String name) { + DomainFactory factory = get(name); + if (factory == null) return null; + return factory.create(name); + } + @Override public Map> getAll() { return ImmutableMap.copyOf(domains); } private CustomDomain getOrCreate(String name, Object value, boolean createUnknown) { - DomainFactory domainFactory = get(name); + CustomDomain customDomain = createDomain(name); - if (domainFactory != null) { - CustomDomain customDomain = domainFactory.create(name); - if (customDomain != null) customDomain.unmarshal(value); + if (customDomain != null) { + customDomain.unmarshal(value); return customDomain; } synchronized (lock) { - domainFactory = get(name); // Load again because the previous load was not synchronized - if (domainFactory != null) { - CustomDomain customDomain = domainFactory.create(name); - if (customDomain != null) customDomain.unmarshal(value); + customDomain = createDomain(name); // Load again because the previous load was not synchronized + if (customDomain != null) { + customDomain.unmarshal(value); return customDomain; } if (createUnknown) { DomainFactory unknownFactory = forceRegister(name, UnknownDomain.FACTORY); if (unknownFactory != null) { - CustomDomain customDomain = unknownFactory.create(name); + customDomain = unknownFactory.create(name); if (customDomain != null) customDomain.unmarshal(value); return customDomain; } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java index ed9ce6826..855e37ed6 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java @@ -135,11 +135,10 @@ public DefaultDomain call() throws UnresolvedNamesException, InvalidDomainFormat domain.addGroup(groupMatcher.group(1)); } else if (customMatcher.matches()) { String domainName = customMatcher.group(1); - DomainFactory domainFactory = WorldGuard.getInstance().getDomainRegistry().get(domainName); - if (domainFactory == null) { + CustomDomain customDomain = WorldGuard.getInstance().getDomainRegistry().createDomain(domainName); + if (customDomain == null) { throw new InvalidDomainFormat("No domain named '" + domainName + "' found."); } - CustomDomain customDomain = domainFactory.create(domainName); customDomain.parseInput(CustomDomainContext.create() .setSender(actor).setInput(customMatcher.group(2)).setObject("region", region).build()); } else { From be23d4b031e4ba670bc6737d3a5813f0f8fa9426 Mon Sep 17 00:00:00 2001 From: Joo200 Date: Sun, 18 Sep 2022 18:31:03 +0200 Subject: [PATCH 09/11] Tidy up PR and fixed wrong javadoc --- .../commands/CommandInputContext.java | 16 +++++++------ .../domains/registry/CustomDomainContext.java | 23 +++++++++++-------- .../domains/registry/DomainRegistry.java | 2 +- .../domains/registry/UnknownDomain.java | 2 +- .../permission/RegionPermissionModel.java | 2 +- .../protection/flags/FlagContext.java | 11 ++++++--- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java index 737d062d3..12e86a27b 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/commands/CommandInputContext.java @@ -26,7 +26,7 @@ import javax.annotation.Nullable; import java.util.Map; -public class CommandInputContext { +public abstract class CommandInputContext { protected final Actor sender; protected final String input; @@ -56,30 +56,32 @@ public String getUserInput() { * @return Player * @throws InvalidFlagFormat if the sender is not a player */ - public LocalPlayer getPlayerSender() throws InvalidFlagFormat { + public LocalPlayer getPlayerSender() throws T { if (sender.isPlayer() && sender instanceof LocalPlayer) { return (LocalPlayer) sender; } else { - throw new InvalidFlagFormat("Not a player"); + throw createException("Not a player"); } } - public Integer getUserInputAsInt() throws InvalidFlagFormat { + public Integer getUserInputAsInt() throws T { try { return Integer.parseInt(input); } catch (NumberFormatException e) { - throw new InvalidFlagFormat("Not a number: " + input); + throw createException("Not a number: " + input); } } - public Double getUserInputAsDouble() throws InvalidFlagFormat { + public Double getUserInputAsDouble() throws T { try { return Double.parseDouble(input); } catch (NumberFormatException e) { - throw new InvalidFlagFormat("Not a number: " + input); + throw createException("Not a number: " + input); } } + protected abstract T createException(String str); + /** * Get an object from the context by key name. * May return null if the object does not exist in the context. diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/CustomDomainContext.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/CustomDomainContext.java index e534bc483..9948e908a 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/CustomDomainContext.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/CustomDomainContext.java @@ -26,7 +26,7 @@ import javax.annotation.Nullable; import java.util.Map; -public final class CustomDomainContext extends CommandInputContext { +public final class CustomDomainContext extends CommandInputContext { private CustomDomainContext(Actor sender, String input, Map values) { super(sender, input, values); @@ -38,16 +38,16 @@ public static CustomDomainContext.CustomDomainContextBuilder create() { } /** - * Create a copy of this FlagContext, with optional substitutions for values + * Create a copy of this CustomDomainContext, with optional substitutions for values * - * If any supplied variable is null, it will be ignored. - * If a map is supplied, it will override this FlagContext's values of the same key, - * but unprovided keys will not be overriden and will be returned as shallow copies. + *

If any supplied variable is null, it will be ignored. + * If a map is supplied, it will override this CustomDomainContext's values of the same key, + * but unprovided keys will not be overriden and will be returned as shallow copies.

* - * @param commandSender CommandSender for the new FlagContext to run under - * @param s String of the user input for the new FlagContext - * @param values map of values to override from the current FlagContext - * @return a copy of this FlagContext + * @param commandSender CommandSender for the new CustomDomainContext to run under + * @param s String of the user input for the new CustomDomainContext + * @param values map of values to override from the current CustomDomainContext + * @return a copy of this CustomDomainContext */ public CustomDomainContext copyWith(@Nullable Actor commandSender, @Nullable String s, @Nullable Map values) { Map map = Maps.newHashMap(); @@ -58,6 +58,11 @@ public CustomDomainContext copyWith(@Nullable Actor commandSender, @Nullable Str return new CustomDomainContext(commandSender == null ? this.sender : commandSender, s == null ? this.input : s, map); } + @Override + protected InvalidDomainFormat createException(String str) { + return new InvalidDomainFormat(str); + } + public static class CustomDomainContextBuilder { private Actor sender; private String input; diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java index 8a7294b95..5fd8ac46b 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/domains/registry/DomainRegistry.java @@ -49,7 +49,7 @@ public interface DomainRegistry extends Iterable> { * no exception will be thrown.

* * @param domains a collection of domain factories - * @throws IllegalStateException If it is not the right time to register new flags + * @throws IllegalStateException If it is not the right time to register new domains */ void registerAll(Map> domains); 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 5aa83f460..2d093ca0d 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 @@ -35,7 +35,7 @@ public UnknownDomain(String name) { @Override public void parseInput(CustomDomainContext context) throws InvalidDomainFormat { - throw new InvalidDomainFormat("The plugin that registered this flag is not currently installed"); + throw new InvalidDomainFormat("The plugin that registered this domain is not currently installed"); } @Override diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/internal/permission/RegionPermissionModel.java b/worldguard-core/src/main/java/com/sk89q/worldguard/internal/permission/RegionPermissionModel.java index 966801375..5806dc7c0 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/internal/permission/RegionPermissionModel.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/internal/permission/RegionPermissionModel.java @@ -179,7 +179,7 @@ public boolean mayRemoveOwners(ProtectedRegion region) { } /** - * Checks to see if the given sender has permission to modify a custom region + * Checks to see if the given sender has permission to set or modify a custom domain * * @param region the region * @param isOwnerLevel whether the domain level is owner (else member) diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/FlagContext.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/FlagContext.java index d5d8cda65..3283de3a5 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/FlagContext.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/flags/FlagContext.java @@ -27,7 +27,7 @@ import javax.annotation.Nullable; import java.util.Map; -public final class FlagContext extends CommandInputContext { +public final class FlagContext extends CommandInputContext { private FlagContext(Actor sender, String input, Map values) { super(sender, input, values); @@ -40,9 +40,9 @@ public static FlagContext.FlagContextBuilder create() { /** * Create a copy of this FlagContext, with optional substitutions for values * - * If any supplied variable is null, it will be ignored. + *

If any supplied variable is null, it will be ignored. * If a map is supplied, it will override this FlagContext's values of the same key, - * but unprovided keys will not be overriden and will be returned as shallow copies. + * but unprovided keys will not be overriden and will be returned as shallow copies.

* * @param commandSender CommandSender for the new FlagContext to run under * @param s String of the user input for the new FlagContext @@ -58,6 +58,11 @@ public FlagContext copyWith(@Nullable Actor commandSender, @Nullable String s, @ return new FlagContext(commandSender == null ? this.sender : commandSender, s == null ? this.input : s, map); } + @Override + protected InvalidFlagFormat createException(String str) { + return new InvalidFlagFormat(str); + } + public static class FlagContextBuilder { private Actor sender; private String input; From c8a6e598f80d31afb748acb6abc4b9c0a8d1f86f Mon Sep 17 00:00:00 2001 From: Joo200 Date: Sun, 25 Sep 2022 12:08:54 +0200 Subject: [PATCH 10/11] Add custom domain to domain when using command --- .../sk89q/worldguard/protection/util/DomainInputResolver.java | 1 + 1 file changed, 1 insertion(+) diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java index 855e37ed6..0d345feff 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/util/DomainInputResolver.java @@ -141,6 +141,7 @@ public DefaultDomain call() throws UnresolvedNamesException, InvalidDomainFormat } customDomain.parseInput(CustomDomainContext.create() .setSender(actor).setInput(customMatcher.group(2)).setObject("region", region).build()); + domain.addCustomDomain(customDomain); } else { UUID uuid = parseUUID(s); if (uuid != null) { From 2dff68071f3a7f7b15a83f7a6fe3f3c59204acd7 Mon Sep 17 00:00:00 2001 From: stonar96 Date: Sat, 8 Oct 2022 14:20:29 +0200 Subject: [PATCH 11/11] 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;