Skip to content

Commit

Permalink
Initial work on namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
DarkArc committed Jan 15, 2020
1 parent b835ee3 commit 1a4dc79
Show file tree
Hide file tree
Showing 16 changed files with 826 additions and 188 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.auth.AuthorizationException;
import com.sk89q.worldedit.util.formatting.component.ErrorFormat;
import com.sk89q.worldedit.util.formatting.component.LabelFormat;
import com.sk89q.worldedit.util.formatting.component.SubtleFormat;
Expand Down Expand Up @@ -68,11 +69,8 @@
import com.sk89q.worldguard.protection.managers.migration.UUIDMigration;
import com.sk89q.worldguard.protection.managers.storage.DriverType;
import com.sk89q.worldguard.protection.managers.storage.RegionDriver;
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.*;
import com.sk89q.worldguard.protection.regions.ProtectedRegion.CircularInheritanceException;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.util.DomainInputResolver.UserLocatorPolicy;
import com.sk89q.worldguard.session.Session;
import com.sk89q.worldguard.util.Enums;
Expand Down Expand Up @@ -133,7 +131,7 @@ public RegionCommands(WorldGuard worldGuard) {
flags = "ng",
desc = "Defines a region",
min = 1)
public void define(CommandContext args, Actor sender) throws CommandException {
public void define(CommandContext args, Actor sender) throws CommandException, AuthorizationException {
warnAboutSaveFailures(sender);
LocalPlayer player = worldGuard.checkPlayer(sender);

Expand All @@ -142,7 +140,7 @@ public void define(CommandContext args, Actor sender) throws CommandException {
throw new CommandPermissionsException();
}

String id = checkRegionId(args.getString(0), false);
RegionIdentifier id = processRegionId(sender, args.getString(0), false);

World world = player.getWorld();
RegionManager manager = checkRegionManager(world);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
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.TextComponent;
Expand All @@ -49,13 +50,11 @@
import com.sk89q.worldguard.protection.flags.FlagContext;
import com.sk89q.worldguard.protection.flags.InvalidFlagFormat;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.*;

import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

class RegionCommandsBase {
Expand Down Expand Up @@ -95,6 +94,25 @@ protected static World checkWorld(CommandContext args, Actor sender, char flag)
}
}

/**
* Validate a region name.
*
* @param name the name
* @param allowGlobal whether __global__ is allowed
* @throws CommandException thrown on an error
*/
protected static void checkName(String name, boolean allowGlobal) throws CommandException {
if (!RegionIdentifier.isValidName(name)) {
throw new CommandException(
"The region name of '" + name + "' contains characters that are not allowed.");
}

if (!allowGlobal && name.equalsIgnoreCase("__global__")) { // Sorry, no global
throw new CommandException(
"Sorry, you can't use __global__ here.");
}
}

/**
* Validate a region ID.
*
Expand All @@ -103,18 +121,127 @@ protected static World checkWorld(CommandContext args, Actor sender, char flag)
* @return the id given
* @throws CommandException thrown on an error
*/
@Deprecated
protected static String checkRegionId(String id, boolean allowGlobal) throws CommandException {
if (!ProtectedRegion.isValidId(id)) {
checkName(id, allowGlobal);
return id;
}

/**
* Validate a region namespace.
*
* @param namespace the namespace name
* @throws CommandException thrown on an error
*/
protected static void checkNamespace(String namespace) throws CommandException {
if (!RegionIdentifier.isValidNamespace(namespace)) {
throw new CommandException(
"The region name of '" + id + "' contains characters that are not allowed.");
"The region namespace of '" + namespace + "' contains characters that are not allowed.");
}
}

if (!allowGlobal && id.equalsIgnoreCase("__global__")) { // Sorry, no global
throw new CommandException(
"Sorry, you can't use __global__ here.");
/**
* Get the unqualified name from a possibly qualified region identifier.
*
* @param id the unprocessed region identifier
* @return the unqualified name, or an empty string if not present
*/
protected static String getUnqualifiedName(String id) {
int namespaceSeparatorIndex = id.lastIndexOf(':');
if (namespaceSeparatorIndex == -1) {
return id;
}

return id;
int unqualifiedNameStartIndex = namespaceSeparatorIndex + 1;
if (unqualifiedNameStartIndex == id.length()) {
return "";
}

return id.substring(unqualifiedNameStartIndex);
}

/**
* Get the namespace name from a possibly qualified region identifier.
*
* @param id the unprocessed region identifier
* @return an optional containing the namespace name, or an empty string if qualified,
* if not qualified, an empty optional is returned
*/
protected static Optional<String> getNamespace(String id) {
int namespaceSeparatorIndex = id.lastIndexOf(':');
if (namespaceSeparatorIndex == -1) {
return Optional.empty();
}

return Optional.of(id.substring(0, namespaceSeparatorIndex));
}

/***
* Expand macros in the namespace name.
*
* @param namespace the unexpanded namespace name
* @return the expanded namespace name
*/
protected static String expandNamespace(String namespace) {
if (namespace.startsWith("#")) {
String playerName = namespace.substring(1);
// TODO: Resolve player uuid from name, and return that instead.
return playerName;
}

return namespace;
}

/**
* Get the default namespace for a given actor.
*
* @param sender the sender who's default namespace we intend to retrieve.
* @return the default namespace
*/
protected static String getDefaultNamespace(Actor sender) {
return sender.getUniqueId().toString();
}

/**
* Process a possibly qualified region identifier into a RegionIdentifier.
*
* This method takes a possibly qualified region identifier, and processes it, expanding any namespace macros,
* running permissions checks, and validating the names for invalid character.
*
* @param sender the contextual sender to use for checks and macro expansions
* @param id the possibly unqualified id
* @param allowGlobal whether or not this method should allow use of the name __global__ name
* @return the processed region id
* @throws AuthorizationException if a permission check fails
* @throws CommandException if a name validation check fails
*/
protected static RegionIdentifier processRegionId(Actor sender, String id, boolean allowGlobal) throws AuthorizationException, CommandException {
String unqualifiedName = getUnqualifiedName(id);
checkName(unqualifiedName, allowGlobal);

Optional<String> optProvidedNamespace = getNamespace(id).map(RegionCommandsBase::expandNamespace);
String namespace = optProvidedNamespace.orElse(getDefaultNamespace(sender));
checkNamespace(namespace);

// TODO use more informative permission checks

if (namespace.equals("")) {
sender.checkPermission("worldguard.region.namespace.global");
return new RegionIdentifier(null, unqualifiedName);
}

try {
UUID namespacePlayerId = UUID.fromString(namespace);
if (namespacePlayerId.equals(sender.getUniqueId())) {
sender.checkPermission("worldguard.region.namespace.player.self");
} else {
sender.checkPermission("worldguard.region.namespace.player.other");
}
} catch (IllegalArgumentException ex) {
sender.checkPermission("worldguard.region.namespace." + namespace);
}

return new RegionIdentifier(namespace, unqualifiedName);
}

/**
Expand Down Expand Up @@ -244,7 +371,19 @@ protected static Region checkSelection(LocalPlayer player) throws CommandExcepti
* @param id the ID
* @throws CommandException thrown if the ID already exists
*/
@Deprecated
protected static void checkRegionDoesNotExist(RegionManager manager, String id, boolean mayRedefine) throws CommandException {
checkRegionDoesNotExist(manager, new RegionIdentifier(id), mayRedefine);
}

/**
* Check that a region with the given ID does not already exist.
*
* @param manager the manager
* @param id the identifier
* @throws CommandException thrown if the ID already exists
*/
protected static void checkRegionDoesNotExist(RegionManager manager, RegionIdentifier id, boolean mayRedefine) throws CommandException {
if (manager.hasRegion(id)) {
throw new CommandException("A region with that name already exists. Please choose another name." +
(mayRedefine ? " To change the shape, use /region redefine " + id + "." : ""));
Expand Down Expand Up @@ -280,7 +419,20 @@ protected static RegionManager checkRegionManager(World world) throws CommandExc
* @return a new region
* @throws CommandException thrown on an error
*/
@Deprecated
protected static ProtectedRegion checkRegionFromSelection(LocalPlayer player, String id) throws CommandException {
return checkRegionFromSelection(player, new RegionIdentifier(id));
}

/**
* Create a {@link ProtectedRegion} from the player's selection.
*
* @param player the player
* @param id the identifier of the new region
* @return a new region
* @throws CommandException thrown on an error
*/
protected static ProtectedRegion checkRegionFromSelection(LocalPlayer player, RegionIdentifier id) throws CommandException {
Region selection = checkSelection(player);

// Detect the type of region from WorldEdit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.sk89q.worldguard.protection.managers.storage.RegionDatabase;
import com.sk89q.worldguard.protection.managers.storage.StorageException;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionIdentifier;
import com.sk89q.worldguard.protection.util.RegionCollectionConsumer;
import com.sk89q.worldguard.util.Normal;

Expand Down Expand Up @@ -242,10 +243,22 @@ public void addRegion(ProtectedRegion region) {
* @param id the name of the region
* @return true if this index contains the region
*/
@Deprecated
public boolean hasRegion(String id) {
return index.contains(id);
}

/**
* Return whether the index contains a region with the given identifier,
* with quality determined by {@link Normal}.
*
* @param id the region identifier
* @return true if this index contains the region
*/
public boolean hasRegion(RegionIdentifier id) {
return index.contains(id.getQualifiedName());
}

/**
* Get the region named by the given name (equality determined using
* {@link Normal}).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,13 @@ private void performAdd(ProtectedRegion region) {
region.setDirty(true);

synchronized (lock) {
String normalId = normalize(region.getId());
String newFullId = region.getIdentifier().getQualifiedName();
String normalId = normalize(newFullId);

ProtectedRegion existing = regions.get(normalId);

// Casing / form of ID has changed
if (existing != null && !existing.getId().equals(region.getId())) {
if (existing != null && !existing.getIdentifier().getQualifiedName().equals(newFullId)) {
removed.add(existing);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* WorldGuard, a suite of tools for Minecraft
* Copyright (C) sk89q <http://www.sk89q.com>
* 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 <http://www.gnu.org/licenses/>.
*/

package com.sk89q.worldguard.protection.managers.storage.file;

import com.sk89q.util.yaml.YAMLNode;
import com.sk89q.worldguard.domains.DefaultDomain;

import java.util.UUID;
import java.util.logging.Level;

class DomainParser {
public static class One {
public static DefaultDomain parseDomain(YAMLNode node) {
if (node == null) {
return new DefaultDomain();
}

DefaultDomain domain = new DefaultDomain();

for (String name : node.getStringList("players", null)) {
if (!name.isEmpty()) {
domain.addPlayer(name);
}
}

for (String stringId : node.getStringList("unique-ids", null)) {
try {
domain.addPlayer(UUID.fromString(stringId));
} catch (IllegalArgumentException e) {
YamlCommon.log.log(Level.WARNING, "Failed to parse UUID '" + stringId + "'", e);
}
}

for (String name : node.getStringList("groups", null)) {
if (!name.isEmpty()) {
domain.addGroup(name);
}
}

return domain;
}
}
}
Loading

0 comments on commit 1a4dc79

Please sign in to comment.