diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java index 66ca52814..405fb940d 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java @@ -46,7 +46,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.UUID; -public class OfflineUUIDWrapper extends UUIDWrapper { +public class OfflineUUIDWrapper implements UUIDWrapper { private final Object[] arg = new Object[0]; private Method getOnline = null; diff --git a/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java b/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java index 70bd11673..56e507873 100644 --- a/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java +++ b/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java @@ -60,9 +60,7 @@ import java.util.UUID; * * @version 5 */ -@SuppressWarnings({"unused", "WeakerAccess"}) -@NoArgsConstructor -public class PlotAPI { +@SuppressWarnings({"unused", "WeakerAccess"}) @NoArgsConstructor public class PlotAPI { /** * Gets all plots. diff --git a/Core/src/main/java/com/plotsquared/core/command/Set.java b/Core/src/main/java/com/plotsquared/core/command/Set.java index 4e6fcafc9..413ae3e4b 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Set.java +++ b/Core/src/main/java/com/plotsquared/core/command/Set.java @@ -76,7 +76,6 @@ public class Set extends SubCommand { @Override public boolean set(PlotPlayer player, final Plot plot, String value) { PlotManager manager = player.getLocation().getPlotManager(); String[] components = manager.getPlotComponents(plot.getId()); - boolean allowUnsafe = DebugAllowUnsafe.unsafeAllowed.contains(player.getUUID()); String[] args = value.split(" "); String material = diff --git a/Core/src/main/java/com/plotsquared/core/plot/comment/CommentManager.java b/Core/src/main/java/com/plotsquared/core/plot/comment/CommentManager.java index 6c41b905c..1e945a8bb 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/comment/CommentManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/comment/CommentManager.java @@ -38,8 +38,7 @@ import java.util.HashMap; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -@Beta -public class CommentManager { +@Beta public class CommentManager { public static final HashMap inboxes = new HashMap<>(); diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/FlagContainer.java b/Core/src/main/java/com/plotsquared/core/plot/flag/FlagContainer.java index 7b60fea97..e0bb40fb8 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/flag/FlagContainer.java +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/FlagContainer.java @@ -42,8 +42,7 @@ import java.util.Map; /** * Container type for {@link PlotFlag plot flags}. */ -@EqualsAndHashCode(of = "flagMap") -public class FlagContainer { +@EqualsAndHashCode(of = "flagMap") public class FlagContainer { private final Map unknownFlags = new HashMap<>(); private final Map, PlotFlag> flagMap = new HashMap<>(); @@ -341,8 +340,7 @@ public class FlagContainer { /** * Handler for update events in {@link FlagContainer flag containers}. */ - @FunctionalInterface - public interface PlotFlagUpdateHandler { + @FunctionalInterface public interface PlotFlagUpdateHandler { /** * Act on the flag update event diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java b/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java index 513398a39..af3306b25 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/PlotFlag.java @@ -41,8 +41,7 @@ import java.util.Collections; * * @param Value contained in the flag. */ -@EqualsAndHashCode(of = "value") -public abstract class PlotFlag> { +@EqualsAndHashCode(of = "value") public abstract class PlotFlag> { private final T value; private final Caption flagCategory; diff --git a/Core/src/main/java/com/plotsquared/core/plot/flag/types/BlockTypeWrapper.java b/Core/src/main/java/com/plotsquared/core/plot/flag/types/BlockTypeWrapper.java index 638653f0e..9af840d4c 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/flag/types/BlockTypeWrapper.java +++ b/Core/src/main/java/com/plotsquared/core/plot/flag/types/BlockTypeWrapper.java @@ -44,6 +44,8 @@ import java.util.Map; */ public class BlockTypeWrapper { + private static final Map blockTypes = new HashMap<>(); + private static final Map blockCategories = new HashMap<>(); @Nullable @Getter private final BlockType blockType; @Nullable private final String blockCategoryId; @Nullable private BlockCategory blockCategory; @@ -66,6 +68,19 @@ public class BlockTypeWrapper { this.blockCategoryId = Preconditions.checkNotNull(blockCategoryId); } + public static BlockTypeWrapper get(final BlockType blockType) { + return blockTypes.computeIfAbsent(blockType, BlockTypeWrapper::new); + } + + public static BlockTypeWrapper get(final BlockCategory blockCategory) { + return blockCategories + .computeIfAbsent(blockCategory.getId(), id -> new BlockTypeWrapper(blockCategory)); + } + + public static BlockTypeWrapper get(final String blockCategoryId) { + return blockCategories.computeIfAbsent(blockCategoryId, BlockTypeWrapper::new); + } + @Override public String toString() { if (this.blockType != null) { final String key = this.blockType.toString(); @@ -135,21 +150,6 @@ public class BlockTypeWrapper { return Objects.hashCode(this.blockType, this.blockCategoryId); } - private static final Map blockTypes = new HashMap<>(); - private static final Map blockCategories = new HashMap<>(); - - public static BlockTypeWrapper get(final BlockType blockType) { - return blockTypes.computeIfAbsent(blockType, BlockTypeWrapper::new); - } - - public static BlockTypeWrapper get(final BlockCategory blockCategory) { - return blockCategories - .computeIfAbsent(blockCategory.getId(), id -> new BlockTypeWrapper(blockCategory)); - } - - public static BlockTypeWrapper get(final String blockCategoryId) { - return blockCategories.computeIfAbsent(blockCategoryId, BlockTypeWrapper::new); - } /** * Prevents exceptions when loading/saving block categories diff --git a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java b/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java index 14c5a03ce..b2e8e0227 100644 --- a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java +++ b/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java @@ -31,17 +31,17 @@ import org.jetbrains.annotations.NotNull; import java.util.UUID; -public abstract class UUIDWrapper { +public interface UUIDWrapper { - @NotNull public abstract UUID getUUID(PlotPlayer player); + @NotNull UUID getUUID(PlotPlayer player); - public abstract UUID getUUID(OfflinePlotPlayer player); + UUID getUUID(OfflinePlotPlayer player); - public abstract UUID getUUID(String name); + UUID getUUID(String name); - public abstract OfflinePlotPlayer getOfflinePlayer(UUID uuid); + OfflinePlotPlayer getOfflinePlayer(UUID uuid); - public abstract OfflinePlotPlayer getOfflinePlayer(String name); + OfflinePlotPlayer getOfflinePlayer(String name); - public abstract OfflinePlotPlayer[] getOfflinePlayers(); + OfflinePlotPlayer[] getOfflinePlayers(); } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/ServiceError.java b/Core/src/main/java/com/plotsquared/core/uuid/ServiceError.java new file mode 100644 index 000000000..b33bd1509 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/uuid/ServiceError.java @@ -0,0 +1,43 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.uuid; + +import org.jetbrains.annotations.NotNull; + +/** + * Thrown by {@link ServiceError} when something goes wrong + */ +public class ServiceError extends RuntimeException { + + public ServiceError(@NotNull final String message) { + super(message); + } + + public ServiceError(@NotNull final String message, @NotNull final Throwable cause) { + super(message, cause); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/ServiceFailure.java b/Core/src/main/java/com/plotsquared/core/uuid/ServiceFailure.java new file mode 100644 index 000000000..a2ce41555 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/uuid/ServiceFailure.java @@ -0,0 +1,49 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.uuid; + +import java.util.concurrent.CompletableFuture; + +/** + * Thrown by a {@link UUIDService} when it cannot + * complete a request. This is not an error and + * will be dealt with silently. + */ +public class ServiceFailure extends Throwable { + + private static final ServiceFailure instance = new ServiceFailure(); + + public static CompletableFuture getFuture() { + final CompletableFuture completableFuture = new CompletableFuture<>(); + completableFuture.completeExceptionally(instance); + return completableFuture; + } + + @Override public Throwable fillInStackTrace() { + return this; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java new file mode 100644 index 000000000..798d586ff --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java @@ -0,0 +1,53 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.uuid; + +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +/** + * A pair consisting of a UUID and a username + */ +public class UUIDMapping { + + private final UUID uuid; + private final String username; + + public UUIDMapping(@NotNull final UUID uuid, final String username) { + this.uuid = uuid; + this.username = username; + } + + @NotNull public String getUsername() { + return this.username; + } + + @NotNull public UUID getUuid() { + return this.uuid; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java new file mode 100644 index 000000000..022bb687a --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -0,0 +1,166 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.uuid; + +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.ListIterator; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +/** + * An UUID pipeline is essentially an ordered list of + * {@link UUIDService uuid services} that each get the + * opportunity of providing usernames or UUIDs. + *

+ * Each request is then passed through a secondary list of + * consumers, that can then be used to cache them, etc + */ +public class UUIDPipeline { + + private final Executor executor; + private final List serviceList; + private final List> consumerList; + + public UUIDPipeline(@NotNull final Executor executor) { + this.executor = executor; + this.serviceList = Lists.newLinkedList(); + this.consumerList = Lists.newLinkedList(); + } + + /** + * Register a UUID service + * + * @param uuidService UUID service to register + */ + public void registerService(@NotNull final UUIDService uuidService) { + this.serviceList.add(uuidService); + } + + /** + * Register a mapping consumer + * + * @param mappingConsumer Consumer to register + */ + public void registerConsumer(@NotNull final Consumer mappingConsumer) { + this.consumerList.add(mappingConsumer); + } + + /** + * Get a copy of the service list + * + * @return Copy of service list + */ + public List getServiceListInstance() { + final List serviceList = Lists.newLinkedList(this.serviceList); + serviceList.add(EndOfPipeline.instance); + return serviceList; + } + + private void consume(@NotNull final UUIDMapping mapping) { + for (final Consumer consumer : this.consumerList) { + consumer.accept(mapping); + } + } + + /** + * Asynchronously attempt to fetch the mapping from a given UUID or username + * + * @param request UUID or username + * @return Future that may complete with the mapping + */ + public CompletableFuture get(@NotNull final Object request) { + if (!(request instanceof String) && !(request instanceof UUID)) { + throw new IllegalArgumentException("Request has to be either a username or UUID"); + } + final CompletableFuture future = new CompletableFuture<>(); + final ListIterator serviceListIterator + = this.getServiceListInstance().listIterator(); + final Runnable[] runnable = new Runnable[1]; + runnable[0] = () -> { + if (serviceListIterator.hasNext()) { + final UUIDService uuidService = serviceListIterator.next(); + uuidService.get(request).whenCompleteAsync(((result, throwable) -> { + if (throwable != null) { + if (throwable instanceof ServiceFailure) { + try { + runnable[0].run(); + } catch (final Throwable inner) { + future.completeExceptionally(inner); + } + } else { + future.completeExceptionally(throwable); + } + } else { + final String username = request instanceof String ? (String) request + : (String) result; + final UUID uuid = request instanceof UUID ? (UUID) request + : (UUID) result; + final UUIDMapping mapping = new UUIDMapping(uuid, username); + future.complete(mapping); + this.consume(mapping); + } + }), this.executor); + } else { + throw new ServiceError("Pipeline is incomplete"); + } + }; + try { + // Start the pipeline traversal + runnable[0].run(); + } catch (final Throwable throwable) { + future.completeExceptionally(throwable); + } + return future; + } + + /** + * Indicates that the end of the pipeline has been reached, this + * will cause the request to fail, as no service was able to + * fulfil the request + */ + private static class EndOfPipeline implements UUIDService { + + public static final EndOfPipeline instance = new EndOfPipeline(); + + @Override @NotNull public CompletableFuture get(@NotNull final UUID uuid) { + final CompletableFuture future = new CompletableFuture<>(); + future.completeExceptionally(new ServiceError("End of pipeline")); + return future; + } + + @Override @NotNull public CompletableFuture get(@NotNull final String username) { + final CompletableFuture future = new CompletableFuture<>(); + future.completeExceptionally(new ServiceError("End of pipeline")); + return future; + } + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java new file mode 100644 index 000000000..98f58b9c4 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java @@ -0,0 +1,74 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.uuid; + +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +/** + * Service used to provide usernames from player UUIDs + */ +public interface UUIDService { + + default CompletableFuture get(@NotNull final Object request) { + if (request instanceof UUID) { + return get((UUID) request); + } else if (request instanceof String) { + return get((String) request); + } else { + throw new IllegalArgumentException("Request has to be either a username or UUID"); + } + } + + /** + * Get a stored username from the service if it exists. + * This should not trigger any fetching of + * usernames from other services. + *

+ * If the username isn't stored in this service, + * this completes with an empty optional. + * + * @param uuid Player UUID + * @return Future that may contain the username if it exists + */ + @NotNull CompletableFuture get(@NotNull final UUID uuid); + + /** + * Get a stored UUID from the service if it exists. + * This should not trigger any fetching of + * UUID from other services. + *

+ * If the UUID isn't stored in this service, + * this completes with an empty optional. + * + * @param username Player username + * @return Future that may contain the UUID if it exists + */ + @NotNull CompletableFuture get(@NotNull final String username); + +} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/offline/OfflineModeUUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/offline/OfflineModeUUIDService.java new file mode 100644 index 000000000..a58ab0863 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/uuid/offline/OfflineModeUUIDService.java @@ -0,0 +1,59 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * PlotSquared plot management system for Minecraft + * Copyright (C) 2020 IntellectualSites + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.plotsquared.core.uuid.offline; + +import com.google.common.base.Charsets; +import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.uuid.ServiceFailure; +import com.plotsquared.core.uuid.UUIDService; +import org.jetbrains.annotations.NotNull; + +import java.util.Locale; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +/** + * Name provider service that creates UUIDs from usernames + */ +public class OfflineModeUUIDService implements UUIDService { + + @NotNull protected final UUID getFromUsername(@NotNull String username) { + if (Settings.UUID.FORCE_LOWERCASE) { + username = username.toLowerCase(Locale.ENGLISH); + } + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(Charsets.UTF_8)); + } + + @Override @NotNull public CompletableFuture get(@NotNull final UUID uuid) { + // This service can only get UUIDs from usernames + return ServiceFailure.getFuture(); + } + + @Override @NotNull public CompletableFuture get(@NotNull final String username) { + return CompletableFuture.completedFuture(this.getFromUsername(username)); + } + +}