From 7591c440c25027d7eae435bedbee0cb83536dc0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 12:40:25 +0200 Subject: [PATCH 001/121] Begin working on the new UUID service API --- .../bukkit/util/uuid/OfflineUUIDWrapper.java | 2 +- .../com/plotsquared/core/api/PlotAPI.java | 4 +- .../com/plotsquared/core/command/Set.java | 1 - .../core/plot/comment/CommentManager.java | 3 +- .../core/plot/flag/FlagContainer.java | 6 +- .../plotsquared/core/plot/flag/PlotFlag.java | 3 +- .../plot/flag/types/BlockTypeWrapper.java | 30 ++-- .../core/util/uuid/UUIDWrapper.java | 14 +- .../plotsquared/core/uuid/ServiceError.java | 43 +++++ .../plotsquared/core/uuid/ServiceFailure.java | 49 ++++++ .../plotsquared/core/uuid/UUIDMapping.java | 53 ++++++ .../plotsquared/core/uuid/UUIDPipeline.java | 166 ++++++++++++++++++ .../plotsquared/core/uuid/UUIDService.java | 74 ++++++++ .../uuid/offline/OfflineModeUUIDService.java | 59 +++++++ 14 files changed, 472 insertions(+), 35 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/uuid/ServiceError.java create mode 100644 Core/src/main/java/com/plotsquared/core/uuid/ServiceFailure.java create mode 100644 Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java create mode 100644 Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java create mode 100644 Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java create mode 100644 Core/src/main/java/com/plotsquared/core/uuid/offline/OfflineModeUUIDService.java 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)); + } + +} From 792fa1f11dbbba13fcbbe5ea43e9094d02fbad38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 12:55:07 +0200 Subject: [PATCH 002/121] Improve design --- .../plotsquared/core/uuid/ServiceFailure.java | 49 ---------- .../plotsquared/core/uuid/UUIDPipeline.java | 89 ++++++------------- .../plotsquared/core/uuid/UUIDService.java | 12 +-- .../uuid/offline/OfflineModeUUIDService.java | 12 ++- 4 files changed, 36 insertions(+), 126 deletions(-) delete mode 100644 Core/src/main/java/com/plotsquared/core/uuid/ServiceFailure.java diff --git a/Core/src/main/java/com/plotsquared/core/uuid/ServiceFailure.java b/Core/src/main/java/com/plotsquared/core/uuid/ServiceFailure.java deleted file mode 100644 index a2ce41555..000000000 --- a/Core/src/main/java/com/plotsquared/core/uuid/ServiceFailure.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 022bb687a..87ef3f529 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -28,8 +28,11 @@ package com.plotsquared.core.uuid; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.List; -import java.util.ListIterator; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -79,9 +82,7 @@ public class UUIDPipeline { * @return Copy of service list */ public List getServiceListInstance() { - final List serviceList = Lists.newLinkedList(this.serviceList); - serviceList.add(EndOfPipeline.instance); - return serviceList; + return Collections.unmodifiableList(this.serviceList); } private void consume(@NotNull final UUIDMapping mapping) { @@ -93,74 +94,34 @@ public class UUIDPipeline { /** * Asynchronously attempt to fetch the mapping from a given UUID or username * - * @param request UUID or username + * @param requests UUIDs or usernames * @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 { + public CompletableFuture> get(@NotNull final Collection requests) { + final List serviceList = this.getServiceListInstance(); + return CompletableFuture.supplyAsync(() -> { + final List mappings = new ArrayList<>(requests.size()); + outer: for (final Object request : requests) { + if (!(request instanceof String) && !(request instanceof UUID)) { + throw new IllegalArgumentException("Request has to be either a username or UUID"); + } + for (final UUIDService service : serviceList) { + final Optional result = service.get(request); + if (result.isPresent()) { final String username = request instanceof String ? (String) request - : (String) result; + : (String) result.get(); final UUID uuid = request instanceof UUID ? (UUID) request - : (UUID) result; + : (UUID) result.get(); final UUIDMapping mapping = new UUIDMapping(uuid, username); - future.complete(mapping); this.consume(mapping); + mappings.add(mapping); + continue outer; } - }), this.executor); - } else { - throw new ServiceError("Pipeline is incomplete"); + } + throw new ServiceError("End of pipeline"); } - }; - 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; - } + return mappings; + }, this.executor); } } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java index 98f58b9c4..db29480d7 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java @@ -27,15 +27,15 @@ package com.plotsquared.core.uuid; import org.jetbrains.annotations.NotNull; +import java.util.Optional; 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) { + default Optional get(@NotNull final Object request) { if (request instanceof UUID) { return get((UUID) request); } else if (request instanceof String) { @@ -54,9 +54,9 @@ public interface UUIDService { * this completes with an empty optional. * * @param uuid Player UUID - * @return Future that may contain the username if it exists + * @return Optional that may contain the username if it exists */ - @NotNull CompletableFuture get(@NotNull final UUID uuid); + @NotNull Optional get(@NotNull final UUID uuid); /** * Get a stored UUID from the service if it exists. @@ -67,8 +67,8 @@ public interface UUIDService { * this completes with an empty optional. * * @param username Player username - * @return Future that may contain the UUID if it exists + * @return Optional that may contain the UUID if it exists */ - @NotNull CompletableFuture get(@NotNull final String username); + @NotNull Optional 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 index a58ab0863..7e397119e 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/offline/OfflineModeUUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/offline/OfflineModeUUIDService.java @@ -27,13 +27,12 @@ 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.Optional; import java.util.UUID; -import java.util.concurrent.CompletableFuture; /** * Name provider service that creates UUIDs from usernames @@ -47,13 +46,12 @@ public class OfflineModeUUIDService implements UUIDService { 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 Optional get(@NotNull final UUID uuid) { + return Optional.empty(); } - @Override @NotNull public CompletableFuture get(@NotNull final String username) { - return CompletableFuture.completedFuture(this.getFromUsername(username)); + @Override @NotNull public Optional get(@NotNull final String username) { + return Optional.of(this.getFromUsername(username)); } } From 29f2863cf41d2392800e596b64f5e4c28844c999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 17:26:48 +0200 Subject: [PATCH 003/121] Progress --- Bukkit/build.gradle | 3 + Bukkit/pom.xml | 6 ++ .../bukkit/uuid/OfflinePlayerUUIDService.java | 57 ++++++++++++ .../bukkit/uuid/PaperUUIDService.java | 65 ++++++++++++++ .../bukkit/uuid/SquirrelIdUUIDService.java | 90 +++++++++++++++++++ .../plotsquared/core/uuid/UUIDPipeline.java | 68 +++++++++----- .../plotsquared/core/uuid/UUIDService.java | 46 +++------- .../uuid/offline/OfflineModeUUIDService.java | 17 ++-- 8 files changed, 292 insertions(+), 60 deletions(-) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/uuid/PaperUUIDService.java create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SquirrelIdUUIDService.java diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 9fa1f8cf1..9b6b862a6 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -31,6 +31,7 @@ dependencies { } implementation("me.clip:placeholderapi:2.10.4") compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false } + compile 'com.github.pavog:SquirrelID:0.6.1' } sourceCompatibility = 1.8 @@ -87,10 +88,12 @@ shadowJar { include(dependency("io.papermc:paperlib:1.0.2")) include(dependency("net.kyori:text-adapter-bukkit:3.0.3")) include(dependency("org.bstats:bstats-bukkit:1.7")) + include(dependency("com.github.pavog:SquirrelID:0.6.1")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") relocate("org.bstats", "com.plotsquared.metrics") + relocate('com.sk89q.squirrelid', 'com.plotsquared.squirrelid') archiveFileName = "${project.name}-${parent.version}.jar" destinationDirectory = file "../target" } diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index 40202c32e..1eace8462 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -59,6 +59,12 @@ Core 0.6.0-SNAPSHOT compile + + + * + * + + com.sk89q.worldedit diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java new file mode 100644 index 000000000..8ba2ad76b --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java @@ -0,0 +1,57 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.bukkit.uuid; + +import com.plotsquared.core.uuid.UUIDService; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; +import java.util.UUID; + +/** + * UUID service that use {@link org.bukkit.OfflinePlayer offline players} + */ +public class OfflinePlayerUUIDService implements UUIDService { + + @Override @NotNull public Optional get(@NotNull final UUID uuid) { + final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); + if (offlinePlayer.hasPlayedBefore()) { + return Optional.ofNullable(offlinePlayer.getName()); + } + return Optional.empty(); + } + + @Override @NotNull public Optional get(@NotNull final String username) { + final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(username); + if (offlinePlayer.hasPlayedBefore()) { + return Optional.of(offlinePlayer.getUniqueId()); + } + return Optional.empty(); + } + +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/PaperUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/PaperUUIDService.java new file mode 100644 index 000000000..4f370c8b3 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/PaperUUIDService.java @@ -0,0 +1,65 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.bukkit.uuid; + +import com.destroystokyo.paper.profile.PlayerProfile; +import com.plotsquared.core.uuid.UUIDMapping; +import com.plotsquared.core.uuid.UUIDService; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * UUID service that uses the Paper profile API + */ +public class PaperUUIDService implements UUIDService { + + @Override @NotNull public List getNames(@NotNull final List uuids) { + final List mappings = new ArrayList<>(uuids.size()); + for (final UUID uuid : uuids) { + final PlayerProfile playerProfile = Bukkit.createProfile(uuid); + if ((playerProfile.isComplete() || playerProfile.completeFromCache()) && playerProfile.getId() != null) { + mappings.add(new UUIDMapping(playerProfile.getId(), playerProfile.getName())); + } + } + return mappings; + } + + @Override @NotNull public List getUUIDs(@NotNull final List usernames) { + final List mappings = new ArrayList<>(usernames.size()); + for (final String username : usernames) { + final PlayerProfile playerProfile = Bukkit.createProfile(username); + if ((playerProfile.isComplete() || playerProfile.completeFromCache()) && playerProfile.getId() != null) { + mappings.add(new UUIDMapping(playerProfile.getId(), playerProfile.getName())); + } + } + return mappings; + } + +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SquirrelIdUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SquirrelIdUUIDService.java new file mode 100644 index 000000000..4580519aa --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SquirrelIdUUIDService.java @@ -0,0 +1,90 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.bukkit.uuid; + +import com.google.common.util.concurrent.RateLimiter; +import com.plotsquared.core.uuid.UUIDMapping; +import com.plotsquared.core.uuid.UUIDService; +import com.sk89q.squirrelid.Profile; +import com.sk89q.squirrelid.resolver.HttpRepositoryService; +import com.sk89q.squirrelid.resolver.ProfileService; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * UUID service using SquirrelID + */ +@SuppressWarnings("UnstableApiUsage") +public class SquirrelIdUUIDService implements UUIDService { + + private final ProfileService profileService; + private final RateLimiter rateLimiter; + + /** + * Create a new SquirrelID UUID service + * + * @param rateLimit Mojangs rate limit is 600 requests per 10 minutes. + * This parameter specifies how many of those requests + * we can use before our internal rate limit kicks in. + */ + public SquirrelIdUUIDService(final int rateLimit) { + this.profileService = HttpRepositoryService.forMinecraft(); + // RateLimiter uses request per seconds. The constructor + // parameter rateLimit is requests per 600 seconds + this.rateLimiter = RateLimiter.create(rateLimit / 600.0D); + } + + @Override @NotNull public List getNames(@NotNull final List uuids) { + final List results = new ArrayList<>(uuids.size()); + this.rateLimiter.acquire(uuids.size()); + try { + for (final Profile profile : this.profileService.findAllById(uuids)) { + results.add(new UUIDMapping(profile.getUniqueId(), profile.getName())); + } + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + return results; + } + + @Override @NotNull public List getUUIDs(@NotNull final List usernames) { + final List results = new ArrayList<>(usernames.size()); + this.rateLimiter.acquire(usernames.size()); + try { + for (final Profile profile : this.profileService.findAllByName(usernames)) { + results.add(new UUIDMapping(profile.getUniqueId(), profile.getName())); + } + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + return results; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 87ef3f529..64da919f4 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -32,7 +32,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -92,35 +91,58 @@ public class UUIDPipeline { } /** - * Asynchronously attempt to fetch the mapping from a given UUID or username + * Asynchronously attempt to fetch the mapping from a list of UUIDs * - * @param requests UUIDs or usernames - * @return Future that may complete with the mapping + * @param requests UUIDs + * @return Mappings */ - public CompletableFuture> get(@NotNull final Collection requests) { + public CompletableFuture> getNames(@NotNull final Collection requests) { final List serviceList = this.getServiceListInstance(); return CompletableFuture.supplyAsync(() -> { final List mappings = new ArrayList<>(requests.size()); - outer: for (final Object request : requests) { - if (!(request instanceof String) && !(request instanceof UUID)) { - throw new IllegalArgumentException("Request has to be either a username or UUID"); + final List remainingRequests = new ArrayList<>(requests); + + for (final UUIDService service : serviceList) { + final List completedRequests = service.getNames(remainingRequests); + for (final UUIDMapping mapping : completedRequests) { + remainingRequests.remove(mapping.getUuid()); } - for (final UUIDService service : serviceList) { - final Optional result = service.get(request); - if (result.isPresent()) { - final String username = request instanceof String ? (String) request - : (String) result.get(); - final UUID uuid = request instanceof UUID ? (UUID) request - : (UUID) result.get(); - final UUIDMapping mapping = new UUIDMapping(uuid, username); - this.consume(mapping); - mappings.add(mapping); - continue outer; - } - } - throw new ServiceError("End of pipeline"); + mappings.addAll(completedRequests); } - return mappings; + + if (mappings.size() == requests.size()) { + return mappings; + } + + throw new ServiceError("End of pipeline"); + }, this.executor); + } + + /** + * Asynchronously attempt to fetch the mapping from a list of names + * + * @param requests Names + * @return Mappings + */ + public CompletableFuture> getUUIDs(@NotNull final Collection requests) { + final List serviceList = this.getServiceListInstance(); + return CompletableFuture.supplyAsync(() -> { + final List mappings = new ArrayList<>(requests.size()); + final List remainingRequests = new ArrayList<>(requests); + + for (final UUIDService service : serviceList) { + final List completedRequests = service.getUUIDs(remainingRequests); + for (final UUIDMapping mapping : completedRequests) { + remainingRequests.remove(mapping.getUsername()); + } + mappings.addAll(completedRequests); + } + + if (mappings.size() == requests.size()) { + return mappings; + } + + throw new ServiceError("End of pipeline"); }, this.executor); } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java index db29480d7..468de09b2 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java @@ -27,7 +27,7 @@ package com.plotsquared.core.uuid; import org.jetbrains.annotations.NotNull; -import java.util.Optional; +import java.util.List; import java.util.UUID; /** @@ -35,40 +35,22 @@ import java.util.UUID; */ public interface UUIDService { - default Optional 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"); - } - } + /** + * Attempt to complete the given requests. Returns the mappings + * that could be created by this server + * + * @param uuids Requests + * @return Completed requests + */ + @NotNull List getNames(@NotNull final List uuids); /** - * 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. + * Attempt to complete the given requests. Returns the mappings + * that could be created by this server * - * @param uuid Player UUID - * @return Optional that may contain the username if it exists + * @param usernames Requests + * @return Completed requests */ - @NotNull Optional 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 Optional that may contain the UUID if it exists - */ - @NotNull Optional get(@NotNull final String username); + @NotNull List getUUIDs(@NotNull final List usernames); } 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 index 7e397119e..49f038db8 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/offline/OfflineModeUUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/offline/OfflineModeUUIDService.java @@ -27,11 +27,14 @@ package com.plotsquared.core.uuid.offline; import com.google.common.base.Charsets; import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.uuid.UUIDMapping; import com.plotsquared.core.uuid.UUIDService; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Locale; -import java.util.Optional; import java.util.UUID; /** @@ -46,12 +49,16 @@ public class OfflineModeUUIDService implements UUIDService { return UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(Charsets.UTF_8)); } - @Override @NotNull public Optional get(@NotNull final UUID uuid) { - return Optional.empty(); + @Override @NotNull public List getNames(@NotNull final List uuids) { + return Collections.emptyList(); } - @Override @NotNull public Optional get(@NotNull final String username) { - return Optional.of(this.getFromUsername(username)); + @Override @NotNull public List getUUIDs(@NotNull List usernames) { + final List mappings = new ArrayList<>(usernames.size()); + for (final String username : usernames) { + mappings.add(new UUIDMapping(getFromUsername(username), username)); + } + return mappings; } } From 64cfe240f9292cc300d1a3335aebdcc3e2577999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 17:36:12 +0200 Subject: [PATCH 004/121] Port OfflinePlayerUUIDService to the new system --- .../bukkit/uuid/OfflinePlayerUUIDService.java | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java index 8ba2ad76b..403832f38 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java @@ -25,12 +25,14 @@ */ package com.plotsquared.bukkit.uuid; +import com.plotsquared.core.uuid.UUIDMapping; import com.plotsquared.core.uuid.UUIDService; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; -import java.util.Optional; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; /** @@ -38,20 +40,26 @@ import java.util.UUID; */ public class OfflinePlayerUUIDService implements UUIDService { - @Override @NotNull public Optional get(@NotNull final UUID uuid) { - final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); - if (offlinePlayer.hasPlayedBefore()) { - return Optional.ofNullable(offlinePlayer.getName()); + @Override public @NotNull List getNames(@NotNull List uuids) { + final List wrappers = new ArrayList<>(uuids.size()); + for (final UUID uuid : uuids) { + final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); + if (offlinePlayer.hasPlayedBefore()) { + wrappers.add(new UUIDMapping(uuid, offlinePlayer.getName())); + } } - return Optional.empty(); + return wrappers; } - @Override @NotNull public Optional get(@NotNull final String username) { - final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(username); - if (offlinePlayer.hasPlayedBefore()) { - return Optional.of(offlinePlayer.getUniqueId()); + @Override public @NotNull List getUUIDs(@NotNull List usernames) { + final List wrappers = new ArrayList<>(usernames.size()); + for (final String username : usernames) { + final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(username); + if (offlinePlayer.hasPlayedBefore()) { + wrappers.add(new UUIDMapping(offlinePlayer.getUniqueId(), offlinePlayer.getName())); + } } - return Optional.empty(); + return wrappers; } } From 95df62e59b2b19fbb8eb260ce3084d616d63289e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 17:48:42 +0200 Subject: [PATCH 005/121] Add missing consumer API methods --- .../plotsquared/core/uuid/UUIDPipeline.java | 60 ++++++++++++++++--- 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 64da919f4..0df18ea94 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -26,6 +26,8 @@ package com.plotsquared.core.uuid; import com.google.common.collect.Lists; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.util.task.TaskManager; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -49,8 +51,14 @@ public class UUIDPipeline { private final Executor executor; private final List serviceList; - private final List> consumerList; + private final List>> consumerList; + /** + * Construct a new UUID pipeline + * + * @param executor Executor that is used to run asynchronous tasks inside + * of the pipeline + */ public UUIDPipeline(@NotNull final Executor executor) { this.executor = executor; this.serviceList = Lists.newLinkedList(); @@ -71,7 +79,7 @@ public class UUIDPipeline { * * @param mappingConsumer Consumer to register */ - public void registerConsumer(@NotNull final Consumer mappingConsumer) { + public void registerConsumer(@NotNull final Consumer> mappingConsumer) { this.consumerList.add(mappingConsumer); } @@ -84,19 +92,54 @@ public class UUIDPipeline { return Collections.unmodifiableList(this.serviceList); } - private void consume(@NotNull final UUIDMapping mapping) { - for (final Consumer consumer : this.consumerList) { - consumer.accept(mapping); + /** + * Let all consumers act on the given mapping. + * + * @param mappings Mappings + */ + public void consume(@NotNull final List mappings) { + final Runnable runnable = () -> { + for (final Consumer> consumer : this.consumerList) { + consumer.accept(mappings); + } + }; + if (PlotSquared.get().isMainThread(Thread.currentThread())) { + TaskManager.runTaskAsync(runnable); + } else { + runnable.run(); } } + /** + * Consume a single mapping + * + * @param mapping Mapping to consume + */ + public void consume(@NotNull final UUIDMapping mapping) { + this.consume(Collections.singletonList(mapping)); + } + + /** + * This will store the given username-UUID pair directly, and overwrite + * any existing caches. This can be used to update usernames automatically + * whenever a player joins the server, to make sure an up-to-date UUID + * mapping is stored + * + * @param username Player username + * @param uuid Player uuid + */ + public void storeImmediately(@NotNull final String username, @NotNull final UUID uuid) { + this.consume(new UUIDMapping(uuid, username)); + } + /** * Asynchronously attempt to fetch the mapping from a list of UUIDs * * @param requests UUIDs * @return Mappings */ - public CompletableFuture> getNames(@NotNull final Collection requests) { + public CompletableFuture> getNames( + @NotNull final Collection requests) { final List serviceList = this.getServiceListInstance(); return CompletableFuture.supplyAsync(() -> { final List mappings = new ArrayList<>(requests.size()); @@ -111,6 +154,7 @@ public class UUIDPipeline { } if (mappings.size() == requests.size()) { + this.consume(mappings); return mappings; } @@ -124,7 +168,8 @@ public class UUIDPipeline { * @param requests Names * @return Mappings */ - public CompletableFuture> getUUIDs(@NotNull final Collection requests) { + public CompletableFuture> getUUIDs( + @NotNull final Collection requests) { final List serviceList = this.getServiceListInstance(); return CompletableFuture.supplyAsync(() -> { final List mappings = new ArrayList<>(requests.size()); @@ -139,6 +184,7 @@ public class UUIDPipeline { } if (mappings.size() == requests.size()) { + this.consume(mappings); return mappings; } From 49f51f24f7b1c27b787c05a4707cdec98b570607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 18:02:26 +0200 Subject: [PATCH 006/121] Don't loop services when all mappings have been found --- .../java/com/plotsquared/core/uuid/UUIDPipeline.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 0df18ea94..e14df5de0 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -140,12 +140,18 @@ public class UUIDPipeline { */ public CompletableFuture> getNames( @NotNull final Collection requests) { + if (requests.isEmpty()) { + return CompletableFuture.completedFuture(Collections.emptyList()); + } final List serviceList = this.getServiceListInstance(); return CompletableFuture.supplyAsync(() -> { final List mappings = new ArrayList<>(requests.size()); final List remainingRequests = new ArrayList<>(requests); for (final UUIDService service : serviceList) { + if (remainingRequests.isEmpty()) { + break; + } final List completedRequests = service.getNames(remainingRequests); for (final UUIDMapping mapping : completedRequests) { remainingRequests.remove(mapping.getUuid()); @@ -170,12 +176,18 @@ public class UUIDPipeline { */ public CompletableFuture> getUUIDs( @NotNull final Collection requests) { + if (requests.isEmpty()) { + return CompletableFuture.completedFuture(Collections.emptyList()); + } final List serviceList = this.getServiceListInstance(); return CompletableFuture.supplyAsync(() -> { final List mappings = new ArrayList<>(requests.size()); final List remainingRequests = new ArrayList<>(requests); for (final UUIDService service : serviceList) { + if (remainingRequests.isEmpty()) { + break; + } final List completedRequests = service.getUUIDs(remainingRequests); for (final UUIDMapping mapping : completedRequests) { remainingRequests.remove(mapping.getUsername()); From 736004d88bcf37fa86b2989e6d43fe4ab1f4059d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 18:03:04 +0200 Subject: [PATCH 007/121] Don't fill in stacktrace for ServiceError --- .../src/main/java/com/plotsquared/core/uuid/ServiceError.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/src/main/java/com/plotsquared/core/uuid/ServiceError.java b/Core/src/main/java/com/plotsquared/core/uuid/ServiceError.java index b33bd1509..0e248a2c5 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/ServiceError.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/ServiceError.java @@ -40,4 +40,8 @@ public class ServiceError extends RuntimeException { super(message, cause); } + @Override public Throwable fillInStackTrace() { + return this; + } + } From 58989c93111ea54107fcd0967889fbc354709b59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 23:20:36 +0200 Subject: [PATCH 008/121] Add some missing methods to the pipeline --- .../plotsquared/core/uuid/UUIDPipeline.java | 73 ++++++++++++++++++- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index e14df5de0..a59c1d264 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -29,6 +29,7 @@ import com.google.common.collect.Lists; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.util.task.TaskManager; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -36,7 +37,10 @@ import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.function.Consumer; /** @@ -132,14 +136,77 @@ public class UUIDPipeline { this.consume(new UUIDMapping(uuid, username)); } + /** + * Get a single UUID from a username. This is blocking. + * + * @param username Username + * @param timeout Timeout in milliseconds + * @return The mapped uuid. Will return null if the request timed out. + */ + @Nullable public UUID getSingle(@NotNull final String username, final long timeout) { + try { + this.getUUIDs(Collections.singletonList(username)).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } catch (TimeoutException ignored) { + // This is completely valid, we just don't care anymore + } + return null; + } + + /** + * Get a single username from a UUID. This is blocking. + * + * @param uuid UUID + * @param timeout Timeout in milliseconds + * @return The mapped username. Will return null if the request timeout. + */ + @Nullable public String getSingle(@NotNull final UUID uuid, final long timeout) { + try { + this.getNames(Collections.singletonList(uuid)).get(timeout, TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } catch (TimeoutException ignored) { + // This is completely valid, we just don't care anymore + } + return null; + } + + /** + * Get a single UUID from a username. This is non-blocking. + * + * @param username Username + * @param uuid UUID consumer + */ + public void getSingle(@NotNull final String username, @NotNull final Consumer uuid) { + this.getUUIDs(Collections.singletonList(username)).thenAccept(uuids -> { + if (!uuids.isEmpty()) { + uuid.accept(uuids.get(0).getUuid()); + } + }); + } + + /** + * Get a single username from a UUID. This is non-blocking. + * + * @param uuid UUID + * @param username Username consumer + */ + public void getSingle(@NotNull final UUID uuid, @NotNull final Consumer username) { + this.getNames(Collections.singletonList(uuid)).thenAccept(uuids -> { + if (!uuids.isEmpty()) { + username.accept(uuids.get(0).getUsername()); + } + }); + } + /** * Asynchronously attempt to fetch the mapping from a list of UUIDs * * @param requests UUIDs * @return Mappings */ - public CompletableFuture> getNames( - @NotNull final Collection requests) { + public CompletableFuture> getNames(@NotNull final Collection requests) { if (requests.isEmpty()) { return CompletableFuture.completedFuture(Collections.emptyList()); } @@ -174,7 +241,7 @@ public class UUIDPipeline { * @param requests Names * @return Mappings */ - public CompletableFuture> getUUIDs( + public CompletableFuture> getUUIDs( @NotNull final Collection requests) { if (requests.isEmpty()) { return CompletableFuture.completedFuture(Collections.emptyList()); From b5f92f500387bc01e1320999c41ca5eb4e2c9a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 23:26:19 +0200 Subject: [PATCH 009/121] Add sync catcher to the blocking pipeline methods --- .../plotsquared/core/util/ThreadUtils.java | 57 +++++++++++++++++++ .../plotsquared/core/uuid/UUIDPipeline.java | 3 + 2 files changed, 60 insertions(+) create mode 100644 Core/src/main/java/com/plotsquared/core/util/ThreadUtils.java diff --git a/Core/src/main/java/com/plotsquared/core/util/ThreadUtils.java b/Core/src/main/java/com/plotsquared/core/util/ThreadUtils.java new file mode 100644 index 000000000..c7c011e3d --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/ThreadUtils.java @@ -0,0 +1,57 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util; + +import com.plotsquared.core.PlotSquared; +import lombok.experimental.UtilityClass; + +@UtilityClass public class ThreadUtils { + + /** + * Throws {@link IllegalStateException} if the method + * is called from the server main thread + * + * @param message Message describing the issue + */ + public void catchSync(final String message) { + if (PlotSquared.get().isMainThread(Thread.currentThread())) { + throw new IllegalStateException(message); + } + } + + /** + * Throws {@link IllegalStateException} if the method + * is not called from the server main thread + * + * @param message Message describing the issue + */ + public void catchAsync(final String message) { + if (!PlotSquared.get().isMainThread(Thread.currentThread())) { + throw new IllegalStateException(message); + } + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index a59c1d264..7add9ef8a 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -27,6 +27,7 @@ package com.plotsquared.core.uuid; import com.google.common.collect.Lists; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.util.ThreadUtils; import com.plotsquared.core.util.task.TaskManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -144,6 +145,7 @@ public class UUIDPipeline { * @return The mapped uuid. Will return null if the request timed out. */ @Nullable public UUID getSingle(@NotNull final String username, final long timeout) { + ThreadUtils.catchSync("Blocking UUID retrieval from the main thread"); try { this.getUUIDs(Collections.singletonList(username)).get(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException | ExecutionException e) { @@ -162,6 +164,7 @@ public class UUIDPipeline { * @return The mapped username. Will return null if the request timeout. */ @Nullable public String getSingle(@NotNull final UUID uuid, final long timeout) { + ThreadUtils.catchSync("Blocking username retrieval from the main thread"); try { this.getNames(Collections.singletonList(uuid)).get(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException | ExecutionException e) { From 67bf90e92f76bb6ff57f677b4bba8153f1b05ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 23:41:59 +0200 Subject: [PATCH 010/121] Create the SQLite UUID service and cache --- .../bukkit/uuid/SQLiteUUIDService.java | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java new file mode 100644 index 000000000..e71ddd280 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java @@ -0,0 +1,124 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.bukkit.uuid; + +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.database.SQLite; +import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.uuid.UUIDMapping; +import com.plotsquared.core.uuid.UUIDService; +import org.jetbrains.annotations.NotNull; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +/** + * UUID service that uses the (legacy) SQL UUID cache + */ +public class SQLiteUUIDService implements UUIDService, Consumer> { + + private final SQLite sqlite; + + public SQLiteUUIDService() { + this.sqlite = + new SQLite(MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), "usercache.db")); + try { + this.sqlite.openConnection(); + } catch (ClassNotFoundException | SQLException e) { + e.printStackTrace(); + } + + try (PreparedStatement stmt = getConnection().prepareStatement( + "CREATE TABLE IF NOT EXISTS `usercache` (uuid VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL, PRIMARY KEY (uuid, username))")) { + stmt.execute(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private Connection getConnection() { + synchronized (this.sqlite) { + return this.sqlite.getConnection(); + } + } + + @Override public @NotNull List getNames(@NotNull final List uuids) { + final List mappings = new ArrayList<>(uuids.size()); + try (final PreparedStatement statement = getConnection() + .prepareStatement("SELECT `username` FROM `usercache` WHERE `uuid` = ?")) { + for (final UUID uuid : uuids) { + statement.setString(1, uuid.toString()); + try (final ResultSet resultSet = statement.executeQuery()) { + if (resultSet.next()) { + mappings.add(new UUIDMapping(uuid, resultSet.getString("username"))); + } + } + } + } catch (final Exception e) { + e.printStackTrace(); + } + return mappings; + } + + @Override public @NotNull List getUUIDs(@NotNull List usernames) { + final List mappings = new ArrayList<>(usernames.size()); + try (final PreparedStatement statement = getConnection() + .prepareStatement("SELECT `uuid` FROM `usercache` WHERE `username` = ?")) { + for (final String username : usernames) { + statement.setString(1, username); + try (final ResultSet resultSet = statement.executeQuery()) { + if (resultSet.next()) { + mappings.add(new UUIDMapping(UUID.fromString(resultSet.getString("uuid")), + username)); + } + } + } + } catch (final Exception e) { + e.printStackTrace(); + } + return mappings; + } + + @Override public void accept(final List uuidWrappers) { + try (final PreparedStatement statement = getConnection() + .prepareStatement("INSERT OR REPLACE INTO `usercache` (`uuid`, `username`) VALUES(?, ?)")) { + for (final UUIDMapping mapping : uuidWrappers) { + statement.setString(1, mapping.getUuid().toString()); + statement.setString(2, mapping.getUsername()); + statement.executeUpdate(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + +} From 12f2cb0d5869c99f427026d2c43cd4b81d6d6bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 23:57:40 +0200 Subject: [PATCH 011/121] Add a cache uuid service --- .../core/uuid/CacheUUIDService.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java diff --git a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java new file mode 100644 index 000000000..81a42bacd --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java @@ -0,0 +1,76 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.cache.Cache; +import com.google.common.cache.CacheBuilder; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +/** + * UUID service backed by a Guava Cache + */ +public class CacheUUIDService implements UUIDService, Consumer> { + + private final Cache usernameCache; + private final Cache uuidCache; + + /** + * Construct a new Cache UUID service with a maximum number of entries. + * Because it stores the mappings in two ways, the actual number + * of entries is two times the specified size + * + * @param size Maximum number of entries + */ + public CacheUUIDService(final int size) { + this.usernameCache = CacheBuilder.newBuilder().maximumSize(size).build(); + this.uuidCache = CacheBuilder.newBuilder().maximumSize(size).build(); + } + + @Override @NotNull public List getNames(@NotNull final List uuids) { + final List mappings = new ArrayList<>(uuids.size()); + mappings.addAll(this.uuidCache.getAllPresent(uuids).values()); + return mappings; + } + + @Override @NotNull public List getUUIDs(@NotNull final List usernames) { + final List mappings = new ArrayList<>(usernames.size()); + mappings.addAll(this.usernameCache.getAllPresent(usernames).values()); + return mappings; + } + + @Override public void accept(final List uuidMappings) { + for (final UUIDMapping mapping : uuidMappings) { + this.uuidCache.put(mapping.getUuid(), mapping); + this.usernameCache.put(mapping.getUsername(), mapping); + } + } + +} From a47527857c24a9366f40722cc5d59e36dab05dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 17 May 2020 23:58:39 +0200 Subject: [PATCH 012/121] Fix wonky annotation placement in SQLiteUUIDService --- .../java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java index e71ddd280..6ad2f01ce 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java @@ -71,7 +71,7 @@ public class SQLiteUUIDService implements UUIDService, Consumer getNames(@NotNull final List uuids) { + @Override @NotNull public List getNames(@NotNull final List uuids) { final List mappings = new ArrayList<>(uuids.size()); try (final PreparedStatement statement = getConnection() .prepareStatement("SELECT `username` FROM `usercache` WHERE `uuid` = ?")) { @@ -89,7 +89,7 @@ public class SQLiteUUIDService implements UUIDService, Consumer getUUIDs(@NotNull List usernames) { + @Override @NotNull public List getUUIDs(@NotNull List usernames) { final List mappings = new ArrayList<>(usernames.size()); try (final PreparedStatement statement = getConnection() .prepareStatement("SELECT `uuid` FROM `usercache` WHERE `username` = ?")) { From 31c84ab18f96e0ba2f3b2261a7cd227ecff002cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Mon, 18 May 2020 00:22:34 +0200 Subject: [PATCH 013/121] Basic pipeline setup --- .../com/plotsquared/bukkit/BukkitMain.java | 44 +++++++++++++++++++ .../com/plotsquared/core/PlotSquared.java | 7 +++ .../core/configuration/Settings.java | 6 +++ 3 files changed, 57 insertions(+) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 779aec999..a03ac3218 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -55,6 +55,10 @@ import com.plotsquared.bukkit.util.uuid.FileUUIDHandler; import com.plotsquared.bukkit.util.uuid.LowerOfflineUUIDWrapper; import com.plotsquared.bukkit.util.uuid.OfflineUUIDWrapper; import com.plotsquared.bukkit.util.uuid.SQLUUIDHandler; +import com.plotsquared.bukkit.uuid.OfflinePlayerUUIDService; +import com.plotsquared.bukkit.uuid.PaperUUIDService; +import com.plotsquared.bukkit.uuid.SQLiteUUIDService; +import com.plotsquared.bukkit.uuid.SquirrelIdUUIDService; import com.plotsquared.core.IPlotMain; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.backup.BackupManager; @@ -101,6 +105,9 @@ import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.uuid.UUIDHandler; import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; import com.plotsquared.core.util.uuid.UUIDWrapper; +import com.plotsquared.core.uuid.CacheUUIDService; +import com.plotsquared.core.uuid.UUIDPipeline; +import com.plotsquared.core.uuid.offline.OfflineModeUUIDService; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.extension.platform.Actor; @@ -221,6 +228,43 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain PlotSquared.log(Captions.PREFIX + "&6Couldn't verify purchase :("); } + // TODO: Do we respect the UUID settings? + final UUIDPipeline impromptuPipeline = PlotSquared.get().getImpromptuUUIDPipeline(); + final UUIDPipeline backgroundPipeline = PlotSquared.get().getBackgroundUUIDPipeline(); + // Services are accessed in order + final CacheUUIDService cacheUUIDService = new CacheUUIDService(Settings.UUID.UUID_CACHE_SIZE); + impromptuPipeline.registerService(cacheUUIDService); + backgroundPipeline.registerService(cacheUUIDService); + impromptuPipeline.registerConsumer(cacheUUIDService); + backgroundPipeline.registerConsumer(cacheUUIDService); + // Now, if the server is in offline mode we can only use profiles and direct UUID + // access, and so we skip the player profile stuff as well as SquirrelID (Mojang lookups) + if (Settings.UUID.OFFLINE) { + final OfflineModeUUIDService offlineModeUUIDService = new OfflineModeUUIDService(); + impromptuPipeline.registerService(offlineModeUUIDService); + backgroundPipeline.registerService(offlineModeUUIDService); + } + final OfflinePlayerUUIDService offlinePlayerUUIDService = new OfflinePlayerUUIDService(); + impromptuPipeline.registerService(offlinePlayerUUIDService); + backgroundPipeline.registerService(offlinePlayerUUIDService); + if (!Settings.UUID.OFFLINE) { + // If running Paper we'll also try to use their profiles + if (PaperLib.isPaper()) { + final PaperUUIDService paperUUIDService = new PaperUUIDService(); + impromptuPipeline.registerService(paperUUIDService); + backgroundPipeline.registerService(paperUUIDService); + } + final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService(); + impromptuPipeline.registerService(sqLiteUUIDService); + backgroundPipeline.registerService(sqLiteUUIDService); + impromptuPipeline.registerConsumer(sqLiteUUIDService); + backgroundPipeline.registerConsumer(sqLiteUUIDService); + final SquirrelIdUUIDService impromptuMojangService = new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT); + impromptuPipeline.registerService(impromptuMojangService); + final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT); + backgroundPipeline.registerService(backgroundMojangService); + } + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { new Placeholders().register(); if (Settings.Enabled_Components.EXTERNAL_PLACEHOLDERS) { diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 452493181..bbb8b66bc 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -84,6 +84,7 @@ import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.logger.ILogger; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.uuid.UUIDHandler; +import com.plotsquared.core.uuid.UUIDPipeline; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; @@ -123,6 +124,7 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.UUID; +import java.util.concurrent.Executors; import java.util.function.Consumer; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -140,6 +142,11 @@ public class PlotSquared { public final IPlotMain IMP; // Current thread private final Thread thread; + // UUID pipelines + @Getter private final UUIDPipeline impromptuUUIDPipeline = + new UUIDPipeline(Executors.newCachedThreadPool()); + @Getter private final UUIDPipeline backgroundUUIDPipeline = + new UUIDPipeline(Executors.newSingleThreadExecutor()); // WorldEdit instance public WorldEdit worldedit; public File styleFile; diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 044642baa..fff645253 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -239,6 +239,12 @@ public class Settings extends Config { @Comment("Use a database to store UUID/name info") public static boolean USE_SQLUUIDHANDLER = false; @Ignore public static boolean NATIVE_UUID_PROVIDER = false; + @Comment("How many UUIDs that may be stored in the cache") + public static int UUID_CACHE_SIZE = 100000; + @Comment("Rate limit (per 10 minutes) for background UUID fetching from the Mojang API") + public static int BACKGROUND_LIMIT = 200; + @Comment("Rate limit (per 10 minutes) for random UUID fetching from the Mojang API") + public static int IMPROMPTU_LIMIT = 300; } From fdfc61cf97870e4e588de3450f83d270bbdc0f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Mon, 18 May 2020 20:45:51 +0200 Subject: [PATCH 014/121] Update username on async pre login event --- .../java/com/plotsquared/bukkit/listener/PlayerEvents.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 069bae68b..11215fcc8 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -178,6 +178,7 @@ import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent; import org.bukkit.event.player.PlayerBucketFillEvent; import org.bukkit.event.player.PlayerChangedWorldEvent; @@ -629,6 +630,11 @@ public class PlayerEvents extends PlotListener implements Listener { } } + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onPreLoin(final AsyncPlayerPreLoginEvent event) { + PlotSquared.get().getImpromptuUUIDPipeline().storeImmediately(event.getName(), event.getUniqueId()); + } + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onConnect(PlayerJoinEvent event) { final Player player = event.getPlayer(); From 37b065a097b05fe68502d5bfb113ad06390ecefe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 19 May 2020 00:28:52 +0200 Subject: [PATCH 015/121] Progress. --- .../com/plotsquared/bukkit/BukkitCommand.java | 5 - .../com/plotsquared/bukkit/BukkitMain.java | 51 +-- .../plotsquared/bukkit/command/DebugUUID.java | 323 ----------------- .../bukkit/listener/PaperListener.java | 48 +++ .../bukkit/listener/PlayerEvents.java | 28 +- .../bukkit/placeholder/Placeholders.java | 7 +- .../bukkit/player/BukkitPlayer.java | 6 +- .../bukkit/player/BukkitPlayerManager.java | 28 +- .../plotsquared/bukkit/util/BukkitUtil.java | 11 +- .../plotsquared/bukkit/util/SendChunk.java | 167 --------- .../bukkit/util/uuid/DatFileFilter.java | 36 -- .../bukkit/util/uuid/FileUUIDHandler.java | 289 ---------------- .../util/uuid/LowerOfflineUUIDWrapper.java | 60 ---- .../bukkit/util/uuid/OfflineUUIDWrapper.java | 131 ------- .../bukkit/util/uuid/SQLUUIDHandler.java | 270 --------------- .../java/com/plotsquared/core/IPlotMain.java | 17 +- .../com/plotsquared/core/PlotSquared.java | 34 +- .../com/plotsquared/core/api/PlotAPI.java | 13 - .../com/plotsquared/core/command/Add.java | 104 +++--- .../com/plotsquared/core/command/Alias.java | 49 ++- .../com/plotsquared/core/command/Cluster.java | 177 +++++----- .../com/plotsquared/core/command/Command.java | 6 + .../com/plotsquared/core/command/Comment.java | 8 +- .../core/command/DebugClaimTest.java | 134 -------- .../core/command/DebugImportWorlds.java | 5 +- .../com/plotsquared/core/command/Deny.java | 74 ++-- .../com/plotsquared/core/command/Merge.java | 2 +- .../com/plotsquared/core/command/Visit.java | 204 ++++++----- .../core/configuration/Captions.java | 1 + .../core/listener/PlotListener.java | 5 +- .../plotsquared/core/player/PlotPlayer.java | 17 +- .../java/com/plotsquared/core/plot/Plot.java | 104 +----- .../com/plotsquared/core/util/MainUtil.java | 72 ++-- .../plotsquared/core/util/PlayerManager.java | 120 +++++++ .../core/util/SchematicHandler.java | 2 +- .../plotsquared/core/util/TabCompletions.java | 82 +++++ .../core/util/uuid/UUIDHandler.java | 198 ----------- .../util/uuid/UUIDHandlerImplementation.java | 324 ------------------ .../core/uuid/CacheUUIDService.java | 5 + .../plotsquared/core/uuid/UUIDMapping.java | 3 +- .../plotsquared/core/uuid/UUIDPipeline.java | 45 ++- .../plotsquared/core/uuid/UUIDService.java | 12 + .../util/UUIDHandlerImplementationTest.java | 5 +- 43 files changed, 759 insertions(+), 2523 deletions(-) delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/command/DebugUUID.java rename Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java => Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java (71%) delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DatFileFilter.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/FileUUIDHandler.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/LowerOfflineUUIDWrapper.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/SQLUUIDHandler.java delete mode 100644 Core/src/main/java/com/plotsquared/core/command/DebugClaimTest.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/PlayerManager.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/TabCompletions.java delete mode 100644 Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandler.java delete mode 100644 Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandlerImplementation.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java index 2d3737ee0..20ab45529 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java @@ -25,7 +25,6 @@ */ package com.plotsquared.bukkit; -import com.plotsquared.bukkit.command.DebugUUID; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.core.command.MainCommand; import com.plotsquared.core.player.ConsolePlayer; @@ -46,10 +45,6 @@ import java.util.List; public class BukkitCommand implements CommandExecutor, TabCompleter { - public BukkitCommand() { - new DebugUUID(); - } - @Override public boolean onCommand(CommandSender commandSender, Command command, String commandLabel, String[] args) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index a03ac3218..90a717fd5 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -38,6 +38,7 @@ import com.plotsquared.bukkit.managers.HyperverseWorldManager; import com.plotsquared.bukkit.managers.MultiverseWorldManager; import com.plotsquared.bukkit.placeholder.PlaceholderFormatter; import com.plotsquared.bukkit.placeholder.Placeholders; +import com.plotsquared.bukkit.player.BukkitPlayerManager; import com.plotsquared.bukkit.queue.BukkitLocalQueue; import com.plotsquared.bukkit.schematic.BukkitSchematicHandler; import com.plotsquared.bukkit.util.BukkitChatManager; @@ -50,11 +51,6 @@ import com.plotsquared.bukkit.util.BukkitTaskManager; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.SetGenCB; import com.plotsquared.bukkit.util.UpdateUtility; -import com.plotsquared.bukkit.util.uuid.DefaultUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.FileUUIDHandler; -import com.plotsquared.bukkit.util.uuid.LowerOfflineUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.OfflineUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.SQLUUIDHandler; import com.plotsquared.bukkit.uuid.OfflinePlayerUUIDService; import com.plotsquared.bukkit.uuid.PaperUUIDService; import com.plotsquared.bukkit.uuid.SQLiteUUIDService; @@ -69,6 +65,7 @@ import com.plotsquared.core.configuration.ChatFormatter; import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.generator.HybridGen; import com.plotsquared.core.generator.HybridUtils; @@ -94,6 +91,7 @@ import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.InventoryUtil; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.PlatformWorldManager; +import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.PremiumVerification; import com.plotsquared.core.util.ReflectionUtils; import com.plotsquared.core.util.RegionManager; @@ -102,9 +100,6 @@ import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; -import com.plotsquared.core.util.uuid.UUIDWrapper; import com.plotsquared.core.uuid.CacheUUIDService; import com.plotsquared.core.uuid.UUIDPipeline; import com.plotsquared.core.uuid.offline.OfflineModeUUIDService; @@ -171,6 +166,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain private boolean metricsStarted; @Getter private BackupManager backupManager; @Getter private PlatformWorldManager worldManager; + @Getter private final PlayerManager playerManager = new BukkitPlayerManager(); @Override public int[] getServerVersion() { if (this.version == null) { @@ -265,6 +261,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain backgroundPipeline.registerService(backgroundMojangService); } + impromptuPipeline.storeImmediately("*", DBFunc.EVERYONE); + if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { new Placeholders().register(); if (Settings.Enabled_Components.EXTERNAL_PLACEHOLDERS) { @@ -842,39 +840,6 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain return new BukkitInventoryUtil(); } - @Override public UUIDHandlerImplementation initUUIDHandler() { - final UUIDWrapper wrapper; - if (Settings.UUID.OFFLINE) { - if (Settings.UUID.FORCE_LOWERCASE) { - wrapper = new LowerOfflineUUIDWrapper(); - } else { - wrapper = new OfflineUUIDWrapper(); - } - Settings.UUID.OFFLINE = true; - } else { - wrapper = new DefaultUUIDWrapper(); - Settings.UUID.OFFLINE = false; - } - if (!Bukkit.getVersion().contains("git-Spigot")) { - if (wrapper instanceof DefaultUUIDWrapper - || wrapper.getClass() == OfflineUUIDWrapper.class && !Bukkit.getOnlineMode()) { - Settings.UUID.NATIVE_UUID_PROVIDER = true; - } - } - if (Settings.UUID.OFFLINE) { - PlotSquared.log(Captions.PREFIX + "&6" + getPluginName() - + " is using Offline Mode UUIDs either because of user preference, or because you are using an old version of " - + "Bukkit"); - } else { - PlotSquared.log(Captions.PREFIX + "&6" + getPluginName() + " is using online UUIDs"); - } - if (Settings.UUID.USE_SQLUUIDHANDLER) { - return new SQLUUIDHandler(wrapper); - } else { - return new FileUUIDHandler(wrapper); - } - } - @Override public void setGenerator(@NonNull final String worldName) { World world = BukkitUtil.getWorld(worldName); if (world == null) { @@ -925,10 +890,10 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain return BukkitUtil.getPlayer((OfflinePlayer) player); } if (player instanceof String) { - return UUIDHandler.getPlayer((String) player); + return PlotSquared.imp().getPlayerManager().getPlayerIfExists((String) player); } if (player instanceof UUID) { - return UUIDHandler.getPlayer((UUID) player); + return PlotSquared.imp().getPlayerManager().getPlayerIfExists((UUID) player); } return null; } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/command/DebugUUID.java b/Bukkit/src/main/java/com/plotsquared/bukkit/command/DebugUUID.java deleted file mode 100644 index 79b411791..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/command/DebugUUID.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.bukkit.command; - -import com.google.common.collect.Sets; -import com.plotsquared.bukkit.util.uuid.DatFileFilter; -import com.plotsquared.bukkit.util.uuid.DefaultUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.LowerOfflineUUIDWrapper; -import com.plotsquared.bukkit.util.uuid.OfflineUUIDWrapper; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.command.Argument; -import com.plotsquared.core.command.CommandCategory; -import com.plotsquared.core.command.CommandDeclaration; -import com.plotsquared.core.command.RequiredType; -import com.plotsquared.core.command.SubCommand; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.database.DBFunc; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.util.MainUtil; -import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDWrapper; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map.Entry; -import java.util.UUID; - -@CommandDeclaration(command = "uuidconvert", - permission = "plots.admin", - description = "Debug UUID conversion", - usage = "/plot uuidconvert ", - requiredType = RequiredType.CONSOLE, - category = CommandCategory.DEBUG) -public class DebugUUID extends SubCommand { - - public DebugUUID() { - super(Argument.String); - } - - @Override public boolean onCommand(final PlotPlayer player, String[] args) { - final UUIDWrapper currentUUIDWrapper = UUIDHandler.getUUIDWrapper(); - final UUIDWrapper newWrapper; - - switch (args[0].toLowerCase()) { - case "lower": - newWrapper = new LowerOfflineUUIDWrapper(); - break; - case "offline": - newWrapper = new OfflineUUIDWrapper(); - break; - case "online": - newWrapper = new DefaultUUIDWrapper(); - break; - default: - try { - Class clazz = Class.forName(args[0]); - newWrapper = (UUIDWrapper) clazz.newInstance(); - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException ignored) { - MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, - "/plot uuidconvert "); - return false; - } - } - - if (args.length != 2 || !"-o".equals(args[1])) { - MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, - "/plot uuidconvert " + args[0] + " -o"); - MainUtil.sendMessage(player, "&cBe aware of the following!"); - MainUtil.sendMessage(player, - "&8 - &cUse the database command or another method to backup your plots beforehand"); - MainUtil.sendMessage(player, - "&8 - &cIf the process is interrupted, all plots could be deleted"); - MainUtil.sendMessage(player, "&8 - &cIf an error occurs, all plots could be deleted"); - MainUtil.sendMessage(player, "&8 - &cPlot settings WILL be lost upon conversion"); - MainUtil - .sendMessage(player, "&cTO REITERATE: BACK UP YOUR DATABASE BEFORE USING THIS!!!"); - MainUtil.sendMessage(player, - "&7Retype the command with the override parameter when ready :)"); - return false; - } - - if (currentUUIDWrapper.getClass().getCanonicalName() - .equals(newWrapper.getClass().getCanonicalName())) { - MainUtil.sendMessage(player, "&cUUID mode already in use!"); - return false; - } - MainUtil.sendMessage(player, "&6Beginning UUID mode conversion"); - MainUtil.sendMessage(player, "&7 - Disconnecting players"); - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - entry.getValue() - .kick("UUID conversion has been initiated. You may reconnect when finished."); - } - - MainUtil.sendMessage(player, "&7 - Initializing map"); - - final HashMap uCMap = new HashMap<>(); - final HashMap uCReverse = new HashMap<>(); - - MainUtil.sendMessage(player, "&7 - Collecting playerdata"); - - HashSet worlds = Sets.newHashSet(WorldUtil.IMP.getMainWorld(), "world"); - HashSet uuids = new HashSet<>(); - HashSet names = new HashSet<>(); - for (String worldName : worlds) { - File playerDataFolder = new File(worldName + File.separator + "playerdata"); - String[] dat = playerDataFolder.list(new DatFileFilter()); - if (dat != null) { - for (String current : dat) { - String s = current.replaceAll(".dat$", ""); - try { - UUID uuid = UUID.fromString(s); - uuids.add(uuid); - } catch (Exception ignored) { - MainUtil.sendMessage(player, - Captions.PREFIX + "Invalid playerdata: " + current); - } - } - } - File playersFolder = new File(worldName + File.separator + "players"); - dat = playersFolder.list(new DatFileFilter()); - if (dat != null) { - for (String current : dat) { - names.add(current.replaceAll(".dat$", "")); - } - } - } - - MainUtil.sendMessage(player, "&7 - Populating map"); - UUID uuid2; - UUIDWrapper wrapper = new DefaultUUIDWrapper(); - for (UUID uuid : uuids) { - try { - OfflinePlotPlayer op = wrapper.getOfflinePlayer(uuid); - uuid = currentUUIDWrapper.getUUID(op); - uuid2 = newWrapper.getUUID(op); - if (!uuid.equals(uuid2) && !uCMap.containsKey(uuid) && !uCReverse - .containsKey(uuid2)) { - uCMap.put(uuid, uuid2); - uCReverse.put(uuid2, uuid); - } - } catch (Throwable ignored) { - MainUtil.sendMessage(player, - Captions.PREFIX + "&6Invalid playerdata: " + uuid.toString() + ".dat"); - } - } - for (String name : names) { - UUID uuid = currentUUIDWrapper.getUUID(name); - uuid2 = newWrapper.getUUID(name); - if (!uuid.equals(uuid2)) { - uCMap.put(uuid, uuid2); - uCReverse.put(uuid2, uuid); - } - } - if (uCMap.isEmpty()) { - MainUtil.sendMessage(player, "&c - Error! Attempting to repopulate"); - for (OfflinePlotPlayer op : currentUUIDWrapper.getOfflinePlayers()) { - if (op.getLastPlayed() != 0) { - // String name = op.getPluginName(); - // StringWrapper wrap = new StringWrapper(name); - UUID uuid = currentUUIDWrapper.getUUID(op); - uuid2 = newWrapper.getUUID(op); - if (!uuid.equals(uuid2)) { - uCMap.put(uuid, uuid2); - uCReverse.put(uuid2, uuid); - } - } - } - if (uCMap.isEmpty()) { - MainUtil.sendMessage(player, "&cError. Failed to collect UUIDs!"); - return false; - } else { - MainUtil.sendMessage(player, "&a - Successfully repopulated"); - } - } - - MainUtil.sendMessage(player, "&7 - Replacing cache"); - TaskManager.runTaskAsync(() -> { - for (Entry entry : uCMap.entrySet()) { - String name = UUIDHandler.getName(entry.getKey()); - if (name != null) { - UUIDHandler.add(new StringWrapper(name), entry.getValue()); - } - } - - MainUtil.sendMessage(player, "&7 - Scanning for applicable files (uuids.txt)"); - - File file = new File(PlotSquared.get().IMP.getDirectory(), "uuids.txt"); - if (file.exists()) { - try { - List lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8); - for (String line : lines) { - try { - line = line.trim(); - if (line.isEmpty()) { - continue; - } - line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", ""); - String[] split = line.split("\\|"); - String name = split[0]; - if (name.isEmpty() || name.length() > 16 || !StringMan - .isAlphanumericUnd(name)) { - continue; - } - UUID old = currentUUIDWrapper.getUUID(name); - if (old == null) { - continue; - } - UUID now = newWrapper.getUUID(name); - UUIDHandler.add(new StringWrapper(name), now); - uCMap.put(old, now); - uCReverse.put(now, old); - } catch (Exception e2) { - e2.printStackTrace(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - MainUtil.sendMessage(player, "&7 - Replacing wrapper"); - UUIDHandler.setUUIDWrapper(newWrapper); - - MainUtil.sendMessage(player, "&7 - Updating plot objects"); - - for (Plot plot : PlotSquared.get().getPlots()) { - UUID value = uCMap.get(plot.getOwnerAbs()); - if (value != null) { - plot.setOwnerAbs(value); - } - plot.getTrusted().clear(); - plot.getMembers().clear(); - plot.getDenied().clear(); - } - - MainUtil.sendMessage(player, "&7 - Deleting database"); - boolean result = DBFunc.deleteTables(); - - MainUtil.sendMessage(player, "&7 - Creating tables"); - - try { - DBFunc.createTables(); - if (!result) { - MainUtil.sendMessage(player, "&cConversion failed! Attempting recovery"); - for (Plot plot : PlotSquared.get().getPlots()) { - UUID value = uCReverse.get(plot.getOwnerAbs()); - if (value != null) { - plot.setOwnerAbs(value); - } - } - DBFunc.createPlotsAndData(new ArrayList<>(PlotSquared.get().getPlots()), - () -> MainUtil.sendMessage(player, "&6Recovery was successful!")); - return; - } - } catch (Exception e) { - e.printStackTrace(); - return; - } - - if (newWrapper instanceof OfflineUUIDWrapper) { - PlotSquared.get().worlds.set("UUID.force-lowercase", false); - PlotSquared.get().worlds.set("UUID.offline", true); - } else if (newWrapper instanceof DefaultUUIDWrapper) { - PlotSquared.get().worlds.set("UUID.force-lowercase", false); - PlotSquared.get().worlds.set("UUID.offline", false); - } - try { - PlotSquared.get().worlds.save(PlotSquared.get().worldsFile); - } catch (IOException ignored) { - MainUtil.sendMessage(player, - "Could not save configuration. It will need to be manual set!"); - } - - MainUtil.sendMessage(player, "&7 - Populating tables"); - - TaskManager.runTaskAsync(() -> { - ArrayList plots = new ArrayList<>(PlotSquared.get().getPlots()); - DBFunc.createPlotsAndData(plots, - () -> MainUtil.sendMessage(player, "&aConversion complete!")); - }); - - MainUtil.sendMessage(player, "&aIt is now safe for players to join"); - MainUtil.sendMessage(player, - "&cConversion is still in progress, you will be notified when it is complete"); - }); - return true; - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java index 6c7e4c9eb..2ff395c52 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java @@ -31,8 +31,11 @@ import com.destroystokyo.paper.event.entity.PreCreatureSpawnEvent; import com.destroystokyo.paper.event.entity.PreSpawnerSpawnEvent; import com.destroystokyo.paper.event.entity.SlimePathfindEvent; import com.destroystokyo.paper.event.player.PlayerLaunchProjectileEvent; +import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.command.Command; +import com.plotsquared.core.command.MainCommand; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.location.Location; @@ -56,6 +59,13 @@ import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.projectiles.ProjectileSource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.regex.Pattern; + /** * Events specific to Paper. Some toit nups here */ @@ -306,4 +316,42 @@ public class PaperListener implements Listener { event.setCancelled(true); } } + + @EventHandler public void onAsyncTabCompletion(final AsyncTabCompleteEvent event) { + PlotSquared.debug("ASYNC COMPLETION"); + String buffer = event.getBuffer(); + if (!(event.getSender() instanceof Player)) { + return; + } + if ((!event.isCommand() && !buffer.startsWith("/")) || buffer.indexOf(' ') == -1) { + return; + } + if (buffer.startsWith("/")) { + buffer = buffer.substring(1); + } + final String[] unprocessedArgs = buffer.split(Pattern.quote(" ")); + if (unprocessedArgs.length == 1) { + return; // We don't do anything in this case + } else if (!Arrays.asList("plots", "p", "plotsquared", "plot2", "p2", "ps", "2", "plotme", "plotz", "ap") + .contains(unprocessedArgs[0].toLowerCase(Locale.ENGLISH))) { + return; + } + final String[] args = new String[unprocessedArgs.length - 1]; + System.arraycopy(unprocessedArgs, 1, args, 0, args.length); + try { + final PlotPlayer player = BukkitUtil.getPlayer((Player) event.getSender()); + final Collection objects = MainCommand.getInstance().tab(player, args, buffer.endsWith(" ")); + if (objects == null) { + return; + } + final List result = new ArrayList<>(); + for (final com.plotsquared.core.command.Command o : objects) { + result.add(o.toString()); + } + event.setCompletions(result); + event.setHandled(true); + PlotSquared.debug("ASYNC COMPLETION HANDLED"); + } catch (final Exception ignored) {} + } + } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 11215fcc8..ddcc15320 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -103,10 +103,8 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.PremiumVerification; import com.plotsquared.core.util.RegExUtil; -import com.plotsquared.core.util.StringWrapper; import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.world.block.BlockType; import io.papermc.lib.PaperLib; @@ -216,7 +214,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Map.Entry; import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -254,8 +251,8 @@ public class PlayerEvents extends PlotListener implements Listener { int x = bloc.getBlockX(); int z = bloc.getBlockZ(); int distance = Bukkit.getViewDistance() * 16; - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer player = entry.getValue(); + + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { Location location = player.getLocation(); if (location.getWorld().equals(world)) { if (16 * Math.abs(location.getX() - x) / 16 > distance @@ -356,18 +353,18 @@ public class PlayerEvents extends PlotListener implements Listener { if (plot.isMerged()) { disable = true; for (UUID owner : plot.getOwners()) { - if (UUIDHandler.getPlayer(owner) != null) { + if (PlotSquared.imp().getPlayerManager().getPlayerIfExists(owner) != null) { disable = false; break; } } } else { - disable = UUIDHandler.getPlayer(plot.guessOwner()) == null; + disable = PlotSquared.imp().getPlayerManager().getPlayerIfExists(plot.getOwnerAbs()) == null; } } if (disable) { for (UUID trusted : plot.getTrusted()) { - if (UUIDHandler.getPlayer(trusted) != null) { + if (PlotSquared.imp().getPlayerManager().getPlayerIfExists(trusted) != null) { disable = false; break; } @@ -379,8 +376,8 @@ public class PlayerEvents extends PlotListener implements Listener { } } if (Settings.Redstone.DISABLE_UNOCCUPIED) { - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - if (plot.equals(entry.getValue().getCurrentPlot())) { + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { + if (plot.equals(player.getCurrentPlot())) { return; } } @@ -638,14 +635,8 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onConnect(PlayerJoinEvent event) { final Player player = event.getPlayer(); - UUIDHandler.getPlayers().remove(player.getName()); BukkitUtil.removePlayer(player.getName()); final PlotPlayer pp = BukkitUtil.getPlayer(player); - // Now - String name = pp.getName(); - StringWrapper sw = new StringWrapper(name); - UUID uuid = pp.getUUID(); - UUIDHandler.add(sw, uuid); Location location = pp.getLocation(); PlotArea area = location.getPlotArea(); @@ -951,8 +942,7 @@ public class PlayerEvents extends PlotListener implements Listener { Set recipients = event.getRecipients(); recipients.clear(); Set spies = new HashSet<>(); - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); + for (final PlotPlayer pp : PlotSquared.imp().getPlayerManager().getPlayers()) { if (pp.getAttribute("chatspy")) { spies.add(((BukkitPlayer) pp).player); } else { @@ -2876,7 +2866,7 @@ public class PlayerEvents extends PlotListener implements Listener { } return true; } else if (dplot != null && (!dplot.equals(vplot) || Objects - .equals(dplot.guessOwner(), vplot.guessOwner()))) { + .equals(dplot.getOwnerAbs(), vplot.getOwnerAbs()))) { return vplot != null && vplot.getFlag(PveFlag.class); } //disable the firework damage. too much of a headache to support at the moment. diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java index bf2a7a8b9..f8a155d21 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java @@ -25,9 +25,9 @@ */ package com.plotsquared.bukkit.placeholder; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.util.uuid.UUIDHandler; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.Bukkit; @@ -62,7 +62,7 @@ public class Placeholders extends PlaceholderExpansion { } @Override public String onPlaceholderRequest(Player p, String identifier) { - final PlotPlayer pl = PlotPlayer.get(p.getName()); + final PlotPlayer pl = PlotSquared.imp().getPlayerManager().getPlayerIfExists(p.getUniqueId()); if (pl == null) { return ""; @@ -122,7 +122,8 @@ public class Placeholders extends PlaceholderExpansion { if (uid == null) { return ""; } - String name = UUIDHandler.getName(uid); + + String name = PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(uid, 5L); if (name != null) { return name; diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java index 854cc6ec0..d2e7930fa 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java @@ -35,7 +35,6 @@ import com.plotsquared.core.plot.PlotWeather; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.world.item.ItemType; @@ -97,10 +96,7 @@ public class BukkitPlayer extends PlotPlayer { } @NotNull @Override public UUID getUUID() { - if (this.uuid == null) { - this.uuid = UUIDHandler.getUUID(this); - } - return this.uuid; + return this.player.getUniqueId(); } @Override public long getLastPlayed() { diff --git a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java similarity index 71% rename from Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java rename to Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java index b2e8e0227..6e628a8a7 100644 --- a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDWrapper.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java @@ -23,25 +23,27 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package com.plotsquared.core.util.uuid; +package com.plotsquared.bukkit.player; -import com.plotsquared.core.player.OfflinePlotPlayer; import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.util.PlayerManager; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.util.UUID; -public interface UUIDWrapper { +/** + * Player manager providing {@link BukkitPlayer Bukkit players} + */ +public class BukkitPlayerManager extends PlayerManager { - @NotNull UUID getUUID(PlotPlayer player); + @Override @NotNull public PlotPlayer createPlayer(@NotNull final UUID uuid) { + final Player player = Bukkit.getPlayer(uuid); + if (player == null || !player.isOnline()) { + throw new NoSuchPlayerException(uuid); + } + return new BukkitPlayer(player); + } - UUID getUUID(OfflinePlotPlayer player); - - UUID getUUID(String name); - - OfflinePlotPlayer getOfflinePlayer(UUID uuid); - - OfflinePlotPlayer getOfflinePlayer(String name); - - OfflinePlotPlayer[] getOfflinePlayers(); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index 23fd8937b..8ba3caa9b 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -39,7 +39,6 @@ import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.math.BlockVector2; @@ -268,15 +267,7 @@ public class BukkitUtil extends WorldUtil { if (player == lastPlayer) { return lastPlotPlayer; } - final String name = player.getName(); - final PlotPlayer plotPlayer = UUIDHandler.getPlayer(name); - if (plotPlayer != null) { - return plotPlayer; - } - lastPlotPlayer = new BukkitPlayer(player); - UUIDHandler.getPlayers().put(name, lastPlotPlayer); - lastPlayer = player; - return lastPlotPlayer; + return PlotSquared.imp().getPlayerManager().getPlayer(player.getUniqueId()); } public static Location getLocation(@NonNull final org.bukkit.Location location) { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java deleted file mode 100644 index 7a920fc8b..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/SendChunk.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.bukkit.util; - -import com.plotsquared.bukkit.player.BukkitPlayer; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.location.Location; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.util.ReflectionUtils.RefClass; -import com.plotsquared.core.util.ReflectionUtils.RefConstructor; -import com.plotsquared.core.util.ReflectionUtils.RefField; -import com.plotsquared.core.util.ReflectionUtils.RefMethod; -import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.sk89q.worldedit.math.BlockVector2; -import io.papermc.lib.PaperLib; -import org.bukkit.Bukkit; -import org.bukkit.Chunk; -import org.bukkit.World; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map.Entry; - -import static com.plotsquared.core.util.ReflectionUtils.getRefClass; - -/** - * An utility that can be used to send chunks, rather than using bukkit code - * to do so (uses heavy NMS). - */ -public class SendChunk { - - private final RefMethod methodGetHandlePlayer; - private final RefMethod methodGetHandleChunk; - private final RefConstructor mapChunk; - private final RefField connection; - private final RefMethod send; - private final RefMethod methodInitLighting; - - /** - * Constructor. - */ - public SendChunk() throws ClassNotFoundException, NoSuchMethodException, NoSuchFieldException { - RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer"); - this.methodGetHandlePlayer = classCraftPlayer.getMethod("getHandle"); - RefClass classCraftChunk = getRefClass("{cb}.CraftChunk"); - this.methodGetHandleChunk = classCraftChunk.getMethod("getHandle"); - RefClass classChunk = getRefClass("{nms}.Chunk"); - this.methodInitLighting = classChunk.getMethod("initLighting"); - RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk"); - this.mapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), int.class); - RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer"); - this.connection = classEntityPlayer.getField("playerConnection"); - RefClass classPacket = getRefClass("{nms}.Packet"); - RefClass classConnection = getRefClass("{nms}.PlayerConnection"); - this.send = classConnection.getMethod("sendPacket", classPacket.getRealClass()); - } - - public void sendChunk(Collection input) { - HashSet chunks = new HashSet<>(input); - HashMap> map = new HashMap<>(); - int view = Bukkit.getServer().getViewDistance(); - for (Chunk chunk : chunks) { - String world = chunk.getWorld().getName(); - ArrayList list = map.computeIfAbsent(world, k -> new ArrayList<>()); - list.add(chunk); - Object c = this.methodGetHandleChunk.of(chunk).call(); - this.methodInitLighting.of(c).call(); - } - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); - Plot plot = pp.getCurrentPlot(); - Location location = null; - String world; - if (plot != null) { - world = plot.getWorldName(); - } else { - location = pp.getLocation(); - world = location.getWorld(); - } - ArrayList list = map.get(world); - if (list == null) { - continue; - } - if (location == null) { - location = pp.getLocation(); - } - int chunkX = location.getX() >> 4; - int chunkZ = location.getZ() >> 4; - Player player = ((BukkitPlayer) pp).player; - Object entity = this.methodGetHandlePlayer.of(player).call(); - - for (Chunk chunk : list) { - int dx = Math.abs(chunkX - chunk.getX()); - int dz = Math.abs(chunkZ - chunk.getZ()); - if ((dx > view) || (dz > view)) { - continue; - } - Object c = this.methodGetHandleChunk.of(chunk).call(); - chunks.remove(chunk); - Object con = this.connection.of(entity).get(); - Object packet = null; - try { - packet = this.mapChunk.create(c, 65535); - } catch (Exception ignored) { - } - if (packet == null) { - PlotSquared.debug("Error with PacketPlayOutMapChunk reflection."); - } - this.send.of(con).call(packet); - } - } - for (final Chunk chunk : chunks) { - TaskManager.runTask(() -> { - try { - chunk.unload(true); - } catch (Throwable ignored) { - String worldName = chunk.getWorld().getName(); - PlotSquared.debug( - "$4Could not save chunk: " + worldName + ';' + chunk.getX() + ";" + chunk - .getZ()); - PlotSquared.debug("$3 - $4File may be open in another process (e.g. MCEdit)"); - PlotSquared.debug("$3 - $4" + worldName + "/level.dat or " + worldName - + "/level_old.dat may be corrupt (try repairing or removing these)"); - } - }); - } - } - - public void sendChunk(String worldName, Collection chunkLocations) { - World myWorld = Bukkit.getWorld(worldName); - ArrayList chunks = new ArrayList<>(); - for (BlockVector2 loc : chunkLocations) { - if (myWorld.isChunkLoaded(loc.getX(), loc.getZ())) { - PaperLib.getChunkAtAsync(myWorld, loc.getX(), loc.getZ()).thenAccept(chunks::add); - } - } - sendChunk(chunks); - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DatFileFilter.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DatFileFilter.java deleted file mode 100644 index 65657fbff..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DatFileFilter.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.bukkit.util.uuid; - -import java.io.File; -import java.io.FilenameFilter; - -public class DatFileFilter implements FilenameFilter { - - @Override public boolean accept(File dir, String name) { - return name.endsWith(".dat"); - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/FileUUIDHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/FileUUIDHandler.java deleted file mode 100644 index c5620ffa1..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/FileUUIDHandler.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.bukkit.util.uuid; - -import com.google.common.collect.HashBiMap; -import com.google.common.collect.Sets; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.plot.expiration.ExpireManager; -import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; -import com.plotsquared.core.util.uuid.UUIDWrapper; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.jnbt.Tag; -import org.bukkit.Bukkit; -import org.bukkit.World; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.zip.GZIPInputStream; - -public class FileUUIDHandler extends UUIDHandlerImplementation { - - public FileUUIDHandler(UUIDWrapper wrapper) { - super(wrapper); - } - - @Override public boolean startCaching(Runnable whenDone) { - return super.startCaching(whenDone) && cache(whenDone); - } - - private Tag readTag(File file) throws IOException { - // Don't chain the creation of the GZIP stream and the NBT stream, because their - // constructors may throw an IOException. - try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(file)); - GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream); - NBTInputStream nbtInputStream = new NBTInputStream(gzipInputStream)) { - return nbtInputStream.readNamedTag().getTag(); - } - } - - public boolean cache(final Runnable whenDone) { - final File container = Bukkit.getWorldContainer(); - List worlds = Bukkit.getWorlds(); - final String world; - if (worlds.isEmpty()) { - world = "world"; - } else { - world = worlds.get(0).getName(); - } - TaskManager.runTaskAsync(() -> { - PlotSquared.debug(Captions.PREFIX + "Starting player data caching for: " + world); - File uuidFile = new File(PlotSquared.get().IMP.getDirectory(), "uuids.txt"); - if (uuidFile.exists()) { - try { - List lines = - Files.readAllLines(uuidFile.toPath(), StandardCharsets.UTF_8); - for (String line : lines) { - try { - line = line.trim(); - if (line.isEmpty()) { - continue; - } - line = line.replaceAll("[\\|][0-9]+[\\|][0-9]+[\\|]", ""); - String[] split = line.split("\\|"); - String name = split[0]; - if (name.isEmpty() || (name.length() > 16) || !StringMan - .isAlphanumericUnd(name)) { - continue; - } - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - if (uuid == null) { - continue; - } - UUIDHandler.add(new StringWrapper(name), uuid); - } catch (Exception e2) { - e2.printStackTrace(); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } - HashBiMap toAdd = HashBiMap.create(new HashMap<>()); - if (Settings.UUID.NATIVE_UUID_PROVIDER) { - HashSet all = UUIDHandler.getAllUUIDS(); - PlotSquared.debug("Fast mode UUID caching enabled!"); - File playerDataFolder = new File(container, world + File.separator + "playerdata"); - String[] dat = playerDataFolder.list(new DatFileFilter()); - boolean check = all.isEmpty(); - if (dat != null) { - for (String current : dat) { - String s = current.replaceAll(".dat$", ""); - try { - UUID uuid = UUID.fromString(s); - if (check || all.remove(uuid)) { - File file = new File(playerDataFolder, current); - CompoundTag compound = (CompoundTag) readTag(file); - if (!compound.containsKey("bukkit")) { - PlotSquared.debug("ERROR: Player data (" + uuid.toString() - + ".dat) does not contain the the key \"bukkit\""); - } else { - Map compoundMap = compound.getValue(); - CompoundTag bukkit = (CompoundTag) compoundMap.get("bukkit"); - Map bukkitMap = bukkit.getValue(); - String name = - (String) bukkitMap.get("lastKnownName").getValue(); - long last = (long) bukkitMap.get("lastPlayed").getValue(); - long first = (long) bukkitMap.get("firstPlayed").getValue(); - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); - ExpireManager.IMP.storeAccountAge(uuid, last - first); - } - toAdd.put(new StringWrapper(name), uuid); - } - } - } catch (Exception e) { - e.printStackTrace(); - PlotSquared.debug(Captions.PREFIX + "Invalid playerdata: " + current); - } - } - } - add(toAdd); - if (all.isEmpty()) { - if (whenDone != null) { - whenDone.run(); - } - return; - } else { - PlotSquared.debug( - "Failed to cache: " + all.size() + " uuids - slowly processing all files"); - } - } - HashSet worlds1 = Sets.newHashSet(world, "world"); - HashSet uuids = new HashSet<>(); - HashSet names = new HashSet<>(); - File playerDataFolder = null; - for (String worldName : worlds1) { - // Getting UUIDs - playerDataFolder = new File(container, worldName + File.separator + "playerdata"); - String[] dat = playerDataFolder.list(new DatFileFilter()); - if ((dat != null) && (dat.length != 0)) { - for (String current : dat) { - String s = current.replaceAll(".dat$", ""); - try { - UUID uuid = UUID.fromString(s); - uuids.add(uuid); - } catch (Exception ignored) { - PlotSquared.debug(Captions.PREFIX + "Invalid PlayerData: " + current); - } - } - break; - } - // Getting names - File playersFolder = new File(worldName + File.separator + "players"); - dat = playersFolder.list(new DatFileFilter()); - if ((dat != null) && (dat.length != 0)) { - for (String current : dat) { - names.add(current.replaceAll(".dat$", "")); - } - break; - } - } - for (UUID uuid : uuids) { - try { - File file = - new File(playerDataFolder + File.separator + uuid.toString() + ".dat"); - if (!file.exists()) { - continue; - } - CompoundTag compound = (CompoundTag) readTag(file); - if (!compound.containsKey("bukkit")) { - PlotSquared.debug("ERROR: Player data (" + uuid.toString() - + ".dat) does not contain the the key \"bukkit\""); - } else { - Map compoundMap = compound.getValue(); - CompoundTag bukkit = (CompoundTag) compoundMap.get("bukkit"); - Map bukkitMap = bukkit.getValue(); - String name = (String) bukkitMap.get("lastKnownName").getValue(); - StringWrapper wrap = new StringWrapper(name); - if (!toAdd.containsKey(wrap)) { - long last = (long) bukkitMap.get("lastPlayed").getValue(); - long first = (long) bukkitMap.get("firstPlayed").getValue(); - if (Settings.UUID.OFFLINE) { - if (Settings.UUID.FORCE_LOWERCASE && !name.toLowerCase() - .equals(name)) { - uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - } else { - long most = (long) compoundMap.get("UUIDMost").getValue(); - long least = (long) compoundMap.get("UUIDLeast").getValue(); - uuid = new UUID(most, least); - } - } - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); - ExpireManager.IMP.storeAccountAge(uuid, last - first); - } - toAdd.put(wrap, uuid); - } - } - } catch (Exception ignored) { - PlotSquared.debug( - Captions.PREFIX + "&6Invalid PlayerData: " + uuid.toString() + ".dat"); - } - } - for (String name : names) { - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(name); - StringWrapper nameWrap = new StringWrapper(name); - toAdd.put(nameWrap, uuid); - } - - if (getUUIDMap().isEmpty()) { - for (OfflinePlotPlayer offlinePlotPlayer : FileUUIDHandler.this.uuidWrapper - .getOfflinePlayers()) { - long last = offlinePlotPlayer.getLastPlayed(); - if (last != 0) { - String name = offlinePlotPlayer.getName(); - StringWrapper wrap = new StringWrapper(name); - if (!toAdd.containsKey(wrap)) { - UUID uuid = FileUUIDHandler.this.uuidWrapper.getUUID(offlinePlotPlayer); - if (toAdd.containsValue(uuid)) { - StringWrapper duplicate = toAdd.inverse().get(uuid); - PlotSquared.debug( - "The UUID: " + uuid.toString() + " is already mapped to " - + duplicate - + "\n It cannot be added to the Map with a key of " + wrap); - } - toAdd.putIfAbsent(wrap, uuid); - if (ExpireManager.IMP != null) { - ExpireManager.IMP.storeDate(uuid, last); - } - } - } - } - } - add(toAdd); - if (whenDone != null) { - whenDone.run(); - } - }); - return true; - } - - @Override public void fetchUUID(final String name, final RunnableVal ifFetch) { - TaskManager.runTaskAsync(() -> { - ifFetch.value = FileUUIDHandler.this.uuidWrapper.getUUID(name); - TaskManager.runTask(ifFetch); - }); - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/LowerOfflineUUIDWrapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/LowerOfflineUUIDWrapper.java deleted file mode 100644 index ad2be7ce3..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/LowerOfflineUUIDWrapper.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.bukkit.util.uuid; - -import com.google.common.base.Charsets; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import org.bukkit.OfflinePlayer; -import org.jetbrains.annotations.NotNull; - -import java.util.Objects; -import java.util.UUID; - -public class LowerOfflineUUIDWrapper extends OfflineUUIDWrapper { - - @NotNull @Override public UUID getUUID(PlotPlayer player) { - return UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8)); - } - - @Override public UUID getUUID(OfflinePlotPlayer player) { - return UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + player.getName().toLowerCase()).getBytes(Charsets.UTF_8)); - } - - @Override public UUID getUUID(OfflinePlayer player) { - return UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + Objects.requireNonNull(player.getName()).toLowerCase()) - .getBytes(Charsets.UTF_8)); - } - - @Override public UUID getUUID(String name) { - return UUID - .nameUUIDFromBytes(("OfflinePlayer:" + name.toLowerCase()).getBytes(Charsets.UTF_8)); - } - -} 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 deleted file mode 100644 index 405fb940d..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/OfflineUUIDWrapper.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.bukkit.util.uuid; - -import com.google.common.base.Charsets; -import com.google.common.collect.BiMap; -import com.plotsquared.bukkit.player.BukkitOfflinePlayer; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDWrapper; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.Server; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; -import java.util.UUID; - -public class OfflineUUIDWrapper implements UUIDWrapper { - - private final Object[] arg = new Object[0]; - private Method getOnline = null; - - public OfflineUUIDWrapper() { - try { - this.getOnline = Server.class.getMethod("getOnlinePlayers"); - } catch (NoSuchMethodException | SecurityException e) { - e.printStackTrace(); - } - } - - @NotNull @Override public UUID getUUID(PlotPlayer player) { - return UUID - .nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)); - } - - @Override public UUID getUUID(OfflinePlotPlayer player) { - return UUID - .nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)); - } - - public UUID getUUID(OfflinePlayer player) { - return UUID - .nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)); - } - - @Override public OfflinePlotPlayer getOfflinePlayer(UUID uuid) { - BiMap map = UUIDHandler.getUuidMap().inverse(); - String name = null; - if (map.containsKey(uuid)) { - name = map.get(uuid).value; - } - if (name != null) { - OfflinePlayer op = Bukkit.getOfflinePlayer(name); - if (op.hasPlayedBefore()) { - return new BukkitOfflinePlayer(op); - } - } - for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { - if (getUUID(player).equals(uuid)) { - return new BukkitOfflinePlayer(player); - } - } - return null; - } - - public Player[] getOnlinePlayers() { - if (this.getOnline == null) { - Collection onlinePlayers = Bukkit.getOnlinePlayers(); - return onlinePlayers.toArray(new Player[0]); - } - try { - Object players = this.getOnline.invoke(Bukkit.getServer(), this.arg); - if (players instanceof Player[]) { - return (Player[]) players; - } else { - @SuppressWarnings("unchecked") Collection p = - (Collection) players; - return p.toArray(new Player[0]); - } - } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException ignored) { - PlotSquared.debug("Failed to resolve online players"); - this.getOnline = null; - Collection onlinePlayers = Bukkit.getOnlinePlayers(); - return onlinePlayers.toArray(new Player[0]); - } - } - - @Override public UUID getUUID(String name) { - return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(Charsets.UTF_8)); - } - - @Override public OfflinePlotPlayer[] getOfflinePlayers() { - OfflinePlayer[] ops = Bukkit.getOfflinePlayers(); - return Arrays.stream(ops).map(BukkitOfflinePlayer::new).toArray(BukkitOfflinePlayer[]::new); - } - - @Override public OfflinePlotPlayer getOfflinePlayer(String name) { - return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(name)); - } -} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/SQLUUIDHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/SQLUUIDHandler.java deleted file mode 100644 index a08956369..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/SQLUUIDHandler.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.bukkit.util.uuid; - -import com.google.common.collect.HashBiMap; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; -import com.plotsquared.core.database.SQLite; -import com.plotsquared.core.util.MainUtil; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; -import com.plotsquared.core.util.uuid.UUIDWrapper; -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayDeque; -import java.util.Collections; -import java.util.HashMap; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - -public class SQLUUIDHandler extends UUIDHandlerImplementation { - - final int MAX_REQUESTS = 500; - private final String PROFILE_URL = - "https://sessionserver.mojang.com/session/minecraft/profile/"; - private final JSONParser jsonParser = new JSONParser(); - private final SQLite sqlite; - - public SQLUUIDHandler(UUIDWrapper wrapper) { - super(wrapper); - this.sqlite = - new SQLite(MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), "usercache.db")); - try { - this.sqlite.openConnection(); - } catch (ClassNotFoundException | SQLException e) { - e.printStackTrace(); - } - - try (PreparedStatement stmt = getConnection().prepareStatement( - "CREATE TABLE IF NOT EXISTS `usercache` (uuid VARCHAR(32) NOT NULL, username VARCHAR(32) NOT NULL, PRIMARY KEY (uuid, username))")) { - stmt.execute(); - } catch (SQLException e) { - e.printStackTrace(); - } - startCaching(null); - } - - private Connection getConnection() { - synchronized (this.sqlite) { - return this.sqlite.getConnection(); - } - } - - @Override public boolean startCaching(final Runnable whenDone) { - if (!super.startCaching(whenDone)) { - return false; - } - TaskManager.runTaskAsync(() -> { - try { - HashBiMap toAdd = HashBiMap.create(new HashMap<>()); - try (PreparedStatement statement = getConnection() - .prepareStatement("SELECT `uuid`, `username` FROM `usercache`"); - ResultSet resultSet = statement.executeQuery()) { - while (resultSet.next()) { - StringWrapper username = new StringWrapper(resultSet.getString("username")); - UUID uuid = UUID.fromString(resultSet.getString("uuid")); - toAdd.put(new StringWrapper(username.value), uuid); - } - } - add(toAdd); - // This should be called as long as there are some unknown plots - final ArrayDeque toFetch = new ArrayDeque<>(); - for (UUID u : UUIDHandler.getAllUUIDS()) { - if (!uuidExists(u)) { - toFetch.add(u); - } - } - if (toFetch.isEmpty()) { - if (whenDone != null) { - whenDone.run(); - } - return; - } - FileUUIDHandler fileHandler = new FileUUIDHandler(SQLUUIDHandler.this.uuidWrapper); - fileHandler.startCaching(() -> { - // If the file based UUID handler didn't cache it, then we can't cache offline mode - // Also, trying to cache based on files again, is useless as that's what the file based uuid cacher does - if (Settings.UUID.OFFLINE) { - if (whenDone != null) { - whenDone.run(); - } - return; - } - - TaskManager.runTaskAsync(() -> { - while (!toFetch.isEmpty()) { - try { - for (int i = 0; i < Math.min(MAX_REQUESTS, toFetch.size()); i++) { - UUID uuid = toFetch.pop(); - HttpURLConnection connection = (HttpURLConnection) new URL( - SQLUUIDHandler.this.PROFILE_URL + uuid.toString() - .replace("-", "")).openConnection(); - try (InputStream con = connection.getInputStream()) { - InputStreamReader reader = new InputStreamReader(con); - JSONObject response = - (JSONObject) SQLUUIDHandler.this.jsonParser - .parse(reader); - String name = (String) response.get("name"); - if (name != null) { - add(new StringWrapper(name), uuid); - } - } - connection.disconnect(); - } - } catch (IOException | ParseException e) { - PlotSquared.debug( - "Invalid response from Mojang: Some UUIDs will be cached later. (`unknown` until then or player joins)"); - } - try { - //Mojang allows requests every 10 minutes according to https://wiki.vg/Mojang_API - //15 Minutes is chosen here since system timers are not always precise - //and it should provide enough time where Mojang won't block requests. - TimeUnit.MINUTES.sleep(15); - } catch (InterruptedException e) { - e.printStackTrace(); - break; - } - } - if (whenDone != null) { - whenDone.run(); - } - }); - }); - } catch (SQLException e) { - throw new SQLUUIDHandlerException("Couldn't select :s", e); - } - }); - return true; - } - - @Override public void fetchUUID(final String name, final RunnableVal ifFetch) { - PlotSquared.debug(Captions.PREFIX + "UUID for '" + name - + "' was null. We'll cache this from the Mojang servers!"); - if (ifFetch == null) { - return; - } - TaskManager.runTaskAsync(() -> { - try { - URL url = new URL(SQLUUIDHandler.this.PROFILE_URL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setUseCaches(false); - connection.setDoInput(true); - connection.setDoOutput(true); - String body = JSONArray.toJSONString(Collections.singletonList(name)); - OutputStream stream = connection.getOutputStream(); - stream.write(body.getBytes()); - stream.flush(); - stream.close(); - JSONArray array = (JSONArray) SQLUUIDHandler.this.jsonParser - .parse(new InputStreamReader(connection.getInputStream())); - JSONObject jsonProfile = (JSONObject) array.get(0); - String id = (String) jsonProfile.get("id"); - String name1 = (String) jsonProfile.get("name"); - ifFetch.value = UUID.fromString( - id.substring(0, 8) + '-' + id.substring(8, 12) + '-' + id.substring(12, 16) - + '-' + id.substring(16, 20) + '-' + id.substring(20, 32)); - } catch (IOException | ParseException e) { - e.printStackTrace(); - } - TaskManager.runTask(ifFetch); - }); - } - - @Override public void handleShutdown() { - super.handleShutdown(); - try { - getConnection().close(); - } catch (SQLException e) { - throw new SQLUUIDHandlerException("Couldn't close database connection", e); - } - } - - /** - * This is useful for name changes - */ - @Override public void rename(final UUID uuid, final StringWrapper name) { - super.rename(uuid, name); - TaskManager.runTaskAsync(() -> { - try (PreparedStatement statement = getConnection() - .prepareStatement("UPDATE usercache SET `username`=? WHERE `uuid`=?")) { - statement.setString(1, name.value); - statement.setString(2, uuid.toString()); - statement.execute(); - PlotSquared.debug( - Captions.PREFIX + "Name change for '" + uuid + "' to '" + name.value + '\''); - } catch (SQLException e) { - e.printStackTrace(); - } - }); - } - - @Override public boolean add(final StringWrapper name, final UUID uuid) { - // Ignoring duplicates - if (super.add(name, uuid)) { - TaskManager.runTaskAsync(() -> { - try (PreparedStatement statement = getConnection() - .prepareStatement("REPLACE INTO usercache (`uuid`, `username`) VALUES(?, ?)")) { - statement.setString(1, uuid.toString()); - statement.setString(2, name.toString()); - statement.execute(); - PlotSquared - .debug(Captions.PREFIX + "&cAdded '&6" + uuid + "&c' - '&6" + name + "&c'"); - } catch (SQLException e) { - e.printStackTrace(); - } - }); - return true; - } - return false; - } - - private static class SQLUUIDHandlerException extends RuntimeException { - - SQLUUIDHandlerException(String s, Throwable c) { - super("SQLUUIDHandler caused an exception: " + s, c); - } - } -} diff --git a/Core/src/main/java/com/plotsquared/core/IPlotMain.java b/Core/src/main/java/com/plotsquared/core/IPlotMain.java index ed6694e01..2705d54c2 100644 --- a/Core/src/main/java/com/plotsquared/core/IPlotMain.java +++ b/Core/src/main/java/com/plotsquared/core/IPlotMain.java @@ -36,13 +36,13 @@ import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.InventoryUtil; import com.plotsquared.core.util.PlatformWorldManager; +import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.logger.ILogger; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; import com.sk89q.worldedit.extension.platform.Actor; import org.jetbrains.annotations.NotNull; @@ -220,12 +220,6 @@ public interface IPlotMain extends ILogger { */ void setGenerator(String world); - /** - * Gets the {@link UUIDHandlerImplementation} which will cache and - * provide UUIDs. - */ - UUIDHandlerImplementation initUUIDHandler(); - /** * Gets the {@link InventoryUtil} class (used for implementation specific * inventory guis). @@ -285,6 +279,13 @@ public interface IPlotMain extends ILogger { * * @return World manager */ - @NotNull PlatformWorldManager getWorldManager(); + @NotNull PlatformWorldManager getWorldManager(); + + /** + * Get the player manager implementation for the platform + * + * @return Player manager + */ + @NotNull PlayerManager getPlayerManager(); } diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index bbb8b66bc..a19f167d7 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -79,11 +79,9 @@ import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.StringWrapper; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.logger.ILogger; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.plotsquared.core.uuid.UUIDPipeline; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.math.BlockVector2; @@ -91,6 +89,7 @@ import com.sk89q.worldedit.regions.CuboidRegion; import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.BufferedReader; @@ -259,15 +258,6 @@ public class PlotSquared { if (Settings.Enabled_Components.CHUNK_PROCESSOR) { this.IMP.registerChunkProcessor(); } - // create UUIDWrapper - UUIDHandler.implementation = this.IMP.initUUIDHandler(); - if (Settings.Enabled_Components.UUID_CACHE) { - startUuidCatching(); - } else { - // Start these separately - UUIDHandler.add(new StringWrapper("*"), DBFunc.EVERYONE); - startExpiryTasks(); - } // Create Event utility class eventDispatcher = new EventDispatcher(); // create Hybrid utility class @@ -392,11 +382,11 @@ public class PlotSquared { return PlotSquared.instance; } - public static IPlotMain imp() { - if (instance != null) { + @NotNull public static IPlotMain imp() { + if (instance != null && instance.IMP != null) { return instance.IMP; } - return null; + throw new IllegalStateException("Plot main implementation is missing"); } /** @@ -437,8 +427,7 @@ public class PlotSquared { private void startUuidCatching() { TaskManager.runTaskLater(() -> { debug("Starting UUID caching"); - UUIDHandler.startCaching(() -> { - UUIDHandler.add(new StringWrapper("*"), DBFunc.EVERYONE); + /*UUIDHandler.startCaching(() -> { forEachPlotRaw(plot -> { if (plot.hasOwner() && plot.temp != -1) { if (UUIDHandler.getName(plot.getOwnerAbs()) == null) { @@ -447,7 +436,8 @@ public class PlotSquared { } }); startExpiryTasks(); - }); + });*/ + // TODO: Re-implement }, 20); } @@ -973,7 +963,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlots(String world, String player) { - final UUID uuid = UUIDHandler.getUUID(player, null); + final UUID uuid = this.impromptuUUIDPipeline.getSingle(player, 10L); return getPlots(world, uuid); } @@ -985,7 +975,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlots(PlotArea area, String player) { - UUID uuid = UUIDHandler.getUUID(player, null); + final UUID uuid = this.impromptuUUIDPipeline.getSingle(player, 10L); return getPlots(area, uuid); } @@ -1018,7 +1008,10 @@ public class PlotSquared { * @param uuid the plot owner * @return Set of plot */ - public Set getPlots(String world, UUID uuid) { + public Set getPlots(String world, @Nullable UUID uuid) { + if (uuid == null) { + return Collections.emptySet(); + } final Set plots = getPlots(world).stream().filter(plot -> plot.hasOwner() && plot.isOwnerAbs(uuid)) .collect(Collectors.toSet()); @@ -1627,7 +1620,6 @@ public class PlotSquared { // Close the connection DBFunc.close(); - UUIDHandler.handleShutdown(); } catch (NullPointerException throwable) { throwable.printStackTrace(); PlotSquared.log("&cCould not close database connection!"); 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 56e507873..3991643a3 100644 --- a/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java +++ b/Core/src/main/java/com/plotsquared/core/api/PlotAPI.java @@ -38,8 +38,6 @@ import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SchematicHandler; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.plotsquared.core.util.uuid.UUIDWrapper; import lombok.NoArgsConstructor; import java.util.Collections; @@ -138,17 +136,6 @@ import java.util.UUID; return GlobalBlockQueue.IMP; } - /** - * UUIDWrapper class has basic methods for getting UUIDS. It's recommended - * to use the UUIDHandler class instead. - * - * @return UUIDWrapper - * @see UUIDWrapper - */ - public UUIDWrapper getUUIDWrapper() { - return UUIDHandler.getUUIDWrapper(); - } - /** * SchematicHandler class contains methods related to pasting, reading * and writing schematics. diff --git a/Core/src/main/java/com/plotsquared/core/command/Add.java b/Core/src/main/java/com/plotsquared/core/command/Add.java index bc4905c68..32750f8d9 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Add.java +++ b/Core/src/main/java/com/plotsquared/core/command/Add.java @@ -36,7 +36,6 @@ import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; import java.util.Iterator; -import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -62,51 +61,64 @@ public class Add extends Command { .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), Captions.NO_PLOT_PERMS); checkTrue(args.length == 1, Captions.COMMAND_SYNTAX, getUsage()); - final Set uuids = MainUtil.getUUIDsFromString(args[0]); - checkTrue(!uuids.isEmpty(), Captions.INVALID_PLAYER, args[0]); - Iterator iterator = uuids.iterator(); - int size = plot.getTrusted().size() + plot.getMembers().size(); - while (iterator.hasNext()) { - UUID uuid = iterator.next(); - if (uuid == DBFunc.EVERYONE && !( - Permissions.hasPermission(player, Captions.PERMISSION_TRUST_EVERYONE) || Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST))) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - if (plot.isOwner(uuid)) { - MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - if (plot.getMembers().contains(uuid)) { - MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - size += plot.getTrusted().contains(uuid) ? 0 : 1; - } - checkTrue(!uuids.isEmpty(), null); - checkTrue(size <= plot.getArea().getMaxPlotMembers() || Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), - Captions.PLOT_MAX_MEMBERS); - // Success - confirm.run(this, () -> { - for (UUID uuid : uuids) { - if (uuid != DBFunc.EVERYONE) { - if (!plot.removeTrusted(uuid)) { - if (plot.getDenied().contains(uuid)) { - plot.removeDenied(uuid); - } - } - } - plot.addMember(uuid); - PlotSquared.get().getEventDispatcher().callMember(player, plot, uuid, true); - MainUtil.sendMessage(player, Captions.MEMBER_ADDED); - } - }, null); - return CompletableFuture.completedFuture(true); + final CompletableFuture future = new CompletableFuture<>(); + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + if (throwable != null) { + Captions.INVALID_PLAYER.send(player, args[0]); + future.completeExceptionally(throwable); + return; + } else { + try { + checkTrue(!uuids.isEmpty(), Captions.INVALID_PLAYER, args[0]); + Iterator iterator = uuids.iterator(); + int size = plot.getTrusted().size() + plot.getMembers().size(); + while (iterator.hasNext()) { + UUID uuid = iterator.next(); + if (uuid == DBFunc.EVERYONE && !( + Permissions.hasPermission(player, Captions.PERMISSION_TRUST_EVERYONE) || Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST))) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + if (plot.isOwner(uuid)) { + MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + if (plot.getMembers().contains(uuid)) { + MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + size += plot.getTrusted().contains(uuid) ? 0 : 1; + } + checkTrue(!uuids.isEmpty(), null); + checkTrue(size <= plot.getArea().getMaxPlotMembers() || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), + Captions.PLOT_MAX_MEMBERS); + // Success + confirm.run(this, () -> { + for (UUID uuid : uuids) { + if (uuid != DBFunc.EVERYONE) { + if (!plot.removeTrusted(uuid)) { + if (plot.getDenied().contains(uuid)) { + plot.removeDenied(uuid); + } + } + } + plot.addMember(uuid); + PlotSquared.get().getEventDispatcher().callMember(player, plot, uuid, true); + MainUtil.sendMessage(player, Captions.MEMBER_ADDED); + } + }, null); + } catch (final Throwable exception) { + future.completeExceptionally(exception); + return; + } + } + future.complete(true); + }); + return future; } } diff --git a/Core/src/main/java/com/plotsquared/core/command/Alias.java b/Core/src/main/java/com/plotsquared/core/command/Alias.java index b1d8d8161..1df9848d0 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Alias.java +++ b/Core/src/main/java/com/plotsquared/core/command/Alias.java @@ -33,8 +33,6 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.uuid.UUIDHandler; @CommandDeclaration(command = "setalias", permission = "plots.alias", @@ -79,7 +77,8 @@ public class Alias extends SubCommand { if (canExecuteCommand(player, Captions.PERMISSION_ALIAS_SET, false) || canExecuteCommand(player, Captions.PERMISSION_ALIAS_SET_OBSOLETE, false)) { - result = setAlias(player, plot, args[1]); + setAlias(player, plot, args[1]); + return true; } else { MainUtil.sendMessage(player, Captions.NO_PERMISSION); } @@ -99,38 +98,32 @@ public class Alias extends SubCommand { } - private boolean setAlias(PlotPlayer player, Plot plot, String alias) { + private void setAlias(PlotPlayer player, Plot plot, String alias) { if (alias.isEmpty()) { Captions.COMMAND_SYNTAX.send(player, getUsage()); - return false; - } - if (alias.length() >= 50) { + } else if (alias.length() >= 50) { MainUtil.sendMessage(player, Captions.ALIAS_TOO_LONG); - return false; - } - if (alias.contains(" ")) { + } else if (alias.contains(" ")) { Captions.NOT_VALID_VALUE.send(player); - return false; - } - if (MathMan.isInteger(alias)) { + } else if (MathMan.isInteger(alias)) { Captions.NOT_VALID_VALUE.send(player); - return false; - } - for (Plot p : PlotSquared.get().getPlots(plot.getArea())) { - if (p.getAlias().equalsIgnoreCase(alias)) { - MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); - return false; + } else { + for (Plot p : PlotSquared.get().getPlots(plot.getArea())) { + if (p.getAlias().equalsIgnoreCase(alias)) { + MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); + return; + } } + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> { + if (uuid != null) { + MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); + } else { + plot.setAlias(alias); + MainUtil.sendMessage(player, + Captions.ALIAS_SET_TO.getTranslated().replaceAll("%alias%", alias)); + } + })); } - if (UUIDHandler.nameExists(new StringWrapper(alias)) || PlotSquared.get() - .hasPlotArea(alias)) { - MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); - return false; - } - plot.setAlias(alias); - MainUtil.sendMessage(player, - Captions.ALIAS_SET_TO.getTranslated().replaceAll("%alias%", alias)); - return true; } private boolean removeAlias(PlotPlayer player, Plot plot) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Cluster.java b/Core/src/main/java/com/plotsquared/core/command/Cluster.java index ae220831e..82f602493 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Cluster.java +++ b/Core/src/main/java/com/plotsquared/core/command/Cluster.java @@ -39,7 +39,6 @@ import com.plotsquared.core.plot.PlotCluster; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.ArrayList; import java.util.HashSet; @@ -371,22 +370,27 @@ public class Cluster extends SubCommand { return false; } } - // check uuid - UUID uuid = UUIDHandler.getUUID(args[1], null); - if (uuid == null) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[2]); - return false; - } - if (!cluster.isAdded(uuid)) { - // add the user if not added - cluster.invited.add(uuid); - DBFunc.setInvited(cluster, uuid); - PlotPlayer player2 = UUIDHandler.getPlayer(uuid); - if (player2 != null) { - MainUtil.sendMessage(player2, Captions.CLUSTER_INVITED, cluster.getName()); - } - } - MainUtil.sendMessage(player, Captions.CLUSTER_ADDED_USER); + + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(args[1], (uuid, throwable) -> { + if (throwable != null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[1]); + } else { + if (!cluster.isAdded(uuid)) { + // add the user if not added + cluster.invited.add(uuid); + DBFunc.setInvited(cluster, uuid); + + final PlotPlayer otherPlayer = + PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); + if (otherPlayer != null) { + MainUtil.sendMessage(otherPlayer, Captions.CLUSTER_INVITED, + cluster.getName()); + } + } + MainUtil.sendMessage(player, Captions.CLUSTER_ADDED_USER); + } + }); return true; } case "k": @@ -420,35 +424,41 @@ public class Cluster extends SubCommand { } } // check uuid - UUID uuid = UUIDHandler.getUUID(args[1], null); - if (uuid == null) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[1]); - return false; - } - // Can't kick if the player is yourself, the owner, or not added to the cluster - if (uuid.equals(player.getUUID()) || uuid.equals(cluster.owner) || !cluster - .isAdded(uuid)) { - MainUtil.sendMessage(player, Captions.CANNOT_KICK_PLAYER, cluster.getName()); - return false; - } - if (cluster.helpers.contains(uuid)) { - cluster.helpers.remove(uuid); - DBFunc.removeHelper(cluster, uuid); - } - cluster.invited.remove(uuid); - DBFunc.removeInvited(cluster, uuid); - PlotPlayer player2 = UUIDHandler.getPlayer(uuid); - if (player2 != null) { - MainUtil.sendMessage(player2, Captions.CLUSTER_REMOVED, cluster.getName()); - } - for (Plot plot : new ArrayList<>( - PlotSquared.get().getPlots(player2.getLocation().getWorld(), uuid))) { - PlotCluster current = plot.getCluster(); - if (current != null && current.equals(cluster)) { - plot.unclaim(); - } - } - MainUtil.sendMessage(player2, Captions.CLUSTER_KICKED_USER); + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(args[1], (uuid, throwable) -> { + if (throwable != null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[1]); + } else { + // Can't kick if the player is yourself, the owner, or not added to the cluster + if (uuid.equals(player.getUUID()) || uuid.equals(cluster.owner) + || !cluster.isAdded(uuid)) { + MainUtil.sendMessage(player, Captions.CANNOT_KICK_PLAYER, + cluster.getName()); + } else { + if (cluster.helpers.contains(uuid)) { + cluster.helpers.remove(uuid); + DBFunc.removeHelper(cluster, uuid); + } + cluster.invited.remove(uuid); + DBFunc.removeInvited(cluster, uuid); + + final PlotPlayer player2 = + PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); + if (player2 != null) { + MainUtil.sendMessage(player2, Captions.CLUSTER_REMOVED, + cluster.getName()); + } + for (Plot plot : new ArrayList<>(PlotSquared.get() + .getPlots(player2.getLocation().getWorld(), uuid))) { + PlotCluster current = plot.getCluster(); + if (current != null && current.equals(cluster)) { + plot.unclaim(); + } + } + MainUtil.sendMessage(player2, Captions.CLUSTER_KICKED_USER); + } + } + }); return true; } case "quit": @@ -529,24 +539,27 @@ public class Cluster extends SubCommand { MainUtil.sendMessage(player, Captions.NOT_IN_CLUSTER); return false; } - UUID uuid = UUIDHandler.getUUID(args[2], null); - if (uuid == null) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[2]); - return false; - } - if (args[1].equalsIgnoreCase("add")) { - cluster.helpers.add(uuid); - DBFunc.setHelper(cluster, uuid); - return MainUtil.sendMessage(player, Captions.CLUSTER_ADDED_HELPER); - } - if (args[1].equalsIgnoreCase("remove")) { - cluster.helpers.remove(uuid); - DBFunc.removeHelper(cluster, uuid); - return MainUtil.sendMessage(player, Captions.CLUSTER_REMOVED_HELPER); - } - MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, - "/plot cluster helpers "); - return false; + + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(args[2], (uuid, throwable) -> { + if (throwable != null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[2]); + } else { + if (args[1].equalsIgnoreCase("add")) { + cluster.helpers.add(uuid); + DBFunc.setHelper(cluster, uuid); + MainUtil.sendMessage(player, Captions.CLUSTER_ADDED_HELPER); + } else if (args[1].equalsIgnoreCase("remove")) { + cluster.helpers.remove(uuid); + DBFunc.removeHelper(cluster, uuid); + MainUtil.sendMessage(player, Captions.CLUSTER_REMOVED_HELPER); + } else { + MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, + "/plot cluster helpers "); + } + } + }); + return true; } case "spawn": case "home": @@ -615,21 +628,27 @@ public class Cluster extends SubCommand { } } String id = cluster.toString(); - String owner = UUIDHandler.getName(cluster.owner); - if (owner == null) { - owner = "unknown"; - } - String name = cluster.getName(); - String size = (cluster.getP2().x - cluster.getP1().x + 1) + "x" + ( - cluster.getP2().y - cluster.getP1().y + 1); - String rights = cluster.isAdded(player.getUUID()) + ""; - String message = Captions.CLUSTER_INFO.getTranslated(); - message = message.replaceAll("%id%", id); - message = message.replaceAll("%owner%", owner); - message = message.replaceAll("%name%", name); - message = message.replaceAll("%size%", size); - message = message.replaceAll("%rights%", rights); - MainUtil.sendMessage(player, message); + + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(cluster.owner, (username, throwable) -> { + final String owner; + if (username == null) { + owner = "unknown"; + } else { + owner = username; + } + String name = cluster.getName(); + String size = (cluster.getP2().x - cluster.getP1().x + 1) + "x" + ( + cluster.getP2().y - cluster.getP1().y + 1); + String rights = cluster.isAdded(player.getUUID()) + ""; + String message = Captions.CLUSTER_INFO.getTranslated(); + message = message.replaceAll("%id%", id); + message = message.replaceAll("%owner%", owner); + message = message.replaceAll("%name%", name); + message = message.replaceAll("%size%", size); + message = message.replaceAll("%rights%", rights); + MainUtil.sendMessage(player, message); + }); return true; } case "sh": diff --git a/Core/src/main/java/com/plotsquared/core/command/Command.java b/Core/src/main/java/com/plotsquared/core/command/Command.java index 6535e3b2c..6e97eb30a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Command.java +++ b/Core/src/main/java/com/plotsquared/core/command/Command.java @@ -37,6 +37,8 @@ import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; +import lombok.SneakyThrows; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -603,6 +605,10 @@ public abstract class Command { return object; } + @SneakyThrows protected static void sneakyThrow(@NotNull final Throwable throwable) { + throw throwable; + } + public enum CommandResult { FAILURE, SUCCESS } diff --git a/Core/src/main/java/com/plotsquared/core/command/Comment.java b/Core/src/main/java/com/plotsquared/core/command/Comment.java index 284587106..501ba4247 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Comment.java +++ b/Core/src/main/java/com/plotsquared/core/command/Comment.java @@ -25,6 +25,7 @@ */ package com.plotsquared.core.command; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; @@ -33,11 +34,9 @@ import com.plotsquared.core.plot.comment.CommentManager; import com.plotsquared.core.plot.comment.PlotComment; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.Arrays; import java.util.Locale; -import java.util.Map.Entry; @CommandDeclaration(command = "comment", aliases = {"msg"}, @@ -96,12 +95,13 @@ public class Comment extends SubCommand { StringMan.join(CommentManager.inboxes.keySet(), "|")); return false; } - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); + + for (final PlotPlayer pp : PlotSquared.imp().getPlayerManager().getPlayers()) { if (pp.getAttribute("chatspy")) { MainUtil.sendMessage(pp, "/plot comment " + StringMan.join(args, " ")); } } + sendMessage(player, Captions.COMMENT_ADDED); return true; } diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugClaimTest.java b/Core/src/main/java/com/plotsquared/core/command/DebugClaimTest.java deleted file mode 100644 index 5412ed6a2..000000000 --- a/Core/src/main/java/com/plotsquared/core/command/DebugClaimTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.command; - -import com.google.common.collect.BiMap; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.location.Location; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.plot.PlotArea; -import com.plotsquared.core.plot.PlotId; -import com.plotsquared.core.plot.PlotManager; -import com.plotsquared.core.util.ChunkManager; -import com.plotsquared.core.util.MainUtil; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.uuid.UUIDHandler; -import com.sk89q.worldedit.math.BlockVector2; - -import java.util.ArrayList; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; - -@CommandDeclaration(command = "debugclaimtest", - description = - "If you accidentally delete your database, this command will attempt to restore all plots based on the data from plot signs. " - + "Execution time may vary", - category = CommandCategory.DEBUG, - requiredType = RequiredType.CONSOLE, - permission = "plots.debugclaimtest") -public class DebugClaimTest extends SubCommand { - - @Override public boolean onCommand(final PlotPlayer player, String[] args) { - if (args.length < 3) { - return !MainUtil.sendMessage(null, - "If you accidentally delete your database, this command will attempt to restore all plots based on the data from the " - + "plot signs. \n\n&cMissing world arg /plot debugclaimtest {world} {PlotId min} {PlotId max}"); - } - PlotArea area = PlotSquared.get().getPlotAreaByString(args[0]); - if (area == null || !WorldUtil.IMP.isWorld(area.getWorldName())) { - Captions.NOT_VALID_PLOT_WORLD.send(player, args[0]); - return false; - } - PlotId min, max; - try { - args[1].split(";"); - args[2].split(";"); - min = PlotId.fromString(args[1]); - max = PlotId.fromString(args[2]); - } catch (Exception ignored) { - return !MainUtil.sendMessage(player, - "&cInvalid min/max values. &7The values are to Plot IDs in the format &cX;Y &7where X;Y are the plot coords\nThe conversion " - + "will only check the plots in the selected area."); - } - MainUtil.sendMessage(player, - "&3Sign Block&8->&3Plot&8: &7Beginning sign to plot conversion. This may take a while..."); - MainUtil.sendMessage(player, - "&3Sign Block&8->&3Plot&8: Found an excess of 250,000 chunks. Limiting search radius... (~3.8 min)"); - PlotManager manager = area.getPlotManager(); - CompletableFuture.runAsync(() -> { - ArrayList ids = MainUtil.getPlotSelectionIds(min, max); - MainUtil.sendMessage(player, - "&3Sign Block&8->&3Plot&8: " + ids.size() + " plot ids to check!"); - for (PlotId id : ids) { - Plot plot = area.getPlotAbs(id); - if (plot.hasOwner()) { - MainUtil.sendMessage(player, " - &cDB Already contains: " + plot.getId()); - continue; - } - Location location = manager.getSignLoc(plot); - BlockVector2 chunk = BlockVector2.at(location.getX() >> 4, location.getZ() >> 4); - ChunkManager.manager.loadChunk(area.getWorldName(), chunk, false).thenRun(() -> { - String[] lines = WorldUtil.IMP.getSignSynchronous(location); - if (lines != null) { - String line = lines[2]; - if (line != null && line.length() > 2) { - line = line.substring(2); - BiMap map = UUIDHandler.getUuidMap(); - UUID uuid = map.get(new StringWrapper(line)); - if (uuid == null) { - for (Map.Entry stringWrapperUUIDEntry : map - .entrySet()) { - if (stringWrapperUUIDEntry.getKey().value.toLowerCase() - .startsWith(line.toLowerCase())) { - uuid = stringWrapperUUIDEntry.getValue(); - break; - } - } - } - if (uuid == null) { - uuid = UUIDHandler.getUUID(line, null); - } - if (uuid != null) { - MainUtil.sendMessage(player, - " - &aFound plot: " + plot.getId() + " : " + line); - plot.setOwner(uuid); - MainUtil.sendMessage(player, " - &8Updated plot: " + plot.getId()); - } else { - MainUtil.sendMessage(player, - " - &cInvalid PlayerName: " + plot.getId() + " : " + line); - } - } - } - }).join(); - } - }).thenRun(() -> MainUtil.sendMessage(player, "&3Sign Block&8->&3Plot&8: Finished scan.")); - return true; - } -} diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java b/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java index 9cca145a5..1eedabb71 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java @@ -27,6 +27,7 @@ package com.plotsquared.core.command; import com.google.common.base.Charsets; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.world.PlotAreaManager; @@ -35,7 +36,6 @@ import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.io.File; import java.util.UUID; @@ -76,7 +76,8 @@ public class DebugImportWorlds extends Command { if (name.length() > 16) { uuid = UUID.fromString(name); } else { - uuid = UUIDHandler.getUUID(name, null); + Captions.FETCHING_PLAYER.send(player); + uuid = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(name, 60000L); } if (uuid == null) { uuid = diff --git a/Core/src/main/java/com/plotsquared/core/command/Deny.java b/Core/src/main/java/com/plotsquared/core/command/Deny.java index d591bfa1a..072975226 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Deny.java +++ b/Core/src/main/java/com/plotsquared/core/command/Deny.java @@ -34,10 +34,8 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.world.gamemode.GameModes; -import java.util.Set; import java.util.UUID; @CommandDeclaration(command = "deny", @@ -68,48 +66,46 @@ public class Deny extends SubCommand { MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); return true; } - Set uuids = MainUtil.getUUIDsFromString(args[0]); - if (uuids.isEmpty()) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); - return false; - } - for (UUID uuid : uuids) { - if (uuid == DBFunc.EVERYONE && !( - Permissions.hasPermission(player, Captions.PERMISSION_DENY_EVERYONE) || Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_DENY))) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); - continue; - } - if (plot.isOwner(uuid)) { - MainUtil.sendMessage(player, Captions.CANT_REMOVE_OWNER, MainUtil.getName(uuid)); - return false; - } - if (plot.getDenied().contains(uuid)) { - MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); - return false; - } - if (uuid != DBFunc.EVERYONE) { - plot.removeMember(uuid); - plot.removeTrusted(uuid); - } - plot.addDenied(uuid); - PlotSquared.get().getEventDispatcher().callDenied(player, plot, uuid, true); - if (!uuid.equals(DBFunc.EVERYONE)) { - handleKick(UUIDHandler.getPlayer(uuid), plot); + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + if (throwable != null || uuids.isEmpty()) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); } else { - for (PlotPlayer plotPlayer : plot.getPlayersInPlot()) { - // Ignore plot-owners - if (plot.isAdded(plotPlayer.getUUID())) { - continue; + for (UUID uuid : uuids) { + if (uuid == DBFunc.EVERYONE && !( + Permissions.hasPermission(player, Captions.PERMISSION_DENY_EVERYONE) || Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_DENY))) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); + } else if (plot.isOwner(uuid)) { + MainUtil.sendMessage(player, Captions.CANT_REMOVE_OWNER, MainUtil.getName(uuid)); + return; + } else if (plot.getDenied().contains(uuid)) { + MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); + return; + } else { + if (uuid != DBFunc.EVERYONE) { + plot.removeMember(uuid); + plot.removeTrusted(uuid); + } + plot.addDenied(uuid); + PlotSquared.get().getEventDispatcher().callDenied(player, plot, uuid, true); + if (!uuid.equals(DBFunc.EVERYONE)) { + handleKick(PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid), plot); + } else { + for (PlotPlayer plotPlayer : plot.getPlayersInPlot()) { + // Ignore plot-owners + if (plot.isAdded(plotPlayer.getUUID())) { + continue; + } + handleKick(plotPlayer, plot); + } + } } - handleKick(plotPlayer, plot); } + MainUtil.sendMessage(player, Captions.DENIED_ADDED); } - } - if (!uuids.isEmpty()) { - MainUtil.sendMessage(player, Captions.DENIED_ADDED); - } + }); + return true; } diff --git a/Core/src/main/java/com/plotsquared/core/command/Merge.java b/Core/src/main/java/com/plotsquared/core/command/Merge.java index 480112c14..7998e3a84 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Merge.java +++ b/Core/src/main/java/com/plotsquared/core/command/Merge.java @@ -172,7 +172,7 @@ public class Merge extends SubCommand { MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); return false; } else { - uuid = plot.guessOwner(); + uuid = plot.getOwnerAbs(); } } if (!force && EconHandler.manager != null && plotArea.useEconomy() && price > 0d diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 372130a2d..0c31076f2 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -38,14 +38,16 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; @CommandDeclaration(command = "visit", permission = "plots.visit", @@ -71,10 +73,71 @@ public class Visit extends Command { if (args.length == 1 && args[0].contains(":")) { args = args[0].split(":"); } - int page = Integer.MIN_VALUE; - Collection unsorted = null; - PlotArea sortByArea = player.getApplicablePlotArea(); - boolean shouldSortByArea = Settings.Teleport.PER_WORLD_VISIT; + + final Collection unsortedPre = new HashSet<>(); + final PlotArea[] sortByArea = new PlotArea[] {player.getApplicablePlotArea()}; + final AtomicBoolean shouldSortByArea = new AtomicBoolean(Settings.Teleport.PER_WORLD_VISIT); + + final Consumer pageConsumer = page -> { + if (page == Integer.MIN_VALUE) { + page = 1; + } + if (unsortedPre.isEmpty()) { + Captions.FOUND_NO_PLOTS.send(player); + } else { + final Collection unsorted = new ArrayList<>(unsortedPre); + if (unsorted.size() > 1) { + unsorted.removeIf(plot -> !plot.isBasePlot()); + } + if (page < 1 || page > unsorted.size()) { + Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); + } else { + List plots; + if (shouldSortByArea.get()) { + plots = PlotSquared.get().sortPlots(unsorted, PlotSquared.SortType.CREATION_DATE, sortByArea[0]); + } else { + plots = PlotSquared.get().sortPlotsByTemp(unsorted); + } + final Plot plot = plots.get(page - 1); + if (!plot.hasOwner()) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_UNOWNED); + return; + } + } else if (plot.isOwner(player.getUUID())) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions.hasPermission(player, Captions.PERMISSION_HOME)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED); + return; + } + } else if (plot.isAdded(player.getUUID())) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_SHARED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_SHARED); + return; + } + } else { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OTHER)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OTHER); + return; + } + if (!plot.getFlag(UntrustedVisitFlag.class) && !Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED); + return; + } + } + confirm.run(this, + () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { + if (result) { + whenDone.run(Visit.this, CommandResult.SUCCESS); + } else { + whenDone.run(Visit.this, CommandResult.FAILURE); + } + }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); + } + } + }; + + final int[] page = new int[]{Integer.MIN_VALUE}; + switch (args.length) { case 3: if (!MathMan.isInteger(args[1])) { @@ -82,109 +145,66 @@ public class Visit extends Command { Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } - page = Integer.parseInt(args[2]); + page[0] = Integer.parseInt(args[2]); case 2: - if (page != Integer.MIN_VALUE || !MathMan.isInteger(args[1])) { - sortByArea = PlotSquared.get().getPlotAreaByString(args[1]); - if (sortByArea == null) { + if (page[0] != Integer.MIN_VALUE || !MathMan.isInteger(args[1])) { + sortByArea[0] = PlotSquared.get().getPlotAreaByString(args[1]); + if (sortByArea[0] == null) { Captions.NOT_VALID_NUMBER.send(player, "(1, ∞)"); Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } - UUID user = UUIDHandler.getUUIDFromString(args[0]); - if (user == null) { - Captions.COMMAND_SYNTAX.send(player, getUsage()); - return CompletableFuture.completedFuture(false); - } - unsorted = PlotSquared.get().getBasePlots(user); - shouldSortByArea = true; + + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + if (throwable != null || uuids.size() != 1) { + Captions.COMMAND_SYNTAX.send(player, getUsage()); + } else { + unsortedPre.addAll(PlotSquared.get().getBasePlots((UUID) uuids.toArray()[0])); + shouldSortByArea.set(true); + pageConsumer.accept(page[0]); + } + }); break; } - page = Integer.parseInt(args[1]); + page[0] = Integer.parseInt(args[1]); case 1: - UUID user = args[0].length() >= 2 ? UUIDHandler.getUUIDFromString(args[0]) : null; - if (user != null && !PlotSquared.get().hasPlot(user)) { - user = null; - } - if (page == Integer.MIN_VALUE && user == null && MathMan.isInteger(args[0])) { - page = Integer.parseInt(args[0]); - unsorted = PlotSquared.get().getBasePlots(player); - break; - } - if (user != null) { - unsorted = PlotSquared.get().getBasePlots(user); - } else { - Plot plot = MainUtil.getPlotFromString(player, args[0], true); - if (plot != null) { - unsorted = Collections.singletonList(plot.getBasePlot(false)); + final String[] finalArgs = args; + final Consumer uuidConsumer = uuid -> { + if (page[0] == Integer.MIN_VALUE && uuid == null && MathMan.isInteger(finalArgs[0])) { + page[0] = Integer.parseInt(finalArgs[0]); + unsortedPre.addAll(PlotSquared.get().getBasePlots(player)); + } else { + if (uuid != null) { + unsortedPre.addAll(PlotSquared.get().getBasePlots(uuid)); + } else { + Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); + if (plot != null) { + unsortedPre.addAll(Collections.singletonList(plot.getBasePlot(false))); + } + } } + pageConsumer.accept(page[0]); + }; + + if (args[0].length() >= 2) { + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(args[0], (uuid, throwable) -> { + if (uuid != null && !PlotSquared.get().hasPlot(uuid)) { + uuidConsumer.accept(null); + } else { + uuidConsumer.accept(uuid); + } + }); + } else { + uuidConsumer.accept(null); } break; case 0: - page = 1; - unsorted = PlotSquared.get().getPlots(player); + unsortedPre.addAll(PlotSquared.get().getPlots(player)); + pageConsumer.accept(1); break; default: } - if (page == Integer.MIN_VALUE) { - page = 1; - } - if (unsorted == null || unsorted.isEmpty()) { - Captions.FOUND_NO_PLOTS.send(player); - return CompletableFuture.completedFuture(false); - } - unsorted = new ArrayList<>(unsorted); - if (unsorted.size() > 1) { - unsorted.removeIf(plot -> !plot.isBasePlot()); - } - if (page < 1 || page > unsorted.size()) { - Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); - return CompletableFuture.completedFuture(false); - } - List plots; - if (shouldSortByArea) { - plots = PlotSquared.get() - .sortPlots(unsorted, PlotSquared.SortType.CREATION_DATE, sortByArea); - } else { - plots = PlotSquared.get().sortPlotsByTemp(unsorted); - } - final Plot plot = plots.get(page - 1); - if (!plot.hasOwner()) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_UNOWNED); - return CompletableFuture.completedFuture(false); - } - } else if (plot.isOwner(player.getUUID())) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions - .hasPermission(player, Captions.PERMISSION_HOME)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED); - return CompletableFuture.completedFuture(false); - } - } else if (plot.isAdded(player.getUUID())) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_SHARED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_SHARED); - return CompletableFuture.completedFuture(false); - } - } else { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OTHER)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OTHER); - return CompletableFuture.completedFuture(false); - } - if (!plot.getFlag(UntrustedVisitFlag.class) && !Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED); - return CompletableFuture.completedFuture(false); - } - } - confirm.run(this, () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { - if (result) { - whenDone.run(Visit.this, CommandResult.SUCCESS); - } else { - whenDone.run(Visit.this, CommandResult.FAILURE); - } - }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); - return CompletableFuture.completedFuture(true); } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 6238ec066..9d9251c61 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -450,6 +450,7 @@ public enum Captions implements Caption { // DEBUG_REPORT_CREATED("$1Uploaded a full debug to: $1%url%", "Paste"), PURGE_SUCCESS("$4Successfully purged %s plots", "Purge"), + FETCHING_PLAYER("$1PlotSquared is attempting to find the specified player from your argument(s). This may take a while.", "Players"), // TRIM_IN_PROGRESS("A world trim task is already in progress!", "Trim"), // diff --git a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java index 08133387e..5a4e43142 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -61,7 +61,6 @@ import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; import com.sk89q.worldedit.world.item.ItemType; @@ -161,7 +160,7 @@ public class PlotListener { if (plot.getFlag(NotifyEnterFlag.class)) { if (!Permissions.hasPermission(player, "plots.flag.notify-enter.bypass")) { for (UUID uuid : plot.getOwners()) { - PlotPlayer owner = UUIDHandler.getPlayer(uuid); + final PlotPlayer owner = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); if (owner != null && !owner.getUUID().equals(player.getUUID())) { MainUtil.sendMessage(owner, Captions.NOTIFY_ENTER.getTranslated() .replace("%player", player.getName()) @@ -337,7 +336,7 @@ public class PlotListener { if (plot.getFlag(NotifyLeaveFlag.class)) { if (!Permissions.hasPermission(player, "plots.flag.notify-enter.bypass")) { for (UUID uuid : plot.getOwners()) { - PlotPlayer owner = UUIDHandler.getPlayer(uuid); + final PlotPlayer owner = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); if ((owner != null) && !owner.getUUID().equals(player.getUUID())) { MainUtil.sendMessage(owner, Captions.NOTIFY_LEAVE.getTranslated() .replace("%player", player.getName()) diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java index 911c56adb..586809880 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -49,7 +49,6 @@ import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.item.ItemType; @@ -108,17 +107,6 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { return PlotSquared.get().IMP.wrapPlayer(player); } - /** - * Get the cached PlotPlayer from a username
- * - This will return null if the player has not finished logging in or is not online - * - * @param name - * @return - */ - public static PlotPlayer get(String name) { - return UUIDHandler.getPlayer(name); - } - public abstract Actor toActor(); /** @@ -363,8 +351,6 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { /** * Get this player's full location (including yaw/pitch) - * - * @return */ public abstract Location getLocationFull(); @@ -563,11 +549,10 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { plot.getId(), getName())); } } - String name = getName(); if (ExpireManager.IMP != null) { ExpireManager.IMP.storeDate(getUUID(), System.currentTimeMillis()); } - UUIDHandler.getPlayers().remove(name); + PlotSquared.imp().getPlayerManager().removePlayer(this); PlotSquared.get().IMP.unregister(this); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 9461219ef..e7cfbcafd 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -25,7 +25,6 @@ */ package com.plotsquared.core.plot; -import com.google.common.collect.BiMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; import com.plotsquared.core.PlotSquared; @@ -56,17 +55,14 @@ import com.plotsquared.core.plot.flag.implementations.KeepFlag; import com.plotsquared.core.plot.schematic.Schematic; import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.LocalBlockQueue; -import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.SchematicHandler; -import com.plotsquared.core.util.StringWrapper; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector2; @@ -83,7 +79,6 @@ import java.awt.geom.PathIterator; import java.awt.geom.Rectangle2D; import java.io.File; import java.net.URL; -import java.nio.charset.StandardCharsets; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; @@ -405,11 +400,10 @@ public class Plot { * @return list of PlotPlayer(s) or an empty list */ public List getPlayersInPlot() { - ArrayList players = new ArrayList<>(); - for (Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer plotPlayer = entry.getValue(); - if (this.equals(plotPlayer.getCurrentPlot())) { - players.add(plotPlayer); + final List players = new ArrayList<>(); + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { + if (this.equals(player.getCurrentPlot())) { + players.add(player); } } return players; @@ -1717,12 +1711,7 @@ public class Plot { this.setSign("unknown"); return; } - String name = UUIDHandler.getName(this.getOwnerAbs()); - if (name == null) { - this.setSign("unknown"); - } else { - this.setSign(name); - } + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(this.getOwnerAbs(), this::setSign); } /** @@ -2372,7 +2361,6 @@ public class Plot { * Check if a plot can be claimed by the provided player. * * @param player the claiming player - * @return */ public boolean canClaim(@NotNull PlotPlayer player) { PlotCluster cluster = this.getCluster(); @@ -2382,81 +2370,13 @@ public class Plot { return false; } } - final UUID owner = this.guessOwner(); + final UUID owner = this.getOwnerAbs(); if (owner != null) { return false; } return !isMerged(); } - /** - * Guess the owner of a plot either by the value in memory, or the sign data
- * Note: Recovering from sign information is useful if e.g. PlotMe conversion wasn't successful - * - * @return UUID - */ - public UUID guessOwner() { - if (this.hasOwner()) { - return this.getOwnerAbs(); - } - if (!this.area.allowSigns() || !Settings.Enabled_Components.GUESS_PLOT_OWNER) { - return null; - } - try { - final Location location = this.getManager().getSignLoc(this); - String[] lines = TaskManager.IMP.sync(new RunnableVal() { - @Override public void run(String[] value) { - ChunkManager.manager - .loadChunk(location.getWorld(), location.getBlockVector2(), false); - this.value = WorldUtil.IMP.getSignSynchronous(location); - } - }); - if (lines == null) { - return null; - } - loop: - for (int i = 4; i > 0; i--) { - String caption = Captions.valueOf("OWNER_SIGN_LINE_" + i).getTranslated(); - int index = caption.indexOf("%plr%"); - if (index < 0) { - continue; - } - String line = lines[i - 1]; - if (line.length() <= index) { - return null; - } - String name = line.substring(index); - if (name.isEmpty()) { - return null; - } - UUID owner = UUIDHandler.getUUID(name, null); - if (owner != null) { - this.setOwnerAbs(owner); - break; - } - if (lines[i - 1].length() == 15) { - BiMap map = UUIDHandler.getUuidMap(); - for (Entry entry : map.entrySet()) { - String key = entry.getKey().value; - if (key.length() > name.length() && key.startsWith(name)) { - this.setOwnerAbs(entry.getValue()); - break loop; - } - } - } - this.setOwnerAbs(UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8))); - break; - } - if (this.hasOwner()) { - this.create(); - } - return this.getOwnerAbs(); - } catch (IllegalArgumentException ignored) { - return null; - } - } - /** * Remove the south road section of a plot
* - Used when a plot is merged
@@ -3099,10 +3019,12 @@ public class Plot { return false; } if (!isMerged()) { - return UUIDHandler.getPlayer(this.getOwnerAbs()) != null; + return PlotSquared.imp().getPlayerManager() + .getPlayerIfExists(Objects.requireNonNull(this.getOwnerAbs())) != null; } for (final Plot current : getConnectedPlots()) { - if (current.hasOwner() && UUIDHandler.getPlayer(current.getOwnerAbs()) != null) { + if (current.hasOwner() && PlotSquared.imp().getPlayerManager() + .getPlayerIfExists(Objects.requireNonNull(current.getOwnerAbs())) != null) { return true; } } @@ -3114,9 +3036,9 @@ public class Plot { * - E.g. floor, wall, border etc.
* - The available components depend on the generator being used
* - * @param component - * @param blocks - * @return + * @param component Component to set + * @param blocks Pattern to use the generation + * @return True if the component was set successfully */ public boolean setComponent(String component, Pattern blocks) { PlotComponentSetEvent event = diff --git a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java index 93cb7b3e4..4e887fead 100644 --- a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java @@ -49,7 +49,7 @@ import com.plotsquared.core.plot.flag.types.DoubleFlag; import com.plotsquared.core.util.net.AbstractDelegateOutputStream; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; +import com.plotsquared.core.uuid.UUIDMapping; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; @@ -73,6 +73,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -81,6 +82,7 @@ import java.util.Optional; import java.util.Scanner; import java.util.Set; import java.util.UUID; +import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.IntConsumer; import java.util.function.IntFunction; @@ -99,12 +101,6 @@ public class MainUtil { FLAG_DECIMAL_FORMAT.setMaximumFractionDigits(340); } - /** - * If the NMS code for sending chunk updates is functional
- * - E.g. If using an older version of Bukkit, or before the plugin is updated to 1.5
- * - Slower fallback code will be used if not.
- */ - public static boolean canSendChunk = false; /** * Cache of mapping x,y,z coordinates to the chunk array
* - Used for efficient world generation
@@ -152,15 +148,6 @@ public class MainUtil { } } - public static void sendAdmin(final String s) { - for (final PlotPlayer player : UUIDHandler.getPlayers().values()) { - if (player.hasPermission(Captions.PERMISSION_ADMIN.getTranslated())) { - player.sendMessage(Captions.color(s)); - } - } - PlotSquared.debug(s); - } - public static void upload(UUID uuid, String file, String extension, final RunnableVal writeTask, final RunnableVal whenDone) { if (writeTask == null) { @@ -396,7 +383,7 @@ public class MainUtil { if (owner.equals(DBFunc.SERVER)) { return Captions.SERVER.getTranslated(); } - String name = UUIDHandler.getName(owner); + String name = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(owner, 10L); if (name == null) { return Captions.UNKNOWN.getTranslated(); } @@ -467,7 +454,7 @@ public class MainUtil { for (String term : split) { try { - UUID uuid = UUIDHandler.getUUID(term, null); + UUID uuid = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(term, 10L); if (uuid == null) { uuid = UUID.fromString(term); } @@ -738,33 +725,44 @@ public class MainUtil { return ratings; } - public static Set getUUIDsFromString(String list) { + public static void getUUIDsFromString(final String list, final BiConsumer, Throwable> consumer) { String[] split = list.split(","); - HashSet result = new HashSet<>(); - for (String name : split) { + + final Set result = new HashSet<>(); + final List request = new LinkedList<>(); + + for (final String name : split) { if (name.isEmpty()) { - // Invalid - return Collections.emptySet(); - } - if ("*".equals(name)) { + consumer.accept(Collections.emptySet(), null); + return; + } else if ("*".equals(name)) { result.add(DBFunc.EVERYONE); - continue; - } - if (name.length() > 16) { + } else if (name.length() > 16) { try { result.add(UUID.fromString(name)); - continue; } catch (IllegalArgumentException ignored) { - return Collections.emptySet(); + consumer.accept(Collections.emptySet(), null); + return; } + } else { + request.add(name); } - UUID uuid = UUIDHandler.getUUID(name, null); - if (uuid == null) { - return Collections.emptySet(); - } - result.add(uuid); } - return result; + + if (request.isEmpty()) { + consumer.accept(result, null); + } else { + PlotSquared.get().getImpromptuUUIDPipeline().getUUIDs(request).whenComplete((uuids, throwable) -> { + if (throwable != null) { + consumer.accept(null, throwable); + } else { + for (final UUIDMapping uuid : uuids) { + result.add(uuid.getUuid()); + } + consumer.accept(result, null); + } + }); + } } /** @@ -931,7 +929,7 @@ public class MainUtil { public static void getPersistentMeta(UUID uuid, final String key, final RunnableVal result) { - PlotPlayer player = UUIDHandler.getPlayer(uuid); + PlotPlayer player = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); if (player != null) { result.run(player.getPersistentMeta(key)); } else { diff --git a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java new file mode 100644 index 000000000..fd1eebe4e --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java @@ -0,0 +1,120 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util; + +import com.plotsquared.core.player.PlotPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Manages player instances + */ +public abstract class PlayerManager { + + private final Map playerMap = new HashMap<>(); + private final Object playerLock = new Object(); + + /** + * Remove a player from the player map + * + * @param plotPlayer Player to remove + */ + public void removePlayer(@NotNull final PlotPlayer plotPlayer) { + synchronized (playerLock) { + this.playerMap.remove(plotPlayer.getUUID()); + } + } + + /** + * Get the player from its UUID if it is stored in the player map. + * + * @param uuid Player UUID + * @return Player, or null + */ + @Nullable public PlotPlayer getPlayerIfExists(@Nullable final UUID uuid) { + if (uuid == null) { + return null; + } + return this.playerMap.get(uuid); + } + + @Nullable public PlotPlayer getPlayerIfExists(@Nullable final String name) { + for (final PlotPlayer plotPlayer : this.playerMap.values()) { + if (plotPlayer.getName().equalsIgnoreCase(name)) { + return plotPlayer; + } + } + return null; + } + + /** + * Get a plot player from a UUID. This method requires + * that the caller actually knows that the player exists. + *

+ * The method will throw an exception if there is no such + * player online. + * + * @param uuid Player UUID + * @return Player object + */ + @NotNull public PlotPlayer getPlayer(@NotNull final UUID uuid) { + synchronized (playerLock) { + PlotPlayer player = this.playerMap.get(uuid); + if (player == null) { + player = createPlayer(uuid); + this.playerMap.put(uuid, player); + } + return player; + } + } + + @NotNull protected abstract PlotPlayer createPlayer(@NotNull final UUID uuid); + + /** + * Get all online players + * + * @return Unmodifiable collection of players + */ + public Collection getPlayers() { + return Collections.unmodifiableCollection(this.playerMap.values()); + } + + + public static final class NoSuchPlayerException extends IllegalArgumentException { + + public NoSuchPlayerException(@NotNull final UUID uuid) { + super(String.format("There is no online player with UUID '%s'", uuid.toString())); + } + + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java index 3adb8d19e..aa9e7a04c 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java @@ -104,7 +104,7 @@ public abstract class SchematicHandler { Iterator i = plots.iterator(); final Plot plot = i.next(); i.remove(); - String owner = UUIDHandler.getName(plot.guessOwner()); + String owner = UUIDHandler.getName(plot.getOwnerAbs()); if (owner == null) { owner = "unknown"; } diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java new file mode 100644 index 000000000..a7c7c2a8f --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java @@ -0,0 +1,82 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.command.Command; +import com.plotsquared.core.command.CommandCategory; +import com.plotsquared.core.command.RequiredType; +import com.plotsquared.core.uuid.UUIDMapping; +import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * Tab completion utilities + */ +@UtilityClass public class TabCompletions { + + private final Cache> cachedCompletionValues = + CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); + + /** + * Get a list of tab completions corresponding to player names. This uses the UUID pipeline + * cache, so it will complete will all names known to PlotSquared + * + * @param input Command input + * @param existing Players that should not be included in completions + * @return List of completions + */ + @NotNull public List completePlayers(@NotNull final String input, + @NotNull final List existing) { + List players = cachedCompletionValues.getIfPresent("players"); + if (players == null) { + final Collection mappings = + PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); + players = new ArrayList<>(mappings.size()); + for (final UUIDMapping mapping : mappings) { + players.add(mapping.getUsername()); + } + cachedCompletionValues.put("players", players); + } + final String processedInput = input.toLowerCase(Locale.ENGLISH); + return players.stream() + .filter(player -> player.toLowerCase(Locale.ENGLISH).startsWith(processedInput)) + .filter(player -> !existing.contains(player)).map( + player -> new Command(null, false, player, "", RequiredType.NONE, + CommandCategory.INFO) { + }).collect(Collectors.toList()); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandler.java b/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandler.java deleted file mode 100644 index 6dd8b1c47..000000000 --- a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandler.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.util.uuid; - -import com.google.common.collect.BiMap; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.database.DBFunc; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.task.RunnableVal; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.UUID; - -public class UUIDHandler { - - public static UUIDHandlerImplementation implementation; - - public static void add(StringWrapper name, UUID uuid) { - implementation.add(name, uuid); - } - - /** - * Get the map containing all names/uuids. - * - * @return map with names + uuids - * @see BiMap - */ - public static BiMap getUuidMap() { - return implementation.getUUIDMap(); - } - - /** - * Check if a uuid is cached - * - * @param uuid to check - * @return true of the uuid is cached - * @see BiMap#containsValue(Object) - */ - public static boolean uuidExists(UUID uuid) { - return implementation.uuidExists(uuid); - } - - /** - * Check if a name is cached - * - * @param name to check - * @return true of the name is cached - * @see BiMap#containsKey(Object) - */ - public static boolean nameExists(StringWrapper name) { - return implementation.nameExists(name); - } - - public static HashSet getAllUUIDS() { - final HashSet uuids = new HashSet<>(); - PlotSquared.get().forEachPlotRaw(plot -> { - if (plot.hasOwner()) { - uuids.add(plot.getOwnerAbs()); - uuids.addAll(plot.getTrusted()); - uuids.addAll(plot.getMembers()); - uuids.addAll(plot.getDenied()); - } - }); - return uuids; - } - - public static UUIDWrapper getUUIDWrapper() { - return implementation.getUUIDWrapper(); - } - - public static void setUUIDWrapper(UUIDWrapper wrapper) { - implementation.setUUIDWrapper(wrapper); - } - - public static void startCaching(Runnable whenDone) { - implementation.startCaching(whenDone); - } - - public static void cache(BiMap toAdd) { - implementation.add(toAdd); - } - - @NotNull public static UUID getUUID(PlotPlayer player) { - return implementation.getUUID(player); - } - - public static UUID getUUID(OfflinePlotPlayer player) { - if (implementation == null) { - return null; - } - return implementation.getUUID(player); - } - - @Nullable public static String getName(UUID uuid) { - if (implementation == null) { - return null; - } - if (uuid != null && uuid.equals(DBFunc.SERVER)) { - return Captions.SERVER.getTranslated(); - } - return implementation.getName(uuid); - } - - @Nullable public static PlotPlayer getPlayer(@Nullable final UUID uuid) { - if (implementation == null || uuid == null) { - return null; - } - return check(implementation.getPlayer(uuid)); - } - - public static PlotPlayer getPlayer(String name) { - if (implementation == null) { - return null; - } - return check(implementation.getPlayer(name)); - } - - private static PlotPlayer check(@Nullable PlotPlayer player) { - if (player != null && !player.isOnline()) { - UUIDHandler.getPlayers().remove(player.getName()); - PlotSquared.get().IMP.unregister(player); - player = null; - } - return player; - } - - public static UUID getUUIDFromString(String nameOrUUIDString) { - if (implementation == null) { - return null; - } - if (nameOrUUIDString.length() > 16) { - try { - return UUID.fromString(nameOrUUIDString); - } catch (IllegalArgumentException e) { - return null; - } - } - return UUIDHandler.getUUID(nameOrUUIDString, null); - } - - public static UUID getUUID(String name, RunnableVal ifFetch) { - if (implementation == null) { - return null; - } - return implementation.getUUID(name, ifFetch); - } - - public static UUID getCachedUUID(String name, RunnableVal ifFetch) { - if (implementation == null) { - return null; - } - return implementation.getUUIDMap().get(new StringWrapper(name)); - } - - public static Map getPlayers() { - if (implementation == null) { - return new HashMap<>(); - } - return implementation.getPlayers(); - } - - public static void handleShutdown() { - if (implementation == null) { - return; - } - implementation.handleShutdown(); - } -} diff --git a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandlerImplementation.java b/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandlerImplementation.java deleted file mode 100644 index 687af58e0..000000000 --- a/Core/src/main/java/com/plotsquared/core/util/uuid/UUIDHandlerImplementation.java +++ /dev/null @@ -1,324 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.util.uuid; - -import com.google.common.base.Charsets; -import com.google.common.collect.BiMap; -import com.google.common.collect.HashBiMap; -import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; -import com.plotsquared.core.database.DBFunc; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.Plot; -import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.StringWrapper; -import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.task.TaskManager; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public abstract class UUIDHandlerImplementation { - - public final HashSet unknown = new HashSet<>(); - private final ConcurrentHashMap players; - protected UUIDWrapper uuidWrapper; - private boolean cached = false; - private BiMap uuidMap = HashBiMap.create(new HashMap<>()); - - public UUIDHandlerImplementation(UUIDWrapper wrapper) { - this.uuidWrapper = wrapper; - this.players = new ConcurrentHashMap<>(); - } - - /** - * If the UUID is not found, some commands can request to fetch the UUID when possible. - * - * @param name - * @param ifFetch - */ - public abstract void fetchUUID(String name, RunnableVal ifFetch); - - /** - * Start UUID caching (this should be an async task) - * Recommended to override this is you want to cache offline players - */ - public boolean startCaching(Runnable whenDone) { - if (this.cached) { - return false; - } - return this.cached = true; - } - - public UUIDWrapper getUUIDWrapper() { - return this.uuidWrapper; - } - - public void setUUIDWrapper(UUIDWrapper wrapper) { - this.uuidWrapper = wrapper; - } - - public void rename(UUID uuid, StringWrapper name) { - this.uuidMap.inverse().remove(uuid); - this.uuidMap.put(name, uuid); - } - - public void add(BiMap toAdd) { - if (this.uuidMap.isEmpty()) { - this.uuidMap = toAdd; - } - for (Map.Entry entry : toAdd.entrySet()) { - UUID uuid = entry.getValue(); - StringWrapper name = entry.getKey(); - if (uuid == null || name == null) { - continue; - } - StringWrapper oldName = this.uuidMap.inverse().get(uuid); - if (oldName != null) { - if (this.uuidMap.containsKey(name)) { - continue; - } - if (getPlayer(uuid) == null) { - rename(uuid, name); - } - continue; - } - this.uuidMap.put(name, uuid); - } - PlotSquared - .debug(Captions.PREFIX + "&6Cached a total of: " + this.uuidMap.size() + " UUIDs"); - } - - public boolean add(final StringWrapper name, final UUID uuid) { - if (uuid == null) { - PlotSquared.debug("UUID cannot be null!"); - return false; - } - if (name == null) { - try { - this.unknown.add(uuid); - } catch (Exception e) { - PlotSquared.log("&c(minor) Invalid UUID mapping: " + uuid); - e.printStackTrace(); - } - return false; - } - - /* - * lazy UUID conversion: - * - Useful if the person misconfigured the database, or settings before - * PlotMe conversion - */ - if (!Settings.UUID.OFFLINE && !this.unknown.isEmpty()) { - TaskManager.runTaskAsync(() -> { - UUID offline = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name.value).getBytes(Charsets.UTF_8)); - if (!UUIDHandlerImplementation.this.unknown.contains(offline) && !name.value - .equals(name.value.toLowerCase())) { - offline = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name.value.toLowerCase()).getBytes(Charsets.UTF_8)); - if (!UUIDHandlerImplementation.this.unknown.contains(offline)) { - offline = null; - } - } - if (offline != null && !offline.equals(uuid)) { - UUIDHandlerImplementation.this.unknown.remove(offline); - Set plots = PlotSquared.get().getPlotsAbs(offline); - if (!plots.isEmpty()) { - for (final Plot plot : plots) { - plot.setOwnerAbs(uuid); - } - DBFunc.replaceUUID(offline, uuid); - PlotSquared.debug("&cDetected invalid UUID stored for: " + name.value); - PlotSquared.debug( - "&7 - Did you recently switch to online-mode storage without running `uuidconvert`?"); - PlotSquared.debug("&6" + PlotSquared.imp().getPluginName() - + " will update incorrect entries when the user logs in, or you can reconstruct your database."); - } - } - }); - } else if (Settings.UUID.FORCE_LOWERCASE && !this.unknown.isEmpty() && !name.value - .equals(name.value.toLowerCase())) { - TaskManager.runTaskAsync(() -> { - UUID offlineUpper = UUID.nameUUIDFromBytes( - ("OfflinePlayer:" + name.value).getBytes(Charsets.UTF_8)); - if (UUIDHandlerImplementation.this.unknown.contains(offlineUpper) && !offlineUpper - .equals(uuid)) { - UUIDHandlerImplementation.this.unknown.remove(offlineUpper); - Set plots = PlotSquared.get().getPlotsAbs(offlineUpper); - if (!plots.isEmpty()) { - for (final Plot plot : plots) { - plot.setOwnerAbs(uuid); - } - replace(offlineUpper, uuid, name.value); - } - } - }); - } - try { - UUID existing = this.uuidMap.put(name, uuid); - if (existing != null) { - if (!existing.equals(uuid)) { - Set plots = PlotSquared.get().getPlots(existing); - if (!plots.isEmpty()) { - for (final Plot plot : plots) { - plot.setOwnerAbs(uuid); - } - replace(existing, uuid, name.value); - } - return true; - } else { - StringWrapper oName = this.uuidMap.inverse().get(existing); - if (!oName.equals(name)) { - this.uuidMap.remove(name); - this.uuidMap.put(name, uuid); - } - } - return false; - } - } catch (Exception ignored) { - BiMap inverse = this.uuidMap.inverse(); - StringWrapper oldName = inverse.get(uuid); - if (oldName != null) { - if (this.uuidMap.containsKey(name)) { - return false; - } - PlotPlayer player = getPlayer(uuid); - if (player == null || player.getName().equalsIgnoreCase(name.value)) { - rename(uuid, name); - return false; - } - StringWrapper newName = new StringWrapper(player.getName()); - UUID newUUID = player.getUUID(); - if (newUUID.equals(uuid) && !newName.equals(oldName)) { - inverse.remove(uuid); - this.uuidMap.put(newName, newUUID); - } - return false; - } - this.uuidMap.put(name, uuid); - } - return true; - } - - private void replace(UUID from, UUID to, String name) { - DBFunc.replaceUUID(from, to); - PlotSquared.debug("&cDetected invalid UUID stored for: " + name); - PlotSquared.debug( - "&7 - Did you recently switch to online-mode storage without running `uuidconvert`?"); - PlotSquared.debug("&6" + PlotSquared.imp().getPluginName() - + " will update incorrect entries when the user logs in, or you can reconstruct your database."); - } - - public boolean uuidExists(UUID uuid) { - return this.uuidMap.containsValue(uuid); - } - - public BiMap getUUIDMap() { - return this.uuidMap; - } - - public boolean nameExists(StringWrapper wrapper) { - return this.uuidMap.containsKey(wrapper); - } - - public void handleShutdown() { - this.players.clear(); - this.uuidMap.clear(); - } - - @Nullable public String getName(UUID uuid) { - if (uuid == null) { - return null; - } - StringWrapper name = this.uuidMap.inverse().get(uuid); - if (name != null) { - return name.value; - } - return null; - } - - @Nullable public UUID getUUID(String name, RunnableVal ifFetch) { - if (name.isEmpty()) { - return null; - } - // check online - PlotPlayer player = getPlayer(name); - if (player != null) { - return player.getUUID(); - } - // check cache - StringWrapper wrap = new StringWrapper(name); - UUID uuid = this.uuidMap.get(wrap); - if (uuid != null) { - return uuid; - } - // Read from disk OR convert directly to offline UUID - if (Settings.UUID.OFFLINE && !StringMan.contains(name, ';')) { - uuid = this.uuidWrapper.getUUID(name); - add(new StringWrapper(name), uuid); - return uuid; - } - if ((ifFetch != null)) { - fetchUUID(name, ifFetch); - return null; - } - return null; - } - - @NotNull public UUID getUUID(PlotPlayer player) { - return this.uuidWrapper.getUUID(player); - } - - public UUID getUUID(OfflinePlotPlayer player) { - return this.uuidWrapper.getUUID(player); - } - - @Nullable public PlotPlayer getPlayer(UUID uuid) { - String name = getName(uuid); - if (name != null) { - return getPlayer(name); - } - return null; - } - - public PlotPlayer getPlayer(String name) { - return this.players.get(name); - } - - public Map getPlayers() { - return this.players; - } - -} diff --git a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java index 81a42bacd..32bbbb6bc 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java @@ -30,6 +30,7 @@ import com.google.common.cache.CacheBuilder; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.function.Consumer; @@ -73,4 +74,8 @@ public class CacheUUIDService implements UUIDService, Consumer } } + @Override @NotNull public Collection getImmediately() { + return this.usernameCache.asMap().values(); + } + } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java index 798d586ff..35a4c6c2c 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDMapping.java @@ -25,6 +25,7 @@ */ package com.plotsquared.core.uuid; +import lombok.EqualsAndHashCode; import org.jetbrains.annotations.NotNull; import java.util.UUID; @@ -32,7 +33,7 @@ import java.util.UUID; /** * A pair consisting of a UUID and a username */ -public class UUIDMapping { +@EqualsAndHashCode public class UUIDMapping { private final UUID uuid; private final String username; diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 7add9ef8a..6d85db51f 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -35,13 +35,16 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.BiConsumer; import java.util.function.Consumer; /** @@ -181,10 +184,16 @@ public class UUIDPipeline { * @param username Username * @param uuid UUID consumer */ - public void getSingle(@NotNull final String username, @NotNull final Consumer uuid) { - this.getUUIDs(Collections.singletonList(username)).thenAccept(uuids -> { - if (!uuids.isEmpty()) { - uuid.accept(uuids.get(0).getUuid()); + public void getSingle(@NotNull final String username, @NotNull final BiConsumer uuid) { + this.getUUIDs(Collections.singletonList(username)).whenComplete((uuids, throwable) -> { + if (throwable != null) { + uuid.accept(null, throwable); + } else { + if (!uuids.isEmpty()) { + uuid.accept(uuids.get(0).getUuid(), null); + } else { + uuid.accept(null, null); + } } }); } @@ -195,10 +204,16 @@ public class UUIDPipeline { * @param uuid UUID * @param username Username consumer */ - public void getSingle(@NotNull final UUID uuid, @NotNull final Consumer username) { - this.getNames(Collections.singletonList(uuid)).thenAccept(uuids -> { - if (!uuids.isEmpty()) { - username.accept(uuids.get(0).getUsername()); + public void getSingle(@NotNull final UUID uuid, @NotNull final BiConsumer username) { + this.getNames(Collections.singletonList(uuid)).whenComplete((uuids, throwable) -> { + if (throwable != null) { + username.accept(null, throwable); + } else { + if (!uuids.isEmpty()) { + username.accept(uuids.get(0).getUsername(), null); + } else { + username.accept(null, null); + } } }); } @@ -274,4 +289,18 @@ public class UUIDPipeline { }, this.executor); } + /** + * Get as many UUID mappings as possible under the condition + * that the operation cannot be blocking (for an extended amount of time) + * + * @return All mappings that could be provided immediately + */ + @NotNull public final Collection getAllImmediately() { + final Set mappings = new LinkedHashSet<>(); + for (final UUIDService service : this.getServiceListInstance()) { + mappings.addAll(service.getImmediately()); + } + return mappings; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java index 468de09b2..25588305e 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java @@ -27,6 +27,8 @@ package com.plotsquared.core.uuid; import org.jetbrains.annotations.NotNull; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.UUID; @@ -53,4 +55,14 @@ public interface UUIDService { */ @NotNull List getUUIDs(@NotNull final List usernames); + /** + * Get as many UUID mappings as possible under the condition + * that the operation cannot be blocking (for an extended amount of time) + * + * @return All mappings that could be provided immediately + */ + default @NotNull Collection getImmediately() { + return Collections.emptyList(); + } + } diff --git a/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java b/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java index 291461478..9bcad05bd 100644 --- a/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java +++ b/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java @@ -28,15 +28,14 @@ package com.plotsquared.core.plot.util; import com.plotsquared.core.database.AbstractDBTest; import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.uuid.UUIDHandlerImplementation; -import com.plotsquared.core.util.uuid.UUIDWrapper; +import com.plotsquared.core.util.uuid.OfflinePlayerService; import org.junit.Before; import java.util.UUID; public class UUIDHandlerImplementationTest extends UUIDHandlerImplementation { - public UUIDHandlerImplementationTest(UUIDWrapper wrapper) { + public UUIDHandlerImplementationTest(OfflinePlayerService wrapper) { super(wrapper); } From 123ca8efe9133c57e7aca017fea21f078c510811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 19 May 2020 17:33:59 +0200 Subject: [PATCH 016/121] Update more commands and add proper request timeouts --- .../bukkit/placeholder/Placeholders.java | 4 +- .../com/plotsquared/core/PlotSquared.java | 4 +- .../com/plotsquared/core/command/Add.java | 8 +- .../com/plotsquared/core/command/Alias.java | 6 +- .../com/plotsquared/core/command/Cluster.java | 47 ++++--- .../com/plotsquared/core/command/Deny.java | 5 +- .../com/plotsquared/core/command/Remove.java | 120 ++++++++---------- .../com/plotsquared/core/command/Trust.java | 104 ++++++++------- .../com/plotsquared/core/command/Visit.java | 9 +- .../core/configuration/Captions.java | 1 + .../core/configuration/Settings.java | 4 + .../com/plotsquared/core/util/MainUtil.java | 7 +- .../plotsquared/core/uuid/UUIDPipeline.java | 54 +++++++- 13 files changed, 226 insertions(+), 147 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java index f8a155d21..0ae44fbcb 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java @@ -26,6 +26,7 @@ package com.plotsquared.bukkit.placeholder; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import me.clip.placeholderapi.PlaceholderAPIPlugin; @@ -123,7 +124,8 @@ public class Placeholders extends PlaceholderExpansion { return ""; } - String name = PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(uid, 5L); + String name = PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(uid, + Settings.UUID.BLOCKING_TIMEOUT); if (name != null) { return name; diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index a19f167d7..67c5cab90 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -963,7 +963,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlots(String world, String player) { - final UUID uuid = this.impromptuUUIDPipeline.getSingle(player, 10L); + final UUID uuid = this.impromptuUUIDPipeline.getSingle(player, Settings.UUID.BLOCKING_TIMEOUT); return getPlots(world, uuid); } @@ -975,7 +975,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlots(PlotArea area, String player) { - final UUID uuid = this.impromptuUUIDPipeline.getSingle(player, 10L); + final UUID uuid = this.impromptuUUIDPipeline.getSingle(player, Settings.UUID.BLOCKING_TIMEOUT); return getPlots(area, uuid); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Add.java b/Core/src/main/java/com/plotsquared/core/command/Add.java index 32750f8d9..bbd0b5559 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Add.java +++ b/Core/src/main/java/com/plotsquared/core/command/Add.java @@ -38,6 +38,7 @@ import com.plotsquared.core.util.task.RunnableVal3; import java.util.Iterator; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; @CommandDeclaration(command = "add", description = "Allow a user to build in a plot while the plot owner is online.", @@ -65,7 +66,11 @@ public class Add extends Command { final CompletableFuture future = new CompletableFuture<>(); MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { if (throwable != null) { - Captions.INVALID_PLAYER.send(player, args[0]); + if (throwable instanceof TimeoutException) { + Captions.FETCHING_PLAYERS_TIMEOUT.send(player); + } else { + Captions.INVALID_PLAYER.send(player, args[0]); + } future.completeExceptionally(throwable); return; } else { @@ -121,4 +126,5 @@ public class Add extends Command { }); return future; } + } diff --git a/Core/src/main/java/com/plotsquared/core/command/Alias.java b/Core/src/main/java/com/plotsquared/core/command/Alias.java index 1df9848d0..3f1273014 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Alias.java +++ b/Core/src/main/java/com/plotsquared/core/command/Alias.java @@ -34,6 +34,8 @@ import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; +import java.util.concurrent.TimeoutException; + @CommandDeclaration(command = "setalias", permission = "plots.alias", description = "Set the plot name", @@ -115,7 +117,9 @@ public class Alias extends SubCommand { } } PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> { - if (uuid != null) { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (uuid != null) { MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); } else { plot.setAlias(alias); diff --git a/Core/src/main/java/com/plotsquared/core/command/Cluster.java b/Core/src/main/java/com/plotsquared/core/command/Cluster.java index 82f602493..c9ce3d5ef 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Cluster.java +++ b/Core/src/main/java/com/plotsquared/core/command/Cluster.java @@ -44,6 +44,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.concurrent.TimeoutException; @CommandDeclaration(command = "cluster", aliases = "clusters", @@ -373,7 +374,9 @@ public class Cluster extends SubCommand { PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(args[1], (uuid, throwable) -> { - if (throwable != null) { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (throwable != null) { MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[1]); } else { if (!cluster.isAdded(uuid)) { @@ -426,7 +429,9 @@ public class Cluster extends SubCommand { // check uuid PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(args[1], (uuid, throwable) -> { - if (throwable != null) { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (throwable != null) { MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[1]); } else { // Can't kick if the player is yourself, the owner, or not added to the cluster @@ -542,7 +547,9 @@ public class Cluster extends SubCommand { PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(args[2], (uuid, throwable) -> { - if (throwable != null) { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (throwable != null) { MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[2]); } else { if (args[1].equalsIgnoreCase("add")) { @@ -631,23 +638,27 @@ public class Cluster extends SubCommand { PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(cluster.owner, (username, throwable) -> { - final String owner; - if (username == null) { - owner = "unknown"; + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); } else { - owner = username; + final String owner; + if (username == null) { + owner = "unknown"; + } else { + owner = username; + } + String name = cluster.getName(); + String size = (cluster.getP2().x - cluster.getP1().x + 1) + "x" + ( + cluster.getP2().y - cluster.getP1().y + 1); + String rights = cluster.isAdded(player.getUUID()) + ""; + String message = Captions.CLUSTER_INFO.getTranslated(); + message = message.replaceAll("%id%", id); + message = message.replaceAll("%owner%", owner); + message = message.replaceAll("%name%", name); + message = message.replaceAll("%size%", size); + message = message.replaceAll("%rights%", rights); + MainUtil.sendMessage(player, message); } - String name = cluster.getName(); - String size = (cluster.getP2().x - cluster.getP1().x + 1) + "x" + ( - cluster.getP2().y - cluster.getP1().y + 1); - String rights = cluster.isAdded(player.getUUID()) + ""; - String message = Captions.CLUSTER_INFO.getTranslated(); - message = message.replaceAll("%id%", id); - message = message.replaceAll("%owner%", owner); - message = message.replaceAll("%name%", name); - message = message.replaceAll("%size%", size); - message = message.replaceAll("%rights%", rights); - MainUtil.sendMessage(player, message); }); return true; } diff --git a/Core/src/main/java/com/plotsquared/core/command/Deny.java b/Core/src/main/java/com/plotsquared/core/command/Deny.java index 072975226..3cf742f0c 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Deny.java +++ b/Core/src/main/java/com/plotsquared/core/command/Deny.java @@ -37,6 +37,7 @@ import com.plotsquared.core.util.WorldUtil; import com.sk89q.worldedit.world.gamemode.GameModes; import java.util.UUID; +import java.util.concurrent.TimeoutException; @CommandDeclaration(command = "deny", aliases = {"d", "ban"}, @@ -68,7 +69,9 @@ public class Deny extends SubCommand { } MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { - if (throwable != null || uuids.isEmpty()) { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (throwable != null || uuids.isEmpty()) { MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); } else { for (UUID uuid : uuids) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Remove.java b/Core/src/main/java/com/plotsquared/core/command/Remove.java index 2ed34aca9..1a079f709 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Remove.java +++ b/Core/src/main/java/com/plotsquared/core/command/Remove.java @@ -33,12 +33,9 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; -import com.plotsquared.core.util.uuid.UUIDHandler; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; +import java.util.concurrent.TimeoutException; @CommandDeclaration(command = "remove", aliases = {"r", "untrust", "ut", "undeny", "unban", "ud"}, @@ -68,74 +65,59 @@ public class Remove extends SubCommand { MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); return true; } - int count = 0; - switch (args[0]) { - case "unknown": { - HashSet all = new HashSet<>(); - all.addAll(plot.getMembers()); - all.addAll(plot.getTrusted()); - all.addAll(plot.getDenied()); - ArrayList toRemove = new ArrayList<>(); - for (UUID uuid : all) { - if (UUIDHandler.getName(uuid) == null) { - toRemove.add(uuid); - count++; - } - } - for (UUID uuid : toRemove) { - plot.removeDenied(uuid); - plot.removeTrusted(uuid); - plot.removeMember(uuid); - } - break; - } - default: - Set uuids = MainUtil.getUUIDsFromString(args[0]); - if (!uuids.isEmpty()) { - for (UUID uuid : uuids) { - if (plot.getTrusted().contains(uuid)) { - if (plot.removeTrusted(uuid)) { - PlotSquared.get().getEventDispatcher() - .callTrusted(player, plot, uuid, false); - count++; - } - } else if (plot.getMembers().contains(uuid)) { - if (plot.removeMember(uuid)) { - PlotSquared.get().getEventDispatcher() - .callMember(player, plot, uuid, false); - count++; - } - } else if (plot.getDenied().contains(uuid)) { - if (plot.removeDenied(uuid)) { - PlotSquared.get().getEventDispatcher() - .callDenied(player, plot, uuid, false); - count++; - } - } else if (uuid == DBFunc.EVERYONE) { - if (plot.removeTrusted(uuid)) { - PlotSquared.get().getEventDispatcher() - .callTrusted(player, plot, uuid, false); - count++; - } else if (plot.removeMember(uuid)) { - PlotSquared.get().getEventDispatcher() - .callMember(player, plot, uuid, false); - count++; - } else if (plot.removeDenied(uuid)) { - PlotSquared.get().getEventDispatcher() - .callDenied(player, plot, uuid, false); - count++; - } + + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + int count = 0; + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + return; + } else if (throwable != null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); + return; + } else if (!uuids.isEmpty()) { + for (UUID uuid : uuids) { + if (plot.getTrusted().contains(uuid)) { + if (plot.removeTrusted(uuid)) { + PlotSquared.get().getEventDispatcher() + .callTrusted(player, plot, uuid, false); + count++; + } + } else if (plot.getMembers().contains(uuid)) { + if (plot.removeMember(uuid)) { + PlotSquared.get().getEventDispatcher() + .callMember(player, plot, uuid, false); + count++; + } + } else if (plot.getDenied().contains(uuid)) { + if (plot.removeDenied(uuid)) { + PlotSquared.get().getEventDispatcher() + .callDenied(player, plot, uuid, false); + count++; + } + } else if (uuid == DBFunc.EVERYONE) { + if (plot.removeTrusted(uuid)) { + PlotSquared.get().getEventDispatcher() + .callTrusted(player, plot, uuid, false); + count++; + } else if (plot.removeMember(uuid)) { + PlotSquared.get().getEventDispatcher() + .callMember(player, plot, uuid, false); + count++; + } else if (plot.removeDenied(uuid)) { + PlotSquared.get().getEventDispatcher() + .callDenied(player, plot, uuid, false); + count++; } } } - break; - } - if (count == 0) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); - return false; - } else { - MainUtil.sendMessage(player, Captions.REMOVED_PLAYERS, count + ""); - } + } + if (count == 0) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); + } else { + MainUtil.sendMessage(player, Captions.REMOVED_PLAYERS, count + ""); + } + }); return true; } + } diff --git a/Core/src/main/java/com/plotsquared/core/command/Trust.java b/Core/src/main/java/com/plotsquared/core/command/Trust.java index 8a93e6cd8..8bcaced4e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Trust.java +++ b/Core/src/main/java/com/plotsquared/core/command/Trust.java @@ -36,9 +36,9 @@ import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; import java.util.Iterator; -import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; @CommandDeclaration(command = "trust", aliases = {"t"}, @@ -65,51 +65,65 @@ public class Trust extends Command { .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), Captions.NO_PLOT_PERMS); checkTrue(args.length == 1, Captions.COMMAND_SYNTAX, getUsage()); - final Set uuids = MainUtil.getUUIDsFromString(args[0]); - checkTrue(!uuids.isEmpty(), Captions.INVALID_PLAYER, args[0]); - Iterator iterator = uuids.iterator(); - int size = currentPlot.getTrusted().size() + currentPlot.getMembers().size(); - while (iterator.hasNext()) { - UUID uuid = iterator.next(); - if (uuid == DBFunc.EVERYONE && !( - Permissions.hasPermission(player, Captions.PERMISSION_TRUST_EVERYONE) || Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST))) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - if (currentPlot.isOwner(uuid)) { - MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - if (currentPlot.getTrusted().contains(uuid)) { - MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); - iterator.remove(); - continue; - } - size += currentPlot.getMembers().contains(uuid) ? 0 : 1; - } - checkTrue(!uuids.isEmpty(), null); - checkTrue(size <= currentPlot.getArea().getMaxPlotMembers() || Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), - Captions.PLOT_MAX_MEMBERS); - // Success - confirm.run(this, () -> { - for (UUID uuid : uuids) { - if (uuid != DBFunc.EVERYONE) { - if (!currentPlot.removeMember(uuid)) { - if (currentPlot.getDenied().contains(uuid)) { - currentPlot.removeDenied(uuid); - } - } - } - currentPlot.addTrusted(uuid); - PlotSquared.get().getEventDispatcher().callTrusted(player, currentPlot, uuid, true); - MainUtil.sendMessage(player, Captions.TRUSTED_ADDED); - } - }, null); + final CompletableFuture future = new CompletableFuture<>(); + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + if (throwable != null) { + if (throwable instanceof TimeoutException) { + Captions.FETCHING_PLAYERS_TIMEOUT.send(player); + } else { + Captions.INVALID_PLAYER.send(player, args[0]); + } + future.completeExceptionally(throwable); + return; + } else { + checkTrue(!uuids.isEmpty(), Captions.INVALID_PLAYER, args[0]); + Iterator iterator = uuids.iterator(); + int size = currentPlot.getTrusted().size() + currentPlot.getMembers().size(); + while (iterator.hasNext()) { + UUID uuid = iterator.next(); + if (uuid == DBFunc.EVERYONE && !( + Permissions.hasPermission(player, Captions.PERMISSION_TRUST_EVERYONE) || Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST))) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + if (currentPlot.isOwner(uuid)) { + MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + if (currentPlot.getTrusted().contains(uuid)) { + MainUtil.sendMessage(player, Captions.ALREADY_ADDED, MainUtil.getName(uuid)); + iterator.remove(); + continue; + } + size += currentPlot.getMembers().contains(uuid) ? 0 : 1; + } + checkTrue(!uuids.isEmpty(), null); + checkTrue(size <= currentPlot.getArea().getMaxPlotMembers() || Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_TRUST), + Captions.PLOT_MAX_MEMBERS); + // Success + confirm.run(this, () -> { + for (UUID uuid : uuids) { + if (uuid != DBFunc.EVERYONE) { + if (!currentPlot.removeMember(uuid)) { + if (currentPlot.getDenied().contains(uuid)) { + currentPlot.removeDenied(uuid); + } + } + } + currentPlot.addTrusted(uuid); + PlotSquared.get().getEventDispatcher().callTrusted(player, currentPlot, uuid, true); + MainUtil.sendMessage(player, Captions.TRUSTED_ADDED); + } + }, null); + } + future.complete(true); + }); return CompletableFuture.completedFuture(true); } + } diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 0c31076f2..78acbd88e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -46,6 +46,7 @@ import java.util.HashSet; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; @@ -156,7 +157,9 @@ public class Visit extends Command { } MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { - if (throwable != null || uuids.size() != 1) { + if (throwable instanceof TimeoutException) { + Captions.FETCHING_PLAYERS_TIMEOUT.send(player); + } else if (throwable != null || uuids.size() != 1) { Captions.COMMAND_SYNTAX.send(player, getUsage()); } else { unsortedPre.addAll(PlotSquared.get().getBasePlots((UUID) uuids.toArray()[0])); @@ -188,7 +191,9 @@ public class Visit extends Command { if (args[0].length() >= 2) { PlotSquared.get().getImpromptuUUIDPipeline().getSingle(args[0], (uuid, throwable) -> { - if (uuid != null && !PlotSquared.get().hasPlot(uuid)) { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (uuid != null && !PlotSquared.get().hasPlot(uuid)) { uuidConsumer.accept(null); } else { uuidConsumer.accept(uuid); diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 9d9251c61..98cb8b9ce 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -451,6 +451,7 @@ public enum Captions implements Caption { DEBUG_REPORT_CREATED("$1Uploaded a full debug to: $1%url%", "Paste"), PURGE_SUCCESS("$4Successfully purged %s plots", "Purge"), FETCHING_PLAYER("$1PlotSquared is attempting to find the specified player from your argument(s). This may take a while.", "Players"), + FETCHING_PLAYERS_TIMEOUT("$2The specified users did not exist in the cache and will be fetched in the background. Please wait a couple of minutes.", "Players"), // TRIM_IN_PROGRESS("A world trim task is already in progress!", "Trim"), // diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index fff645253..85e493088 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -245,6 +245,10 @@ public class Settings extends Config { public static int BACKGROUND_LIMIT = 200; @Comment("Rate limit (per 10 minutes) for random UUID fetching from the Mojang API") public static int IMPROMPTU_LIMIT = 300; + @Comment("Timeout (in milliseconds) for non-blocking UUID requests (mostly commands)") + public static long NON_BLOCKING_TIMEOUT = 3000L; + @Comment("Timeout (in milliseconds) for blocking UUID requests (events)") + public static long BLOCKING_TIMEOUT = 10L; } diff --git a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java index 4e887fead..e214e382a 100644 --- a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java @@ -383,7 +383,7 @@ public class MainUtil { if (owner.equals(DBFunc.SERVER)) { return Captions.SERVER.getTranslated(); } - String name = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(owner, 10L); + String name = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(owner, Settings.UUID.BLOCKING_TIMEOUT); if (name == null) { return Captions.UNKNOWN.getTranslated(); } @@ -454,7 +454,7 @@ public class MainUtil { for (String term : split) { try { - UUID uuid = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(term, 10L); + UUID uuid = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(term, Settings.UUID.BLOCKING_TIMEOUT); if (uuid == null) { uuid = UUID.fromString(term); } @@ -752,7 +752,8 @@ public class MainUtil { if (request.isEmpty()) { consumer.accept(result, null); } else { - PlotSquared.get().getImpromptuUUIDPipeline().getUUIDs(request).whenComplete((uuids, throwable) -> { + PlotSquared.get().getImpromptuUUIDPipeline().getUUIDs(request, Settings.UUID.NON_BLOCKING_TIMEOUT) + .whenComplete((uuids, throwable) -> { if (throwable != null) { consumer.accept(null, throwable); } else { diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 6d85db51f..12d49abaa 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -27,6 +27,7 @@ package com.plotsquared.core.uuid; import com.google.common.collect.Lists; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.util.ThreadUtils; import com.plotsquared.core.util.task.TaskManager; import org.jetbrains.annotations.NotNull; @@ -42,10 +43,13 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Function; /** * An UUID pipeline is essentially an ordered list of @@ -60,6 +64,7 @@ public class UUIDPipeline { private final Executor executor; private final List serviceList; private final List>> consumerList; + private final ScheduledExecutorService timeoutExecutor; /** * Construct a new UUID pipeline @@ -71,6 +76,7 @@ public class UUIDPipeline { this.executor = executor; this.serviceList = Lists.newLinkedList(); this.consumerList = Lists.newLinkedList(); + this.timeoutExecutor = Executors.newSingleThreadScheduledExecutor(); } /** @@ -184,8 +190,10 @@ public class UUIDPipeline { * @param username Username * @param uuid UUID consumer */ - public void getSingle(@NotNull final String username, @NotNull final BiConsumer uuid) { - this.getUUIDs(Collections.singletonList(username)).whenComplete((uuids, throwable) -> { + public void getSingle(@NotNull final String username, + @NotNull final BiConsumer uuid) { + this.getUUIDs(Collections.singletonList(username)).applyToEither(timeoutAfter(Settings.UUID.NON_BLOCKING_TIMEOUT), Function.identity()) + .whenComplete((uuids, throwable) -> { if (throwable != null) { uuid.accept(null, throwable); } else { @@ -204,8 +212,10 @@ public class UUIDPipeline { * @param uuid UUID * @param username Username consumer */ - public void getSingle(@NotNull final UUID uuid, @NotNull final BiConsumer username) { - this.getNames(Collections.singletonList(uuid)).whenComplete((uuids, throwable) -> { + public void getSingle(@NotNull final UUID uuid, + @NotNull final BiConsumer username) { + this.getNames(Collections.singletonList(uuid)).applyToEither(timeoutAfter(Settings.UUID.NON_BLOCKING_TIMEOUT), Function.identity()) + .whenComplete((uuids, throwable) -> { if (throwable != null) { username.accept(null, throwable); } else { @@ -218,6 +228,42 @@ public class UUIDPipeline { }); } + /** + * Asynchronously attempt to fetch the mapping from a list of UUIDs. + *

+ * This will timeout after the specified time and throws a {@link TimeoutException} + * if this happens + * + * @param requests UUIDs + * @param timeout Timeout in milliseconds + * @return Mappings + */ + public CompletableFuture> getNames(@NotNull final Collection requests, + final long timeout) { + return this.getNames(requests).applyToEither(timeoutAfter(timeout), Function.identity()); + } + + /** + * Asynchronously attempt to fetch the mapping from a list of names. + *

+ * This will timeout after the specified time and throws a {@link TimeoutException} + * if this happens + * + * @param requests Names + * @param timeout Timeout in milliseconds + * @return Mappings + */ + public CompletableFuture> getUUIDs(@NotNull final Collection requests, + final long timeout) { + return this.getUUIDs(requests).applyToEither(timeoutAfter(timeout), Function.identity()); + } + + private CompletableFuture> timeoutAfter(final long timeout) { + final CompletableFuture> result = new CompletableFuture<>(); + this.timeoutExecutor.schedule(() -> result.completeExceptionally(new TimeoutException()), timeout, TimeUnit.MILLISECONDS); + return result; + } + /** * Asynchronously attempt to fetch the mapping from a list of UUIDs * From 7aba70ea6548929dbae382eace7cab9f5c23b271 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Tue, 19 May 2020 16:54:12 +0100 Subject: [PATCH 017/121] Make plot clears/sets less crashy. There's still the issue of Spigot's (or paper's) terrible GC that does nothing and stores everything in PS old gen memory so the server just numpties itself though. --- .../bukkit/queue/BukkitLocalQueue.java | 21 +++++++++++++++---- .../com/plotsquared/core/PlotSquared.java | 2 +- .../core/configuration/Settings.java | 7 +++++++ .../core/queue/GlobalBlockQueue.java | 17 +++++++++++---- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java index 3f93ebb63..c8d6d929f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java @@ -31,6 +31,7 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.queue.BasicLocalBlockQueue; import com.plotsquared.core.util.BlockUtil; import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.task.TaskManager; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; @@ -50,7 +51,6 @@ import org.bukkit.block.Biome; import org.bukkit.block.Block; import org.bukkit.block.Container; import org.bukkit.block.data.BlockData; -import org.bukkit.inventory.BlockInventoryHolder; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; @@ -117,9 +117,6 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { @Override public final void setComponents(LocalChunk lc) throws ExecutionException, InterruptedException { setBaseBlocks(lc); - if (setBiome() && lc.biomes != null) { - setBiomes(lc); - } } public void setBaseBlocks(LocalChunk localChunk) { @@ -165,6 +162,22 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { } } } + if (setBiome() && localChunk.biomes != null) { + for (int x = 0; x < localChunk.biomes.length; x++) { + BiomeType[] biomeZ = localChunk.biomes[x]; + if (biomeZ != null) { + for (int z = 0; z < biomeZ.length; z++) { + if (biomeZ[z] != null) { + BiomeType biomeType = biomeZ[z]; + + Biome biome = BukkitAdapter.adapt(biomeType); + worldObj.setBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, + biome); + } + } + } + } + } }; if (isForceSync()) { chunkConsumer.accept(getChunk(worldObj, localChunk)); diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 452493181..4cb0731d5 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -270,7 +270,7 @@ public class PlotSquared { // create setup util class SetupUtils.manager = this.IMP.initSetupUtils(); // Set block - GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1); + GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1, Settings.QUEUE.TARGET_TIME); GlobalBlockQueue.IMP.runTask(); // Set chunk ChunkManager.manager = this.IMP.initChunkManager(); diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 044642baa..3fbd71394 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -489,6 +489,13 @@ public class Settings extends Config { public static boolean TILE_ENTITY_CHECK = true; } + @Comment("Settings relating to PlotSquared's GlobalBlockQueue") + public static final class QUEUE { + @Comment({"Average time per tick spent completing chunk tasks in ms. Target average TPS = 20 * 50 / TARGET_TIME.", + "Waits (chunk task time / target_time) ticks before completely the next task."}) + public static int TARGET_TIME = 65; + } + @Comment({"Enable or disable parts of the plugin", "Note: A cache will use some memory if enabled"}) diff --git a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java index 68a059583..3b63a94c0 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -44,8 +44,8 @@ public class GlobalBlockQueue { private final ConcurrentLinkedDeque inactiveQueues; private final ConcurrentLinkedDeque runnables; private final AtomicBoolean running; + private final int targetTime; private QueueProvider provider; - /** * Used to calculate elapsed time in milliseconds and ensure block placement doesn't lag the * server @@ -53,6 +53,7 @@ public class GlobalBlockQueue { private long last; private long secondLast; private long lastSuccess; + private double lastPeriod = 0; private final RunnableVal2 SET_TASK = new RunnableVal2() { @Override public void run(Long free, LocalBlockQueue queue) { @@ -65,17 +66,19 @@ public class GlobalBlockQueue { } return; } - } while (((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) - - GlobalBlockQueue.this.last) < free); + } while ((lastPeriod = + ((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) + - GlobalBlockQueue.this.last)) < free); } }; - public GlobalBlockQueue(QueueProvider provider, int threads) { + public GlobalBlockQueue(QueueProvider provider, int threads, int targetTime) { this.provider = provider; this.activeQueues = new ConcurrentLinkedDeque<>(); this.inactiveQueues = new ConcurrentLinkedDeque<>(); this.runnables = new ConcurrentLinkedDeque<>(); this.running = new AtomicBoolean(); + this.targetTime = targetTime; this.PARALLEL_THREADS = threads; } @@ -112,9 +115,15 @@ public class GlobalBlockQueue { @Override public void run() { if (inactiveQueues.isEmpty() && activeQueues.isEmpty()) { lastSuccess = System.currentTimeMillis(); + lastPeriod = 0; GlobalBlockQueue.this.runEmptyTasks(); return; } + // Server laggy? Skip. + if (lastPeriod > targetTime) { + lastPeriod -= targetTime; + return; + } SET_TASK.value1 = 50 + Math.min( (50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = System.currentTimeMillis()), From 973c18623f4f9899515efd97594a2b37f34a5057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 19 May 2020 19:34:33 +0200 Subject: [PATCH 018/121] Port more commands and add more tab completion utilities --- .../com/plotsquared/core/command/ListCmd.java | 185 ++++++++++-------- .../com/plotsquared/core/command/Set.java | 7 +- .../plotsquared/core/util/PatternUtil.java | 2 +- .../plotsquared/core/util/TabCompletions.java | 18 +- 4 files changed, 118 insertions(+), 94 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java index 8d151fb10..e9304e53f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java @@ -29,6 +29,7 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared.SortType; import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.Captions; +import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -44,20 +45,25 @@ import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.task.RunnableVal3; -import com.plotsquared.core.util.uuid.UUIDHandler; +import com.plotsquared.core.uuid.UUIDMapping; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Map.Entry; import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; @CommandDeclaration(command = "list", aliases = {"l", "find", "search"}, description = "List plots", permission = "plots.list", category = CommandCategory.INFO, - usage = "/plot list > [#]") + usage = "/plot list > [#]") public class ListCmd extends SubCommand { private String[] getArgumentList(PlotPlayer player) { @@ -84,9 +90,6 @@ public class ListCmd extends SubCommand { if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNOWNED)) { args.add("unowned"); } - if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNKNOWN)) { - args.add("unknown"); - } if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_PLAYER)) { args.add(""); } @@ -115,25 +118,44 @@ public class ListCmd extends SubCommand { noArgs(player); return false; } - int page = 0; + + final int page; if (args.length > 1) { + int tempPage = -1; try { - page = Integer.parseInt(args[args.length - 1]); - --page; - if (page < 0) { - page = 0; + tempPage = Integer.parseInt(args[args.length - 1]); + --tempPage; + if (tempPage < 0) { + tempPage = 0; } } catch (NumberFormatException ignored) { - page = -1; } + page = tempPage; + } else { + page = 0; } - List plots = null; - String world = player.getLocation().getWorld(); PlotArea area = player.getApplicablePlotArea(); String arg = args[0].toLowerCase(); - boolean sort = true; + final boolean[] sort = new boolean[] {true}; + + final Consumer> plotConsumer = plots -> { + if (plots == null) { + sendMessage(player, Captions.DID_YOU_MEAN, + new StringComparison<>(args[0], new String[] {"mine", "shared", "world", "all"}) + .getBestMatch()); + return; + } + + if (plots.isEmpty()) { + MainUtil.sendMessage(player, Captions.FOUND_NO_PLOTS); + return; + } + displayPlots(player, new ArrayList<>(plots), 12, page, area, args, sort[0]); + }; + + final List plots = new ArrayList<>(); switch (arg) { case "mine": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_MINE)) { @@ -141,8 +163,9 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_MINE); return false; } - sort = false; - plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getBasePlots(player)); + sort[0] = false; + plotConsumer.accept( + PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getBasePlots(player))); break; case "shared": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_SHARED)) { @@ -150,13 +173,13 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_SHARED); return false; } - plots = new ArrayList<>(); for (Plot plot : PlotSquared.get().getPlots()) { if (plot.getTrusted().contains(player.getUUID()) || plot.getMembers() .contains(player.getUUID())) { plots.add(plot); } } + plotConsumer.accept(plots); break; case "world": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_WORLD)) { @@ -171,7 +194,7 @@ public class ListCmd extends SubCommand { world)); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots(world)); + plotConsumer.accept(PlotSquared.get().getPlots(world)); break; case "expired": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_EXPIRED)) { @@ -179,9 +202,9 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_EXPIRED); return false; } - plots = ExpireManager.IMP == null ? - new ArrayList() : - new ArrayList<>(ExpireManager.IMP.getPendingExpired()); + plotConsumer.accept(ExpireManager.IMP == null ? + new ArrayList<>() : + new ArrayList<>(ExpireManager.IMP.getPendingExpired())); break; case "area": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_AREA)) { @@ -196,7 +219,8 @@ public class ListCmd extends SubCommand { world)); return false; } - plots = area == null ? new ArrayList() : new ArrayList<>(area.getPlots()); + plotConsumer.accept( + area == null ? new ArrayList() : new ArrayList<>(area.getPlots())); break; case "all": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_ALL)) { @@ -204,7 +228,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_ALL); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots()); + plotConsumer.accept(new ArrayList<>(PlotSquared.get().getPlots())); break; case "done": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_DONE)) { @@ -212,7 +236,6 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_DONE); return false; } - plots = new ArrayList<>(); for (Plot plot : PlotSquared.get().getPlots()) { if (DoneFlag.isDone(plot)) { plots.add(plot); @@ -229,7 +252,8 @@ public class ListCmd extends SubCommand { } return 1; }); - sort = false; + sort[0] = false; + plotConsumer.accept(plots); break; case "top": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_TOP)) { @@ -237,7 +261,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_TOP); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots()); + plots.addAll(PlotSquared.get().getPlots()); plots.sort((p1, p2) -> { double v1 = 0; int p1s = p1.getSettings().getRatings().size(); @@ -262,7 +286,8 @@ public class ListCmd extends SubCommand { } return (int) Math.signum(v2 - v1); }); - sort = false; + sort[0] = false; + plotConsumer.accept(plots); break; case "forsale": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_FOR_SALE)) { @@ -273,12 +298,12 @@ public class ListCmd extends SubCommand { if (EconHandler.manager == null) { break; } - plots = new ArrayList<>(); for (Plot plot : PlotSquared.get().getPlots()) { if (plot.getFlag(PriceFlag.class) > 0) { plots.add(plot); } } + plotConsumer.accept(plots); break; case "unowned": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNOWNED)) { @@ -286,28 +311,12 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_UNOWNED); return false; } - plots = new ArrayList<>(); for (Plot plot : PlotSquared.get().getPlots()) { if (plot.getOwner() == null) { plots.add(plot); } } - break; - case "unknown": - if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNKNOWN)) { - MainUtil.sendMessage(player, Captions.NO_PERMISSION, - Captions.PERMISSION_LIST_UNKNOWN); - return false; - } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getOwner() == null) { - continue; - } - if (UUIDHandler.getName(plot.getOwner()) == null) { - plots.add(plot); - } - } + plotConsumer.accept(plots); break; case "fuzzy": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_FUZZY)) { @@ -325,8 +334,8 @@ public class ListCmd extends SubCommand { } else { term = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); } - plots = MainUtil.getPlotsBySearch(term); - sort = false; + sort[0] = false; + plotConsumer.accept(MainUtil.getPlotsBySearch(term)); break; default: if (PlotSquared.get().hasPlotArea(args[0])) { @@ -343,40 +352,39 @@ public class ListCmd extends SubCommand { args[0])); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots(args[0])); - break; - } - UUID uuid = UUIDHandler.getUUID(args[0], null); - if (uuid == null) { - try { - uuid = UUID.fromString(args[0]); - } catch (Exception ignored) { - } - } - if (uuid != null) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_PLAYER)) { - MainUtil.sendMessage(player, Captions.NO_PERMISSION, - Captions.PERMISSION_LIST_PLAYER); - return false; - } - sort = false; - plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getPlots(uuid)); + plotConsumer.accept(new ArrayList<>(PlotSquared.get().getPlots(args[0]))); break; } + + PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(args[0], (uuid, throwable) -> { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (throwable != null) { + if (uuid == null) { + try { + uuid = UUID.fromString(args[0]); + } catch (Exception ignored) { + } + } + } + if (uuid == null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); + } else { + if (!Permissions + .hasPermission(player, Captions.PERMISSION_LIST_PLAYER)) { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, + Captions.PERMISSION_LIST_PLAYER); + } else { + sort[0] = false; + plotConsumer.accept(PlotSquared.get() + .sortPlotsByTemp(PlotSquared.get().getPlots(uuid))); + } + } + }); + break; } - if (plots == null) { - sendMessage(player, Captions.DID_YOU_MEAN, - new StringComparison<>(args[0], new String[] {"mine", "shared", "world", "all"}) - .getBestMatch()); - return false; - } - - if (plots.isEmpty()) { - MainUtil.sendMessage(player, Captions.FOUND_NO_PLOTS); - return false; - } - displayPlots(player, plots, 12, page, area, args, sort); return true; } @@ -417,22 +425,25 @@ public class ListCmd extends SubCommand { .command("/plot info " + plot.getArea() + ";" + plot.getId()).color(color) .text(" - ").color("$2"); String prefix = ""; - for (UUID uuid : plot.getOwners()) { - String name = UUIDHandler.getName(uuid); - if (name == null) { - message = message.text(prefix).color("$4").text("unknown").color("$2") - .tooltip(uuid.toString()).suggest(uuid.toString()); - } else { - PlotPlayer pp = UUIDHandler.getPlayer(uuid); + + try { + final List names = PlotSquared.get().getImpromptuUUIDPipeline() + .getNames(plot.getOwners()).get(Settings.UUID.BLOCKING_TIMEOUT, TimeUnit.MILLISECONDS); + for (final UUIDMapping uuidMapping : names) { + PlotPlayer pp = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuidMapping.getUuid()); if (pp != null) { - message = message.text(prefix).color("$4").text(name).color("$1") + message = message.text(prefix).color("$4").text(uuidMapping.getUsername()).color("$1") .tooltip(new PlotMessage("Online").color("$4")); } else { - message = message.text(prefix).color("$4").text(name).color("$1") + message = message.text(prefix).color("$4").text(uuidMapping.getUsername()).color("$1") .tooltip(new PlotMessage("Offline").color("$3")); } + prefix = ", "; } - prefix = ", "; + } catch (InterruptedException | ExecutionException e) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER); + } catch (TimeoutException e) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); } } }, "/plot list " + args[0], Captions.PLOT_LIST_HEADER_PAGED.getTranslated()); 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 413ae3e4b..bf5285691 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Set.java +++ b/Core/src/main/java/com/plotsquared/core/command/Set.java @@ -37,6 +37,7 @@ import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.StringMan; +import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.WorldUtil; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.world.block.BlockCategory; @@ -158,11 +159,7 @@ public class Set extends SubCommand { @Override public Collection tab(final PlotPlayer player, final String[] args, final boolean space) { - return PatternUtil.getSuggestions(player, StringMan.join(args, ",").trim()).stream() - .map(value -> value.toLowerCase(Locale.ENGLISH).replace("minecraft:", "")) - .filter(value -> value.startsWith(args[0].toLowerCase(Locale.ENGLISH))) - .map(value -> new Command(null, false, value, "", RequiredType.NONE, null) { - }).collect(Collectors.toList()); + return TabCompletions.completePatterns(StringMan.join(args, ",")); } }; } diff --git a/Core/src/main/java/com/plotsquared/core/util/PatternUtil.java b/Core/src/main/java/com/plotsquared/core/util/PatternUtil.java index ee390cc04..c8d18c136 100644 --- a/Core/src/main/java/com/plotsquared/core/util/PatternUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/PatternUtil.java @@ -62,7 +62,7 @@ public class PatternUtil { return parse(plotPlayer, input, true); } - public static List getSuggestions(PlotPlayer plotPlayer, String input) { + public static List getSuggestions(String input) { try { return WorldEdit.getInstance().getPatternFactory().getSuggestions(input); } catch (final Exception ignored) { diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java index a7c7c2a8f..0c1dbf4df 100644 --- a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java +++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java @@ -45,7 +45,8 @@ import java.util.stream.Collectors; /** * Tab completion utilities */ -@UtilityClass public class TabCompletions { +@UtilityClass +public class TabCompletions { private final Cache> cachedCompletionValues = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); @@ -79,4 +80,19 @@ import java.util.stream.Collectors; }).collect(Collectors.toList()); } + /** + * Get a list of completions corresponding to WorldEdit(/FAWE) patterns. This uses + * WorldEdit's pattern completer internally. + * + * @param input Command input + * @return List of completions + */ + @NotNull public List completePatterns(@NotNull final String input) { + return PatternUtil.getSuggestions(input.trim()).stream() + .map(value -> value.toLowerCase(Locale.ENGLISH).replace("minecraft:", "")) + .filter(value -> value.startsWith(input.toLowerCase(Locale.ENGLISH))) + .map(value -> new Command(null, false, value, "", RequiredType.NONE, null) { + }).collect(Collectors.toList()); + } + } From 8efc78e1c95c1114b4f56fb1ed4e5619b72028e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 19 May 2020 23:05:36 +0200 Subject: [PATCH 019/121] IT COMPILES! --- .../bukkit/player/BukkitPlayerManager.java | 17 +- .../bukkit/util/uuid/DefaultUUIDWrapper.java | 66 ------- .../java/com/plotsquared/core/IPlotMain.java | 2 +- .../core/backup/PlayerBackupProfile.java | 2 +- .../com/plotsquared/core/command/Buy.java | 9 +- .../plotsquared/core/command/DebugExec.java | 27 --- .../plotsquared/core/command/DebugPaste.java | 3 +- .../com/plotsquared/core/command/Grant.java | 76 ++++---- .../com/plotsquared/core/command/Kick.java | 99 +++++----- .../plotsquared/core/command/MainCommand.java | 1 - .../com/plotsquared/core/command/Merge.java | 5 +- .../com/plotsquared/core/command/Owner.java | 175 ++++++++++-------- .../com/plotsquared/core/command/Purge.java | 17 +- .../java/com/plotsquared/core/plot/Plot.java | 5 +- .../core/plot/expiration/ExpireManager.java | 52 ++---- .../core/queue/LocalBlockQueue.java | 8 +- .../plotsquared/core/util/PlayerManager.java | 35 +++- .../core/util/SchematicHandler.java | 15 +- .../util/UUIDHandlerImplementationTest.java | 49 ----- 19 files changed, 267 insertions(+), 396 deletions(-) delete mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DefaultUUIDWrapper.java delete mode 100644 Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java index 6e628a8a7..cdb770e2f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java @@ -25,20 +25,20 @@ */ package com.plotsquared.bukkit.player; -import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.PlayerManager; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.UUID; /** * Player manager providing {@link BukkitPlayer Bukkit players} */ -public class BukkitPlayerManager extends PlayerManager { +public class BukkitPlayerManager extends PlayerManager { - @Override @NotNull public PlotPlayer createPlayer(@NotNull final UUID uuid) { + @Override @NotNull public BukkitPlayer createPlayer(@NotNull final UUID uuid) { final Player player = Bukkit.getPlayer(uuid); if (player == null || !player.isOnline()) { throw new NoSuchPlayerException(uuid); @@ -46,4 +46,15 @@ public class BukkitPlayerManager extends PlayerManager { return new BukkitPlayer(player); } + @Nullable @Override public BukkitOfflinePlayer getOfflinePlayer(@Nullable final UUID uuid) { + if (uuid == null) { + return null; + } + return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(uuid)); + } + + @NotNull @Override public BukkitOfflinePlayer getOfflinePlayer(@NotNull final String username) { + return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(username)); + } + } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DefaultUUIDWrapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DefaultUUIDWrapper.java deleted file mode 100644 index a2898ee91..000000000 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/uuid/DefaultUUIDWrapper.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.bukkit.util.uuid; - -import com.plotsquared.bukkit.player.BukkitOfflinePlayer; -import com.plotsquared.bukkit.player.BukkitPlayer; -import com.plotsquared.core.player.OfflinePlotPlayer; -import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.util.uuid.UUIDWrapper; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.jetbrains.annotations.NotNull; - -import java.util.Arrays; -import java.util.UUID; - -public class DefaultUUIDWrapper extends UUIDWrapper { - - @NotNull @Override public UUID getUUID(PlotPlayer player) { - return ((BukkitPlayer) player).player.getUniqueId(); - } - - @Override public UUID getUUID(OfflinePlotPlayer player) { - return player.getUUID(); - } - - @Override public OfflinePlotPlayer getOfflinePlayer(UUID uuid) { - return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(uuid)); - } - - @Override public UUID getUUID(String name) { - return Bukkit.getOfflinePlayer(name).getUniqueId(); - } - - @Override public OfflinePlotPlayer[] getOfflinePlayers() { - OfflinePlayer[] ops = Bukkit.getOfflinePlayers(); - return Arrays.stream(ops).map(BukkitOfflinePlayer::new).toArray(BukkitOfflinePlayer[]::new); - } - - @Override public OfflinePlotPlayer getOfflinePlayer(String name) { - return new BukkitOfflinePlayer(Bukkit.getOfflinePlayer(name)); - } -} diff --git a/Core/src/main/java/com/plotsquared/core/IPlotMain.java b/Core/src/main/java/com/plotsquared/core/IPlotMain.java index 2705d54c2..9e04d85ec 100644 --- a/Core/src/main/java/com/plotsquared/core/IPlotMain.java +++ b/Core/src/main/java/com/plotsquared/core/IPlotMain.java @@ -286,6 +286,6 @@ public interface IPlotMain extends ILogger { * * @return Player manager */ - @NotNull PlayerManager getPlayerManager(); + @NotNull PlayerManager getPlayerManager(); } diff --git a/Core/src/main/java/com/plotsquared/core/backup/PlayerBackupProfile.java b/Core/src/main/java/com/plotsquared/core/backup/PlayerBackupProfile.java index 8853f3dff..c71057ab5 100644 --- a/Core/src/main/java/com/plotsquared/core/backup/PlayerBackupProfile.java +++ b/Core/src/main/java/com/plotsquared/core/backup/PlayerBackupProfile.java @@ -142,7 +142,7 @@ public class PlayerBackupProfile implements BackupProfile { } final List plots = Collections.singletonList(plot); final boolean result = SchematicHandler.manager.exportAll(plots, getBackupDirectory().toFile(), - "%world%-%id%-%owner%-" + System.currentTimeMillis(), () -> + "%world%-%id%-" + System.currentTimeMillis(), () -> future.complete(new Backup(this, System.currentTimeMillis(), null))); if (!result) { future.completeExceptionally(new RuntimeException("Failed to complete the backup")); diff --git a/Core/src/main/java/com/plotsquared/core/command/Buy.java b/Core/src/main/java/com/plotsquared/core/command/Buy.java index a660a39a1..b986a7983 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Buy.java +++ b/Core/src/main/java/com/plotsquared/core/command/Buy.java @@ -37,7 +37,6 @@ import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.Set; import java.util.concurrent.CompletableFuture; @@ -82,10 +81,10 @@ public class Buy extends Command { // Success confirm.run(this, () -> { Captions.REMOVED_BALANCE.send(player, price); - EconHandler.manager - .depositMoney(UUIDHandler.getUUIDWrapper().getOfflinePlayer(plot.getOwnerAbs()), - price); - PlotPlayer owner = UUIDHandler.getPlayer(plot.getOwnerAbs()); + + EconHandler.manager.depositMoney(PlotSquared.imp().getPlayerManager().getOfflinePlayer(plot.getOwnerAbs()), price); + + PlotPlayer owner = PlotSquared.imp().getPlayerManager().getPlayerIfExists(plot.getOwnerAbs()); if (owner != null) { Captions.PLOT_SOLD.send(owner, plot.getId(), player.getName(), price); } diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java index 8976c3348..9f179803f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java @@ -35,7 +35,6 @@ import com.plotsquared.core.events.Result; import com.plotsquared.core.generator.HybridUtils; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.ConsolePlayer; -import com.plotsquared.core.player.OfflinePlotPlayer; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -59,7 +58,6 @@ import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.world.block.BlockState; import javax.script.Bindings; @@ -71,13 +69,10 @@ import javax.script.SimpleScriptContext; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.sql.Timestamp; import java.util.Arrays; -import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.UUID; import java.util.concurrent.CompletableFuture; @CommandDeclaration(command = "debugexec", @@ -172,7 +167,6 @@ public class DebugExec extends SubCommand { this.scope.put("SetupUtils", SetupUtils.manager); this.scope.put("EventUtil", PlotSquared.get().getEventDispatcher()); this.scope.put("EconHandler", EconHandler.manager); - this.scope.put("UUIDHandler", UUIDHandler.implementation); this.scope.put("DBFunc", DBFunc.dbManager); this.scope.put("HybridUtils", HybridUtils.manager); this.scope.put("IMP", PlotSquared.get().IMP); @@ -301,27 +295,6 @@ public class DebugExec extends SubCommand { } else { return MainUtil.sendMessage(player, "Plot expiry task already started"); } - case "seen": - if (args.length != 2) { - return MainUtil.sendMessage(player, "Use /plot debugexec seen "); - } - UUID uuid = UUIDHandler.getUUID(args[1], null); - if (uuid == null) { - return MainUtil.sendMessage(player, "Player not found: " + args[1]); - } - OfflinePlotPlayer op = UUIDHandler.getUUIDWrapper().getOfflinePlayer(uuid); - if (op == null || op.getLastPlayed() == 0) { - return MainUtil - .sendMessage(player, "Player hasn't connected before: " + args[1]); - } - Timestamp stamp = new Timestamp(op.getLastPlayed()); - Date date = new Date(stamp.getTime()); - MainUtil.sendMessage(player, "PLAYER: " + args[1]); - MainUtil.sendMessage(player, "UUID: " + uuid); - MainUtil.sendMessage(player, "Object: " + date.toGMTString()); - MainUtil.sendMessage(player, "GMT: " + date.toGMTString()); - MainUtil.sendMessage(player, "Local: " + date.toLocaleString()); - return true; case "h": case "he": case "?": diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java b/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java index c5c42a4c2..412d2b066 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java @@ -35,7 +35,6 @@ import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.PremiumVerification; import com.plotsquared.core.util.net.IncendoPaster; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import lombok.NonNull; import java.io.BufferedReader; @@ -90,7 +89,7 @@ public class DebugPaste extends SubCommand { b.append("# Server Information\n"); b.append("Server Version: ").append(PlotSquared.get().IMP.getServerImplementation()) .append("\n"); - b.append("online_mode: ").append(UUIDHandler.getUUIDWrapper()).append(';') + b.append("online_mode: ").append(!Settings.UUID.OFFLINE).append(';') .append(!Settings.UUID.OFFLINE).append('\n'); b.append("Plugins:"); for (Map.Entry, Boolean> pluginInfo : PlotSquared diff --git a/Core/src/main/java/com/plotsquared/core/command/Grant.java b/Core/src/main/java/com/plotsquared/core/command/Grant.java index acec1b084..39351c27f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Grant.java +++ b/Core/src/main/java/com/plotsquared/core/command/Grant.java @@ -26,6 +26,7 @@ package com.plotsquared.core.command; import com.google.common.primitives.Ints; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.database.DBFunc; @@ -35,10 +36,10 @@ import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; @CommandDeclaration(command = "grant", category = CommandCategory.CLAIMING, @@ -69,43 +70,44 @@ public class Grant extends Command { if (args.length > 2) { break; } - final UUID uuid; - if (args.length == 2) { - uuid = UUIDHandler.getUUIDFromString(args[1]); - } else { - uuid = player.getUUID(); - } - if (uuid == null) { - Captions.INVALID_PLAYER.send(player, args[1]); - return CompletableFuture.completedFuture(false); - } - MainUtil.getPersistentMeta(uuid, "grantedPlots", new RunnableVal() { - @Override public void run(byte[] array) { - if (arg0.equals("check")) { // check - int granted; - if (array == null) { - granted = 0; - } else { - granted = Ints.fromByteArray(array); + MainUtil.getUUIDsFromString(args[1], (uuids, throwable) -> { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (throwable != null || uuids.size() != 1) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER); + } else { + final UUID uuid = uuids.toArray(new UUID[0])[0]; + MainUtil.getPersistentMeta(uuid, + "grantedPlots", new RunnableVal() { + @Override public void run(byte[] array) { + if (arg0.equals("check")) { // check + int granted; + if (array == null) { + granted = 0; + } else { + granted = Ints.fromByteArray(array); + } + Captions.GRANTED_PLOTS.send(player, granted); + } else { // add + int amount; + if (array == null) { + amount = 1; + } else { + amount = 1 + Ints.fromByteArray(array); + } + boolean replace = array != null; + String key = "grantedPlots"; + byte[] rawData = Ints.toByteArray(amount); + + PlotPlayer online = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); + if (online != null) { + online.setPersistentMeta(key, rawData); + } else { + DBFunc.addPersistentMeta(uuid, key, rawData, replace); + } + } } - Captions.GRANTED_PLOTS.send(player, granted); - } else { // add - int amount; - if (array == null) { - amount = 1; - } else { - amount = 1 + Ints.fromByteArray(array); - } - boolean replace = array != null; - String key = "grantedPlots"; - byte[] rawData = Ints.toByteArray(amount); - PlotPlayer online = UUIDHandler.getPlayer(uuid); - if (online != null) { - online.setPersistentMeta(key, rawData); - } else { - DBFunc.addPersistentMeta(uuid, key, rawData, replace); - } - } + }); } }); return CompletableFuture.completedFuture(true); diff --git a/Core/src/main/java/com/plotsquared/core/command/Kick.java b/Core/src/main/java/com/plotsquared/core/command/Kick.java index 1d113a874..69ace1482 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Kick.java +++ b/Core/src/main/java/com/plotsquared/core/command/Kick.java @@ -34,11 +34,11 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.HashSet; import java.util.Set; import java.util.UUID; +import java.util.concurrent.TimeoutException; @CommandDeclaration(command = "kick", aliases = "k", @@ -64,57 +64,62 @@ public class Kick extends SubCommand { MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); return false; } - Set uuids = MainUtil.getUUIDsFromString(args[0]); - if (uuids.isEmpty()) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); - return false; - } - Set players = new HashSet<>(); - for (UUID uuid : uuids) { - if (uuid == DBFunc.EVERYONE) { - for (PlotPlayer pp : plot.getPlayersInPlot()) { - if (pp == player || Permissions - .hasPermission(pp, Captions.PERMISSION_ADMIN_ENTRY_DENIED)) { + + MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (throwable != null || uuids.isEmpty()) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER); + } else { + Set players = new HashSet<>(); + for (UUID uuid : uuids) { + if (uuid == DBFunc.EVERYONE) { + for (PlotPlayer pp : plot.getPlayersInPlot()) { + if (pp == player || Permissions + .hasPermission(pp, Captions.PERMISSION_ADMIN_ENTRY_DENIED)) { + continue; + } + players.add(pp); + } continue; } - players.add(pp); + PlotPlayer pp = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); + if (pp != null) { + players.add(pp); + } } - continue; - } - PlotPlayer pp = UUIDHandler.getPlayer(uuid); - if (pp != null) { - players.add(pp); - } - } - players.remove(player); // Don't ever kick the calling player - if (players.isEmpty()) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); - return false; - } - for (PlotPlayer player2 : players) { - if (!plot.equals(player2.getCurrentPlot())) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); - return false; - } - if (Permissions.hasPermission(player2, Captions.PERMISSION_ADMIN_ENTRY_DENIED)) { - Captions.CANNOT_KICK_PLAYER.send(player, player2.getName()); - return false; - } - Location spawn = WorldUtil.IMP.getSpawn(location.getWorld()); - Captions.YOU_GOT_KICKED.send(player2); - if (plot.equals(spawn.getPlot())) { - Location newSpawn = WorldUtil.IMP - .getSpawn(PlotSquared.get().getPlotAreaManager().getAllWorlds()[0]); - if (plot.equals(newSpawn.getPlot())) { - // Kick from server if you can't be teleported to spawn - player2.kick(Captions.YOU_GOT_KICKED.getTranslated()); - } else { - player2.plotkick(newSpawn); + players.remove(player); // Don't ever kick the calling player + if (players.isEmpty()) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); + return; + } + for (PlotPlayer player2 : players) { + if (!plot.equals(player2.getCurrentPlot())) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); + return; + } + if (Permissions.hasPermission(player2, Captions.PERMISSION_ADMIN_ENTRY_DENIED)) { + Captions.CANNOT_KICK_PLAYER.send(player, player2.getName()); + return; + } + Location spawn = WorldUtil.IMP.getSpawn(location.getWorld()); + Captions.YOU_GOT_KICKED.send(player2); + if (plot.equals(spawn.getPlot())) { + Location newSpawn = WorldUtil.IMP + .getSpawn(PlotSquared.get().getPlotAreaManager().getAllWorlds()[0]); + if (plot.equals(newSpawn.getPlot())) { + // Kick from server if you can't be teleported to spawn + player2.kick(Captions.YOU_GOT_KICKED.getTranslated()); + } else { + player2.plotkick(newSpawn); + } + } else { + player2.plotkick(spawn); + } } - } else { - player2.plotkick(spawn); } - } + }); + return true; } } diff --git a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java index 03be061ca..133e27ab2 100644 --- a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java @@ -99,7 +99,6 @@ public class MainCommand extends Command { new DebugPaste(); new Unlink(); new Kick(); - new DebugClaimTest(); new Inbox(); new Comment(); new DatabaseCommand(); diff --git a/Core/src/main/java/com/plotsquared/core/command/Merge.java b/Core/src/main/java/com/plotsquared/core/command/Merge.java index 7998e3a84..53f88e2e7 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Merge.java +++ b/Core/src/main/java/com/plotsquared/core/command/Merge.java @@ -40,7 +40,6 @@ import com.plotsquared.core.util.Expression; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.UUID; @@ -213,7 +212,7 @@ public class Merge extends SubCommand { java.util.Set uuids = adjacent.getOwners(); boolean isOnline = false; for (final UUID owner : uuids) { - final PlotPlayer accepter = UUIDHandler.getPlayer(owner); + final PlotPlayer accepter = PlotSquared.imp().getPlayerManager().getPlayerIfExists(owner); if (!force && accepter == null) { continue; } @@ -222,7 +221,7 @@ public class Merge extends SubCommand { Runnable run = () -> { MainUtil.sendMessage(accepter, Captions.MERGE_ACCEPTED); plot.autoMerge(dir, maxSize - size, owner, terrain); - PlotPlayer plotPlayer = UUIDHandler.getPlayer(player.getUUID()); + PlotPlayer plotPlayer = PlotSquared.imp().getPlayerManager().getPlayerIfExists(player.getUUID()); if (plotPlayer == null) { sendMessage(accepter, Captions.MERGE_NOT_VALID); return; diff --git a/Core/src/main/java/com/plotsquared/core/command/Owner.java b/Core/src/main/java/com/plotsquared/core/command/Owner.java index 2c3d8e965..cb436fad2 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Owner.java +++ b/Core/src/main/java/com/plotsquared/core/command/Owner.java @@ -36,10 +36,11 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.Set; import java.util.UUID; +import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; @CommandDeclaration(command = "setowner", permission = "plots.set.owner", @@ -57,91 +58,103 @@ public class Owner extends SetCommand { return false; } Set plots = plot.getConnectedPlots(); - UUID uuid = null; + + final Consumer uuidConsumer = uuid -> { + if (uuid == null && !value.equalsIgnoreCase("none") && !value.equalsIgnoreCase("null") + && !value.equalsIgnoreCase("-")) { + Captions.INVALID_PLAYER.send(player, value); + return; + } + PlotChangeOwnerEvent event = PlotSquared.get().getEventDispatcher() + .callOwnerChange(player, plot, plot.hasOwner() ? plot.getOwnerAbs() : null, uuid, + plot.hasOwner()); + if (event.getEventResult() == Result.DENY) { + sendMessage(player, Captions.EVENT_DENIED, "Owner change"); + return; + } + uuid = event.getNewOwner(); + boolean force = event.getEventResult() == Result.FORCE; + if (uuid == null) { + if (!force && !Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_SET_OWNER.getTranslated(), + true)) { + return; + } + PlotUnlinkEvent unlinkEvent = PlotSquared.get().getEventDispatcher() + .callUnlink(plot.getArea(), plot, false, false, PlotUnlinkEvent.REASON.NEW_OWNER); + if (unlinkEvent.getEventResult() == Result.DENY) { + sendMessage(player, Captions.EVENT_DENIED, "Unlink on owner change"); + return; + } + plot.unlinkPlot(unlinkEvent.isCreateRoad(), unlinkEvent.isCreateRoad()); + Set connected = plot.getConnectedPlots(); + for (Plot current : connected) { + current.unclaim(); + current.removeSign(); + } + MainUtil.sendMessage(player, Captions.SET_OWNER); + return; + } + final PlotPlayer other = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); + if (plot.isOwner(uuid)) { + Captions.ALREADY_OWNER.send(player, MainUtil.getName(uuid)); + return; + } + if (!force && !Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_SET_OWNER)) { + if (other == null) { + Captions.INVALID_PLAYER_OFFLINE.send(player, value); + return; + } + int size = plots.size(); + int currentPlots = (Settings.Limit.GLOBAL ? + other.getPlotCount() : + other.getPlotCount(plot.getWorldName())) + size; + if (currentPlots > other.getAllowedPlots()) { + sendMessage(player, Captions.CANT_TRANSFER_MORE_PLOTS); + return; + } + } + final UUID finalUUID = uuid; + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(uuid, (finalName, throwable) -> { + final boolean removeDenied = plot.isDenied(finalUUID); + Runnable run = () -> { + if (plot.setOwner(finalUUID, player)) { + if (removeDenied) + plot.removeDenied(finalUUID); + plot.setSign(finalName); + MainUtil.sendMessage(player, Captions.SET_OWNER); + if (other != null) { + MainUtil.sendMessage(other, Captions.NOW_OWNER, + plot.getArea() + ";" + plot.getId()); + } + } else { + MainUtil.sendMessage(player, Captions.SET_OWNER_CANCELLED); + } + }; + if (hasConfirmation(player)) { + CmdConfirm.addPending(player, "/plot set owner " + value, run); + } else { + TaskManager.runTask(run); + } + }); + }; + if (value.length() == 36) { try { - uuid = UUID.fromString(value); + uuidConsumer.accept(UUID.fromString(value)); } catch (Exception ignored) { } } else { - uuid = UUIDHandler.getUUID(value, null); - } - if (uuid == null && !value.equalsIgnoreCase("none") && !value.equalsIgnoreCase("null") - && !value.equalsIgnoreCase("-")) { - Captions.INVALID_PLAYER.send(player, value); - return false; - } - PlotChangeOwnerEvent event = PlotSquared.get().getEventDispatcher() - .callOwnerChange(player, plot, plot.hasOwner() ? plot.getOwnerAbs() : null, uuid, - plot.hasOwner()); - if (event.getEventResult() == Result.DENY) { - sendMessage(player, Captions.EVENT_DENIED, "Owner change"); - return false; - } - uuid = event.getNewOwner(); - boolean force = event.getEventResult() == Result.FORCE; - if (uuid == null) { - if (!force && !Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_SET_OWNER.getTranslated(), - true)) { - return false; - } - PlotUnlinkEvent unlinkEvent = PlotSquared.get().getEventDispatcher() - .callUnlink(plot.getArea(), plot, false, false, PlotUnlinkEvent.REASON.NEW_OWNER); - if (unlinkEvent.getEventResult() == Result.DENY) { - sendMessage(player, Captions.EVENT_DENIED, "Unlink on owner change"); - return true; - } - plot.unlinkPlot(unlinkEvent.isCreateRoad(), unlinkEvent.isCreateRoad()); - Set connected = plot.getConnectedPlots(); - for (Plot current : connected) { - current.unclaim(); - current.removeSign(); - } - MainUtil.sendMessage(player, Captions.SET_OWNER); - return true; - } - final PlotPlayer other = UUIDHandler.getPlayer(uuid); - if (plot.isOwner(uuid)) { - Captions.ALREADY_OWNER.send(player, MainUtil.getName(uuid)); - return false; - } - if (!force && !Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_SET_OWNER)) { - if (other == null) { - Captions.INVALID_PLAYER_OFFLINE.send(player, value); - return false; - } - int size = plots.size(); - int currentPlots = (Settings.Limit.GLOBAL ? - other.getPlotCount() : - other.getPlotCount(plot.getWorldName())) + size; - if (currentPlots > other.getAllowedPlots()) { - sendMessage(player, Captions.CANT_TRANSFER_MORE_PLOTS); - return false; - } - } - final String finalName = UUIDHandler.getName(uuid); - final UUID finalUUID = uuid; - final boolean removeDenied = plot.isDenied(finalUUID); - Runnable run = () -> { - if (plot.setOwner(finalUUID, player)) { - if (removeDenied) - plot.removeDenied(finalUUID); - plot.setSign(finalName); - MainUtil.sendMessage(player, Captions.SET_OWNER); - if (other != null) { - MainUtil.sendMessage(other, Captions.NOW_OWNER, - plot.getArea() + ";" + plot.getId()); - } - } else { - MainUtil.sendMessage(player, Captions.SET_OWNER_CANCELLED); - } - }; - if (hasConfirmation(player)) { - CmdConfirm.addPending(player, "/plot set owner " + value, run); - } else { - TaskManager.runTask(run); + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(value, (uuid, throwable) -> { + if (throwable instanceof TimeoutException) { + MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); + } else if (throwable != null) { + MainUtil.sendMessage(player, Captions.INVALID_PLAYER); + } else { + uuidConsumer.accept(uuid); + } + }); } return true; } diff --git a/Core/src/main/java/com/plotsquared/core/command/Purge.java b/Core/src/main/java/com/plotsquared/core/command/Purge.java index 3691f44c9..50b323300 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Purge.java +++ b/Core/src/main/java/com/plotsquared/core/command/Purge.java @@ -36,7 +36,6 @@ import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.HashMap; import java.util.HashSet; @@ -65,7 +64,6 @@ public class Purge extends SubCommand { PlotId id = null; UUID owner = null; UUID added = null; - boolean unknown = false; boolean clear = false; for (String arg : args) { String[] split = arg.split(":"); @@ -97,7 +95,7 @@ public class Purge extends SubCommand { break; case "owner": case "o": - owner = UUIDHandler.getUUID(split[1], null); + owner = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(split[1], Settings.UUID.BLOCKING_TIMEOUT); if (owner == null) { Captions.INVALID_PLAYER.send(player, split[1]); return false; @@ -105,17 +103,12 @@ public class Purge extends SubCommand { break; case "shared": case "s": - added = UUIDHandler.getUUID(split[1], null); + added = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(split[1], Settings.UUID.BLOCKING_TIMEOUT); if (added == null) { Captions.INVALID_PLAYER.send(player, split[1]); return false; } break; - case "unknown": - case "?": - case "u": - unknown = Boolean.parseBoolean(split[1]); - break; case "clear": case "c": case "delete": @@ -145,9 +138,6 @@ public class Purge extends SubCommand { if (added != null && !plot.isAdded(added)) { continue; } - if (unknown && UUIDHandler.getName(plot.getOwnerAbs()) != null) { - continue; - } toDelete.addAll(plot.getConnectedPlots()); } if (PlotSquared.get().plots_tmp != null) { @@ -168,9 +158,6 @@ public class Purge extends SubCommand { if (added != null && !plot.isAdded(added)) { continue; } - if (unknown && UUIDHandler.getName(plot.getOwnerAbs()) != null) { - continue; - } toDelete.add(plot); } } diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index e7cfbcafd..9ac482be6 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -496,7 +496,7 @@ public class Plot { } if (isMerged()) { Set plots = getConnectedPlots(); - Plot[] array = plots.toArray(new Plot[plots.size()]); + Plot[] array = plots.toArray(new Plot[0]); ImmutableSet.Builder owners = ImmutableSet.builder(); UUID last = this.getOwner(); owners.add(this.getOwner()); @@ -1711,7 +1711,8 @@ public class Plot { this.setSign("unknown"); return; } - PlotSquared.get().getImpromptuUUIDPipeline().getSingle(this.getOwnerAbs(), this::setSign); + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(this.getOwnerAbs(), (username, sign) -> + this.setSign(username)); } /** diff --git a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java index 6b5f2bbae..16d4ee41f 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java @@ -27,7 +27,6 @@ package com.plotsquared.core.plot.expiration; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.events.PlotFlagAddEvent; import com.plotsquared.core.events.PlotUnlinkEvent; @@ -48,7 +47,6 @@ import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.ArrayDeque; import java.util.ArrayList; @@ -411,13 +409,13 @@ public class ExpireManager { } } for (UUID helper : plot.getTrusted()) { - PlotPlayer player = UUIDHandler.getPlayer(helper); + PlotPlayer player = PlotSquared.imp().getPlayerManager().getPlayerIfExists(helper); if (player != null) { MainUtil.sendMessage(player, Captions.PLOT_REMOVED_USER, plot.toString()); } } for (UUID helper : plot.getMembers()) { - PlotPlayer player = UUIDHandler.getPlayer(helper); + PlotPlayer player = PlotSquared.imp().getPlayerManager().getPlayerIfExists(helper); if (player != null) { MainUtil.sendMessage(player, Captions.PLOT_REMOVED_USER, plot.toString()); } @@ -433,56 +431,34 @@ public class ExpireManager { .getString(plots)); PlotSquared.debug("$4 - Area: " + plot.getArea()); if (plot.hasOwner()) { - PlotSquared.debug("$4 - Owner: " + UUIDHandler.getName(plot.getOwner())); + PlotSquared.debug("$4 - Owner: " + plot.getOwner()); } else { PlotSquared.debug("$4 - Owner: Unowned"); } } public long getAge(UUID uuid) { - if (UUIDHandler.getPlayer(uuid) != null) { + if (PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid) != null) { return 0; } - String name = UUIDHandler.getName(uuid); - if (name != null) { - Long last = this.dates_cache.get(uuid); - if (last == null) { - OfflinePlotPlayer opp; - if (Settings.UUID.NATIVE_UUID_PROVIDER) { - opp = UUIDHandler.getUUIDWrapper().getOfflinePlayer(uuid); - } else { - opp = UUIDHandler.getUUIDWrapper().getOfflinePlayer(name); - } - if (opp != null && (last = opp.getLastPlayed()) != 0) { - this.dates_cache.put(uuid, last); - } else { - return 0; - } - } - if (last == 0) { + Long last = this.dates_cache.get(uuid); + if (last == null) { + OfflinePlotPlayer opp = PlotSquared.imp().getPlayerManager().getOfflinePlayer(uuid); + if (opp != null && (last = opp.getLastPlayed()) != 0) { + this.dates_cache.put(uuid, last); + } else { return 0; } - return System.currentTimeMillis() - last; } - return 0; - } - - public long getAccountAge(Plot plot) { - if (!plot.hasOwner() || Objects.equals(DBFunc.EVERYONE, plot.getOwner()) - || UUIDHandler.getPlayer(plot.getOwner()) != null || plot.getRunning() > 0) { - return Long.MAX_VALUE; + if (last == 0) { + return 0; } - long max = 0; - for (UUID owner : plot.getOwners()) { - long age = getAccountAge(owner); - max = Math.max(age, max); - } - return max; + return System.currentTimeMillis() - last; } public long getAge(Plot plot) { if (!plot.hasOwner() || Objects.equals(DBFunc.EVERYONE, plot.getOwner()) - || UUIDHandler.getPlayer(plot.getOwner()) != null || plot.getRunning() > 0) { + || PlotSquared.imp().getPlayerManager().getPlayerIfExists(plot.getOwner()) != null || plot.getRunning() > 0) { return 0; } diff --git a/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java index f979b4e9f..76fa5e28a 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/LocalBlockQueue.java @@ -25,13 +25,13 @@ */ package com.plotsquared.core.queue; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector2; @@ -43,8 +43,6 @@ import lombok.Setter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Map; - public abstract class LocalBlockQueue { @Getter @Setter private boolean forceSync = false; @@ -124,8 +122,8 @@ public abstract class LocalBlockQueue { regenChunk(x, z); fixChunkLighting(x, z); BlockVector2 loc = BlockVector2.at(x, z); - for (Map.Entry entry : UUIDHandler.getPlayers().entrySet()) { - PlotPlayer pp = entry.getValue(); + + for (final PlotPlayer pp : PlotSquared.imp().getPlayerManager().getPlayers()) { Location pLoc = pp.getLocation(); if (!StringMan.isEqual(getWorld(), pLoc.getWorld()) || !pLoc.getBlockVector2() .equals(loc)) { diff --git a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java index fd1eebe4e..473826b2d 100644 --- a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java @@ -25,6 +25,7 @@ */ package com.plotsquared.core.util; +import com.plotsquared.core.player.OfflinePlotPlayer; import com.plotsquared.core.player.PlotPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,9 +39,9 @@ import java.util.UUID; /** * Manages player instances */ -public abstract class PlayerManager { +public abstract class PlayerManager

{ - private final Map playerMap = new HashMap<>(); + private final Map playerMap = new HashMap<>(); private final Object playerLock = new Object(); /** @@ -60,15 +61,15 @@ public abstract class PlayerManager { * @param uuid Player UUID * @return Player, or null */ - @Nullable public PlotPlayer getPlayerIfExists(@Nullable final UUID uuid) { + @Nullable public P getPlayerIfExists(@Nullable final UUID uuid) { if (uuid == null) { return null; } return this.playerMap.get(uuid); } - @Nullable public PlotPlayer getPlayerIfExists(@Nullable final String name) { - for (final PlotPlayer plotPlayer : this.playerMap.values()) { + @Nullable public P getPlayerIfExists(@Nullable final String name) { + for (final P plotPlayer : this.playerMap.values()) { if (plotPlayer.getName().equalsIgnoreCase(name)) { return plotPlayer; } @@ -86,9 +87,9 @@ public abstract class PlayerManager { * @param uuid Player UUID * @return Player object */ - @NotNull public PlotPlayer getPlayer(@NotNull final UUID uuid) { + @NotNull public P getPlayer(@NotNull final UUID uuid) { synchronized (playerLock) { - PlotPlayer player = this.playerMap.get(uuid); + P player = this.playerMap.get(uuid); if (player == null) { player = createPlayer(uuid); this.playerMap.put(uuid, player); @@ -97,14 +98,30 @@ public abstract class PlayerManager { } } - @NotNull protected abstract PlotPlayer createPlayer(@NotNull final UUID uuid); + @NotNull protected abstract P createPlayer(@NotNull final UUID uuid); + + /** + * Get an an offline player object from the player's UUID + * + * @param uuid Player UUID + * @return Offline player object + */ + @Nullable public abstract O getOfflinePlayer(@Nullable final UUID uuid); + + /** + * Get an offline player object from the player's username + * + * @param username Player name + * @return Offline player object + */ + @Nullable public abstract O getOfflinePlayer(@NotNull final String username); /** * Get all online players * * @return Unmodifiable collection of players */ - public Collection getPlayers() { + public Collection

getPlayers() { return Collections.unmodifiableCollection(this.playerMap.values()); } diff --git a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java index aa9e7a04c..78cc7192c 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java @@ -35,7 +35,6 @@ import com.plotsquared.core.plot.schematic.Schematic; import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; -import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.NBTInputStream; import com.sk89q.jnbt.NBTOutputStream; @@ -104,16 +103,24 @@ public abstract class SchematicHandler { Iterator i = plots.iterator(); final Plot plot = i.next(); i.remove(); - String owner = UUIDHandler.getName(plot.getOwnerAbs()); - if (owner == null) { + + PlotSquared.get().getImpromptuUUIDPipeline().getSingle(plot.getOwnerAbs(), (username, throwable) -> { + + }); + + final String owner; + if (plot.hasOwner()) { + owner = plot.getOwnerAbs().toString(); + } else { owner = "unknown"; } + final String name; if (namingScheme == null) { name = plot.getId().x + ";" + plot.getId().y + ',' + plot.getArea() + ',' + owner; } else { - name = namingScheme.replaceAll("%owner%", owner) + name = namingScheme .replaceAll("%id%", plot.getId().toString()) .replaceAll("%idx%", plot.getId().x + "") .replaceAll("%idy%", plot.getId().y + "") diff --git a/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java b/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java deleted file mode 100644 index 9bcad05bd..000000000 --- a/Core/src/test/java/com/plotsquared/core/plot/util/UUIDHandlerImplementationTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * _____ _ _ _____ _ - * | __ \| | | | / ____| | | - * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | - * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | - * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | - * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| - * | | - * |_| - * 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.plot.util; - -import com.plotsquared.core.database.AbstractDBTest; -import com.plotsquared.core.database.DBFunc; -import com.plotsquared.core.util.task.RunnableVal; -import com.plotsquared.core.util.uuid.OfflinePlayerService; -import org.junit.Before; - -import java.util.UUID; - -public class UUIDHandlerImplementationTest extends UUIDHandlerImplementation { - - public UUIDHandlerImplementationTest(OfflinePlayerService wrapper) { - super(wrapper); - } - - @Before public void setUp() throws Exception { - DBFunc.dbManager = new AbstractDBTest(); - } - - @Override public void fetchUUID(String name, RunnableVal ifFetch) { - - } -} From ea41c842bc379af8a2ebc8d152da23cd5202b748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 20 May 2020 00:31:59 +0200 Subject: [PATCH 020/121] Fix a bunch of minor issues --- Bukkit/pom.xml | 6 ++ .../bukkit/listener/PaperListener.java | 4 +- .../com/plotsquared/core/command/Add.java | 7 ++ .../com/plotsquared/core/command/Debug.java | 7 ++ .../com/plotsquared/core/command/Owner.java | 2 +- .../com/plotsquared/core/command/Trust.java | 7 ++ .../com/plotsquared/core/util/MainUtil.java | 64 +++++++++++--- .../core/uuid/CacheUUIDService.java | 3 + .../plotsquared/core/uuid/UUIDPipeline.java | 85 +++++++++++++++---- .../plotsquared/core/uuid/UUIDService.java | 10 +++ 10 files changed, 160 insertions(+), 35 deletions(-) diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index 1eace8462..68e49c901 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -66,6 +66,12 @@ + + com.github.pavog + SquirrelID + 0.6.1 + compile + com.sk89q.worldedit worldedit-core diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java index 2ff395c52..925798a8a 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java @@ -318,7 +318,6 @@ public class PaperListener implements Listener { } @EventHandler public void onAsyncTabCompletion(final AsyncTabCompleteEvent event) { - PlotSquared.debug("ASYNC COMPLETION"); String buffer = event.getBuffer(); if (!(event.getSender() instanceof Player)) { return; @@ -332,7 +331,7 @@ public class PaperListener implements Listener { final String[] unprocessedArgs = buffer.split(Pattern.quote(" ")); if (unprocessedArgs.length == 1) { return; // We don't do anything in this case - } else if (!Arrays.asList("plots", "p", "plotsquared", "plot2", "p2", "ps", "2", "plotme", "plotz", "ap") + } else if (!Arrays.asList("plot", "plots", "p", "plotsquared", "plot2", "p2", "ps", "2", "plotme", "plotz", "ap") .contains(unprocessedArgs[0].toLowerCase(Locale.ENGLISH))) { return; } @@ -350,7 +349,6 @@ public class PaperListener implements Listener { } event.setCompletions(result); event.setHandled(true); - PlotSquared.debug("ASYNC COMPLETION HANDLED"); } catch (final Exception ignored) {} } diff --git a/Core/src/main/java/com/plotsquared/core/command/Add.java b/Core/src/main/java/com/plotsquared/core/command/Add.java index bbd0b5559..3a3aa7ab7 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Add.java +++ b/Core/src/main/java/com/plotsquared/core/command/Add.java @@ -32,9 +32,12 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; +import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -127,4 +130,8 @@ public class Add extends Command { return future; } + @Override public Collection tab(final PlotPlayer player, final String[] args, final boolean space) { + return TabCompletions.completePlayers(String.join(",", args).trim(), Collections.emptyList()); + } + } diff --git a/Core/src/main/java/com/plotsquared/core/command/Debug.java b/Core/src/main/java/com/plotsquared/core/command/Debug.java index 7d0ced991..e104da337 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Debug.java +++ b/Core/src/main/java/com/plotsquared/core/command/Debug.java @@ -34,8 +34,10 @@ import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.entity.EntityCategories; import com.plotsquared.core.util.entity.EntityCategory; import com.plotsquared.core.util.task.TaskManager; +import com.plotsquared.core.uuid.UUIDMapping; import com.sk89q.worldedit.world.entity.EntityType; +import java.util.Collection; import java.util.Comparator; import java.util.Map; @@ -65,6 +67,11 @@ public class Debug extends SubCommand { .currentThread().getName())); return true; } + if (args.length > 0 && "uuids".equalsIgnoreCase(args[0])) { + final Collection mappings = PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); + MainUtil.sendMessage(player, String.format("There are %d cached UUIDs", mappings.size())); + return true; + } if (args.length > 0 && "entitytypes".equalsIgnoreCase(args[0])) { EntityCategories.init(); player.sendMessage(Captions.PREFIX.getTranslated() + "§cEntity Categories: "); diff --git a/Core/src/main/java/com/plotsquared/core/command/Owner.java b/Core/src/main/java/com/plotsquared/core/command/Owner.java index cb436fad2..f19790dc5 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Owner.java +++ b/Core/src/main/java/com/plotsquared/core/command/Owner.java @@ -150,7 +150,7 @@ public class Owner extends SetCommand { if (throwable instanceof TimeoutException) { MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); } else if (throwable != null) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER); + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, value); } else { uuidConsumer.accept(uuid); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Trust.java b/Core/src/main/java/com/plotsquared/core/command/Trust.java index 8bcaced4e..4f9c15e38 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Trust.java +++ b/Core/src/main/java/com/plotsquared/core/command/Trust.java @@ -32,9 +32,12 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; +import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -126,4 +129,8 @@ public class Trust extends Command { return CompletableFuture.completedFuture(true); } + @Override public Collection tab(final PlotPlayer player, final String[] args, final boolean space) { + return TabCompletions.completePlayers(String.join(",", args).trim(), Collections.emptyList()); + } + } diff --git a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java index e214e382a..8546298b6 100644 --- a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java @@ -82,6 +82,7 @@ import java.util.Optional; import java.util.Scanner; import java.util.Set; import java.util.UUID; +import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Function; import java.util.function.IntConsumer; @@ -902,24 +903,61 @@ public class MainUtil { return (directory.delete()); } - /** - * Get a list of names given a list of uuids.
- * - Uses the format {@link Captions#PLOT_USER_LIST} for the returned string - * - * @param uuids - * @return - */ - public static String getPlayerList(Collection uuids) { - ArrayList l = new ArrayList<>(uuids); - if (l.size() < 1) { + /* + @NotNull public static String getName(UUID owner) { + if (owner == null) { return Captions.NONE.getTranslated(); } - List users = - l.stream().map(MainUtil::getName).sorted().collect(Collectors.toList()); + if (owner.equals(DBFunc.EVERYONE)) { + return Captions.EVERYONE.getTranslated(); + } + if (owner.equals(DBFunc.SERVER)) { + return Captions.SERVER.getTranslated(); + } + String name = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(owner, Settings.UUID.BLOCKING_TIMEOUT); + if (name == null) { + return Captions.UNKNOWN.getTranslated(); + } + return name; + } + */ + + /** + * Get a list of names given a list of UUIDs. + * - Uses the format {@link Captions#PLOT_USER_LIST} for the returned string + */ + public static String getPlayerList(final Collection uuids) { + if (uuids.size() < 1) { + return Captions.NONE.getTranslated(); + } + + final List players = new LinkedList<>(); + final List users = new LinkedList<>(); + for (final UUID uuid : uuids) { + if (uuid == null) { + users.add(Captions.NONE.getTranslated()); + } else if (DBFunc.EVERYONE.equals(uuid)) { + users.add(Captions.EVERYONE.getTranslated()); + } else if (DBFunc.SERVER.equals(uuid)) { + users.add(Captions.SERVER.getTranslated()); + } else { + players.add(uuid); + } + } + + try { + for (final UUIDMapping mapping : PlotSquared.get().getImpromptuUUIDPipeline().getNames(players).get(Settings.UUID.BLOCKING_TIMEOUT, + TimeUnit.MILLISECONDS)) { + users.add(mapping.getUsername()); + } + } catch (final Exception e) { + e.printStackTrace(); + } + String c = Captions.PLOT_USER_LIST.getTranslated(); StringBuilder list = new StringBuilder(); for (int x = 0; x < users.size(); x++) { - if (x + 1 == l.size()) { + if (x + 1 == uuids.size()) { list.append(c.replace("%user%", users.get(x)).replace(",", "")); } else { list.append(c.replace("%user%", users.get(x))); diff --git a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java index 32bbbb6bc..484146dae 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java @@ -78,4 +78,7 @@ public class CacheUUIDService implements UUIDService, Consumer return this.usernameCache.asMap().values(); } + @Override public boolean canBeSynchronous() { + return true; + } } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 12d49abaa..3518fa5f8 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -27,6 +27,7 @@ package com.plotsquared.core.uuid; import com.google.common.collect.Lists; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.util.ThreadUtils; import com.plotsquared.core.util.task.TaskManager; @@ -156,10 +157,14 @@ public class UUIDPipeline { @Nullable public UUID getSingle(@NotNull final String username, final long timeout) { ThreadUtils.catchSync("Blocking UUID retrieval from the main thread"); try { - this.getUUIDs(Collections.singletonList(username)).get(timeout, TimeUnit.MILLISECONDS); + final List mappings = this.getUUIDs(Collections.singletonList(username)).get(timeout, TimeUnit.MILLISECONDS); + if (mappings.size() == 1) { + return mappings.get(0).getUuid(); + } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } catch (TimeoutException ignored) { + PlotSquared.log(Captions.PREFIX + " (UUID) Request for " + username + " timed out"); // This is completely valid, we just don't care anymore } return null; @@ -175,10 +180,14 @@ public class UUIDPipeline { @Nullable public String getSingle(@NotNull final UUID uuid, final long timeout) { ThreadUtils.catchSync("Blocking username retrieval from the main thread"); try { - this.getNames(Collections.singletonList(uuid)).get(timeout, TimeUnit.MILLISECONDS); + final List mappings = this.getNames(Collections.singletonList(uuid)).get(timeout, TimeUnit.MILLISECONDS); + if (mappings.size() == 1) { + return mappings.get(0).getUsername(); + } } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } catch (TimeoutException ignored) { + PlotSquared.log(Captions.PREFIX + " (UUID) Request for " + uuid + " timed out"); // This is completely valid, we just don't care anymore } return null; @@ -274,25 +283,45 @@ public class UUIDPipeline { if (requests.isEmpty()) { return CompletableFuture.completedFuture(Collections.emptyList()); } - final List serviceList = this.getServiceListInstance(); - return CompletableFuture.supplyAsync(() -> { - final List mappings = new ArrayList<>(requests.size()); - final List remainingRequests = new ArrayList<>(requests); - for (final UUIDService service : serviceList) { - if (remainingRequests.isEmpty()) { - break; - } + final List serviceList = this.getServiceListInstance(); + final List mappings = new ArrayList<>(requests.size()); + final List remainingRequests = new ArrayList<>(requests); + + for (final UUIDService service : serviceList) { + // We can chain multiple synchronous + // ones in a row + if (service.canBeSynchronous()) { final List completedRequests = service.getNames(remainingRequests); for (final UUIDMapping mapping : completedRequests) { remainingRequests.remove(mapping.getUuid()); } mappings.addAll(completedRequests); + } else { + break; + } + if (remainingRequests.isEmpty()) { + return CompletableFuture.completedFuture(mappings); + } + } + + return CompletableFuture.supplyAsync(() -> { + for (final UUIDService service : serviceList) { + final List completedRequests = service.getNames(remainingRequests); + for (final UUIDMapping mapping : completedRequests) { + remainingRequests.remove(mapping.getUuid()); + } + mappings.addAll(completedRequests); + if (remainingRequests.isEmpty()) { + break; + } } if (mappings.size() == requests.size()) { this.consume(mappings); return mappings; + } else if (Settings.DEBUG) { + PlotSquared.log("Failed to find all usernames"); } throw new ServiceError("End of pipeline"); @@ -310,25 +339,45 @@ public class UUIDPipeline { if (requests.isEmpty()) { return CompletableFuture.completedFuture(Collections.emptyList()); } - final List serviceList = this.getServiceListInstance(); - return CompletableFuture.supplyAsync(() -> { - final List mappings = new ArrayList<>(requests.size()); - final List remainingRequests = new ArrayList<>(requests); - for (final UUIDService service : serviceList) { - if (remainingRequests.isEmpty()) { - break; - } + final List serviceList = this.getServiceListInstance(); + final List mappings = new ArrayList<>(requests.size()); + final List remainingRequests = new ArrayList<>(requests); + + for (final UUIDService service : serviceList) { + // We can chain multiple synchronous + // ones in a row + if (service.canBeSynchronous()) { final List completedRequests = service.getUUIDs(remainingRequests); for (final UUIDMapping mapping : completedRequests) { remainingRequests.remove(mapping.getUsername()); } mappings.addAll(completedRequests); + } else { + break; + } + if (remainingRequests.isEmpty()) { + return CompletableFuture.completedFuture(mappings); + } + } + + return CompletableFuture.supplyAsync(() -> { + for (final UUIDService service : serviceList) { + final List completedRequests = service.getUUIDs(remainingRequests); + for (final UUIDMapping mapping : completedRequests) { + remainingRequests.remove(mapping.getUsername()); + } + mappings.addAll(completedRequests); + if (remainingRequests.isEmpty()) { + break; + } } if (mappings.size() == requests.size()) { this.consume(mappings); return mappings; + } else if (Settings.DEBUG) { + PlotSquared.log("Failed to find all UUIDs"); } throw new ServiceError("End of pipeline"); diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java index 25588305e..3b6419bd6 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java @@ -65,4 +65,14 @@ public interface UUIDService { return Collections.emptyList(); } + /** + * Check whether or not this service can be safely used synchronously + * without blocking the server for an extended amount of time. + * + * @return True if the service can be used synchronously + */ + default boolean canBeSynchronous() { + return false; + } + } From 0160c2bb551d9cbab5659f4c2f2bb57a99b6b2d2 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 20 May 2020 08:43:58 +0100 Subject: [PATCH 021/121] Add setCuboids method to RegionManager - Allow FAWE to take charge of big operations like /plot set all --- .../core/generator/ClassicPlotManager.java | 68 +++++-------------- .../plotsquared/core/util/RegionManager.java | 16 +++++ 2 files changed, 32 insertions(+), 52 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java index 022f7037d..52557144e 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java +++ b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java @@ -36,6 +36,7 @@ import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.BlockUtil; import com.plotsquared.core.util.MathMan; +import com.plotsquared.core.util.RegionManager; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.block.BlockTypes; @@ -92,75 +93,38 @@ public class ClassicPlotManager extends SquarePlotManager { public boolean setFloor(PlotId plotId, Pattern blocks) { Plot plot = classicPlotWorld.getPlotAbs(plotId); - LocalBlockQueue queue = classicPlotWorld.getQueue(false); if (plot.isBasePlot()) { - for (CuboidRegion region : plot.getRegions()) { - Location pos1 = - new Location(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), - classicPlotWorld.PLOT_HEIGHT, region.getMinimumPoint().getZ()); - Location pos2 = - new Location(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), - classicPlotWorld.PLOT_HEIGHT, region.getMaximumPoint().getZ()); - queue.setCuboid(pos1, pos2, blocks); - } + return RegionManager.manager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, + classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.PLOT_HEIGHT); } - return queue.enqueue(); + return false; } public boolean setAll(PlotId plotId, Pattern blocks) { Plot plot = classicPlotWorld.getPlotAbs(plotId); - if (!plot.isBasePlot()) { - return false; + if (plot.isBasePlot()) { + return RegionManager.manager + .setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, getWorldHeight()); } - LocalBlockQueue queue = classicPlotWorld.getQueue(false); - int maxY = getWorldHeight(); - for (CuboidRegion region : plot.getRegions()) { - Location pos1 = - new Location(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), 1, - region.getMinimumPoint().getZ()); - Location pos2 = - new Location(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), maxY, - region.getMaximumPoint().getZ()); - queue.setCuboid(pos1, pos2, blocks); - } - return queue.enqueue(); + return false; } public boolean setAir(PlotId plotId, Pattern blocks) { Plot plot = classicPlotWorld.getPlotAbs(plotId); - if (!plot.isBasePlot()) { - return false; + if (plot.isBasePlot()) { + return RegionManager.manager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, + classicPlotWorld.PLOT_HEIGHT + 1, getWorldHeight()); } - LocalBlockQueue queue = classicPlotWorld.getQueue(false); - int maxY = getWorldHeight(); - for (CuboidRegion region : plot.getRegions()) { - Location pos1 = - new Location(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), - classicPlotWorld.PLOT_HEIGHT + 1, region.getMinimumPoint().getZ()); - Location pos2 = - new Location(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), maxY, - region.getMaximumPoint().getZ()); - queue.setCuboid(pos1, pos2, blocks); - } - return queue.enqueue(); + return false; } public boolean setMain(PlotId plotId, Pattern blocks) { Plot plot = classicPlotWorld.getPlotAbs(plotId); - if (!plot.isBasePlot()) { - return false; + if (plot.isBasePlot()) { + return RegionManager.manager.setCuboids(classicPlotWorld, plot.getRegions(), blocks, 1, + classicPlotWorld.PLOT_HEIGHT - 1); } - LocalBlockQueue queue = classicPlotWorld.getQueue(false); - for (CuboidRegion region : plot.getRegions()) { - Location pos1 = - new Location(classicPlotWorld.getWorldName(), region.getMinimumPoint().getX(), 1, - region.getMinimumPoint().getZ()); - Location pos2 = - new Location(classicPlotWorld.getWorldName(), region.getMaximumPoint().getX(), - classicPlotWorld.PLOT_HEIGHT - 1, region.getMaximumPoint().getZ()); - queue.setCuboid(pos1, pos2, blocks); - } - return queue.enqueue(); + return false; } public boolean setMiddle(PlotId plotId, Pattern blocks) { diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java index 5ab1a8350..ab3333a19 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionManager.java @@ -28,8 +28,11 @@ package com.plotsquared.core.util; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.TaskManager; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; @@ -147,6 +150,19 @@ public abstract class RegionManager { }); } + public boolean setCuboids(final PlotArea area, final Set regions, + final Pattern blocks, int minY, int maxY) { + LocalBlockQueue queue = area.getQueue(false); + for (CuboidRegion region : regions) { + Location pos1 = new Location(area.getWorldName(), region.getMinimumPoint().getX(), minY, + region.getMinimumPoint().getZ()); + Location pos2 = new Location(area.getWorldName(), region.getMaximumPoint().getX(), maxY, + region.getMaximumPoint().getZ()); + queue.setCuboid(pos1, pos2, blocks); + } + return queue.enqueue(); + } + /** * Copy a region to a new location (in the same world) */ From 525ba648ae0910c16e4f65fc332967b13edc92fb Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 20 May 2020 09:44:45 +0100 Subject: [PATCH 022/121] ignore build/ and update bukkit pom.xml apparently --- .gitignore | 1 + Bukkit/pom.xml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.gitignore b/.gitignore index 24f46cd56..3423dd222 100644 --- a/.gitignore +++ b/.gitignore @@ -142,3 +142,4 @@ p2error.txt *.bat Nukkit/build/resources/main/plugin.yml docs/ +build/ diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index 40202c32e..1eace8462 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -59,6 +59,12 @@ Core 0.6.0-SNAPSHOT compile + + + * + * + +
com.sk89q.worldedit From 2417dace2d9a9d4a6dfd92e068a3f81bb01e4dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 20 May 2020 15:12:09 +0200 Subject: [PATCH 023/121] Add UUID caching --- .../com/plotsquared/bukkit/BukkitMain.java | 60 ++++++++++++++++++- .../bukkit/uuid/SQLiteUUIDService.java | 21 +++++++ .../com/plotsquared/core/PlotSquared.java | 17 ------ 3 files changed, 80 insertions(+), 18 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 90a717fd5..7effa5b4a 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -136,10 +136,17 @@ import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Queue; +import java.util.Set; import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import static com.plotsquared.core.util.PremiumVerification.getDownloadID; import static com.plotsquared.core.util.PremiumVerification.getResourceID; @@ -243,6 +250,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain final OfflinePlayerUUIDService offlinePlayerUUIDService = new OfflinePlayerUUIDService(); impromptuPipeline.registerService(offlinePlayerUUIDService); backgroundPipeline.registerService(offlinePlayerUUIDService); + + final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService(); if (!Settings.UUID.OFFLINE) { // If running Paper we'll also try to use their profiles if (PaperLib.isPaper()) { @@ -250,7 +259,6 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain impromptuPipeline.registerService(paperUUIDService); backgroundPipeline.registerService(paperUUIDService); } - final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService(); impromptuPipeline.registerService(sqLiteUUIDService); backgroundPipeline.registerService(sqLiteUUIDService); impromptuPipeline.registerConsumer(sqLiteUUIDService); @@ -259,9 +267,15 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain impromptuPipeline.registerService(impromptuMojangService); final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT); backgroundPipeline.registerService(backgroundMojangService); + } else { + impromptuPipeline.registerService(sqLiteUUIDService); + backgroundPipeline.registerService(sqLiteUUIDService); + impromptuPipeline.registerConsumer(sqLiteUUIDService); + backgroundPipeline.registerConsumer(sqLiteUUIDService); } impromptuPipeline.storeImmediately("*", DBFunc.EVERYONE); + this.startUuidCatching(sqLiteUUIDService, cacheUUIDService); if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) { new Placeholders().register(); @@ -384,6 +398,50 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain } } + private void startUuidCatching(@NotNull final SQLiteUUIDService sqLiteUUIDService, + @NotNull final CacheUUIDService cacheUUIDService) { + // Load all uuids into a big chunky boi queue + final Queue uuidQueue = new LinkedBlockingQueue<>(); + PlotSquared.get().forEachPlotRaw(plot -> { + final Set uuids = new HashSet<>(); + uuids.add(plot.getOwnerAbs()); + uuids.addAll(plot.getMembers()); + uuids.addAll(plot.getTrusted()); + uuids.addAll(plot.getDenied()); + for (final UUID uuid : uuids) { + if (!uuidQueue.contains(uuid)) { + uuidQueue.add(uuid); + } + } + }); + PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) " + uuidQueue.size() + " UUIDs will be cached."); + + Executors.newSingleThreadScheduledExecutor().schedule(() -> { + // Begin by reading all the SQLite cache at once + cacheUUIDService.accept(sqLiteUUIDService.getAll()); + // Now fetch names for all known UUIDs + final int totalSize = uuidQueue.size(); + int read = 0; + PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) PlotSquared will fetch UUIDs in groups of " + + Settings.UUID.BACKGROUND_LIMIT); + final List uuidList = new ArrayList<>(Settings.UUID.BACKGROUND_LIMIT); + while (!uuidQueue.isEmpty()) { + for (int i = 0; i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) { + uuidList.add(uuidQueue.poll()); + read++; + } + try { + PlotSquared.get().getBackgroundUUIDPipeline().getNames(uuidList).get(); + } catch (final InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + final double percentage = ((double) read / (double) totalSize) * 100.0D; + PlotSquared.log(Captions.PREFIX.getTranslated() + String.format("(UUID) PlotSquared has cached %.1f%% of UUIDs", percentage)); + } + PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) PlotSquared has cached all UUIDs"); + }, 10, TimeUnit.SECONDS); + } + @Override public void onDisable() { PlotSquared.get().disable(); Bukkit.getScheduler().cancelTasks(this); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java index 6ad2f01ce..dc251bec4 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java @@ -37,6 +37,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import java.util.UUID; import java.util.function.Consumer; @@ -121,4 +122,24 @@ public class SQLiteUUIDService implements UUIDService, Consumer getAll() { + final List mappings = new LinkedList<>(); + try (final PreparedStatement statement = getConnection().prepareStatement("SELECT * FROM `usercache`")) { + try (final ResultSet resultSet = statement.executeQuery()) { + while (resultSet.next()) { + mappings.add(new UUIDMapping(UUID.fromString(resultSet.getString("uuid")), resultSet.getString("username"))); + } + } + } catch (final Exception e) { + e.printStackTrace(); + } + return mappings; + } + + } diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 4d632ff2f..6c3b78ba3 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -424,23 +424,6 @@ public class PlotSquared { } } - private void startUuidCatching() { - TaskManager.runTaskLater(() -> { - debug("Starting UUID caching"); - /*UUIDHandler.startCaching(() -> { - forEachPlotRaw(plot -> { - if (plot.hasOwner() && plot.temp != -1) { - if (UUIDHandler.getName(plot.getOwnerAbs()) == null) { - UUIDHandler.implementation.unknown.add(plot.getOwnerAbs()); - } - } - }); - startExpiryTasks(); - });*/ - // TODO: Re-implement - }, 20); - } - private void startExpiryTasks() { if (Settings.Enabled_Components.PLOT_EXPIRY) { ExpireManager.IMP = new ExpireManager(); From f01b242e4adac1666b7284755a5df53532dc7f22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 20 May 2020 15:26:20 +0200 Subject: [PATCH 024/121] For sign updating to be scheduled asynchronously. It then forces it back on the main thread, so it's fine, but this way we can safely wait for the UUID mapping to be fetched. --- Core/src/main/java/com/plotsquared/core/plot/Plot.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 9ac482be6..df9ee12c4 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -1046,9 +1046,11 @@ public class Plot { } if (createSign) { GlobalBlockQueue.IMP.addEmptyTask(() -> { - for (Plot current : plots) { - current.setSign(MainUtil.getName(current.getOwnerAbs())); - } + TaskManager.runTaskAsync(() -> { + for (Plot current : plots) { + current.setSign(MainUtil.getName(current.getOwnerAbs())); + } + }); }); } if (createRoad) { From 3ede0447b024b34f62150091707d6a5627d0768f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:06:04 +0200 Subject: [PATCH 025/121] Fix up the plot area nightmare --- Core/build.gradle | 2 + .../com/plotsquared/core/plot/PlotWorld.java | 105 +++++++ .../plot/world/DefaultPlotAreaManager.java | 269 +++++------------- .../core/plot/world/PlotAreaManager.java | 3 +- .../core/plot/world/ScatteredPlotWorld.java | 110 +++++++ .../core/plot/world/StandardPlotWorld.java | 65 +++++ .../com/plotsquared/core/util/RegionUtil.java | 10 + 7 files changed, 372 insertions(+), 192 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java create mode 100644 Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java create mode 100644 Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java diff --git a/Core/build.gradle b/Core/build.gradle index ee6edfda2..8581a39a4 100644 --- a/Core/build.gradle +++ b/Core/build.gradle @@ -16,6 +16,7 @@ dependencies { testAnnotationProcessor("org.projectlombok:lombok:1.18.8") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.3.72") implementation("org.jetbrains:annotations:19.0.0") + implementation 'com.github.davidmoten:rtree:0.8.7' } sourceCompatibility = 1.8 @@ -73,6 +74,7 @@ shadowJar { include(dependency("net.kyori:text-serializer-gson:3.0.2")) include(dependency("net.kyori:text-serializer-legacy:3.0.2")) include(dependency("net.kyori:text-serializer-plain:3.0.2")) + include(dependency("com.github.davidmoten:rtree:0.8.7")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("org.json", "com.plotsquared.json") { diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java new file mode 100644 index 000000000..ed7b854c2 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java @@ -0,0 +1,105 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.plot; + +import com.plotsquared.core.location.Location; +import com.sk89q.worldedit.regions.CuboidRegion; +import lombok.EqualsAndHashCode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * A world that contains plots + */ +@EqualsAndHashCode +public abstract class PlotWorld { + + private final String world; + + /** + * Create a new plot world with a given world name + * + * @param world World name + */ + protected PlotWorld(@NotNull final String world) { + this.world = world; + } + + /** + * Get the plot area that contains the given location, or null + * if the location is not a part of a plot area. + * + * @param location Location + * @return Containing plot area, or null + */ + @Nullable public abstract PlotArea getArea(@NotNull final Location location); + + /** + * Get all plot areas in the world + * + * @return All plot areas in the world + */ + @NotNull public abstract Collection getAreas(); + + /** + * Get all plot areas in a specified region + * + * @param region Region + * @return All areas in the region + */ + @NotNull public abstract Collection getAreasInRegion( + @NotNull final CuboidRegion region); + + /** + * Register a new area in the world + * + * @param area Plot area + */ + public void addArea(@NotNull final PlotArea area) { + throw new UnsupportedOperationException("This world type does not allow adding new areas"); + } + + /** + * Remove an area from the world + * + * @param area Plot area + */ + public void removeArea(@NotNull final PlotArea area) { + throw new UnsupportedOperationException("This world type does not allow removing areas"); + } + + /** + * Get the world name + * + * @return World name + */ + public String getWorld() { + return this.world; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java index 833bf3d4f..f86b5b8b6 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java @@ -25,143 +25,96 @@ */ package com.plotsquared.core.plot.world; -import com.plotsquared.core.collection.QuadMap; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.plot.PlotWorld; import com.plotsquared.core.util.StringMan; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; import java.util.Set; public class DefaultPlotAreaManager implements PlotAreaManager { final PlotArea[] noPlotAreas = new PlotArea[0]; - // All plot areas mapped by world - private final HashMap plotAreaMap = new HashMap<>(); - // All plot areas mapped by position - private final HashMap> plotAreaGrid = new HashMap<>(); - private final HashSet plotAreaHashCheck = new HashSet<>(); - // All plot areas - private PlotArea[] plotAreas = new PlotArea[0]; + + private final Map plotWorlds = new HashMap<>(); // Optimization if there are no hash collisions private boolean plotAreaHasCollision = false; - private String[] worlds = new String[0]; @Override public PlotArea[] getAllPlotAreas() { - return plotAreas; - } - - @Override public PlotArea getApplicablePlotArea(Location location) { - switch (this.plotAreas.length) { - case 0: - return null; - case 1: - return this.plotAreas[0].getWorldHash() == location.getWorld().hashCode() - && this.plotAreas[0].contains(location) && (!this.plotAreaHasCollision - || location.getWorld().equals(this.plotAreas[0].getWorldName())) ? - this.plotAreas[0] : - null; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - String world = location.getWorld(); - int hash = world.hashCode(); - for (PlotArea area : this.plotAreas) { - if (hash == area.getWorldHash()) { - if (area.contains(location.getX(), location.getZ()) && ( - !this.plotAreaHasCollision || world.equals(area.getWorldName()))) { - return area; - } - } - } - return null; - default: - PlotArea[] areas = this.plotAreaMap.get(location.getWorld()); - if (areas == null) { - return null; - } - int z; - int x; - switch (areas.length) { - case 1: - return areas[0]; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - x = location.getX(); - z = location.getZ(); - for (PlotArea area : areas) { - if (area.contains(x, z)) { - return area; - } - } - return null; - default: - QuadMap search = this.plotAreaGrid.get(location.getWorld()); - return search.get(location.getX(), location.getZ()); - } + final Set area = new HashSet<>(); + for (final PlotWorld world : plotWorlds.values()) { + area.addAll(world.getAreas()); } + return area.toArray(new PlotArea[0]); } - @Override public void addPlotArea(PlotArea plotArea) { - HashSet localAreas = - new HashSet<>(Arrays.asList(getPlotAreas(plotArea.getWorldName(), null))); - HashSet globalAreas = new HashSet<>(Arrays.asList(plotAreas)); - localAreas.add(plotArea); - globalAreas.add(plotArea); - this.plotAreas = globalAreas.toArray(new PlotArea[0]); - this.plotAreaMap.put(plotArea.getWorldName(), localAreas.toArray(new PlotArea[0])); - QuadMap map = this.plotAreaGrid.get(plotArea.getWorldName()); - if (map == null) { - map = new QuadMap(Integer.MAX_VALUE, 0, 0) { - @Override public CuboidRegion getRegion(PlotArea value) { - return value.getRegion(); - } - }; - this.plotAreaGrid.put(plotArea.getWorldName(), map); + @Override @Nullable public PlotArea getApplicablePlotArea(final Location location) { + if (location == null) { + return null; } - map.add(plotArea); + final PlotWorld world = this.plotWorlds.get(location.getWorld()); + if (world == null) { + return null; + } + return world.getArea(location); } - @Override public void removePlotArea(PlotArea area) { - ArrayList globalAreas = new ArrayList<>(Arrays.asList(plotAreas)); - globalAreas.remove(area); - this.plotAreas = globalAreas.toArray(new PlotArea[0]); - if (globalAreas.isEmpty()) { - this.plotAreaMap.remove(area.getWorldName()); - this.plotAreaGrid.remove(area.getWorldName()); + @Override public void addPlotArea(final PlotArea plotArea) { + PlotWorld world = this.plotWorlds.get(plotArea.getWorldName()); + if (world != null) { + if (world instanceof StandardPlotWorld && world.getAreas().isEmpty()) { + this.plotWorlds.remove(plotArea.getWorldName()); + } else { + world.addArea(plotArea); + return; + } + } + if (plotArea.getType() != PlotAreaType.PARTIAL) { + world = new StandardPlotWorld(plotArea.getWorldName(), plotArea); } else { - this.plotAreaMap.put(area.getWorldName(), globalAreas.toArray(new PlotArea[0])); - this.plotAreaGrid.get(area.getWorldName()).remove(area); + world = new ScatteredPlotWorld(plotArea.getWorldName()); + world.addArea(plotArea); + } + this.plotWorlds.put(plotArea.getWorldName(), world); + } + + @Override public void removePlotArea(final PlotArea area) { + final PlotWorld world = this.plotWorlds.get(area.getWorldName()); + if (world == null) { + return; + } + if (world instanceof StandardPlotWorld) { + this.plotWorlds.remove(world.getWorld()); + } else { + world.removeArea(area); + if (world.getAreas().isEmpty()) { + this.plotWorlds.remove(world.getWorld()); + } } } - @Override public PlotArea getPlotArea(String world, String id) { - PlotArea[] areas = this.plotAreaMap.get(world); - if (areas == null) { + @Override public PlotArea getPlotArea(final String world, final String id) { + final PlotWorld plotWorld = this.plotWorlds.get(world); + if (plotWorld == null) { return null; } - if (areas.length == 1) { - return areas[0]; - } else if (id == null) { + final List areas = new ArrayList<>(plotWorld.getAreas()); + if (areas.size() == 1) { + return areas.get(0); + } + if (id == null) { return null; } - for (PlotArea area : areas) { + for (final PlotArea area : areas) { if (StringMan.isEqual(id, area.getId())) { return area; } @@ -169,103 +122,37 @@ public class DefaultPlotAreaManager implements PlotAreaManager { return null; } - @Override public PlotArea getPlotArea(@NotNull Location location) { - switch (this.plotAreas.length) { - case 0: - return null; - case 1: - PlotArea pa = this.plotAreas[0]; - if (pa.contains(location)) { - return pa; - } else { - return null; - } - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - String world = location.getWorld(); - int hash = world.hashCode(); - for (PlotArea area : this.plotAreas) { - if (hash == area.getWorldHash()) { - if (area.contains(location.getX(), location.getZ()) && ( - !this.plotAreaHasCollision || world.equals(area.getWorldName()))) { - return area; - } - } - } - return null; - default: - PlotArea[] areas = this.plotAreaMap.get(location.getWorld()); - if (areas == null) { - return null; - } - int x; - int z; - switch (areas.length) { - case 0: - PlotArea a = areas[0]; - return a.contains(location.getX(), location.getZ()) ? a : null; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - x = location.getX(); - z = location.getZ(); - for (PlotArea area : areas) { - if (area.contains(x, z)) { - return area; - } - } - return null; - default: - QuadMap search = this.plotAreaGrid.get(location.getWorld()); - return search.get(location.getX(), location.getZ()); - } - } + @Override public PlotArea getPlotArea(@NotNull final Location location) { + return this.getApplicablePlotArea(location); } - @Override public PlotArea[] getPlotAreas(String world, CuboidRegion region) { - if (region == null) { - PlotArea[] areas = this.plotAreaMap.get(world); - if (areas == null) { - return noPlotAreas; - } - return areas; - } - QuadMap areas = this.plotAreaGrid.get(world); - if (areas == null) { + @Override public PlotArea[] getPlotAreas(final String world, final CuboidRegion region) { + final PlotWorld plotWorld = this.plotWorlds.get(world); + if (plotWorld == null) { return noPlotAreas; - } else { - Set found = areas.get(region); - return found.toArray(new PlotArea[0]); } + if (region == null) { + return plotWorld.getAreas().toArray(new PlotArea[0]); + } + return plotWorld.getAreasInRegion(region).toArray(new PlotArea[0]); } - @Override public void addWorld(String worldName) { - if (!this.plotAreaHasCollision && !this.plotAreaHashCheck.add(worldName.hashCode())) { - this.plotAreaHasCollision = true; + @Override public void addWorld(final String worldName) { + PlotWorld world = this.plotWorlds.get(worldName); + if (world != null) { + return; } - Set tmp = new LinkedHashSet<>(); - Collections.addAll(tmp, worlds); - tmp.add(worldName); - worlds = tmp.toArray(new String[0]); + // Create a new empty world. When a new area is added + // the world will be re-recreated with the correct type + world = new StandardPlotWorld(worldName, null); + this.plotWorlds.put(worldName, world); } - @Override public void removeWorld(String worldName) { - Set tmp = new LinkedHashSet<>(); - Collections.addAll(tmp, worlds); - tmp.remove(worldName); - worlds = tmp.toArray(new String[0]); + @Override public void removeWorld(final String worldName) { + this.plotWorlds.remove(worldName); } @Override public String[] getAllWorlds() { - return worlds; + return this.plotWorlds.keySet().toArray(new String[0]); } } diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java index b6d23b3d4..34033cb2b 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java @@ -29,6 +29,7 @@ import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.PlotArea; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface PlotAreaManager { @@ -44,7 +45,7 @@ public interface PlotAreaManager { * @param location The location * @return An applicable area, or null */ - PlotArea getApplicablePlotArea(Location location); + @Nullable PlotArea getApplicablePlotArea(Location location); /** * Get the plot area, if there is any, for the given diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java new file mode 100644 index 000000000..78cb0b7b2 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java @@ -0,0 +1,110 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.plot.world; + +import com.github.davidmoten.rtree.Entry; +import com.github.davidmoten.rtree.RTree; +import com.github.davidmoten.rtree.geometry.Geometries; +import com.github.davidmoten.rtree.geometry.Geometry; +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotWorld; +import com.plotsquared.core.util.RegionUtil; +import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import rx.Observable; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Plot world that contains several plot areas (clusters) + */ +public class ScatteredPlotWorld extends PlotWorld { + + private final List areas = new LinkedList<>(); + private final Object treeLock = new Object(); + private RTree areaTree; + + /** + * Create a new plot world with a given world name + * + * @param world World name + */ + public ScatteredPlotWorld(@NotNull final String world) { + super(world); + } + + @Override @Nullable public PlotArea getArea(@NotNull final Location location) { + synchronized (this.treeLock) { + final Observable> area = + areaTree.search(Geometries.point(location.getX(), location.getZ())); + if (area.isEmpty().toBlocking().first()) { + return null; + } + return area.toBlocking().first().value(); + } + } + + @Override @NotNull public Collection getAreas() { + return Collections.unmodifiableCollection(this.areas); + } + + @Override public void addArea(@NotNull final PlotArea area) { + this.areas.add(area); + this.buildTree(); + } + + @Override public void removeArea(@NotNull final PlotArea area) { + this.areas.remove(area); + this.buildTree(); + } + + @Override @NotNull public Collection getAreasInRegion(@NotNull final CuboidRegion region) { + synchronized (this.treeLock) { + final List areas = new LinkedList<>(); + this.areaTree.search(RegionUtil.toRectangle(region)).toBlocking().forEach(entry -> areas.add(entry.value())); + return areas; + } + } + + /** + * Rebuild the area tree + */ + private void buildTree() { + synchronized (this.treeLock) { + this.areaTree = RTree.create(); + for (final PlotArea area : areas) { + this.areaTree = this.areaTree.add(area, + RegionUtil.toRectangle(area.getRegion())); + } + } + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java new file mode 100644 index 000000000..162cf0e9f --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java @@ -0,0 +1,65 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.plot.world; + +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotWorld; +import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; + +/** + * Ordinary plot world with a single plot area + */ +public class StandardPlotWorld extends PlotWorld { + + private final PlotArea area; + + public StandardPlotWorld(@NotNull final String world, @Nullable final PlotArea area) { + super(world); + this.area = area; + } + + @Override @Nullable public PlotArea getArea(@NotNull final Location location) { + return this.area; + } + + @Override @NotNull public Collection getAreas() { + if (this.area == null) { + return Collections.emptyList(); + } + return Collections.singletonList(this.area); + } + + @Override @NotNull public Collection getAreasInRegion(@NotNull final CuboidRegion region) { + return this.getAreas(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java b/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java index fe4d83a96..59b14651a 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java @@ -25,9 +25,13 @@ */ package com.plotsquared.core.util; +import com.github.davidmoten.rtree.geometry.Geometries; +import com.github.davidmoten.rtree.geometry.Rectangle; import com.plotsquared.core.plot.Plot; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; public class RegionUtil { public static CuboidRegion createRegion(int pos1x, int pos2x, int pos1z, int pos2z) { @@ -54,6 +58,12 @@ public class RegionUtil { .getY() && y <= max.getY(); } + @NotNull public static Rectangle toRectangle(@NotNull final CuboidRegion region) { + final BlockVector2 min = region.getMinimumPoint().toBlockVector2(); + final BlockVector2 max = region.getMaximumPoint().toBlockVector2(); + return Geometries.rectangle(min.getX(), min.getZ(), max.getX(), max.getZ()); + } + // Because WE (not fawe) lack this for CuboidRegion public static boolean intersects(CuboidRegion region, CuboidRegion other) { BlockVector3 regionMin = region.getMinimumPoint(); From 1c6075df2bed1308e1c2a01fa720c1f7be02a992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:06:37 +0200 Subject: [PATCH 026/121] Get rid of unused field --- .../plotsquared/core/plot/world/DefaultPlotAreaManager.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java index f86b5b8b6..9ce0b1623 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java @@ -44,10 +44,7 @@ import java.util.Set; public class DefaultPlotAreaManager implements PlotAreaManager { final PlotArea[] noPlotAreas = new PlotArea[0]; - private final Map plotWorlds = new HashMap<>(); - // Optimization if there are no hash collisions - private boolean plotAreaHasCollision = false; @Override public PlotArea[] getAllPlotAreas() { final Set area = new HashSet<>(); From 38a7c771bee6d2aef959e80535c9c67e7272a45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:23:36 +0200 Subject: [PATCH 027/121] Don't access tree until it has been created --- .../com/plotsquared/core/plot/world/ScatteredPlotWorld.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java index 78cb0b7b2..9f245a5ba 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java @@ -62,6 +62,9 @@ public class ScatteredPlotWorld extends PlotWorld { } @Override @Nullable public PlotArea getArea(@NotNull final Location location) { + if (this.areas.isEmpty()) { + return null; + } synchronized (this.treeLock) { final Observable> area = areaTree.search(Geometries.point(location.getX(), location.getZ())); @@ -87,6 +90,9 @@ public class ScatteredPlotWorld extends PlotWorld { } @Override @NotNull public Collection getAreasInRegion(@NotNull final CuboidRegion region) { + if (this.areas.isEmpty()) { + return Collections.emptyList(); + } synchronized (this.treeLock) { final List areas = new LinkedList<>(); this.areaTree.search(RegionUtil.toRectangle(region)).toBlocking().forEach(entry -> areas.add(entry.value())); From 3b7057ad4fe82ee0b9b451cee95612f771fd4e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 21:24:55 +0200 Subject: [PATCH 028/121] do a second attempt at fetching uuid batches even if it errors --- .../com/plotsquared/bukkit/BukkitMain.java | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 7effa5b4a..84ba2f591 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -425,18 +425,40 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) PlotSquared will fetch UUIDs in groups of " + Settings.UUID.BACKGROUND_LIMIT); final List uuidList = new ArrayList<>(Settings.UUID.BACKGROUND_LIMIT); - while (!uuidQueue.isEmpty()) { - for (int i = 0; i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) { - uuidList.add(uuidQueue.poll()); - read++; + + // Used to indicate that the second retrieval has been attempted + boolean secondRun = false; + + while (!uuidQueue.isEmpty() || !uuidList.isEmpty()) { + if (!uuidList.isEmpty() && secondRun) { + PlotSquared.log("Giving up on last batch. Fetching new batch instead."); + uuidList.clear(); + } + if (uuidList.isEmpty()) { + // Retrieve the secondRun variable to indicate that we're retrieving a + // fresh batch + secondRun = false; + // Populate the request list + for (int i = 0; i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) { + uuidList.add(uuidQueue.poll()); + read++; + } + } else { + // If the list isn't empty then this is a second run for + // an old batch, so we re-use the patch + secondRun = true; } try { PlotSquared.get().getBackgroundUUIDPipeline().getNames(uuidList).get(); + // Clear the list if we successfully index all the names + uuidList.clear(); + // Print progress + final double percentage = ((double) read / (double) totalSize) * 100.0D; + PlotSquared.log(Captions.PREFIX.getTranslated() + String.format("(UUID) PlotSquared has cached %.1f%% of UUIDs", percentage)); } catch (final InterruptedException | ExecutionException e) { + PlotSquared.log("Failed to retrieve that batch. Will try again."); e.printStackTrace(); } - final double percentage = ((double) read / (double) totalSize) * 100.0D; - PlotSquared.log(Captions.PREFIX.getTranslated() + String.format("(UUID) PlotSquared has cached %.1f%% of UUIDs", percentage)); } PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) PlotSquared has cached all UUIDs"); }, 10, TimeUnit.SECONDS); From 9752e5f62b41942cced1158901044a49e2bb831b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:48:32 +0200 Subject: [PATCH 029/121] Start working on single plot areas --- Core/pom.xml | 6 + .../com/plotsquared/core/command/Area.java | 106 ++++++++++++++++++ .../core/configuration/Captions.java | 10 ++ .../core/generator/HybridPlotWorld.java | 12 +- 4 files changed, 132 insertions(+), 2 deletions(-) diff --git a/Core/pom.xml b/Core/pom.xml index 280cd8b1a..4e53e831a 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -92,6 +92,12 @@ 1.3.72 runtime + + com.github.davidmoten + rtree + 0.8.7 + runtime + junit junit diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index f5d494868..fcb4993c7 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -33,6 +33,7 @@ import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.AugmentedUtils; import com.plotsquared.core.generator.HybridPlotWorld; import com.plotsquared.core.location.Location; +import com.plotsquared.core.player.ConsolePlayer; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaTerrainType; @@ -50,9 +51,18 @@ import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal3; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; +import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.Region; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Objects; @@ -74,6 +84,102 @@ public class Area extends SubCommand { return false; } switch (args[0].toLowerCase()) { + case "single": + if (player instanceof ConsolePlayer) { + MainUtil.sendMessage(player, Captions.IS_CONSOLE); + return false; + } + if (!Permissions.hasPermission(player, Captions.PERMISSION_AREA_CREATE)) { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_AREA_CREATE); + return false; + } + if (args.length < 2) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_NEEDS_NAME); + return false; + } + if (PlotSquared.get().getPlotArea(player.getLocation().getWorld(), args[1]) != null) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_NAME_TAKEN); + return false; + } + final LocalSession localSession = WorldEdit.getInstance().getSessionManager().getIfPresent(player.toActor()); + if (localSession == null) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION); + return false; + } + Region selectedRegion = null; + try { + selectedRegion = localSession.getSelection(((Player) player.toActor()).getWorld()); + } catch (final Exception ignored) {} + if (selectedRegion == null) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION); + return false; + } + if (selectedRegion.getWidth() != selectedRegion.getLength()) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_NOT_SQUARE); + return false; + } + if (PlotSquared.get().getPlotAreaManager().getPlotAreas( + Objects.requireNonNull(selectedRegion.getWorld()).getName(), CuboidRegion.makeCuboid(selectedRegion)).length != 0) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_OVERLAPPING); + } + // There's only one plot in the area... + final PlotId plotId = new PlotId(1, 1); + final HybridPlotWorld hybridPlotWorld = new HybridPlotWorld(player.getLocation().getWorld(), args[1], + Objects.requireNonNull(PlotSquared.imp()).getDefaultGenerator(), plotId, plotId); + // Plot size is the same as the region width + hybridPlotWorld.SIZE = (short) selectedRegion.getWidth(); + // We use a schematic generator + hybridPlotWorld.setTerrain(PlotAreaTerrainType.ALL); + // It is always a partial plot world + hybridPlotWorld.setType(PlotAreaType.PARTIAL); + // We save the schematic :D + final File parentFile = MainUtil.getFile(PlotSquared.imp().getDirectory(), "schematics" + File.separator + + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator + + hybridPlotWorld.getId()); + if (!parentFile.exists() && !parentFile.mkdirs()) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_COULD_NOT_MAKE_DIRECTORIES); + return false; + } + final File file = new File(parentFile, "plot.schem"); + try (final ClipboardWriter clipboardWriter = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file))) { + final BlockArrayClipboard clipboard = new BlockArrayClipboard(selectedRegion); + clipboardWriter.write(clipboard); + } catch (final Exception e) { + MainUtil.sendMessage(player, Captions.SINGLE_AREA_FAILED_TO_SAVE); + e.printStackTrace(); + return false; + } + // Now the schematic is saved, which is wonderful! + final SetupObject singleSetup = new SetupObject(); + singleSetup.world = hybridPlotWorld.getWorldName(); + singleSetup.id = hybridPlotWorld.getId(); + singleSetup.terrain = hybridPlotWorld.getTerrain(); + singleSetup.type = hybridPlotWorld.getType(); + singleSetup.plotManager = PlotSquared.imp().getPluginName(); + singleSetup.setupGenerator = PlotSquared.imp().getPluginName(); + singleSetup.step = hybridPlotWorld.getSettingNodes(); + singleSetup.max = plotId; + singleSetup.min = plotId; + Runnable singleRun = () -> { + final String world = SetupUtils.manager.setupWorld(singleSetup); + if (WorldUtil.IMP.isWorld(world)) { + PlotSquared.get().loadWorld(world, null); + Captions.SETUP_FINISHED.send(player); + player.teleport(WorldUtil.IMP.getSpawn(world), + TeleportCause.COMMAND); + } else { + MainUtil.sendMessage(player, + "An error occurred while creating the world: " + hybridPlotWorld + .getWorldName()); + } + }; + if (hasConfirmation(player)) { + CmdConfirm.addPending(player, + getCommandString() + " create pos2 (Creates world)", singleRun); + } else { + singleRun.run(); + } + return true; case "c": case "setup": case "create": diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 6238ec066..4e1fc9482 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -783,6 +783,16 @@ public enum Captions implements Caption { GENERIC_INVALID_CHOICE("invalid choice", "Generic"), // + // + SINGLE_AREA_MISSING_SELECTION("$2Error! You need to select a square region", "Single"), + SINGLE_AREA_NOT_SQUARE("$2Error! Your selection needs to be a square", "Single"), + SINGLE_AREA_OVERLAPPING("$2Error! Your selection overlaps with an existing plot area", "Single"), + SINGLE_AREA_NEEDS_NAME("$2Error! Please specify a plot name: /plot area single ", "Single"), + SINGLE_AREA_NAME_TAKEN("$2Error! The plot name is already taken", "Single"), + SINGLE_AREA_FAILED_TO_SAVE("$2Error! Failed to save the area schematic", "Single"), + SINGLE_AREA_COULD_NOT_MAKE_DIRECTORIES("$2Error! Failed to create the schematic directory", "Single"), + // + /** * Legacy Configuration Conversion */ diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java index da7f46a47..e8bb47f66 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java @@ -195,8 +195,16 @@ public class HybridPlotWorld extends ClassicPlotWorld { public void setupSchematics() throws SchematicHandler.UnsupportedFormatException { this.G_SCH = new HashMap<>(); this.G_SCH_B = new HashMap<>(); - File root = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), - "schematics/GEN_ROAD_SCHEMATIC/" + this.getWorldName()); + + // Try to determine root. This means that plot areas can have separate schematic + // directories + File root; + if (!(root = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), "schematics/GEN_ROAD_SCHEMATIC/" + + this.getWorldName() + "/" + this.getId())).exists()) { + root = MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), + "schematics/GEN_ROAD_SCHEMATIC/" + this.getWorldName()); + } + File schematic1File = new File(root, "sideroad.schem"); if (!schematic1File.exists()) schematic1File = new File(root, "sideroad.schematic"); From 7c080770f03e84438613719abe65d255b80cd184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:51:40 +0200 Subject: [PATCH 030/121] Shade r-tree into the bukkit module --- Bukkit/build.gradle | 1 + Core/pom.xml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 9fa1f8cf1..4e69d6a41 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -87,6 +87,7 @@ shadowJar { include(dependency("io.papermc:paperlib:1.0.2")) include(dependency("net.kyori:text-adapter-bukkit:3.0.3")) include(dependency("org.bstats:bstats-bukkit:1.7")) + include(dependency("com.github.davidmoten:rtree:0.8.7")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") diff --git a/Core/pom.xml b/Core/pom.xml index 280cd8b1a..4e53e831a 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -92,6 +92,12 @@ 1.3.72 runtime + + com.github.davidmoten + rtree + 0.8.7 + runtime + junit junit From a3179bf11478fb483a8ff5c6e62da6f3c1f590a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:54:10 +0200 Subject: [PATCH 031/121] Shade rx into the bukkot module --- Bukkit/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 4e69d6a41..1e1f8bb02 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -88,6 +88,7 @@ shadowJar { include(dependency("net.kyori:text-adapter-bukkit:3.0.3")) include(dependency("org.bstats:bstats-bukkit:1.7")) include(dependency("com.github.davidmoten:rtree:0.8.7")) + include(dependency("io.reactivex:rxjava:1.3.8")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") From d4bd08415a4c0c4f0ffaa5d3b243bc460e89c7a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:56:23 +0200 Subject: [PATCH 032/121] Shade guava-mini into the bukkot module --- Bukkit/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 1e1f8bb02..5a1c91e20 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -89,6 +89,7 @@ shadowJar { include(dependency("org.bstats:bstats-bukkit:1.7")) include(dependency("com.github.davidmoten:rtree:0.8.7")) include(dependency("io.reactivex:rxjava:1.3.8")) + include(dependency("com.github.davidmoten:guava-mini:0.1.1")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") From b61dfd6f973b49e9f639c2938e90e39ade80d65b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 03:20:11 +0200 Subject: [PATCH 033/121] Single plot area progress --- .../com/plotsquared/core/command/Area.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index fcb4993c7..e2c1e828e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -58,6 +58,7 @@ import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.math.BlockVector2; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; @@ -97,7 +98,8 @@ public class Area extends SubCommand { MainUtil.sendMessage(player, Captions.SINGLE_AREA_NEEDS_NAME); return false; } - if (PlotSquared.get().getPlotArea(player.getLocation().getWorld(), args[1]) != null) { + final PlotArea existingArea = PlotSquared.get().getPlotArea(player.getLocation().getWorld(), args[1]); + if (existingArea != null && existingArea.getId().equalsIgnoreCase(args[1])) { MainUtil.sendMessage(player, Captions.SINGLE_AREA_NAME_TAKEN); return false; } @@ -127,12 +129,15 @@ public class Area extends SubCommand { final HybridPlotWorld hybridPlotWorld = new HybridPlotWorld(player.getLocation().getWorld(), args[1], Objects.requireNonNull(PlotSquared.imp()).getDefaultGenerator(), plotId, plotId); // Plot size is the same as the region width - hybridPlotWorld.SIZE = (short) selectedRegion.getWidth(); + hybridPlotWorld.PLOT_WIDTH = hybridPlotWorld.SIZE = (short) selectedRegion.getWidth(); // We use a schematic generator hybridPlotWorld.setTerrain(PlotAreaTerrainType.ALL); // It is always a partial plot world hybridPlotWorld.setType(PlotAreaType.PARTIAL); // We save the schematic :D + hybridPlotWorld.PLOT_SCHEMATIC = true; + // Set the road width to 0 + hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0; final File parentFile = MainUtil.getFile(PlotSquared.imp().getDirectory(), "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator + hybridPlotWorld.getId()); @@ -149,6 +154,9 @@ public class Area extends SubCommand { e.printStackTrace(); return false; } + // Calculate the offset + final BlockVector3 singlePos1 = selectedRegion.getMinimumPoint(); + // Now the schematic is saved, which is wonderful! final SetupObject singleSetup = new SetupObject(); singleSetup.world = hybridPlotWorld.getWorldName(); @@ -161,6 +169,19 @@ public class Area extends SubCommand { singleSetup.max = plotId; singleSetup.min = plotId; Runnable singleRun = () -> { + final String path = + "worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld.getId() + '-' + + singleSetup.min + '-' + singleSetup.max; + final int offsetX = singlePos1.getX(); + final int offsetZ = singlePos1.getZ(); + if (offsetX != 0) { + PlotSquared.get().worlds + .set(path + ".road.offset.x", offsetX); + } + if (offsetZ != 0) { + PlotSquared.get().worlds + .set(path + ".road.offset.z", offsetZ); + } final String world = SetupUtils.manager.setupWorld(singleSetup); if (WorldUtil.IMP.isWorld(world)) { PlotSquared.get().loadWorld(world, null); From bbde2f5e069379a6bb09cca70747dcc7d3c88c4f Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 22 May 2020 10:44:51 +0100 Subject: [PATCH 034/121] Slow down queue a bit because 1.13+ performance is bad --- .../com/plotsquared/core/configuration/Settings.java | 4 ++-- .../com/plotsquared/core/queue/GlobalBlockQueue.java | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 3fbd71394..2be87ada3 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -491,9 +491,9 @@ public class Settings extends Config { @Comment("Settings relating to PlotSquared's GlobalBlockQueue") public static final class QUEUE { - @Comment({"Average time per tick spent completing chunk tasks in ms. Target average TPS = 20 * 50 / TARGET_TIME.", + @Comment({"Average time per tick spent completing chunk tasks in ms.", "Waits (chunk task time / target_time) ticks before completely the next task."}) - public static int TARGET_TIME = 65; + public static int TARGET_TIME = 40; } diff --git a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java index 3b63a94c0..6abfea8f8 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -57,6 +57,7 @@ public class GlobalBlockQueue { private final RunnableVal2 SET_TASK = new RunnableVal2() { @Override public void run(Long free, LocalBlockQueue queue) { + long t1 = System.currentTimeMillis(); do { boolean more = queue.next(); if (!more) { @@ -66,9 +67,9 @@ public class GlobalBlockQueue { } return; } - } while ((lastPeriod = - ((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) - - GlobalBlockQueue.this.last)) < free); + } while (((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) + - GlobalBlockQueue.this.last) < free); + lastPeriod = System.currentTimeMillis() - t1; } }; @@ -124,8 +125,8 @@ public class GlobalBlockQueue { lastPeriod -= targetTime; return; } - SET_TASK.value1 = 50 + Math.min( - (50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = + SET_TASK.value1 = 30 + Math.min( + (30 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = System.currentTimeMillis()), GlobalBlockQueue.this.secondLast - System.currentTimeMillis()); SET_TASK.value2 = GlobalBlockQueue.this.getNextQueue(); From 1e3379b00a553987026831f6177ff8242e40d0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:06:04 +0200 Subject: [PATCH 035/121] Fix up the plot area nightmare --- Core/build.gradle | 2 + .../com/plotsquared/core/plot/PlotWorld.java | 105 +++++++ .../plot/world/DefaultPlotAreaManager.java | 269 +++++------------- .../core/plot/world/PlotAreaManager.java | 3 +- .../core/plot/world/ScatteredPlotWorld.java | 110 +++++++ .../core/plot/world/StandardPlotWorld.java | 65 +++++ .../com/plotsquared/core/util/RegionUtil.java | 10 + 7 files changed, 372 insertions(+), 192 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java create mode 100644 Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java create mode 100644 Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java diff --git a/Core/build.gradle b/Core/build.gradle index ee6edfda2..8581a39a4 100644 --- a/Core/build.gradle +++ b/Core/build.gradle @@ -16,6 +16,7 @@ dependencies { testAnnotationProcessor("org.projectlombok:lombok:1.18.8") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.3.72") implementation("org.jetbrains:annotations:19.0.0") + implementation 'com.github.davidmoten:rtree:0.8.7' } sourceCompatibility = 1.8 @@ -73,6 +74,7 @@ shadowJar { include(dependency("net.kyori:text-serializer-gson:3.0.2")) include(dependency("net.kyori:text-serializer-legacy:3.0.2")) include(dependency("net.kyori:text-serializer-plain:3.0.2")) + include(dependency("com.github.davidmoten:rtree:0.8.7")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("org.json", "com.plotsquared.json") { diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java new file mode 100644 index 000000000..ed7b854c2 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotWorld.java @@ -0,0 +1,105 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.plot; + +import com.plotsquared.core.location.Location; +import com.sk89q.worldedit.regions.CuboidRegion; +import lombok.EqualsAndHashCode; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * A world that contains plots + */ +@EqualsAndHashCode +public abstract class PlotWorld { + + private final String world; + + /** + * Create a new plot world with a given world name + * + * @param world World name + */ + protected PlotWorld(@NotNull final String world) { + this.world = world; + } + + /** + * Get the plot area that contains the given location, or null + * if the location is not a part of a plot area. + * + * @param location Location + * @return Containing plot area, or null + */ + @Nullable public abstract PlotArea getArea(@NotNull final Location location); + + /** + * Get all plot areas in the world + * + * @return All plot areas in the world + */ + @NotNull public abstract Collection getAreas(); + + /** + * Get all plot areas in a specified region + * + * @param region Region + * @return All areas in the region + */ + @NotNull public abstract Collection getAreasInRegion( + @NotNull final CuboidRegion region); + + /** + * Register a new area in the world + * + * @param area Plot area + */ + public void addArea(@NotNull final PlotArea area) { + throw new UnsupportedOperationException("This world type does not allow adding new areas"); + } + + /** + * Remove an area from the world + * + * @param area Plot area + */ + public void removeArea(@NotNull final PlotArea area) { + throw new UnsupportedOperationException("This world type does not allow removing areas"); + } + + /** + * Get the world name + * + * @return World name + */ + public String getWorld() { + return this.world; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java index 833bf3d4f..f86b5b8b6 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java @@ -25,143 +25,96 @@ */ package com.plotsquared.core.plot.world; -import com.plotsquared.core.collection.QuadMap; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.plot.PlotWorld; import com.plotsquared.core.util.StringMan; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; import java.util.Set; public class DefaultPlotAreaManager implements PlotAreaManager { final PlotArea[] noPlotAreas = new PlotArea[0]; - // All plot areas mapped by world - private final HashMap plotAreaMap = new HashMap<>(); - // All plot areas mapped by position - private final HashMap> plotAreaGrid = new HashMap<>(); - private final HashSet plotAreaHashCheck = new HashSet<>(); - // All plot areas - private PlotArea[] plotAreas = new PlotArea[0]; + + private final Map plotWorlds = new HashMap<>(); // Optimization if there are no hash collisions private boolean plotAreaHasCollision = false; - private String[] worlds = new String[0]; @Override public PlotArea[] getAllPlotAreas() { - return plotAreas; - } - - @Override public PlotArea getApplicablePlotArea(Location location) { - switch (this.plotAreas.length) { - case 0: - return null; - case 1: - return this.plotAreas[0].getWorldHash() == location.getWorld().hashCode() - && this.plotAreas[0].contains(location) && (!this.plotAreaHasCollision - || location.getWorld().equals(this.plotAreas[0].getWorldName())) ? - this.plotAreas[0] : - null; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - String world = location.getWorld(); - int hash = world.hashCode(); - for (PlotArea area : this.plotAreas) { - if (hash == area.getWorldHash()) { - if (area.contains(location.getX(), location.getZ()) && ( - !this.plotAreaHasCollision || world.equals(area.getWorldName()))) { - return area; - } - } - } - return null; - default: - PlotArea[] areas = this.plotAreaMap.get(location.getWorld()); - if (areas == null) { - return null; - } - int z; - int x; - switch (areas.length) { - case 1: - return areas[0]; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - x = location.getX(); - z = location.getZ(); - for (PlotArea area : areas) { - if (area.contains(x, z)) { - return area; - } - } - return null; - default: - QuadMap search = this.plotAreaGrid.get(location.getWorld()); - return search.get(location.getX(), location.getZ()); - } + final Set area = new HashSet<>(); + for (final PlotWorld world : plotWorlds.values()) { + area.addAll(world.getAreas()); } + return area.toArray(new PlotArea[0]); } - @Override public void addPlotArea(PlotArea plotArea) { - HashSet localAreas = - new HashSet<>(Arrays.asList(getPlotAreas(plotArea.getWorldName(), null))); - HashSet globalAreas = new HashSet<>(Arrays.asList(plotAreas)); - localAreas.add(plotArea); - globalAreas.add(plotArea); - this.plotAreas = globalAreas.toArray(new PlotArea[0]); - this.plotAreaMap.put(plotArea.getWorldName(), localAreas.toArray(new PlotArea[0])); - QuadMap map = this.plotAreaGrid.get(plotArea.getWorldName()); - if (map == null) { - map = new QuadMap(Integer.MAX_VALUE, 0, 0) { - @Override public CuboidRegion getRegion(PlotArea value) { - return value.getRegion(); - } - }; - this.plotAreaGrid.put(plotArea.getWorldName(), map); + @Override @Nullable public PlotArea getApplicablePlotArea(final Location location) { + if (location == null) { + return null; } - map.add(plotArea); + final PlotWorld world = this.plotWorlds.get(location.getWorld()); + if (world == null) { + return null; + } + return world.getArea(location); } - @Override public void removePlotArea(PlotArea area) { - ArrayList globalAreas = new ArrayList<>(Arrays.asList(plotAreas)); - globalAreas.remove(area); - this.plotAreas = globalAreas.toArray(new PlotArea[0]); - if (globalAreas.isEmpty()) { - this.plotAreaMap.remove(area.getWorldName()); - this.plotAreaGrid.remove(area.getWorldName()); + @Override public void addPlotArea(final PlotArea plotArea) { + PlotWorld world = this.plotWorlds.get(plotArea.getWorldName()); + if (world != null) { + if (world instanceof StandardPlotWorld && world.getAreas().isEmpty()) { + this.plotWorlds.remove(plotArea.getWorldName()); + } else { + world.addArea(plotArea); + return; + } + } + if (plotArea.getType() != PlotAreaType.PARTIAL) { + world = new StandardPlotWorld(plotArea.getWorldName(), plotArea); } else { - this.plotAreaMap.put(area.getWorldName(), globalAreas.toArray(new PlotArea[0])); - this.plotAreaGrid.get(area.getWorldName()).remove(area); + world = new ScatteredPlotWorld(plotArea.getWorldName()); + world.addArea(plotArea); + } + this.plotWorlds.put(plotArea.getWorldName(), world); + } + + @Override public void removePlotArea(final PlotArea area) { + final PlotWorld world = this.plotWorlds.get(area.getWorldName()); + if (world == null) { + return; + } + if (world instanceof StandardPlotWorld) { + this.plotWorlds.remove(world.getWorld()); + } else { + world.removeArea(area); + if (world.getAreas().isEmpty()) { + this.plotWorlds.remove(world.getWorld()); + } } } - @Override public PlotArea getPlotArea(String world, String id) { - PlotArea[] areas = this.plotAreaMap.get(world); - if (areas == null) { + @Override public PlotArea getPlotArea(final String world, final String id) { + final PlotWorld plotWorld = this.plotWorlds.get(world); + if (plotWorld == null) { return null; } - if (areas.length == 1) { - return areas[0]; - } else if (id == null) { + final List areas = new ArrayList<>(plotWorld.getAreas()); + if (areas.size() == 1) { + return areas.get(0); + } + if (id == null) { return null; } - for (PlotArea area : areas) { + for (final PlotArea area : areas) { if (StringMan.isEqual(id, area.getId())) { return area; } @@ -169,103 +122,37 @@ public class DefaultPlotAreaManager implements PlotAreaManager { return null; } - @Override public PlotArea getPlotArea(@NotNull Location location) { - switch (this.plotAreas.length) { - case 0: - return null; - case 1: - PlotArea pa = this.plotAreas[0]; - if (pa.contains(location)) { - return pa; - } else { - return null; - } - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - String world = location.getWorld(); - int hash = world.hashCode(); - for (PlotArea area : this.plotAreas) { - if (hash == area.getWorldHash()) { - if (area.contains(location.getX(), location.getZ()) && ( - !this.plotAreaHasCollision || world.equals(area.getWorldName()))) { - return area; - } - } - } - return null; - default: - PlotArea[] areas = this.plotAreaMap.get(location.getWorld()); - if (areas == null) { - return null; - } - int x; - int z; - switch (areas.length) { - case 0: - PlotArea a = areas[0]; - return a.contains(location.getX(), location.getZ()) ? a : null; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - x = location.getX(); - z = location.getZ(); - for (PlotArea area : areas) { - if (area.contains(x, z)) { - return area; - } - } - return null; - default: - QuadMap search = this.plotAreaGrid.get(location.getWorld()); - return search.get(location.getX(), location.getZ()); - } - } + @Override public PlotArea getPlotArea(@NotNull final Location location) { + return this.getApplicablePlotArea(location); } - @Override public PlotArea[] getPlotAreas(String world, CuboidRegion region) { - if (region == null) { - PlotArea[] areas = this.plotAreaMap.get(world); - if (areas == null) { - return noPlotAreas; - } - return areas; - } - QuadMap areas = this.plotAreaGrid.get(world); - if (areas == null) { + @Override public PlotArea[] getPlotAreas(final String world, final CuboidRegion region) { + final PlotWorld plotWorld = this.plotWorlds.get(world); + if (plotWorld == null) { return noPlotAreas; - } else { - Set found = areas.get(region); - return found.toArray(new PlotArea[0]); } + if (region == null) { + return plotWorld.getAreas().toArray(new PlotArea[0]); + } + return plotWorld.getAreasInRegion(region).toArray(new PlotArea[0]); } - @Override public void addWorld(String worldName) { - if (!this.plotAreaHasCollision && !this.plotAreaHashCheck.add(worldName.hashCode())) { - this.plotAreaHasCollision = true; + @Override public void addWorld(final String worldName) { + PlotWorld world = this.plotWorlds.get(worldName); + if (world != null) { + return; } - Set tmp = new LinkedHashSet<>(); - Collections.addAll(tmp, worlds); - tmp.add(worldName); - worlds = tmp.toArray(new String[0]); + // Create a new empty world. When a new area is added + // the world will be re-recreated with the correct type + world = new StandardPlotWorld(worldName, null); + this.plotWorlds.put(worldName, world); } - @Override public void removeWorld(String worldName) { - Set tmp = new LinkedHashSet<>(); - Collections.addAll(tmp, worlds); - tmp.remove(worldName); - worlds = tmp.toArray(new String[0]); + @Override public void removeWorld(final String worldName) { + this.plotWorlds.remove(worldName); } @Override public String[] getAllWorlds() { - return worlds; + return this.plotWorlds.keySet().toArray(new String[0]); } } diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java index b6d23b3d4..34033cb2b 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/PlotAreaManager.java @@ -29,6 +29,7 @@ import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.PlotArea; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface PlotAreaManager { @@ -44,7 +45,7 @@ public interface PlotAreaManager { * @param location The location * @return An applicable area, or null */ - PlotArea getApplicablePlotArea(Location location); + @Nullable PlotArea getApplicablePlotArea(Location location); /** * Get the plot area, if there is any, for the given diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java new file mode 100644 index 000000000..78cb0b7b2 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java @@ -0,0 +1,110 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.plot.world; + +import com.github.davidmoten.rtree.Entry; +import com.github.davidmoten.rtree.RTree; +import com.github.davidmoten.rtree.geometry.Geometries; +import com.github.davidmoten.rtree.geometry.Geometry; +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotWorld; +import com.plotsquared.core.util.RegionUtil; +import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import rx.Observable; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Plot world that contains several plot areas (clusters) + */ +public class ScatteredPlotWorld extends PlotWorld { + + private final List areas = new LinkedList<>(); + private final Object treeLock = new Object(); + private RTree areaTree; + + /** + * Create a new plot world with a given world name + * + * @param world World name + */ + public ScatteredPlotWorld(@NotNull final String world) { + super(world); + } + + @Override @Nullable public PlotArea getArea(@NotNull final Location location) { + synchronized (this.treeLock) { + final Observable> area = + areaTree.search(Geometries.point(location.getX(), location.getZ())); + if (area.isEmpty().toBlocking().first()) { + return null; + } + return area.toBlocking().first().value(); + } + } + + @Override @NotNull public Collection getAreas() { + return Collections.unmodifiableCollection(this.areas); + } + + @Override public void addArea(@NotNull final PlotArea area) { + this.areas.add(area); + this.buildTree(); + } + + @Override public void removeArea(@NotNull final PlotArea area) { + this.areas.remove(area); + this.buildTree(); + } + + @Override @NotNull public Collection getAreasInRegion(@NotNull final CuboidRegion region) { + synchronized (this.treeLock) { + final List areas = new LinkedList<>(); + this.areaTree.search(RegionUtil.toRectangle(region)).toBlocking().forEach(entry -> areas.add(entry.value())); + return areas; + } + } + + /** + * Rebuild the area tree + */ + private void buildTree() { + synchronized (this.treeLock) { + this.areaTree = RTree.create(); + for (final PlotArea area : areas) { + this.areaTree = this.areaTree.add(area, + RegionUtil.toRectangle(area.getRegion())); + } + } + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java new file mode 100644 index 000000000..162cf0e9f --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/plot/world/StandardPlotWorld.java @@ -0,0 +1,65 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.plot.world; + +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotWorld; +import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; + +/** + * Ordinary plot world with a single plot area + */ +public class StandardPlotWorld extends PlotWorld { + + private final PlotArea area; + + public StandardPlotWorld(@NotNull final String world, @Nullable final PlotArea area) { + super(world); + this.area = area; + } + + @Override @Nullable public PlotArea getArea(@NotNull final Location location) { + return this.area; + } + + @Override @NotNull public Collection getAreas() { + if (this.area == null) { + return Collections.emptyList(); + } + return Collections.singletonList(this.area); + } + + @Override @NotNull public Collection getAreasInRegion(@NotNull final CuboidRegion region) { + return this.getAreas(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java b/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java index fe4d83a96..59b14651a 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java @@ -25,9 +25,13 @@ */ package com.plotsquared.core.util; +import com.github.davidmoten.rtree.geometry.Geometries; +import com.github.davidmoten.rtree.geometry.Rectangle; import com.plotsquared.core.plot.Plot; +import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; +import org.jetbrains.annotations.NotNull; public class RegionUtil { public static CuboidRegion createRegion(int pos1x, int pos2x, int pos1z, int pos2z) { @@ -54,6 +58,12 @@ public class RegionUtil { .getY() && y <= max.getY(); } + @NotNull public static Rectangle toRectangle(@NotNull final CuboidRegion region) { + final BlockVector2 min = region.getMinimumPoint().toBlockVector2(); + final BlockVector2 max = region.getMaximumPoint().toBlockVector2(); + return Geometries.rectangle(min.getX(), min.getZ(), max.getX(), max.getZ()); + } + // Because WE (not fawe) lack this for CuboidRegion public static boolean intersects(CuboidRegion region, CuboidRegion other) { BlockVector3 regionMin = region.getMinimumPoint(); From dd4c5014fc2eb65540a93f2e89b98ec5eb4f39d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:06:37 +0200 Subject: [PATCH 036/121] Get rid of unused field --- .../plotsquared/core/plot/world/DefaultPlotAreaManager.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java index f86b5b8b6..9ce0b1623 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/DefaultPlotAreaManager.java @@ -44,10 +44,7 @@ import java.util.Set; public class DefaultPlotAreaManager implements PlotAreaManager { final PlotArea[] noPlotAreas = new PlotArea[0]; - private final Map plotWorlds = new HashMap<>(); - // Optimization if there are no hash collisions - private boolean plotAreaHasCollision = false; @Override public PlotArea[] getAllPlotAreas() { final Set area = new HashSet<>(); From 93619b39888791e9dd37c1d918b16dad60e442d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 21 May 2020 20:23:36 +0200 Subject: [PATCH 037/121] Don't access tree until it has been created --- .../com/plotsquared/core/plot/world/ScatteredPlotWorld.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java index 78cb0b7b2..9f245a5ba 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java @@ -62,6 +62,9 @@ public class ScatteredPlotWorld extends PlotWorld { } @Override @Nullable public PlotArea getArea(@NotNull final Location location) { + if (this.areas.isEmpty()) { + return null; + } synchronized (this.treeLock) { final Observable> area = areaTree.search(Geometries.point(location.getX(), location.getZ())); @@ -87,6 +90,9 @@ public class ScatteredPlotWorld extends PlotWorld { } @Override @NotNull public Collection getAreasInRegion(@NotNull final CuboidRegion region) { + if (this.areas.isEmpty()) { + return Collections.emptyList(); + } synchronized (this.treeLock) { final List areas = new LinkedList<>(); this.areaTree.search(RegionUtil.toRectangle(region)).toBlocking().forEach(entry -> areas.add(entry.value())); From d2af342a5d15b43d6b3f19d29796257f93f33b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:51:40 +0200 Subject: [PATCH 038/121] Shade r-tree into the bukkit module --- Bukkit/build.gradle | 1 + Core/pom.xml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 9fa1f8cf1..4e69d6a41 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -87,6 +87,7 @@ shadowJar { include(dependency("io.papermc:paperlib:1.0.2")) include(dependency("net.kyori:text-adapter-bukkit:3.0.3")) include(dependency("org.bstats:bstats-bukkit:1.7")) + include(dependency("com.github.davidmoten:rtree:0.8.7")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") diff --git a/Core/pom.xml b/Core/pom.xml index 280cd8b1a..4e53e831a 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -92,6 +92,12 @@ 1.3.72 runtime + + com.github.davidmoten + rtree + 0.8.7 + runtime + junit junit From a833803bdf223793573162448b50688f55bf3ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:54:10 +0200 Subject: [PATCH 039/121] Shade rx into the bukkot module --- Bukkit/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 4e69d6a41..1e1f8bb02 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -88,6 +88,7 @@ shadowJar { include(dependency("net.kyori:text-adapter-bukkit:3.0.3")) include(dependency("org.bstats:bstats-bukkit:1.7")) include(dependency("com.github.davidmoten:rtree:0.8.7")) + include(dependency("io.reactivex:rxjava:1.3.8")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") From eee04ab87d272e494b8dd6931ace9f68b6d1ea5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 22 May 2020 02:56:23 +0200 Subject: [PATCH 040/121] Shade guava-mini into the bukkot module --- Bukkit/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 1e1f8bb02..5a1c91e20 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -89,6 +89,7 @@ shadowJar { include(dependency("org.bstats:bstats-bukkit:1.7")) include(dependency("com.github.davidmoten:rtree:0.8.7")) include(dependency("io.reactivex:rxjava:1.3.8")) + include(dependency("com.github.davidmoten:guava-mini:0.1.1")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") From 5e6b27e21f4f6af015917d8b2217dfd005ef4532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 00:33:30 +0200 Subject: [PATCH 041/121] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 17dc0331c..f001d121e 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ is to provide a lag-free and smooth experience. * [Download](https://www.spigotmc.org/resources/plotsquared-v5.77506/) * [Discord](https://discord.gg/KxkjDVg) * [Wiki](https://wiki.intellectualsites.com/plotsquared/home) +* [Issues](https://issues.intellectualsites.com/projects/6572cc05-7756-4c9e-92de-bd28b9aabc3f) ### Developer Resources * [API Documentation](https://wiki.intellectualsites.com/en/plotsquared/developer/development-portal) From 6090c7ccacc764b5a056a35fe3e9a8fca2e3cf90 Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Sat, 23 May 2020 01:25:18 +0200 Subject: [PATCH 042/121] Link issues to new issue tracker for legacy reasons --- .github/FUNDING.yml | 2 +- .github/ISSUE_TEMPLATE.md | 3 +- .../bug-issue-report-for-plotsquared.md | 101 ------------------ .github/ISSUE_TEMPLATE/config.yml | 3 + README.md | 2 +- 5 files changed, 7 insertions(+), 104 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug-issue-report-for-plotsquared.md diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 717a9cdfc..9b0dbc13e 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +custom: https://www.paypal.me/AlexanderBrandes # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index a70ab837c..f1ee68845 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -28,6 +28,7 @@ assignees: '' +**/plot debugpaste:** ### Server type: **Select one** @@ -97,4 +98,4 @@ for short (20 lines or less) text blobs, or a paste service for large blobs --> - [] I made sure there are no duplicates of this report [(Use Search)](https://github.com/IntellectualSites/PlotSquared/issues?utf8=%E2%9C%93&q=is%3Aissue) - [] I made sure I am using an up-to-date version of PlotSquared - [] I made sure the bug/error is not caused by any other plugin -- [x] I didn't read but checked everything above. +- [x] I didn't read but checked everything above. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug-issue-report-for-plotsquared.md b/.github/ISSUE_TEMPLATE/bug-issue-report-for-plotsquared.md deleted file mode 100644 index c619a6d14..000000000 --- a/.github/ISSUE_TEMPLATE/bug-issue-report-for-plotsquared.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -name: Bug/Issue report for PlotSquared -about: Bug / Issue report about this plugin -title: '' -labels: "[?] Testing Required" -assignees: '' - ---- - - - - - - - -# Bug Report Template: - -## Required Information section: -> ALL FIELDS IN THIS SECTION ARE REQUIRED, and must contain appropriate information -### Server config info (/plot debugpaste / file paste links): - - - -**/plot debugpaste:** - -### Server type: -**Select one** - -- [] Spigot / Paper *(CraftBukkit should not be used, re-test with Spigot first!)* -- [] Sponge -- [] NukkitX - -### PlotSquared version: - -``` -Paste the output here, between the tick marks, replacing this text -``` - -### Minecraft Version: -**Select one** - -- [] Minecraft 1.15.2 -- [] Minecraft 1.14.4 -- [] Minecraft 1.13.2 -- [] Minecraft 1.12.2 -- [] Minecraft 1.11.2 -- [] Minecraft 1.10.2 -- [] Minecraft 1.9.4 -- [] Minecraft 1.8.8 -- [] Minecraft Java Edition *other versions, please specify*: -- [] Minecraft Bedrock Edition *specify version*: -- [] Minecraft Sponge *specify version*: - -### Server build info: - -``` -Paste the output here, between the tick marks, replacing this text -``` - -### WorldEdit/FAWE versions: - -- [] FAWE version: -- [] WorldEdit version: - -### Description of the problem: - - - -### How to replicate: - - -## Additional Information: -> The information here is optional for you to provide, however it may help us to more readily diagnose any compatibility and bug issues. - -### Other plugins being used on the server: - - -### Relevant console output, log lines, and/or screenshots: - - -### Additional relevant comments/remarks: - - -# AFFIRMATION OF COMPLETION: - -- [] I included all information required in the sections above -- [] I made sure there are no duplicates of this report [(Use Search)](https://github.com/IntellectualSites/PlotSquared/issues?utf8=%E2%9C%93&q=is%3Aissue) -- [] I made sure I am using an up-to-date version of PlotSquared -- [] I made sure the bug/error is not caused by any other plugin -- [x] I didn't read but checked everything above. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 83661f8c6..fd39e3738 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,8 @@ blank_issues_enabled: false contact_links: + - name: PlotSquared Issue Tracker + url: https://issues.intellectualsites.com/projects/ps + about: Click here to move to our new issue tracker - name: PlotSquared Suggestions url: https://github.com/IntellectualSites/PlotSquaredSuggestions about: If you want to submit feature or suggestion ideas, do that here \ No newline at end of file diff --git a/README.md b/README.md index f001d121e..64a012710 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ is to provide a lag-free and smooth experience. * [Download](https://www.spigotmc.org/resources/plotsquared-v5.77506/) * [Discord](https://discord.gg/KxkjDVg) * [Wiki](https://wiki.intellectualsites.com/plotsquared/home) -* [Issues](https://issues.intellectualsites.com/projects/6572cc05-7756-4c9e-92de-bd28b9aabc3f) +* [Issues](https://issues.intellectualsites.com/projects/ps) ### Developer Resources * [API Documentation](https://wiki.intellectualsites.com/en/plotsquared/developer/development-portal) From 32a55127f1029c2da0aed0e68a7701d8e9d861e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 14:32:02 +0200 Subject: [PATCH 043/121] Fix partial area regeneration when using PlotSquared generation. Also fix issues with region height and road width. --- .../bukkit/util/BukkitRegionManager.java | 2 +- .../com/plotsquared/core/PlotSquared.java | 22 ++++++++++++++++++- .../com/plotsquared/core/command/Area.java | 4 +++- .../plotsquared/core/util/ChunkManager.java | 2 +- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java index 16c63d093..158f90928 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitRegionManager.java @@ -348,7 +348,7 @@ public class BukkitRegionManager extends RegionManager { CuboidRegion currentPlotClear = RegionUtil .createRegion(pos1.getX(), pos2.getX(), pos1.getZ(), pos2.getZ()); map.saveEntitiesOut(chunkObj, currentPlotClear); - AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager.manager + AugmentedUtils.bypass(ignoreAugment, () -> ChunkManager .setChunkInPlotArea(null, new RunnableVal() { @Override public void run(ScopedLocalBlockQueue value) { Location min = value.getMin(); diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 4cb0731d5..535406a96 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -53,6 +53,7 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.BlockBucket; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotCluster; import com.plotsquared.core.plot.PlotFilter; @@ -90,6 +91,7 @@ import com.sk89q.worldedit.regions.CuboidRegion; import lombok.Getter; import lombok.NonNull; import lombok.Setter; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.BufferedReader; @@ -270,7 +272,8 @@ public class PlotSquared { // create setup util class SetupUtils.manager = this.IMP.initSetupUtils(); // Set block - GlobalBlockQueue.IMP = new GlobalBlockQueue(IMP.initBlockQueue(), 1, Settings.QUEUE.TARGET_TIME); + GlobalBlockQueue.IMP = + new GlobalBlockQueue(IMP.initBlockQueue(), 1, Settings.QUEUE.TARGET_TIME); GlobalBlockQueue.IMP.runTask(); // Set chunk ChunkManager.manager = this.IMP.initChunkManager(); @@ -2014,6 +2017,23 @@ public class PlotSquared { return Collections.unmodifiableSet(set); } + /** + * Check if the chunk uses vanilla/non-PlotSquared generation + * + * @param world World name + * @param chunkCoordinates Chunk coordinates + * @return True if the chunk uses non-standard generation, false if not + */ + public boolean isNonStandardGeneration(@NotNull final String world, + @NotNull final BlockVector2 chunkCoordinates) { + final Location location = new Location(world, chunkCoordinates.getBlockX() << 4, 64, chunkCoordinates.getBlockZ() << 4); + final PlotArea area = plotAreaManager.getApplicablePlotArea(location); + if (area == null) { + return true; + } + return area.getTerrain() != PlotAreaTerrainType.NONE; + } + public boolean isAugmented(@NonNull final String world) { final PlotArea[] areas = plotAreaManager.getPlotAreas(world, null); return areas != null && (areas.length > 1 || areas[0].getType() != PlotAreaType.NORMAL); diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index e2c1e828e..05d97faca 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -131,13 +131,15 @@ public class Area extends SubCommand { // Plot size is the same as the region width hybridPlotWorld.PLOT_WIDTH = hybridPlotWorld.SIZE = (short) selectedRegion.getWidth(); // We use a schematic generator - hybridPlotWorld.setTerrain(PlotAreaTerrainType.ALL); + hybridPlotWorld.setTerrain(PlotAreaTerrainType.NONE); // It is always a partial plot world hybridPlotWorld.setType(PlotAreaType.PARTIAL); // We save the schematic :D hybridPlotWorld.PLOT_SCHEMATIC = true; // Set the road width to 0 hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0; + // Set the plot height to the selection height + hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = selectedRegion.getHeight(); final File parentFile = MainUtil.getFile(PlotSquared.imp().getDirectory(), "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator + hybridPlotWorld.getId()); diff --git a/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java b/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java index 7bbea34d1..3e052737a 100644 --- a/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/ChunkManager.java @@ -52,7 +52,7 @@ public abstract class ChunkManager { public static void setChunkInPlotArea(RunnableVal force, RunnableVal add, String world, BlockVector2 loc) { LocalBlockQueue queue = GlobalBlockQueue.IMP.getNewQueue(world, false); - if (PlotSquared.get().isAugmented(world)) { + if (PlotSquared.get().isAugmented(world) && PlotSquared.get().isNonStandardGeneration(world, loc)) { int blockX = loc.getX() << 4; int blockZ = loc.getZ() << 4; ScopedLocalBlockQueue scoped = From 47c74cfa6d7650675f631e5882313909b4e2709e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 14:39:28 +0200 Subject: [PATCH 044/121] Set correct region height --- Core/src/main/java/com/plotsquared/core/command/Area.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index 05d97faca..f8846fbf7 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -139,7 +139,7 @@ public class Area extends SubCommand { // Set the road width to 0 hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0; // Set the plot height to the selection height - hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = selectedRegion.getHeight(); + hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = selectedRegion.getMaximumPoint().getBlockY(); final File parentFile = MainUtil.getFile(PlotSquared.imp().getDirectory(), "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator + hybridPlotWorld.getId()); From 8c37cc53407f8526f4a7c9793a9321f4a8e5c8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 15:02:31 +0200 Subject: [PATCH 045/121] Fix minor issues --- .../com/plotsquared/core/command/Area.java | 22 +++++++------ .../core/generator/HybridPlotWorld.java | 31 +------------------ .../com/plotsquared/core/plot/PlotArea.java | 2 +- 3 files changed, 15 insertions(+), 40 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index f8846fbf7..15705da27 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -46,6 +46,7 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.RegionUtil; +import com.plotsquared.core.util.SchematicHandler; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; @@ -140,6 +141,8 @@ public class Area extends SubCommand { hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0; // Set the plot height to the selection height hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = selectedRegion.getMaximumPoint().getBlockY(); + // No sign plz + hybridPlotWorld.setAllowSigns(false); final File parentFile = MainUtil.getFile(PlotSquared.imp().getDirectory(), "schematics" + File.separator + "GEN_ROAD_SCHEMATIC" + File.separator + hybridPlotWorld.getWorldName() + File.separator + hybridPlotWorld.getId()); @@ -156,6 +159,14 @@ public class Area extends SubCommand { e.printStackTrace(); return false; } + + // Setup schematic + try { + hybridPlotWorld.setupSchematics(); + } catch (final SchematicHandler.UnsupportedFormatException e) { + e.printStackTrace(); + } + // Calculate the offset final BlockVector3 singlePos1 = selectedRegion.getMinimumPoint(); @@ -187,21 +198,14 @@ public class Area extends SubCommand { final String world = SetupUtils.manager.setupWorld(singleSetup); if (WorldUtil.IMP.isWorld(world)) { PlotSquared.get().loadWorld(world, null); - Captions.SETUP_FINISHED.send(player); - player.teleport(WorldUtil.IMP.getSpawn(world), - TeleportCause.COMMAND); + MainUtil.sendMessage(player, Captions.SINGLE_AREA_CREATED); } else { MainUtil.sendMessage(player, "An error occurred while creating the world: " + hybridPlotWorld .getWorldName()); } }; - if (hasConfirmation(player)) { - CmdConfirm.addPending(player, - getCommandString() + " create pos2 (Creates world)", singleRun); - } else { - singleRun.run(); - } + singleRun.run(); return true; case "c": case "setup": diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java index e8bb47f66..c2c1323c5 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java @@ -280,37 +280,8 @@ public class HybridPlotWorld extends ClassicPlotWorld { (short) (z + shift + oddshift + centerShiftZ), biome); } } -/* HashMap items = schematic3.getTiles(); - if (!items.isEmpty()) { - this.G_SCH_STATE = new HashMap<>(); - outer: - for (Map.Entry entry : items.entrySet()) { - BlockLoc loc = entry.getKey(); - short x = (short) (loc.x + shift + oddshift + centerShiftX); - short z = (short) (loc.z + shift + oddshift + centerShiftZ); - short y = (short) (loc.y + this.PLOT_HEIGHT); - int pair = MathMan.pair(x, z); - HashMap existing = this.G_SCH_STATE.get(pair); - if (existing == null) { - existing = new HashMap<>(); - this.G_SCH_STATE.put(pair, existing); - } - existing.put((int) y, entry.getValue()); - CompoundTag tag = entry.getValue(); - Map map = ReflectionUtils.getMap(tag.getValue()); - for (int i = 1; i <= 4; i++) { - String ln = tag.getString("Line" + i); - if (ln == null || ln.length() > 11) - continue outer; - } - SIGN_LOCATION = - new Location(worldname, loc.x + centerShiftX, this.PLOT_HEIGHT + loc.y, - loc.z + centerShiftZ); - ALLOW_SIGNS = true; - continue outer; - } - }*/ + PlotSquared.debug(Captions.PREFIX + "&3 - plot schematic: &7true"); } if (schematic1 == null || schematic2 == null || this.ROAD_WIDTH == 0) { PlotSquared.debug(Captions.PREFIX + "&3 - schematic: &7false"); diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java index 45749d9e1..fc2c12453 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java @@ -1023,7 +1023,7 @@ public abstract class PlotArea { * @return true if plot signs are allow, false otherwise. */ public boolean allowSigns() { - return allowSigns; + return allowSigns && (this.plots.size() > 1) /* Do not generate signs for single plots */; } /** From 4dd2613f2f6d88947044a71b471ec30282adbbdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 15:02:53 +0200 Subject: [PATCH 046/121] Add missing caption --- .../main/java/com/plotsquared/core/configuration/Captions.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 4e1fc9482..1e411d38c 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -791,6 +791,7 @@ public enum Captions implements Caption { SINGLE_AREA_NAME_TAKEN("$2Error! The plot name is already taken", "Single"), SINGLE_AREA_FAILED_TO_SAVE("$2Error! Failed to save the area schematic", "Single"), SINGLE_AREA_COULD_NOT_MAKE_DIRECTORIES("$2Error! Failed to create the schematic directory", "Single"), + SINGLE_AREA_CREATED("$1The area was created successfully!", "Single"), // /** From 113da81f29f1397d970f6eb2f2ce22d935375fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 16:15:48 +0200 Subject: [PATCH 047/121] Actually save the schematic --- .../com/plotsquared/core/command/Area.java | 27 ++++++++++++++----- .../core/generator/HybridPlotWorld.java | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index 15705da27..932bbf0ab 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -52,12 +52,15 @@ import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; import com.plotsquared.core.util.task.RunnableVal3; +import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; +import com.sk89q.worldedit.function.operation.ForwardExtentCopy; +import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; @@ -109,22 +112,29 @@ public class Area extends SubCommand { MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION); return false; } - Region selectedRegion = null; + Region playerSelectedRegion = null; try { - selectedRegion = localSession.getSelection(((Player) player.toActor()).getWorld()); + playerSelectedRegion = localSession.getSelection(((Player) player.toActor()).getWorld()); } catch (final Exception ignored) {} - if (selectedRegion == null) { + if (playerSelectedRegion == null) { MainUtil.sendMessage(player, Captions.SINGLE_AREA_MISSING_SELECTION); return false; } - if (selectedRegion.getWidth() != selectedRegion.getLength()) { + if (playerSelectedRegion.getWidth() != playerSelectedRegion.getLength()) { MainUtil.sendMessage(player, Captions.SINGLE_AREA_NOT_SQUARE); return false; } if (PlotSquared.get().getPlotAreaManager().getPlotAreas( - Objects.requireNonNull(selectedRegion.getWorld()).getName(), CuboidRegion.makeCuboid(selectedRegion)).length != 0) { + Objects.requireNonNull(playerSelectedRegion.getWorld()).getName(), CuboidRegion.makeCuboid(playerSelectedRegion)).length != 0) { MainUtil.sendMessage(player, Captions.SINGLE_AREA_OVERLAPPING); } + // Alter the region + final BlockVector3 playerSelectionMin = playerSelectedRegion.getMinimumPoint(); + final BlockVector3 playerSelectionMax = playerSelectedRegion.getMaximumPoint(); + // Create a new selection that spans the entire vertical range of the world + final CuboidRegion selectedRegion = new CuboidRegion(playerSelectedRegion.getWorld(), + BlockVector3.at(playerSelectionMin.getX(), 0, playerSelectionMin.getZ()), + BlockVector3.at(playerSelectionMax.getX(), 255, playerSelectionMax.getZ())); // There's only one plot in the area... final PlotId plotId = new PlotId(1, 1); final HybridPlotWorld hybridPlotWorld = new HybridPlotWorld(player.getLocation().getWorld(), args[1], @@ -140,7 +150,7 @@ public class Area extends SubCommand { // Set the road width to 0 hybridPlotWorld.ROAD_WIDTH = hybridPlotWorld.ROAD_OFFSET_X = hybridPlotWorld.ROAD_OFFSET_Z = 0; // Set the plot height to the selection height - hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = selectedRegion.getMaximumPoint().getBlockY(); + hybridPlotWorld.PLOT_HEIGHT = hybridPlotWorld.ROAD_HEIGHT = hybridPlotWorld.WALL_HEIGHT = playerSelectionMin.getBlockY(); // No sign plz hybridPlotWorld.setAllowSigns(false); final File parentFile = MainUtil.getFile(PlotSquared.imp().getDirectory(), "schematics" + File.separator + @@ -153,6 +163,11 @@ public class Area extends SubCommand { final File file = new File(parentFile, "plot.schem"); try (final ClipboardWriter clipboardWriter = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(new FileOutputStream(file))) { final BlockArrayClipboard clipboard = new BlockArrayClipboard(selectedRegion); + final EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(selectedRegion.getWorld(), -1); + final ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(editSession, selectedRegion, clipboard, selectedRegion.getMinimumPoint()); + forwardExtentCopy.setCopyingBiomes(true); + forwardExtentCopy.setCopyingEntities(true); + Operations.complete(forwardExtentCopy); clipboardWriter.write(clipboard); } catch (final Exception e) { MainUtil.sendMessage(player, Captions.SINGLE_AREA_FAILED_TO_SAVE); diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java index c2c1323c5..49a5c0da4 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java @@ -281,7 +281,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { } } - PlotSquared.debug(Captions.PREFIX + "&3 - plot schematic: &7true"); + PlotSquared.debug(Captions.PREFIX + "&3 - plot schematic: &7" + schematic3File.getPath()); } if (schematic1 == null || schematic2 == null || this.ROAD_WIDTH == 0) { PlotSquared.debug(Captions.PREFIX + "&3 - schematic: &7false"); From 6c6c2b57a127e8a88eb25995fbc805a994d4eefa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 17:20:09 +0200 Subject: [PATCH 048/121] Add options to disable tab completion and extend username completion, also limit the total number of username suggestions to 200 per request --- .../bukkit/listener/PaperListener.java | 3 ++ .../core/configuration/Settings.java | 9 +++--- .../plotsquared/core/util/TabCompletions.java | 32 +++++++++++++------ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java index 925798a8a..ec5384ab5 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java @@ -318,6 +318,9 @@ public class PaperListener implements Listener { } @EventHandler public void onAsyncTabCompletion(final AsyncTabCompleteEvent event) { + if (!Settings.Paper_Components.ASYNC_TAB_COMPLETION) { + return; + } String buffer = event.getBuffer(); if (!(event.getSender() instanceof Player)) { return; diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index f295c465f..0c2e30be9 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -238,7 +238,6 @@ public class Settings extends Config { @Comment("Force using lowercase UUIDs") public static boolean FORCE_LOWERCASE = false; @Comment("Use a database to store UUID/name info") public static boolean USE_SQLUUIDHANDLER = false; - @Ignore public static boolean NATIVE_UUID_PROVIDER = false; @Comment("How many UUIDs that may be stored in the cache") public static int UUID_CACHE_SIZE = 100000; @Comment("Rate limit (per 10 minutes) for background UUID fetching from the Mojang API") @@ -497,6 +496,8 @@ public class Settings extends Config { public static boolean CREATURE_SPAWN = true; @Comment("Check the tile entity limit on block placement") public static boolean TILE_ENTITY_CHECK = true; + @Comment("Use Paper's async tab completion") + public static boolean ASYNC_TAB_COMPLETION; } @Comment("Settings relating to PlotSquared's GlobalBlockQueue") @@ -514,8 +515,6 @@ public class Settings extends Config { @Comment("Events are needed to track a lot of things") public static boolean EVENTS = true; @Comment("Commands are used to interact with the plugin") public static boolean COMMANDS = true; - @Comment("The UUID cacher is used to resolve player names") public static boolean - UUID_CACHE = true; @Comment("Whether we should notify you about updates or not.") public static boolean UPDATE_NOTIFICATIONS = true; @Comment("Stores user metadata in a database") public static boolean PERSISTENT_META = true; @@ -544,10 +543,10 @@ public class Settings extends Config { public static boolean EXTERNAL_PLACEHOLDERS = true; @Comment("Make road regeneration persistent across restarts") public static boolean PERSISTENT_ROAD_REGEN = false; - @Comment("Try to guess plot owners from sign data. This may decrease server performance") - public static boolean GUESS_PLOT_OWNER = false; @Comment("Plot component preset GUI") public static boolean COMPONENT_PRESETS = true; + @Comment("Use UUID cache to complete usernames") + public static boolean EXTENDED_USERNAME_COMPLETION = true; } } diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java index 0c1dbf4df..0369ad730 100644 --- a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java +++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java @@ -31,6 +31,8 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.command.Command; import com.plotsquared.core.command.CommandCategory; import com.plotsquared.core.command.RequiredType; +import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.uuid.UUIDMapping; import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; @@ -61,15 +63,24 @@ public class TabCompletions { */ @NotNull public List completePlayers(@NotNull final String input, @NotNull final List existing) { - List players = cachedCompletionValues.getIfPresent("players"); - if (players == null) { - final Collection mappings = - PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); - players = new ArrayList<>(mappings.size()); - for (final UUIDMapping mapping : mappings) { - players.add(mapping.getUsername()); + List players; + if (Settings.Enabled_Components.EXTENDED_USERNAME_COMPLETION) { + players = cachedCompletionValues.getIfPresent("players"); + if (players == null) { + final Collection mappings = + PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); + players = new ArrayList<>(mappings.size()); + for (final UUIDMapping mapping : mappings) { + players.add(mapping.getUsername()); + } + cachedCompletionValues.put("players", players); + } + } else { + final Collection onlinePlayers = PlotSquared.imp().getPlayerManager().getPlayers(); + players = new ArrayList<>(onlinePlayers.size()); + for (final PlotPlayer player : onlinePlayers) { + players.add(player.getName()); } - cachedCompletionValues.put("players", players); } final String processedInput = input.toLowerCase(Locale.ENGLISH); return players.stream() @@ -77,7 +88,10 @@ public class TabCompletions { .filter(player -> !existing.contains(player)).map( player -> new Command(null, false, player, "", RequiredType.NONE, CommandCategory.INFO) { - }).collect(Collectors.toList()); + }) + /* If there are more than 200 suggestions, just send the first 200 */ + .limit(200) + .collect(Collectors.toList()); } /** From 2875b050c535ea795c0953866060a90dc15e3314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 19:43:32 +0200 Subject: [PATCH 049/121] Add plugin UUID services. They probably work. --- Bukkit/build.gradle | 3 + .../com/plotsquared/bukkit/BukkitMain.java | 37 +++++++- .../bukkit/uuid/EssentialsUUIDService.java | 70 ++++++++++++++++ .../bukkit/uuid/LuckPermsUUIDService.java | 84 +++++++++++++++++++ 4 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/uuid/EssentialsUUIDService.java create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/uuid/LuckPermsUUIDService.java diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 9b6b862a6..965928520 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -11,6 +11,7 @@ repositories { name = "papermc" url = "https://papermc.io/repo/repository/maven-public/" } + maven { url = "https://ci.ender.zone/plugin/repository/everything/" } maven { url = "https://mvn.intellectualsites.com/content/repositories/snapshots" } mavenLocal() } @@ -30,6 +31,8 @@ dependencies { exclude(module: "bukkit") } implementation("me.clip:placeholderapi:2.10.4") + implementation("net.luckperms:api:5.0") + implementation("net.ess3:EssentialsX:2.16.1") compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false } compile 'com.github.pavog:SquirrelID:0.6.1' } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 84ba2f591..588813d5f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -51,6 +51,8 @@ import com.plotsquared.bukkit.util.BukkitTaskManager; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.SetGenCB; import com.plotsquared.bukkit.util.UpdateUtility; +import com.plotsquared.bukkit.uuid.EssentialsUUIDService; +import com.plotsquared.bukkit.uuid.LuckPermsUUIDService; import com.plotsquared.bukkit.uuid.OfflinePlayerUUIDService; import com.plotsquared.bukkit.uuid.PaperUUIDService; import com.plotsquared.bukkit.uuid.SQLiteUUIDService; @@ -231,38 +233,71 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain PlotSquared.log(Captions.PREFIX + "&6Couldn't verify purchase :("); } - // TODO: Do we respect the UUID settings? final UUIDPipeline impromptuPipeline = PlotSquared.get().getImpromptuUUIDPipeline(); final UUIDPipeline backgroundPipeline = PlotSquared.get().getBackgroundUUIDPipeline(); + // Services are accessed in order final CacheUUIDService cacheUUIDService = new CacheUUIDService(Settings.UUID.UUID_CACHE_SIZE); impromptuPipeline.registerService(cacheUUIDService); backgroundPipeline.registerService(cacheUUIDService); impromptuPipeline.registerConsumer(cacheUUIDService); backgroundPipeline.registerConsumer(cacheUUIDService); + // Now, if the server is in offline mode we can only use profiles and direct UUID // access, and so we skip the player profile stuff as well as SquirrelID (Mojang lookups) if (Settings.UUID.OFFLINE) { final OfflineModeUUIDService offlineModeUUIDService = new OfflineModeUUIDService(); impromptuPipeline.registerService(offlineModeUUIDService); backgroundPipeline.registerService(offlineModeUUIDService); + PlotSquared.log(Captions.PREFIX + "(UUID) Using the offline mode UUID service"); } + final OfflinePlayerUUIDService offlinePlayerUUIDService = new OfflinePlayerUUIDService(); impromptuPipeline.registerService(offlinePlayerUUIDService); backgroundPipeline.registerService(offlinePlayerUUIDService); final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService(); + + final LuckPermsUUIDService luckPermsUUIDService; + if (Bukkit.getPluginManager().getPlugin("LuckPerms") != null) { + luckPermsUUIDService = new LuckPermsUUIDService(); + PlotSquared.log(Captions.PREFIX + "(UUID) Using LuckPerms as a complementary UUID service"); + } else { + luckPermsUUIDService = null; + } + + final EssentialsUUIDService essentialsUUIDService; + if (Bukkit.getPluginManager().getPlugin("Essentials") != null) { + essentialsUUIDService = new EssentialsUUIDService(); + PlotSquared.log(Captions.PREFIX + "(UUID) Using Essentials as a complementary UUID service"); + } else { + essentialsUUIDService = null; + } + if (!Settings.UUID.OFFLINE) { // If running Paper we'll also try to use their profiles if (PaperLib.isPaper()) { final PaperUUIDService paperUUIDService = new PaperUUIDService(); impromptuPipeline.registerService(paperUUIDService); backgroundPipeline.registerService(paperUUIDService); + PlotSquared.log(Captions.PREFIX + "(UUID) Using Paper as a complementary UUID service"); } + impromptuPipeline.registerService(sqLiteUUIDService); backgroundPipeline.registerService(sqLiteUUIDService); impromptuPipeline.registerConsumer(sqLiteUUIDService); backgroundPipeline.registerConsumer(sqLiteUUIDService); + + // Plugin providers + if (luckPermsUUIDService != null) { + impromptuPipeline.registerService(luckPermsUUIDService); + backgroundPipeline.registerService(luckPermsUUIDService); + } + if (essentialsUUIDService != null) { + impromptuPipeline.registerService(essentialsUUIDService); + backgroundPipeline.registerService(essentialsUUIDService); + } + final SquirrelIdUUIDService impromptuMojangService = new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT); impromptuPipeline.registerService(impromptuMojangService); final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/EssentialsUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/EssentialsUUIDService.java new file mode 100644 index 000000000..eb473d67e --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/EssentialsUUIDService.java @@ -0,0 +1,70 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.bukkit.uuid; + +import com.earth2me.essentials.Essentials; +import com.earth2me.essentials.User; +import com.plotsquared.core.uuid.UUIDMapping; +import com.plotsquared.core.uuid.UUIDService; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +/** + * UUID service using the EssentialsX API + */ +public class EssentialsUUIDService implements UUIDService { + + private final Essentials essentials; + + public EssentialsUUIDService() { + this.essentials = Essentials.getPlugin(Essentials.class); + } + + @Override @NotNull public List getNames(@NotNull final List uuids) { + return Collections.emptyList(); + } + + @Override @NotNull public List getUUIDs(@NotNull final List usernames) { + final List mappings = new ArrayList<>(usernames.size()); + for (final String username : usernames) { + try { + final User user = essentials.getUser(username); + if (user != null) { + final UUID uuid = user.getConfigUUID(); + if (uuid != null) { + mappings.add(new UUIDMapping(uuid, username)); + } + } + } catch (final Exception ignored){} + } + return mappings; + } + +} diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/LuckPermsUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/LuckPermsUUIDService.java new file mode 100644 index 000000000..47bcc9bb3 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/LuckPermsUUIDService.java @@ -0,0 +1,84 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.bukkit.uuid; + +import com.plotsquared.core.uuid.UUIDMapping; +import com.plotsquared.core.uuid.UUIDService; +import net.luckperms.api.LuckPerms; +import net.luckperms.api.model.user.UserManager; +import org.bukkit.Bukkit; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * UUID service that uses the LuckPerms API + */ +public class LuckPermsUUIDService implements UUIDService { + + private final LuckPerms luckPerms; + + public LuckPermsUUIDService() { + final RegisteredServiceProvider provider = Bukkit.getServicesManager().getRegistration(LuckPerms.class); + if (provider != null) { + this.luckPerms = provider.getProvider(); + } else { + throw new IllegalStateException("LuckPerms not available"); + } + } + + @Override @NotNull public List getNames(@NotNull final List uuids) { + final List mappings = new ArrayList<>(uuids.size()); + final UserManager userManager = this.luckPerms.getUserManager(); + for (final UUID uuid : uuids) { + try { + final String username = userManager.lookupUsername(uuid).get(); + if (username != null) { + mappings.add(new UUIDMapping(uuid, username)); + } + } catch (final Exception ignored) {} + } + return mappings; + } + + @Override @NotNull public List getUUIDs(@NotNull final List usernames) { + final List mappings = new ArrayList<>(usernames.size()); + final UserManager userManager = this.luckPerms.getUserManager(); + for (final String username : usernames) { + try { + final UUID uuid = userManager.lookupUniqueId(username).get(); + if (username != null) { + mappings.add(new UUIDMapping(uuid, username)); + } + } catch (final Exception ignored) {} + } + return mappings; + } + +} From 75dbc2db98446e399cbd8d5faab7505408201b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 04:27:20 +0200 Subject: [PATCH 050/121] Fix offline mode UUIDs --- Bukkit/pom.xml | 12 ++++++++++++ .../com/plotsquared/bukkit/BukkitMain.java | 16 ++++++++-------- .../bukkit/listener/PlayerEvents.java | 15 ++++++++++++++- .../bukkit/player/BukkitPlayer.java | 13 ++++++++++++- .../bukkit/uuid/OfflinePlayerUUIDService.java | 19 ++++++++++++++----- 5 files changed, 60 insertions(+), 15 deletions(-) diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index 68e49c901..57d06b615 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -140,6 +140,18 @@ 2.10.4 runtime + + net.luckperms + api + 5.0 + runtime + + + net.ess3 + EssentialsX + 2.16.1 + runtime + junit junit diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 588813d5f..f75d9ce57 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -274,15 +274,15 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain essentialsUUIDService = null; } - if (!Settings.UUID.OFFLINE) { - // If running Paper we'll also try to use their profiles - if (PaperLib.isPaper()) { - final PaperUUIDService paperUUIDService = new PaperUUIDService(); - impromptuPipeline.registerService(paperUUIDService); - backgroundPipeline.registerService(paperUUIDService); - PlotSquared.log(Captions.PREFIX + "(UUID) Using Paper as a complementary UUID service"); - } + // If running Paper we'll also try to use their profiles + if (PaperLib.isPaper()) { + final PaperUUIDService paperUUIDService = new PaperUUIDService(); + impromptuPipeline.registerService(paperUUIDService); + backgroundPipeline.registerService(paperUUIDService); + PlotSquared.log(Captions.PREFIX + "(UUID) Using Paper as a complementary UUID service"); + } + if (!Settings.UUID.OFFLINE) { impromptuPipeline.registerService(sqLiteUUIDService); backgroundPipeline.registerService(sqLiteUUIDService); impromptuPipeline.registerConsumer(sqLiteUUIDService); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index ddcc15320..70d3c6d6b 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -26,6 +26,7 @@ package com.plotsquared.bukkit.listener; import com.destroystokyo.paper.MaterialTags; +import com.google.common.base.Charsets; import com.plotsquared.bukkit.player.BukkitPlayer; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.UpdateUtility; @@ -629,7 +630,19 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPreLoin(final AsyncPlayerPreLoginEvent event) { - PlotSquared.get().getImpromptuUUIDPipeline().storeImmediately(event.getName(), event.getUniqueId()); + final UUID uuid; + if (Settings.UUID.OFFLINE) { + if (Settings.UUID.FORCE_LOWERCASE) { + uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + + event.getName().toLowerCase()).getBytes(Charsets.UTF_8)); + } else { + uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + + event.getName()).getBytes(Charsets.UTF_8)); + } + } else { + uuid = event.getUniqueId(); + } + PlotSquared.get().getImpromptuUUIDPipeline().storeImmediately(event.getName(), uuid); } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java index d2e7930fa..23d856860 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java @@ -25,9 +25,11 @@ */ package com.plotsquared.bukkit.player; +import com.google.common.base.Charsets; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; +import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.PlotPlayer; @@ -96,7 +98,16 @@ public class BukkitPlayer extends PlotPlayer { } @NotNull @Override public UUID getUUID() { - return this.player.getUniqueId(); + if (Settings.UUID.OFFLINE) { + if (Settings.UUID.FORCE_LOWERCASE) { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + + getName().toLowerCase()).getBytes(Charsets.UTF_8)); + } else { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + + getName()).getBytes(Charsets.UTF_8)); + } + } + return player.getUniqueId(); } @Override public long getLastPlayed() { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java index 403832f38..9c9f02344 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java @@ -25,6 +25,8 @@ */ package com.plotsquared.bukkit.uuid; +import com.google.common.base.Charsets; +import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.uuid.UUIDMapping; import com.plotsquared.core.uuid.UUIDService; import org.bukkit.Bukkit; @@ -32,6 +34,7 @@ import org.bukkit.OfflinePlayer; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.UUID; @@ -40,7 +43,10 @@ import java.util.UUID; */ public class OfflinePlayerUUIDService implements UUIDService { - @Override public @NotNull List getNames(@NotNull List uuids) { + @Override @NotNull public List getNames(@NotNull final List uuids) { + if (Settings.UUID.FORCE_LOWERCASE) { + return Collections.emptyList(); // This is useless now + } final List wrappers = new ArrayList<>(uuids.size()); for (final UUID uuid : uuids) { final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); @@ -51,12 +57,15 @@ public class OfflinePlayerUUIDService implements UUIDService { return wrappers; } - @Override public @NotNull List getUUIDs(@NotNull List usernames) { + @Override @NotNull public List getUUIDs(@NotNull final List usernames) { final List wrappers = new ArrayList<>(usernames.size()); for (final String username : usernames) { - final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(username); - if (offlinePlayer.hasPlayedBefore()) { - wrappers.add(new UUIDMapping(offlinePlayer.getUniqueId(), offlinePlayer.getName())); + if (Settings.UUID.FORCE_LOWERCASE) { + wrappers.add(new UUIDMapping(UUID.nameUUIDFromBytes(("OfflinePlayer:" + + username.toLowerCase()).getBytes(Charsets.UTF_8)), username)); + } else { + wrappers.add(new UUIDMapping(UUID.nameUUIDFromBytes(("OfflinePlayer:" + + username).getBytes(Charsets.UTF_8)), username)); } } return wrappers; From d19df3b6ebca7a9bdcd29f89f7536e1152e2a252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 04:28:29 +0200 Subject: [PATCH 051/121] Fix offline mode UUIDs --- .../java/com/plotsquared/bukkit/BukkitMain.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index f75d9ce57..588813d5f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -274,15 +274,15 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain essentialsUUIDService = null; } - // If running Paper we'll also try to use their profiles - if (PaperLib.isPaper()) { - final PaperUUIDService paperUUIDService = new PaperUUIDService(); - impromptuPipeline.registerService(paperUUIDService); - backgroundPipeline.registerService(paperUUIDService); - PlotSquared.log(Captions.PREFIX + "(UUID) Using Paper as a complementary UUID service"); - } - if (!Settings.UUID.OFFLINE) { + // If running Paper we'll also try to use their profiles + if (PaperLib.isPaper()) { + final PaperUUIDService paperUUIDService = new PaperUUIDService(); + impromptuPipeline.registerService(paperUUIDService); + backgroundPipeline.registerService(paperUUIDService); + PlotSquared.log(Captions.PREFIX + "(UUID) Using Paper as a complementary UUID service"); + } + impromptuPipeline.registerService(sqLiteUUIDService); backgroundPipeline.registerService(sqLiteUUIDService); impromptuPipeline.registerConsumer(sqLiteUUIDService); From cc168d5ae9821f940cb4bc03d71dca325e3a6630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 04:48:19 +0200 Subject: [PATCH 052/121] Fix SQLite table creation statement and add legacy SQLite uuids as a provider --- .../src/main/java/com/plotsquared/bukkit/BukkitMain.java | 9 ++++++++- .../com/plotsquared/bukkit/uuid/SQLiteUUIDService.java | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 588813d5f..d5e582e8c 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -256,7 +256,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain impromptuPipeline.registerService(offlinePlayerUUIDService); backgroundPipeline.registerService(offlinePlayerUUIDService); - final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService(); + final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService("user_cache.db"); + final SQLiteUUIDService legacyUUIDSerivce = new SQLiteUUIDService("usercache.db"); final LuckPermsUUIDService luckPermsUUIDService; if (Bukkit.getPluginManager().getPlugin("LuckPerms") != null) { @@ -288,6 +289,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain impromptuPipeline.registerConsumer(sqLiteUUIDService); backgroundPipeline.registerConsumer(sqLiteUUIDService); + impromptuPipeline.registerService(legacyUUIDSerivce); + backgroundPipeline.registerService(legacyUUIDSerivce); + // Plugin providers if (luckPermsUUIDService != null) { impromptuPipeline.registerService(luckPermsUUIDService); @@ -307,6 +311,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain backgroundPipeline.registerService(sqLiteUUIDService); impromptuPipeline.registerConsumer(sqLiteUUIDService); backgroundPipeline.registerConsumer(sqLiteUUIDService); + + impromptuPipeline.registerService(legacyUUIDSerivce); + backgroundPipeline.registerService(legacyUUIDSerivce); } impromptuPipeline.storeImmediately("*", DBFunc.EVERYONE); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java index dc251bec4..16b3abff5 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/SQLiteUUIDService.java @@ -49,9 +49,9 @@ public class SQLiteUUIDService implements UUIDService, Consumer Date: Sun, 24 May 2020 05:00:36 +0200 Subject: [PATCH 053/121] Add option to disable legacy cache, also add an option to return "Unknown" when a request cannot be fulfilled (old behaviour) This should fix issues where lowercase offline mode UUIDs don't have access to their old cache. --- .../com/plotsquared/bukkit/BukkitMain.java | 20 ++++++++++++++----- .../core/configuration/Settings.java | 4 ++++ .../plotsquared/core/uuid/UUIDPipeline.java | 9 ++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index d5e582e8c..84e474319 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -257,7 +257,13 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain backgroundPipeline.registerService(offlinePlayerUUIDService); final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService("user_cache.db"); - final SQLiteUUIDService legacyUUIDSerivce = new SQLiteUUIDService("usercache.db"); + + final SQLiteUUIDService legacyUUIDService; + if (Settings.UUID.LEGACY_DATABASE_SUPPORT && MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), "usercache.db").exists()) { + legacyUUIDService = new SQLiteUUIDService("usercache.db"); + } else { + legacyUUIDService = null; + } final LuckPermsUUIDService luckPermsUUIDService; if (Bukkit.getPluginManager().getPlugin("LuckPerms") != null) { @@ -289,8 +295,10 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain impromptuPipeline.registerConsumer(sqLiteUUIDService); backgroundPipeline.registerConsumer(sqLiteUUIDService); - impromptuPipeline.registerService(legacyUUIDSerivce); - backgroundPipeline.registerService(legacyUUIDSerivce); + if (legacyUUIDService != null) { + impromptuPipeline.registerService(legacyUUIDService); + backgroundPipeline.registerService(legacyUUIDService); + } // Plugin providers if (luckPermsUUIDService != null) { @@ -312,8 +320,10 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain impromptuPipeline.registerConsumer(sqLiteUUIDService); backgroundPipeline.registerConsumer(sqLiteUUIDService); - impromptuPipeline.registerService(legacyUUIDSerivce); - backgroundPipeline.registerService(legacyUUIDSerivce); + if (legacyUUIDService != null) { + impromptuPipeline.registerService(legacyUUIDService); + backgroundPipeline.registerService(legacyUUIDService); + } } impromptuPipeline.storeImmediately("*", DBFunc.EVERYONE); diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 0c2e30be9..e5bbd3180 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -248,6 +248,10 @@ public class Settings extends Config { public static long NON_BLOCKING_TIMEOUT = 3000L; @Comment("Timeout (in milliseconds) for blocking UUID requests (events)") public static long BLOCKING_TIMEOUT = 10L; + @Comment("Whether or not PlotSquared should read from the legacy database") + public static boolean LEGACY_DATABASE_SUPPORT = true; + @Comment("Whether or not PlotSquared should return Unknown if it fails to fulfill a request") + public static boolean UNKNOWN_AS_DEFAULT = true; } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 3518fa5f8..8c8baa06d 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -324,7 +324,14 @@ public class UUIDPipeline { PlotSquared.log("Failed to find all usernames"); } - throw new ServiceError("End of pipeline"); + if (Settings.UUID.UNKNOWN_AS_DEFAULT) { + for (final UUID uuid : remainingRequests) { + mappings.add(new UUIDMapping(uuid, Captions.UNKNOWN.getTranslated())); + } + return mappings; + } else { + throw new ServiceError("End of pipeline"); + } }, this.executor); } From 98322d5d116a032b08508bafd7a512dc16282099 Mon Sep 17 00:00:00 2001 From: Aurora Date: Sun, 24 May 2020 14:32:34 +0200 Subject: [PATCH 054/121] Add BungeePerms UUID service. This should probably work. --- Bukkit/build.gradle | 2 + Bukkit/pom.xml | 6 ++ .../com/plotsquared/bukkit/BukkitMain.java | 13 +++ .../bukkit/uuid/BungeePermsUUIDService.java | 85 +++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/uuid/BungeePermsUUIDService.java diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 965928520..0c86fe2f0 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -13,6 +13,7 @@ repositories { } maven { url = "https://ci.ender.zone/plugin/repository/everything/" } maven { url = "https://mvn.intellectualsites.com/content/repositories/snapshots" } + maven { url = "https://repo.wea-ondara.net/repository/public/" } mavenLocal() } @@ -33,6 +34,7 @@ dependencies { implementation("me.clip:placeholderapi:2.10.4") implementation("net.luckperms:api:5.0") implementation("net.ess3:EssentialsX:2.16.1") + implementation("net.alpenblock:BungeePerms:4.0-dev-106") compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false } compile 'com.github.pavog:SquirrelID:0.6.1' } diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index 57d06b615..42fce3d0a 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -152,6 +152,12 @@ 2.16.1 runtime + + net.alpenblock + BungeePerms + 4.0-dev-106 + runtime + junit junit diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 84e474319..02cf4db04 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -51,6 +51,7 @@ import com.plotsquared.bukkit.util.BukkitTaskManager; import com.plotsquared.bukkit.util.BukkitUtil; import com.plotsquared.bukkit.util.SetGenCB; import com.plotsquared.bukkit.util.UpdateUtility; +import com.plotsquared.bukkit.uuid.BungeePermsUUIDService; import com.plotsquared.bukkit.uuid.EssentialsUUIDService; import com.plotsquared.bukkit.uuid.LuckPermsUUIDService; import com.plotsquared.bukkit.uuid.OfflinePlayerUUIDService; @@ -273,6 +274,14 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain luckPermsUUIDService = null; } + final BungeePermsUUIDService bungeePermsUUIDService; + if (Bukkit.getPluginManager().getPlugin("BungeePerms") != null) { + bungeePermsUUIDService = new BungeePermsUUIDService(); + PlotSquared.log(Captions.PREFIX + "(UUID) Using BungeePerms as a complementary UUID service"); + } else { + bungeePermsUUIDService = null; + } + final EssentialsUUIDService essentialsUUIDService; if (Bukkit.getPluginManager().getPlugin("Essentials") != null) { essentialsUUIDService = new EssentialsUUIDService(); @@ -305,6 +314,10 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain impromptuPipeline.registerService(luckPermsUUIDService); backgroundPipeline.registerService(luckPermsUUIDService); } + if (bungeePermsUUIDService != null) { + impromptuPipeline.registerService(bungeePermsUUIDService); + backgroundPipeline.registerService(bungeePermsUUIDService); + } if (essentialsUUIDService != null) { impromptuPipeline.registerService(essentialsUUIDService); backgroundPipeline.registerService(essentialsUUIDService); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/BungeePermsUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/BungeePermsUUIDService.java new file mode 100644 index 000000000..4de1bdb92 --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/BungeePermsUUIDService.java @@ -0,0 +1,85 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.bukkit.uuid; + +import com.plotsquared.core.uuid.UUIDMapping; +import com.plotsquared.core.uuid.UUIDService; +import net.luckperms.api.model.user.UserManager; +import org.bukkit.Bukkit; +import org.bukkit.plugin.RegisteredServiceProvider; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import net.alpenblock.bungeeperms.BungeePerms; +import net.alpenblock.bungeeperms.io.UUIDPlayerDB; + +/** + * UUID service that uses the BungeePerms API + */ +public class BungeePermsUUIDService implements UUIDService { + + private final BungeePerms bp; + + public BungeePermsUUIDService() { + final RegisteredServiceProvider provider = Bukkit.getServicesManager().getRegistration(BungeePerms.class); + if (provider != null) { + this.bp = provider.getProvider(); + } else { + throw new IllegalStateException("BungeePerms is not available"); + } + } + + @Override @NotNull public List getNames(@NotNull final List uuids) { + final List mappings = new ArrayList<>(uuids.size()); + final UUIDPlayerDB uuiddb = BungeePerms.getInstance().getPermissionsManager().getUUIDPlayerDB(); + for (final UUID uuid : uuids) { + try { + final String username = uuiddb.getPlayerName(uuid); + if (username != null) { + mappings.add(new UUIDMapping(uuid, username)); + } + } catch (final Exception ignored) {} + } + return mappings; + } + + @Override @NotNull public List getUUIDs(@NotNull final List usernames) { + final List mappings = new ArrayList<>(usernames.size()); + final UUIDPlayerDB uuiddb = BungeePerms.getInstance().getPermissionsManager().getUUIDPlayerDB(); + for (final String username : usernames) { + try { + final UUID uuid = uuiddb.getUUID(username); + if (username != null) { + mappings.add(new UUIDMapping(uuid, username)); + } + } catch (final Exception ignored) {} + } + return mappings; + } + +} From e912909aade0eff98e66c093d4b64346d36b44b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 22:20:57 +0200 Subject: [PATCH 055/121] Add plot query system --- .../com/plotsquared/core/PlotSquared.java | 99 ++------ .../core/util/query/AliasFilter.java | 43 ++++ .../util/query/AreaLimitedPlotProvider.java | 46 ++++ .../core/util/query/GlobalPlotProvider.java | 39 +++ .../core/util/query/MemberFilter.java | 45 ++++ .../core/util/query/OwnerFilter.java | 46 ++++ .../core/util/query/PaginatedPlotResult.java | 73 ++++++ .../core/util/query/PlotFilter.java | 41 ++++ .../core/util/query/PlotProvider.java | 36 +++ .../core/util/query/PlotQuery.java | 228 ++++++++++++++++++ .../core/util/query/PredicateFilter.java | 45 ++++ 11 files changed, 667 insertions(+), 74 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/AliasFilter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/MemberFilter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/OwnerFilter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PaginatedPlotResult.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PlotFilter.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/PredicateFilter.java diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 4cb0731d5..e83cc56ba 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -82,6 +82,7 @@ import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.StringWrapper; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.logger.ILogger; +import com.plotsquared.core.util.query.PlotQuery; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.uuid.UUIDHandler; import com.sk89q.worldedit.WorldEdit; @@ -116,6 +117,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -640,17 +642,7 @@ public class PlotSquared { * @return Set of base Plots */ public Set getBasePlots() { - int size = getPlotCount(); - final Set result = new HashSet<>(size); - forEachPlotArea(value -> { - for (Plot plot : value.getPlots()) { - if (!plot.isBasePlot()) { - continue; - } - result.add(plot); - } - }); - return Collections.unmodifiableSet(result); + return PlotQuery.newQuery().whereBasePlot().asSet(); } public List sortPlotsByTemp(Collection plots) { @@ -905,25 +897,22 @@ public class PlotSquared { * @return a filtered set of plots */ public Set getPlots(final PlotFilter... filters) { - final HashSet set = new HashSet<>(); - forEachPlotArea(value -> { - for (PlotFilter filter : filters) { - if (!filter.allowsArea(value)) { - return; + final List areas = new LinkedList<>(); + for (final PlotArea plotArea : this.getPlotAreas()) { + for (final PlotFilter filter : filters) { + if (filter.allowsArea(plotArea)) { + areas.add(plotArea); } } - loop: - for (Entry entry2 : value.getPlotEntries()) { - Plot plot = entry2.getValue(); - for (PlotFilter filter : filters) { - if (!filter.allowsPlot(plot)) { - continue loop; - } + } + return PlotQuery.newQuery().inAreas(areas).thatPasses(plot -> { + for (final PlotFilter filter : filters) { + if (!filter.allowsPlot(plot)) { + return false; } - set.add(plot); } - }); - return set; + return true; + }).asSet(); } /** @@ -990,7 +979,7 @@ public class PlotSquared { * @return Set of plot */ public Set getPlots(String world, PlotPlayer player) { - return getPlots(world, player.getUUID()); + return PlotQuery.newQuery().inWorld(world).ownedBy(player).asSet(); } /** @@ -1001,7 +990,7 @@ public class PlotSquared { * @return Set of plot */ public Set getPlots(PlotArea area, PlotPlayer player) { - return getPlots(area, player.getUUID()); + return PlotQuery.newQuery().inArea(area).ownedBy(player).asSet(); } /** @@ -1012,10 +1001,7 @@ public class PlotSquared { * @return Set of plot */ public Set getPlots(String world, UUID uuid) { - final Set plots = - getPlots(world).stream().filter(plot -> plot.hasOwner() && plot.isOwnerAbs(uuid)) - .collect(Collectors.toSet()); - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().inWorld(world).ownedBy(uuid).asSet(); } /** @@ -1026,13 +1012,7 @@ public class PlotSquared { * @return Set of plots */ public Set getPlots(PlotArea area, UUID uuid) { - final Set plots = new HashSet<>(); - for (Plot plot : getPlots(area)) { - if (plot.hasOwner() && plot.isOwnerAbs(uuid)) { - plots.add(plot); - } - } - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().inArea(area).ownedBy(uuid).asSet(); } /** @@ -1047,9 +1027,7 @@ public class PlotSquared { } public Collection getPlots(String world) { - final Set set = new HashSet<>(); - forEachPlotArea(world, value -> set.addAll(value.getPlots())); - return set; + return PlotQuery.newQuery().inWorld(world).asCollection(); } /** @@ -1059,7 +1037,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlots(PlotPlayer player) { - return getPlots(player.getUUID()); + return PlotQuery.newQuery().ownedBy(player).asSet(); } public Collection getPlots(PlotArea area) { @@ -1081,13 +1059,7 @@ public class PlotSquared { * @return Set of Plot's owned by the player */ public Set getPlots(final UUID uuid) { - final Set plots = new HashSet<>(); - forEachPlot(value -> { - if (value.isOwnerAbs(uuid)) { - plots.add(value); - } - }); - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().ownedBy(uuid).asSet(); } public boolean hasPlot(final UUID uuid) { @@ -1096,13 +1068,7 @@ public class PlotSquared { } public Set getBasePlots(final UUID uuid) { - final Set plots = new HashSet<>(); - forEachBasePlot(value -> { - if (value.isOwner(uuid)) { - plots.add(value); - } - }); - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().ownedBy(uuid).whereBasePlot().asSet(); } /** @@ -1112,13 +1078,7 @@ public class PlotSquared { * @return Set of Plot */ public Set getPlotsAbs(final UUID uuid) { - final Set plots = new HashSet<>(); - forEachPlot(value -> { - if (value.isOwnerAbs(uuid)) { - plots.add(value); - } - }); - return Collections.unmodifiableSet(plots); + return PlotQuery.newQuery().ownedBy(uuid).asSet(); } /** @@ -2103,16 +2063,7 @@ public class PlotSquared { */ public Set getPlotsByAlias(@Nullable final String alias, @NonNull final String worldname) { - final Set result = new HashSet<>(); - if (alias != null) { - for (final Plot plot : getPlots()) { - if (alias.equals(plot.getAlias()) && (worldname == null || worldname - .equals(plot.getWorldName()))) { - result.add(plot); - } - } - } - return Collections.unmodifiableSet(result); + return PlotQuery.newQuery().inWorld(worldname).withAlias(alias).asSet(); } public Set getPlotAreas(final String world, final CuboidRegion region) { diff --git a/Core/src/main/java/com/plotsquared/core/util/query/AliasFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/AliasFilter.java new file mode 100644 index 000000000..808f34797 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/AliasFilter.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.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +class AliasFilter implements PlotFilter { + + private final String alias; + + AliasFilter(@NotNull final String alias) { + this.alias = alias; + } + + @Override public boolean accepts(@NotNull final Plot plot) { + return this.alias.equalsIgnoreCase(plot.getAlias()); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java new file mode 100644 index 000000000..21a149176 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java @@ -0,0 +1,46 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotArea; + +import java.util.Collection; +import java.util.stream.Stream; + +class AreaLimitedPlotProvider implements PlotProvider { + + private final Collection areas; + + AreaLimitedPlotProvider(Collection areas) { + this.areas = areas; + } + + @Override public Stream getPlots() { + return areas.stream().flatMap(area -> area.getPlots().stream()); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java new file mode 100644 index 000000000..82965aec3 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java @@ -0,0 +1,39 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.plot.Plot; + +import java.util.stream.Stream; + +class GlobalPlotProvider implements PlotProvider { + + @Override public Stream getPlots() { + return PlotSquared.get().getPlots().stream(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/MemberFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/MemberFilter.java new file mode 100644 index 000000000..3f9670d08 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/MemberFilter.java @@ -0,0 +1,45 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +class MemberFilter implements PlotFilter { + + @NotNull private final UUID uuid; + + MemberFilter(@NotNull final UUID uuid) { + this.uuid = uuid; + } + + @Override public boolean accepts(@NotNull final Plot plot) { + return plot.isAdded(uuid); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/OwnerFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/OwnerFilter.java new file mode 100644 index 000000000..cae258722 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/OwnerFilter.java @@ -0,0 +1,46 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.UUID; + +class OwnerFilter implements PlotFilter { + + private final UUID owner; + + OwnerFilter(@NotNull final UUID owner) { + this.owner = owner; + } + + @Override public boolean accepts(@NotNull final Plot plot) { + return plot.hasOwner() && Objects.equals(plot.getOwnerAbs(), this.owner); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PaginatedPlotResult.java b/Core/src/main/java/com/plotsquared/core/util/query/PaginatedPlotResult.java new file mode 100644 index 000000000..2c0ed9152 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PaginatedPlotResult.java @@ -0,0 +1,73 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.google.common.base.Preconditions; +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; + +/** + * Paginated collection of plots as a result of a {@link PlotQuery query} + */ +public final class PaginatedPlotResult { + + private final List plots; + private final int pageSize; + + PaginatedPlotResult(@NotNull final List plots, final int pageSize) { + this.plots = plots; + this.pageSize = pageSize; + } + + /** + * Get the plots belonging to a certain page. + * + * @param page Positive page number. Indexed from 1 + * @return Plots that belong to the specified page + */ + public List getPage(final int page) { + Preconditions.checkState(page >= 0, "Page must be positive"); + final int from = (page - 1) * this.pageSize; + if (this.plots.size() < from) { + return Collections.emptyList(); + } + final int to = Math.max(from + pageSize, this.plots.size()); + return this.plots.subList(from, to); + } + + /** + * Get the number of available pages + * + * @return Available pages + */ + public int getPages() { + return (int) Math.ceil((double) plots.size() / (double) pageSize); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotFilter.java new file mode 100644 index 000000000..c017b21b0 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotFilter.java @@ -0,0 +1,41 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; + +@FunctionalInterface interface PlotFilter extends Predicate { + + @Override default boolean test(@NotNull final Plot plot) { + return this.accepts(plot); + } + + boolean accepts(@NotNull final Plot plot); + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java new file mode 100644 index 000000000..783288850 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java @@ -0,0 +1,36 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; + +import java.util.stream.Stream; + +@FunctionalInterface interface PlotProvider { + + Stream getPlots(); + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java new file mode 100644 index 000000000..0c6132fd9 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -0,0 +1,228 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.google.common.base.Preconditions; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotArea; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * This represents a plot query, and can be used to + * search for plots matching certain criteria. + *

+ * The queries can be reused as no results are stored + * in the query itself + */ +public final class PlotQuery { + + private PlotProvider plotProvider = new GlobalPlotProvider(); + private final Collection filters = new LinkedList<>(); + + private PlotQuery() { + } + + /** + * Create a new plot query instance + * + * @return New query + */ + public static PlotQuery newQuery() { + return new PlotQuery(); + } + + /** + * Query for plots in a single area + * + * @param area Area + * @return The query instance + */ + @NotNull public PlotQuery inArea(@NotNull final PlotArea area) { + Preconditions.checkNotNull(area, "Area may not be null"); + this.plotProvider = new AreaLimitedPlotProvider(Collections.singletonList(area)); + return this; + } + + /** + * Query for plots in all areas in a world + * + * @param world World name + * @return The query instance + */ + @NotNull public PlotQuery inWorld(@NotNull final String world) { + Preconditions.checkNotNull(world, "World may not be null"); + this.plotProvider = new AreaLimitedPlotProvider(PlotSquared.get().getPlotAreas(world)); + return this; + } + + /** + * Query for plots in specific areas + * + * @param areas Plot areas + * @return The query instance + */ + @NotNull public PlotQuery inAreas(@NotNull final Collection areas) { + Preconditions.checkNotNull(areas, "Areas may not be null"); + Preconditions.checkState(!areas.isEmpty(), "At least one area must be provided"); + this.plotProvider = new AreaLimitedPlotProvider(Collections.unmodifiableCollection(areas)); + return this; + } + + /** + * Query for base plots only + * + * @return The query instance + */ + @NotNull public PlotQuery whereBasePlot() { + return this.addFilter(new PredicateFilter(Plot::isBasePlot)); + } + + /** + * Query for plots owned by a specific player + * + * @param owner Owner UUID + * @return The query instance + */ + @NotNull public PlotQuery ownedBy(@NotNull final UUID owner) { + Preconditions.checkNotNull(owner, "Owner may not be null"); + return this.addFilter(new OwnerFilter(owner)); + } + + /** + * Query for plots owned by a specific player + * + * @param owner Owner + * @return The query instance + */ + @NotNull public PlotQuery ownedBy(@NotNull final PlotPlayer owner) { + Preconditions.checkNotNull(owner, "Owner may not be null"); + return this.addFilter(new OwnerFilter(owner.getUUID())); + } + + /** + * Query for plots with a specific alias + * + * @param alias Plot alias + * @return The query instance + */ + @NotNull public PlotQuery withAlias(@NotNull final String alias) { + Preconditions.checkNotNull(alias, "Alias may not be null"); + return this.addFilter(new AliasFilter(alias)); + } + + /** + * Query for plots with a specific member (added/trusted/owner) + * + * @param member Member UUID + * @return The query instance + */ + @NotNull public PlotQuery withMember(@NotNull final UUID member) { + Preconditions.checkNotNull(member, "Member may not be null"); + return this.addFilter(new MemberFilter(member)); + } + + /** + * Query for plots that passes a given predicate + * + * @param predicate Predicate + * @return The query instance + */ + @NotNull public PlotQuery thatPasses(@NotNull final Predicate predicate) { + Preconditions.checkNotNull(predicate, "Predicate may not be null"); + return this.addFilter(new PredicateFilter(predicate)); + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots + */ + @NotNull public Stream asStream() { + Stream plots = this.plotProvider.getPlots(); + for (final PlotFilter filter : this.filters) { + plots = plots.filter(filter); + } + return plots; + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots as an immutable list + */ + @NotNull public List asList() { + return Collections.unmodifiableList(this.asStream().collect(Collectors.toList())); + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots as an immutable set + */ + @NotNull public Set asSet() { + return Collections.unmodifiableSet(this.asStream().collect(Collectors.toSet())); + } + + /** + * Get all plots that match the given criteria + * in the form of a {@link PaginatedPlotResult} + * + * @param pageSize The size of the pages. Must be positive. + * @return Paginated plot result + */ + @NotNull public PaginatedPlotResult getPaginated(final int pageSize) { + Preconditions.checkState(pageSize > 0, "Page size must be greater than 0"); + return new PaginatedPlotResult(this.asList(), pageSize); + } + + /** + * Get all plots that match the given criteria + * + * @return Matching plots as an immutable collection + */ + @NotNull public Collection asCollection() { + return this.asList(); + } + + @NotNull private PlotQuery addFilter(@NotNull final PlotFilter filter) { + this.filters.add(filter); + return this; + } + + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PredicateFilter.java b/Core/src/main/java/com/plotsquared/core/util/query/PredicateFilter.java new file mode 100644 index 000000000..dd68f081d --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/PredicateFilter.java @@ -0,0 +1,45 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Predicate; + +class PredicateFilter implements PlotFilter { + + private final Predicate predicate; + + PredicateFilter(@NotNull final Predicate predicate) { + this.predicate = predicate; + } + + @Override public boolean accepts(@NotNull final Plot plot) { + return predicate.test(plot); + } + +} From 508fdce70485a111bbe75e79988b323aef28311f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sat, 23 May 2020 23:58:24 +0200 Subject: [PATCH 056/121] Add missing methods to PlotQuery and use PlotQuery in ListCmd --- .../com/plotsquared/core/command/ListCmd.java | 135 ++++++----------- .../util/query/AreaLimitedPlotProvider.java | 11 +- .../core/util/query/ExploredPlotProvider.java | 39 +++++ .../core/util/query/GlobalPlotProvider.java | 6 +- .../core/util/query/NullProvider.java | 39 +++++ .../core/util/query/PlotProvider.java | 4 +- .../core/util/query/PlotQuery.java | 139 ++++++++++++++++-- .../core/util/query/SearchPlotProvider.java | 46 ++++++ .../core/util/query/SortingStrategy.java | 52 +++++++ 9 files changed, 364 insertions(+), 107 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/NullProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/SearchPlotProvider.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java diff --git a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java index 8d151fb10..c83ee5c4a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java @@ -26,13 +26,11 @@ package com.plotsquared.core.command; import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.PlotSquared.SortType; import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; -import com.plotsquared.core.plot.Rating; import com.plotsquared.core.plot.expiration.ExpireManager; import com.plotsquared.core.plot.flag.implementations.DoneFlag; import com.plotsquared.core.plot.flag.implementations.PriceFlag; @@ -43,13 +41,14 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.StringMan; +import com.plotsquared.core.util.query.PlotQuery; +import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.util.uuid.UUIDHandler; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map.Entry; import java.util.UUID; @CommandDeclaration(command = "list", @@ -128,12 +127,13 @@ public class ListCmd extends SubCommand { } } - List plots = null; - String world = player.getLocation().getWorld(); PlotArea area = player.getApplicablePlotArea(); String arg = args[0].toLowerCase(); boolean sort = true; + + PlotQuery query = null; + switch (arg) { case "mine": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_MINE)) { @@ -141,8 +141,8 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_MINE); return false; } + query = PlotQuery.newQuery().ownedBy(player).whereBasePlot().withSortingStrategy(SortingStrategy.SORT_BY_TEMP); sort = false; - plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getBasePlots(player)); break; case "shared": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_SHARED)) { @@ -150,13 +150,8 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_SHARED); return false; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getTrusted().contains(player.getUUID()) || plot.getMembers() - .contains(player.getUUID())) { - plots.add(plot); - } - } + // withMember checks for trusted + members + owner, we don't want the owner part + query = PlotQuery.newQuery().withMember(player.getUUID()).thatPasses(plot -> !plot.isOwnerAbs(player.getUUID())); break; case "world": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_WORLD)) { @@ -171,7 +166,7 @@ public class ListCmd extends SubCommand { world)); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots(world)); + query = PlotQuery.newQuery().inWorld(world); break; case "expired": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_EXPIRED)) { @@ -179,9 +174,11 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_EXPIRED); return false; } - plots = ExpireManager.IMP == null ? - new ArrayList() : - new ArrayList<>(ExpireManager.IMP.getPendingExpired()); + if (ExpireManager.IMP == null) { + query = PlotQuery.newQuery().noPlots(); + } else { + query = PlotQuery.newQuery().expiredPlots(); + } break; case "area": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_AREA)) { @@ -196,7 +193,11 @@ public class ListCmd extends SubCommand { world)); return false; } - plots = area == null ? new ArrayList() : new ArrayList<>(area.getPlots()); + if (area == null) { + query = PlotQuery.newQuery().noPlots(); + } else { + query = PlotQuery.newQuery().inArea(area); + } break; case "all": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_ALL)) { @@ -204,7 +205,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_ALL); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots()); + query = PlotQuery.newQuery().allPlots(); break; case "done": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_DONE)) { @@ -212,23 +213,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_DONE); return false; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { - if (DoneFlag.isDone(plot)) { - plots.add(plot); - } - } - plots.sort((a, b) -> { - String va = a.getFlag(DoneFlag.class); - String vb = b.getFlag(DoneFlag.class); - if (MathMan.isInteger(va)) { - if (MathMan.isInteger(vb)) { - return Integer.parseInt(vb) - Integer.parseInt(va); - } - return -1; - } - return 1; - }); + query = PlotQuery.newQuery().allPlots().thatPasses(DoneFlag::isDone).withSortingStrategy(SortingStrategy.SORT_BY_DONE); sort = false; break; case "top": @@ -237,31 +222,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_TOP); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots()); - plots.sort((p1, p2) -> { - double v1 = 0; - int p1s = p1.getSettings().getRatings().size(); - int p2s = p2.getRatings().size(); - if (!p1.getSettings().getRatings().isEmpty()) { - v1 = p1.getRatings().values().stream().mapToDouble(Rating::getAverageRating) - .map(av -> av * av).sum(); - v1 /= p1s; - v1 += p1s; - } - double v2 = 0; - if (!p2.getSettings().getRatings().isEmpty()) { - for (Entry entry : p2.getRatings().entrySet()) { - double av = entry.getValue().getAverageRating(); - v2 += av * av; - } - v2 /= p2s; - v2 += p2s; - } - if (v2 == v1 && v2 != 0) { - return p2s - p1s; - } - return (int) Math.signum(v2 - v1); - }); + query = PlotQuery.newQuery().allPlots().withSortingStrategy(SortingStrategy.SORT_BY_RATING); sort = false; break; case "forsale": @@ -273,12 +234,7 @@ public class ListCmd extends SubCommand { if (EconHandler.manager == null) { break; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getFlag(PriceFlag.class) > 0) { - plots.add(plot); - } - } + query = PlotQuery.newQuery().allPlots().thatPasses(plot -> plot.getFlag(PriceFlag.class) > 0); break; case "unowned": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNOWNED)) { @@ -286,12 +242,7 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_UNOWNED); return false; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { - if (plot.getOwner() == null) { - plots.add(plot); - } - } + query = PlotQuery.newQuery().allPlots().thatPasses(plot -> plot.getOwner() == null); break; case "unknown": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNKNOWN)) { @@ -299,15 +250,12 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_UNKNOWN); return false; } - plots = new ArrayList<>(); - for (Plot plot : PlotSquared.get().getPlots()) { + query = PlotQuery.newQuery().allPlots().thatPasses(plot -> { if (plot.getOwner() == null) { - continue; + return false; } - if (UUIDHandler.getName(plot.getOwner()) == null) { - plots.add(plot); - } - } + return UUIDHandler.getName(plot.getOwner()) == null; + }); break; case "fuzzy": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_FUZZY)) { @@ -325,7 +273,7 @@ public class ListCmd extends SubCommand { } else { term = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); } - plots = MainUtil.getPlotsBySearch(term); + query = PlotQuery.newQuery().plotsBySearch(term); sort = false; break; default: @@ -343,7 +291,7 @@ public class ListCmd extends SubCommand { args[0])); return false; } - plots = new ArrayList<>(PlotSquared.get().getPlots(args[0])); + query = PlotQuery.newQuery().inWorld(args[0]); break; } UUID uuid = UUIDHandler.getUUID(args[0], null); @@ -360,33 +308,40 @@ public class ListCmd extends SubCommand { return false; } sort = false; - plots = PlotSquared.get().sortPlotsByTemp(PlotSquared.get().getPlots(uuid)); + query = PlotQuery.newQuery().ownedBy(uuid).withSortingStrategy(SortingStrategy.SORT_BY_TEMP); break; } } - if (plots == null) { + if (query == null) { sendMessage(player, Captions.DID_YOU_MEAN, new StringComparison<>(args[0], new String[] {"mine", "shared", "world", "all"}) .getBestMatch()); return false; } + + if (area != null) { + query.relativeToArea(area); + } + + if (sort) { + query.withSortingStrategy(SortingStrategy.SORT_BY_CREATION); + } + + final List plots = query.asList(); + if (plots.isEmpty()) { MainUtil.sendMessage(player, Captions.FOUND_NO_PLOTS); return false; } - displayPlots(player, plots, 12, page, area, args, sort); + displayPlots(player, plots, 12, page, args); return true; } - public void displayPlots(final PlotPlayer player, List plots, int pageSize, int page, - PlotArea area, String[] args, boolean sort) { + public void displayPlots(final PlotPlayer player, List plots, int pageSize, int page, String[] args) { // Header plots.removeIf(plot -> !plot.isBasePlot()); - if (sort) { - plots = PlotSquared.get().sortPlots(plots, SortType.CREATION_DATE, area); - } this.paginate(player, plots, pageSize, page, new RunnableVal3() { @Override public void run(Integer i, Plot plot, PlotMessage message) { diff --git a/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java index 21a149176..2a6e88171 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/AreaLimitedPlotProvider.java @@ -29,7 +29,8 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; import java.util.Collection; -import java.util.stream.Stream; +import java.util.LinkedList; +import java.util.List; class AreaLimitedPlotProvider implements PlotProvider { @@ -39,8 +40,12 @@ class AreaLimitedPlotProvider implements PlotProvider { this.areas = areas; } - @Override public Stream getPlots() { - return areas.stream().flatMap(area -> area.getPlots().stream()); + @Override public Collection getPlots() { + final List plots = new LinkedList<>(); + for (final PlotArea area : areas) { + plots.addAll(area.getPlots()); + } + return plots; } } diff --git a/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java new file mode 100644 index 000000000..94bf9b92e --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java @@ -0,0 +1,39 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.expiration.ExpireManager; + +import java.util.Collection; + +class ExploredPlotProvider implements PlotProvider { + + @Override public Collection getPlots() { + return ExpireManager.IMP.getPendingExpired(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java index 82965aec3..3fb2420c5 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/GlobalPlotProvider.java @@ -28,12 +28,12 @@ package com.plotsquared.core.util.query; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.plot.Plot; -import java.util.stream.Stream; +import java.util.Collection; class GlobalPlotProvider implements PlotProvider { - @Override public Stream getPlots() { - return PlotSquared.get().getPlots().stream(); + @Override public Collection getPlots() { + return PlotSquared.get().getPlots(); } } diff --git a/Core/src/main/java/com/plotsquared/core/util/query/NullProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/NullProvider.java new file mode 100644 index 000000000..6cf3a70d4 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/NullProvider.java @@ -0,0 +1,39 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; + +import java.util.Collection; +import java.util.Collections; + +class NullProvider implements PlotProvider { + + @Override public Collection getPlots() { + return Collections.emptyList(); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java index 783288850..c8048da1a 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java @@ -27,10 +27,10 @@ package com.plotsquared.core.util.query; import com.plotsquared.core.plot.Plot; -import java.util.stream.Stream; +import java.util.Collection; @FunctionalInterface interface PlotProvider { - Stream getPlots(); + Collection getPlots(); } diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 0c6132fd9..612c4c21c 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -30,16 +30,21 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; +import com.plotsquared.core.plot.Rating; +import com.plotsquared.core.plot.flag.implementations.DoneFlag; +import com.plotsquared.core.util.MathMan; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.function.Predicate; -import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -51,8 +56,10 @@ import java.util.stream.Stream; */ public final class PlotQuery { - private PlotProvider plotProvider = new GlobalPlotProvider(); private final Collection filters = new LinkedList<>(); + private PlotProvider plotProvider = new GlobalPlotProvider(); + private SortingStrategy sortingStrategy = SortingStrategy.NO_SORTING; + private PlotArea priorityArea; private PlotQuery() { } @@ -103,6 +110,47 @@ public final class PlotQuery { return this; } + /** + * Query for expired plots + * + * @return The query instance + */ + @NotNull public PlotQuery expiredPlots() { + this.plotProvider = new ExploredPlotProvider(); + return this; + } + + /** + * Query for all plots + * + * @return The query instance + */ + @NotNull public PlotQuery allPlots() { + this.plotProvider = new GlobalPlotProvider(); + return this; + } + + /** + * Don't query at all + * + * @return The query instance + */ + @NotNull public PlotQuery noPlots() { + this.plotProvider = new NullProvider(); + return this; + } + + /** + * Query for plots based on a search term + * + * @return The query instance + */ + @NotNull public PlotQuery plotsBySearch(@NotNull final String searchTerm) { + Preconditions.checkNotNull(searchTerm, "Search term may not be null"); + this.plotProvider = new SearchPlotProvider(searchTerm); + return this; + } + /** * Query for base plots only * @@ -167,17 +215,32 @@ public final class PlotQuery { return this.addFilter(new PredicateFilter(predicate)); } + /** + * Specify the sorting strategy that will decide how to + * sort the results. This only matters if you use {@link #asList()} + * + * @param strategy Strategy + * @return The query instance + */ + @NotNull public PlotQuery withSortingStrategy(@NotNull final SortingStrategy strategy) { + Preconditions.checkNotNull(strategy, "Strategy may not be null"); + this.sortingStrategy = strategy; + return this; + } + + @NotNull public PlotQuery relativeToArea(@NotNull final PlotArea plotArea) { + Preconditions.checkNotNull(plotArea, "Area may not be null"); + this.priorityArea = plotArea; + return this; + } + /** * Get all plots that match the given criteria * * @return Matching plots */ @NotNull public Stream asStream() { - Stream plots = this.plotProvider.getPlots(); - for (final PlotFilter filter : this.filters) { - plots = plots.filter(filter); - } - return plots; + return this.asList().stream(); } /** @@ -186,7 +249,65 @@ public final class PlotQuery { * @return Matching plots as an immutable list */ @NotNull public List asList() { - return Collections.unmodifiableList(this.asStream().collect(Collectors.toList())); + final List result; + if (this.filters.isEmpty()) { + result = new ArrayList<>(this.plotProvider.getPlots()); + } else { + final Collection plots = this.plotProvider.getPlots(); + result = new ArrayList<>(plots.size()); + for (final Plot plot : plots) { + for (final PlotFilter filter : this.filters) { + if (filter.accepts(plot)) { + result.add(plot); + } + } + } + } + if (this.sortingStrategy == SortingStrategy.NO_SORTING) { + return result; + } else if (this.sortingStrategy == SortingStrategy.SORT_BY_TEMP) { + return PlotSquared.get().sortPlotsByTemp(result); + } else if (this.sortingStrategy == SortingStrategy.SORT_BY_DONE) { + result.sort((a, b) -> { + String va = a.getFlag(DoneFlag.class); + String vb = b.getFlag(DoneFlag.class); + if (MathMan.isInteger(va)) { + if (MathMan.isInteger(vb)) { + return Integer.parseInt(vb) - Integer.parseInt(va); + } + return -1; + } + return 1; + }); + } else if (this.sortingStrategy == SortingStrategy.SORT_BY_RATING) { + result.sort((p1, p2) -> { + double v1 = 0; + int p1s = p1.getSettings().getRatings().size(); + int p2s = p2.getRatings().size(); + if (!p1.getSettings().getRatings().isEmpty()) { + v1 = p1.getRatings().values().stream().mapToDouble(Rating::getAverageRating) + .map(av -> av * av).sum(); + v1 /= p1s; + v1 += p1s; + } + double v2 = 0; + if (!p2.getSettings().getRatings().isEmpty()) { + for (Map.Entry entry : p2.getRatings().entrySet()) { + double av = entry.getValue().getAverageRating(); + v2 += av * av; + } + v2 /= p2s; + v2 += p2s; + } + if (v2 == v1 && v2 != 0) { + return p2s - p1s; + } + return (int) Math.signum(v2 - v1); + }); + } else if (this.sortingStrategy == SortingStrategy.SORT_BY_CREATION) { + return PlotSquared.get().sortPlots(result, PlotSquared.SortType.CREATION_DATE, this.priorityArea); + } + return result; } /** @@ -195,7 +316,7 @@ public final class PlotQuery { * @return Matching plots as an immutable set */ @NotNull public Set asSet() { - return Collections.unmodifiableSet(this.asStream().collect(Collectors.toSet())); + return new HashSet<>(this.asList()); } /** diff --git a/Core/src/main/java/com/plotsquared/core/util/query/SearchPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/SearchPlotProvider.java new file mode 100644 index 000000000..91193a79e --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/SearchPlotProvider.java @@ -0,0 +1,46 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.util.MainUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; + +class SearchPlotProvider implements PlotProvider { + + private final String searchTerm; + + SearchPlotProvider(@NotNull final String searchTerm) { + this.searchTerm = searchTerm; + } + + @Override public Collection getPlots() { + return MainUtil.getPlotsBySearch(this.searchTerm); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java b/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java new file mode 100644 index 000000000..2e6351dcc --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java @@ -0,0 +1,52 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +/** + * Strategy used when sorting plot results + */ +public enum SortingStrategy { + /** + * Plots won't be sorted at all + */ + NO_SORTING, + /** + * Sort by the temporary (magic) plot ID + */ + SORT_BY_TEMP, + /** + * Sort by the value in the plot's {@link com.plotsquared.core.plot.flag.implementations.DoneFlag} + */ + SORT_BY_DONE, + /** + * Sort by the plot rating + */ + SORT_BY_RATING, + /** + * Sort by creation date + */ + SORT_BY_CREATION +} From 6b31743fb30462fa7ffc8cd2f1209d01fc05e7b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:02:08 +0200 Subject: [PATCH 057/121] add missing javadoc --- .../java/com/plotsquared/core/util/query/PlotQuery.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 612c4c21c..379702e12 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -228,6 +228,13 @@ public final class PlotQuery { return this; } + /** + * Defines the area around which plots may be sorted, depending on the + * sorting strategy + * + * @param plotArea Plot area + * @return The query instance + */ @NotNull public PlotQuery relativeToArea(@NotNull final PlotArea plotArea) { Preconditions.checkNotNull(plotArea, "Area may not be null"); this.priorityArea = plotArea; From 1aa144e47deb7fab83ce63f0c0fc61077e0a5898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:05:55 +0200 Subject: [PATCH 058/121] Deprecate old PlotFilter class --- Core/src/main/java/com/plotsquared/core/PlotSquared.java | 3 ++- .../src/main/java/com/plotsquared/core/plot/PlotFilter.java | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index e83cc56ba..bf0ef762b 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -895,8 +895,9 @@ public class PlotSquared { * * @param filters the filter * @return a filtered set of plots + * @deprecated Use {@link PlotQuery} */ - public Set getPlots(final PlotFilter... filters) { + @Deprecated public Set getPlots(final PlotFilter... filters) { final List areas = new LinkedList<>(); for (final PlotArea plotArea : this.getPlotAreas()) { for (final PlotFilter filter : filters) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotFilter.java b/Core/src/main/java/com/plotsquared/core/plot/PlotFilter.java index f7433a2ae..9319c048e 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotFilter.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotFilter.java @@ -25,7 +25,10 @@ */ package com.plotsquared.core.plot; -public abstract class PlotFilter { +/** + * Use {@link com.plotsquared.core.util.query.PlotQuery} instead + */ +@Deprecated public abstract class PlotFilter { public boolean allowsArea(final PlotArea area) { return true; } @@ -33,4 +36,5 @@ public abstract class PlotFilter { public boolean allowsPlot(final Plot plot) { return true; } + } From a0d1da32742ddb73b7889abe487931e487fba9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:08:52 +0200 Subject: [PATCH 059/121] fix dum typo --- .../{ExploredPlotProvider.java => ExpiredPlotProvider.java} | 2 +- .../main/java/com/plotsquared/core/util/query/PlotQuery.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename Core/src/main/java/com/plotsquared/core/util/query/{ExploredPlotProvider.java => ExpiredPlotProvider.java} (96%) diff --git a/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java similarity index 96% rename from Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java rename to Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java index 94bf9b92e..9b369dc4e 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/ExploredPlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/ExpiredPlotProvider.java @@ -30,7 +30,7 @@ import com.plotsquared.core.plot.expiration.ExpireManager; import java.util.Collection; -class ExploredPlotProvider implements PlotProvider { +class ExpiredPlotProvider implements PlotProvider { @Override public Collection getPlots() { return ExpireManager.IMP.getPendingExpired(); diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 379702e12..208fac5d7 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -116,7 +116,7 @@ public final class PlotQuery { * @return The query instance */ @NotNull public PlotQuery expiredPlots() { - this.plotProvider = new ExploredPlotProvider(); + this.plotProvider = new ExpiredPlotProvider(); return this; } From 76913d4a78d581067ec2db93d5b27c1484f6bc68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:14:33 +0200 Subject: [PATCH 060/121] immutable -> mutable --- .../main/java/com/plotsquared/core/util/query/PlotQuery.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 208fac5d7..67abfd1fa 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -253,7 +253,7 @@ public final class PlotQuery { /** * Get all plots that match the given criteria * - * @return Matching plots as an immutable list + * @return Matching plots as a mutable */ @NotNull public List asList() { final List result; @@ -320,7 +320,7 @@ public final class PlotQuery { /** * Get all plots that match the given criteria * - * @return Matching plots as an immutable set + * @return Matching plots as a mutable set */ @NotNull public Set asSet() { return new HashSet<>(this.asList()); From 0ac6383c2cf3bc6fe687f70a35876e209db0608d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 00:27:38 +0200 Subject: [PATCH 061/121] Use PlotQuery in Visit --- .../com/plotsquared/core/command/Visit.java | 41 +++++++++++------ .../core/util/query/FixedPlotProvider.java | 46 +++++++++++++++++++ .../core/util/query/PlotQuery.java | 28 +++++++++++ .../core/util/query/SortingStrategy.java | 6 ++- 4 files changed, 105 insertions(+), 16 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/util/query/FixedPlotProvider.java diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 372130a2d..442c40aeb 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -36,13 +36,13 @@ import com.plotsquared.core.plot.flag.implementations.UntrustedVisitFlag; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.query.PlotQuery; +import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; import com.plotsquared.core.util.uuid.UUIDHandler; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -72,9 +72,11 @@ public class Visit extends Command { args = args[0].split(":"); } int page = Integer.MIN_VALUE; - Collection unsorted = null; PlotArea sortByArea = player.getApplicablePlotArea(); boolean shouldSortByArea = Settings.Teleport.PER_WORLD_VISIT; + + final PlotQuery query = PlotQuery.newQuery(); + switch (args.length) { case 3: if (!MathMan.isInteger(args[1])) { @@ -96,7 +98,7 @@ public class Visit extends Command { Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } - unsorted = PlotSquared.get().getBasePlots(user); + query.ownedBy(user).whereBasePlot(); shouldSortByArea = true; break; } @@ -108,21 +110,21 @@ public class Visit extends Command { } if (page == Integer.MIN_VALUE && user == null && MathMan.isInteger(args[0])) { page = Integer.parseInt(args[0]); - unsorted = PlotSquared.get().getBasePlots(player); + query.ownedBy(player).whereBasePlot(); break; } if (user != null) { - unsorted = PlotSquared.get().getBasePlots(user); + query.ownedBy(player).whereBasePlot(); } else { Plot plot = MainUtil.getPlotFromString(player, args[0], true); if (plot != null) { - unsorted = Collections.singletonList(plot.getBasePlot(false)); + query.withPlot(plot); } } break; case 0: page = 1; - unsorted = PlotSquared.get().getPlots(player); + query.ownedBy(player); break; default: @@ -130,25 +132,33 @@ public class Visit extends Command { if (page == Integer.MIN_VALUE) { page = 1; } - if (unsorted == null || unsorted.isEmpty()) { + + // We get the query once, + // then we get it another time further on + final List unsorted = query.asList(); + + if (unsorted.isEmpty()) { Captions.FOUND_NO_PLOTS.send(player); return CompletableFuture.completedFuture(false); } - unsorted = new ArrayList<>(unsorted); + if (unsorted.size() > 1) { - unsorted.removeIf(plot -> !plot.isBasePlot()); + query.whereBasePlot(); } + if (page < 1 || page > unsorted.size()) { Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); return CompletableFuture.completedFuture(false); } - List plots; + if (shouldSortByArea) { - plots = PlotSquared.get() - .sortPlots(unsorted, PlotSquared.SortType.CREATION_DATE, sortByArea); + query.relativeToArea(sortByArea).withSortingStrategy(SortingStrategy.SORT_BY_CREATION); } else { - plots = PlotSquared.get().sortPlotsByTemp(unsorted); + query.withSortingStrategy(SortingStrategy.SORT_BY_TEMP); } + + final List plots = query.asList(); + final Plot plot = plots.get(page - 1); if (!plot.hasOwner()) { if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { @@ -177,6 +187,7 @@ public class Visit extends Command { return CompletableFuture.completedFuture(false); } } + confirm.run(this, () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { if (result) { whenDone.run(Visit.this, CommandResult.SUCCESS); diff --git a/Core/src/main/java/com/plotsquared/core/util/query/FixedPlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/FixedPlotProvider.java new file mode 100644 index 000000000..3bf79c783 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/query/FixedPlotProvider.java @@ -0,0 +1,46 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util.query; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Collections; + +class FixedPlotProvider implements PlotProvider { + + private final Plot plot; + + FixedPlotProvider(@NotNull final Plot plot) { + this.plot = plot; + } + + @Override public Collection getPlots() { + return Collections.singleton(plot); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 67abfd1fa..6c90e969f 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -38,6 +38,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -60,6 +61,7 @@ public final class PlotQuery { private PlotProvider plotProvider = new GlobalPlotProvider(); private SortingStrategy sortingStrategy = SortingStrategy.NO_SORTING; private PlotArea priorityArea; + private Comparator plotComparator; private PlotQuery() { } @@ -151,6 +153,17 @@ public final class PlotQuery { return this; } + /** + * Query with a pre-defined result + * + * @return The query instance + */ + @NotNull public PlotQuery withPlot(@NotNull final Plot plot) { + Preconditions.checkNotNull(plot, "Plot may not be null"); + this.plotProvider = new FixedPlotProvider(plot); + return this; + } + /** * Query for base plots only * @@ -228,6 +241,19 @@ public final class PlotQuery { return this; } + /** + * Use a custom comparator to sort the results + * + * @param comparator Comparator + * @return The query instance + */ + @NotNull public PlotQuery sorted(@NotNull final Comparator comparator) { + Preconditions.checkNotNull(comparator, "Comparator may not be null"); + this.sortingStrategy = SortingStrategy.COMPARATOR; + this.plotComparator = comparator; + return this; + } + /** * Defines the area around which plots may be sorted, depending on the * sorting strategy @@ -313,6 +339,8 @@ public final class PlotQuery { }); } else if (this.sortingStrategy == SortingStrategy.SORT_BY_CREATION) { return PlotSquared.get().sortPlots(result, PlotSquared.SortType.CREATION_DATE, this.priorityArea); + } else if (this.sortingStrategy == SortingStrategy.COMPARATOR) { + result.sort(this.plotComparator); } return result; } diff --git a/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java b/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java index 2e6351dcc..7a70b46fd 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/SortingStrategy.java @@ -48,5 +48,9 @@ public enum SortingStrategy { /** * Sort by creation date */ - SORT_BY_CREATION + SORT_BY_CREATION, + /** + * Sort using a comparator + */ + COMPARATOR; } From 0b12c4e5b25e42d2e65bd332ab051e53905fb291 Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Sun, 24 May 2020 18:48:15 +0200 Subject: [PATCH 062/121] Update issue link --- Core/src/main/java/com/plotsquared/core/command/DebugPaste.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java b/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java index c5c42a4c2..ea223c60a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java @@ -122,7 +122,7 @@ public class DebugPaste extends SubCommand { b.append("OS Arch: ").append(System.getProperty("os.arch")).append('\n'); b.append("# Okay :D Great. You are now ready to create your bug report!"); b.append( - "\n# You can do so at https://github.com/IntellectualSites/PlotSquared/issues"); + "\n# You can do so at https://issues.intellectualsites.com/projects/ps"); b.append("\n# or via our Discord at https://discord.gg/KxkjDVg"); final IncendoPaster incendoPaster = new IncendoPaster("plotsquared"); From 172bd6f0f2be60c9abb4a5e3e69aa9fc41a3381a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 19:05:09 +0200 Subject: [PATCH 063/121] This should hopefully fix that broken merge. Maybe. Possibly. Idk. --- .../com/plotsquared/core/command/ListCmd.java | 44 ++++--------------- .../com/plotsquared/core/command/Visit.java | 13 +++--- 2 files changed, 14 insertions(+), 43 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java index dfd582f0f..489208adf 100644 --- a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java @@ -49,7 +49,6 @@ import com.plotsquared.core.uuid.UUIDMapping; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -139,20 +138,19 @@ public class ListCmd extends SubCommand { String arg = args[0].toLowerCase(); final boolean[] sort = new boolean[] {true}; - final Consumer plotConsumer = plots -> { + final Consumer plotConsumer = query -> { if (query == null) { sendMessage(player, Captions.DID_YOU_MEAN, new StringComparison<>(args[0], new String[] {"mine", "shared", "world", "all"}) .getBestMatch()); - return false; + return; } - if (area != null) { query.relativeToArea(area); } - if (sort) { + if (sort[0]) { query.withSortingStrategy(SortingStrategy.SORT_BY_CREATION); } @@ -160,7 +158,7 @@ public class ListCmd extends SubCommand { if (plots.isEmpty()) { MainUtil.sendMessage(player, Captions.FOUND_NO_PLOTS); - return false; + return; } displayPlots(player, plots, 12, page, args); }; @@ -198,7 +196,6 @@ public class ListCmd extends SubCommand { } plotConsumer.accept(PlotQuery.newQuery().inWorld(world)); break; - plotConsumer.accept(PlotSquared.get().getPlots(world)); case "expired": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_EXPIRED)) { MainUtil.sendMessage(player, Captions.NO_PERMISSION, @@ -211,9 +208,6 @@ public class ListCmd extends SubCommand { plotConsumer.accept(PlotQuery.newQuery().expiredPlots()); } break; - plotConsumer.accept(ExpireManager.IMP == null ? - new ArrayList<>() : - new ArrayList<>(ExpireManager.IMP.getPendingExpired())); case "area": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_AREA)) { MainUtil @@ -239,7 +233,7 @@ public class ListCmd extends SubCommand { .sendMessage(player, Captions.NO_PERMISSION, Captions.PERMISSION_LIST_ALL); return false; } - plotConsumer.accept(PlotQuery().newQuery().allPlots()); + plotConsumer.accept(PlotQuery.newQuery().allPlots()); break; case "done": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_DONE)) { @@ -248,7 +242,7 @@ public class ListCmd extends SubCommand { return false; } sort[0] = false; - plotConsumer.accept(PlotQuery.newQuery().allPlots().thatPasses(DoneFlag::isDone).withSortingStrategy(SortingStrategy.SORT_BY_DONE)) + plotConsumer.accept(PlotQuery.newQuery().allPlots().thatPasses(DoneFlag::isDone).withSortingStrategy(SortingStrategy.SORT_BY_DONE)); break; case "top": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_TOP)) { @@ -257,7 +251,7 @@ public class ListCmd extends SubCommand { return false; } sort[0] = false; - plotConsumer.accept(PlotQuery.newQuery().allPlots().withSortingStrategy(SortingStrategy.SORT_BY_RATING)) + plotConsumer.accept(PlotQuery.newQuery().allPlots().withSortingStrategy(SortingStrategy.SORT_BY_RATING)); break; case "forsale": if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_FOR_SALE)) { @@ -337,36 +331,16 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_PLAYER); } else { sort[0] = false; - plotConsumer.accept(PlotSquared.get() - .sortPlotsByTemp(PlotSquared.get().getPlots(uuid))); + plotConsumer.accept(PlotQuery.newQuery().ownedBy(uuid).withSortingStrategy(SortingStrategy.SORT_BY_TEMP)); } } }); - - - UUID uuid = UUIDHandler.getUUID(args[0], null); - if (uuid == null) { - try { - uuid = UUID.fromString(args[0]); - } catch (Exception ignored) { - } - } - if (uuid != null) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_LIST_PLAYER)) { - MainUtil.sendMessage(player, Captions.NO_PERMISSION, - Captions.PERMISSION_LIST_PLAYER); - return false; - } - sort[0] = false; - plotConsumer.accept(PlotQuery.newQuery().ownedBy(uuid).withSortingStrategy(SortingStrategy.SORT_BY_TEMP)); - break; - } } return true; } - public void displayPlots(final PlotPlayer player, List plots, int pageSize, int page, String[] args { + public void displayPlots(final PlotPlayer player, List plots, int pageSize, int page, String[] args) { // Header plots.removeIf(plot -> !plot.isBasePlot()); this.paginate(player, plots, pageSize, page, diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index cd541c33e..3a18fc7d9 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -41,10 +41,7 @@ import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -79,7 +76,7 @@ public class Visit extends Command { final PlotQuery query = PlotQuery.newQuery(); final PlotArea[] sortByArea = new PlotArea[] {player.getApplicablePlotArea()}; - final Atomicboolean shouldSortByArea = new AtomicBoolean(Settings.Teleport.PER_WORLD_VISIT); + final AtomicBoolean shouldSortByArea = new AtomicBoolean(Settings.Teleport.PER_WORLD_VISIT); final Consumer pageConsumer = page -> { // We get the query once, @@ -88,7 +85,7 @@ public class Visit extends Command { if (unsorted.isEmpty()) { Captions.FOUND_NO_PLOTS.send(player); - return CompletableFuture.completedFuture(false); + return; } if (unsorted.size() > 1) { @@ -97,11 +94,11 @@ public class Visit extends Command { if (page < 1 || page > unsorted.size()) { Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); - return CompletableFuture.completedFuture(false); + return; } if (shouldSortByArea.get()) { - query.relativeToArea(sortByArea).withSortingStrategy(SortingStrategy.SORT_BY_CREATION); + query.relativeToArea(sortByArea[0]).withSortingStrategy(SortingStrategy.SORT_BY_CREATION); } else { query.withSortingStrategy(SortingStrategy.SORT_BY_TEMP); } @@ -171,7 +168,7 @@ public class Visit extends Command { } else if (throwable != null || uuids.size() != 1) { Captions.COMMAND_SYNTAX.send(player, getUsage()); } else { - query.ownedBy(user).whereBasePlot(); + query.ownedBy(uuids.toArray(new UUID[0])[0]).whereBasePlot(); shouldSortByArea.set(true); pageConsumer.accept(page[0]); } From 69cfb431b145a26ba2aea50cbf87a0d966e4d6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 20:18:02 +0200 Subject: [PATCH 064/121] Unstupidify Visit --- .../com/plotsquared/core/command/Visit.java | 248 ++++++++++-------- .../core/configuration/Captions.java | 1 + .../core/util/query/PlotQuery.java | 7 +- 3 files changed, 149 insertions(+), 107 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 3a18fc7d9..3c1ed70c3 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -27,7 +27,6 @@ package com.plotsquared.core.command; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; @@ -40,14 +39,13 @@ import com.plotsquared.core.util.query.PlotQuery; import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; +import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; @CommandDeclaration(command = "visit", permission = "plots.visit", @@ -66,152 +64,194 @@ public class Visit extends Command { return tabOf(player, args, space, getUsage()); } + private void visit(@NotNull final PlotPlayer player, @NotNull final PlotQuery query, final PlotArea sortByArea, + final RunnableVal3 confirm, final RunnableVal2 whenDone) { + this.visit(player, query, sortByArea, confirm, whenDone, 1); + } + + private void visit(@NotNull final PlotPlayer player, @NotNull final PlotQuery query, final PlotArea sortByArea, + final RunnableVal3 confirm, final RunnableVal2 whenDone, int page) { + // We get the query once, + // then we get it another time further on + final List unsorted = query.asList(); + + if (unsorted.isEmpty()) { + Captions.FOUND_NO_PLOTS.send(player); + return; + } + + if (unsorted.size() > 1) { + query.whereBasePlot(); + } + + if (page == Integer.MIN_VALUE) { + page = 1; + } + + if (page < 1 || page > unsorted.size()) { + MainUtil.sendMessage(player, String.format("(1, %d)", unsorted.size())); + return; + } + + if (sortByArea != null) { + query.relativeToArea(sortByArea).withSortingStrategy(SortingStrategy.SORT_BY_CREATION); + } else { + query.withSortingStrategy(SortingStrategy.SORT_BY_TEMP); + } + + final List plots = query.asList(); + + final Plot plot = plots.get(page - 1); + if (!plot.hasOwner()) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_UNOWNED); + return; + } + } else if (plot.isOwner(player.getUUID())) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions + .hasPermission(player, Captions.PERMISSION_HOME)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED); + return; + } + } else if (plot.isAdded(player.getUUID())) { + if (!Permissions.hasPermission(player, Captions.PERMISSION_SHARED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_SHARED); + return; + } + } else { + if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OTHER)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OTHER); + return; + } + if (!plot.getFlag(UntrustedVisitFlag.class) && !Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED)) { + Captions.NO_PERMISSION.send(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED); + return; + } + } + + confirm.run(this, () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { + if (result) { + whenDone.run(Visit.this, CommandResult.SUCCESS); + } else { + whenDone.run(Visit.this, CommandResult.FAILURE); + } + }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); + } + @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, - RunnableVal3 confirm, + public CompletableFuture execute(final PlotPlayer player, + String[] args, + final RunnableVal3 confirm, final RunnableVal2 whenDone) throws CommandException { if (args.length == 1 && args[0].contains(":")) { args = args[0].split(":"); } - final PlotQuery query = PlotQuery.newQuery(); - final PlotArea[] sortByArea = new PlotArea[] {player.getApplicablePlotArea()}; - final AtomicBoolean shouldSortByArea = new AtomicBoolean(Settings.Teleport.PER_WORLD_VISIT); + PlotArea sortByArea; - final Consumer pageConsumer = page -> { - // We get the query once, - // then we get it another time further on - final List unsorted = query.asList(); - - if (unsorted.isEmpty()) { - Captions.FOUND_NO_PLOTS.send(player); - return; - } - - if (unsorted.size() > 1) { - query.whereBasePlot(); - } - - if (page < 1 || page > unsorted.size()) { - Captions.NOT_VALID_NUMBER.send(player, "(1, " + unsorted.size() + ")"); - return; - } - - if (shouldSortByArea.get()) { - query.relativeToArea(sortByArea[0]).withSortingStrategy(SortingStrategy.SORT_BY_CREATION); - } else { - query.withSortingStrategy(SortingStrategy.SORT_BY_TEMP); - } - - final List plots = query.asList(); - - final Plot plot = plots.get(page - 1); - if (!plot.hasOwner()) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_UNOWNED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_UNOWNED); - return; - } - } else if (plot.isOwner(player.getUUID())) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OWNED) && !Permissions - .hasPermission(player, Captions.PERMISSION_HOME)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OWNED); - return; - } - } else if (plot.isAdded(player.getUUID())) { - if (!Permissions.hasPermission(player, Captions.PERMISSION_SHARED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_SHARED); - return; - } - } else { - if (!Permissions.hasPermission(player, Captions.PERMISSION_VISIT_OTHER)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_VISIT_OTHER); - return; - } - if (!plot.getFlag(UntrustedVisitFlag.class) && !Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED)) { - Captions.NO_PERMISSION.send(player, Captions.PERMISSION_ADMIN_VISIT_UNTRUSTED); - return; - } - } - - confirm.run(this, () -> plot.teleportPlayer(player, TeleportCause.COMMAND, result -> { - if (result) { - whenDone.run(Visit.this, CommandResult.SUCCESS); - } else { - whenDone.run(Visit.this, CommandResult.FAILURE); - } - }), () -> whenDone.run(Visit.this, CommandResult.FAILURE)); - }; - - final int[] page = new int[]{Integer.MIN_VALUE}; + int page = Integer.MIN_VALUE; switch (args.length) { + // /p v [...] [...] case 3: if (!MathMan.isInteger(args[1])) { Captions.NOT_VALID_NUMBER.send(player, "(1, ∞)"); Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } - page[0] = Integer.parseInt(args[2]); + page = Integer.parseInt(args[2]); + // /p v [page] + // /p v [page] case 2: - if (page[0] != Integer.MIN_VALUE || !MathMan.isInteger(args[1])) { - sortByArea[0] = PlotSquared.get().getPlotAreaByString(args[1]); - if (sortByArea[0] == null) { + if (page != Integer.MIN_VALUE || !MathMan.isInteger(args[1])) { + sortByArea = PlotSquared.get().getPlotAreaByString(args[1]); + if (sortByArea == null) { Captions.NOT_VALID_NUMBER.send(player, "(1, ∞)"); Captions.COMMAND_SYNTAX.send(player, getUsage()); return CompletableFuture.completedFuture(false); } + final PlotArea finalSortByArea = sortByArea; + int finalPage1 = page; MainUtil.getUUIDsFromString(args[0], (uuids, throwable) -> { if (throwable instanceof TimeoutException) { Captions.FETCHING_PLAYERS_TIMEOUT.send(player); } else if (throwable != null || uuids.size() != 1) { Captions.COMMAND_SYNTAX.send(player, getUsage()); } else { - query.ownedBy(uuids.toArray(new UUID[0])[0]).whereBasePlot(); - shouldSortByArea.set(true); - pageConsumer.accept(page[0]); + final UUID uuid = uuids.toArray(new UUID[0])[0]; + this.visit(player, PlotQuery.newQuery().ownedBy(uuid).whereBasePlot(), finalSortByArea, confirm, whenDone, finalPage1); } }); break; } - page[0] = Integer.parseInt(args[1]); + page = Integer.parseInt(args[1]); + // /p v [page] + // /p v [page] + // /p v [page] + // /p v [page] case 1: final String[] finalArgs = args; - final Consumer uuidConsumer = uuid -> { - if (page[0] == Integer.MIN_VALUE && uuid == null && MathMan.isInteger(finalArgs[0])) { - page[0] = Integer.parseInt(finalArgs[0]); - query.ownedBy(player).whereBasePlot(); - } else { - if (uuid != null) { - query.ownedBy(player).whereBasePlot(); - } else { - Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); - if (plot != null) { - query.withPlot(plot); - } - } - } - pageConsumer.accept(page[0]); - }; - + int finalPage = page; if (args[0].length() >= 2) { PlotSquared.get().getImpromptuUUIDPipeline().getSingle(args[0], (uuid, throwable) -> { if (throwable instanceof TimeoutException) { + // The request timed out MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); } else if (uuid != null && !PlotSquared.get().hasPlot(uuid)) { - uuidConsumer.accept(null); + // It was a valid UUID but the player has no plots + MainUtil.sendMessage(player, Captions.PLAYER_NO_PLOTS); + } else if (uuid == null) { + if (finalPage == Integer.MIN_VALUE && MathMan.isInteger(finalArgs[0])) { + // The argument was a number, so we assume it's the page number + int parsedPage; + try { + parsedPage = Integer.parseInt(finalArgs[0]); + } catch (final Throwable t) { + MainUtil.sendMessage(player, Captions.NOT_A_NUMBER, finalArgs[0]); + return; + } + this.visit(player, PlotQuery.newQuery().ownedBy(player).whereBasePlot(), null, + confirm, whenDone, parsedPage); + } else { + // Try to parse a plot + final Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); + if (plot == null) { + MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID); + return; + } + this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1); + } } else { - uuidConsumer.accept(uuid); + this.visit(player, PlotQuery.newQuery().ownedBy(uuid).whereBasePlot(), null, confirm, whenDone, finalPage); } }); } else { - uuidConsumer.accept(null); + if (finalPage == Integer.MIN_VALUE && MathMan.isInteger(finalArgs[0])) { + // The argument was a number, so we assume it's the page number + int parsedPage; + try { + parsedPage = Integer.parseInt(finalArgs[0]); + this.visit(player, PlotQuery.newQuery().ownedBy(player).whereBasePlot(), null, confirm, + whenDone, parsedPage); + } catch (final Throwable throwable) { + MainUtil.sendMessage(player, Captions.NOT_A_NUMBER, finalArgs[0]); + } + } else { + // Try to parse a plot + final Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); + if (plot == null) { + MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID); + } else { + this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1); + } + } } break; case 0: - query.ownedBy(player); - pageConsumer.accept(1); + // /p v + this.visit(player, PlotQuery.newQuery().ownedBy(player), null, confirm, whenDone); break; default: } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 98cb8b9ce..eb5f6f444 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -445,6 +445,7 @@ public enum Captions implements Caption { NOT_VALID_WORLD("$2That is not a valid world (case sensitive)", "Errors"), NOT_VALID_PLOT_WORLD("$2That is not a valid plot area (case sensitive)", "Errors"), NO_PLOTS("$2You don't have any plots", "Errors"), + PLAYER_NO_PLOTS("$2That player does not own any plots", "Errors"), WAIT_FOR_TIMER("$2A set block timer is bound to either the current plot or you. Please wait for it to finish", "Errors"), TILE_ENTITY_CAP_REACHED("$2The total number of tile entities in this chunk may not exceed $1%s", "Errors"), // diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 6c90e969f..40d883062 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -288,12 +288,13 @@ public final class PlotQuery { } else { final Collection plots = this.plotProvider.getPlots(); result = new ArrayList<>(plots.size()); - for (final Plot plot : plots) { + outer: for (final Plot plot : plots) { for (final PlotFilter filter : this.filters) { - if (filter.accepts(plot)) { - result.add(plot); + if (!filter.accepts(plot)) { + continue outer; } } + result.add(plot); } } if (this.sortingStrategy == SortingStrategy.NO_SORTING) { From 862467c0fa3eeab412ffa6220eade3c52c1973ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 20:53:16 +0200 Subject: [PATCH 065/121] Tab complete `/plot visit` --- .../com/plotsquared/core/command/Visit.java | 61 +++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 3c1ed70c3..2b64746c2 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -35,6 +35,7 @@ import com.plotsquared.core.plot.flag.implementations.UntrustedVisitFlag; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.query.PlotQuery; import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal2; @@ -42,6 +43,8 @@ import com.plotsquared.core.util.task.RunnableVal3; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -60,10 +63,6 @@ public class Visit extends Command { super(MainCommand.getInstance(), true); } - @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { - return tabOf(player, args, space, getUsage()); - } - private void visit(@NotNull final PlotPlayer player, @NotNull final PlotQuery query, final PlotArea sortByArea, final RunnableVal3 confirm, final RunnableVal2 whenDone) { this.visit(player, query, sortByArea, confirm, whenDone, 1); @@ -194,7 +193,7 @@ public class Visit extends Command { case 1: final String[] finalArgs = args; int finalPage = page; - if (args[0].length() >= 2) { + if (args[0].length() >= 2 && !args[0].contains(";") && !args[0].contains(",")) { PlotSquared.get().getImpromptuUUIDPipeline().getSingle(args[0], (uuid, throwable) -> { if (throwable instanceof TimeoutException) { // The request timed out @@ -259,4 +258,56 @@ public class Visit extends Command { return CompletableFuture.completedFuture(true); } + public Collection tab(PlotPlayer player, String[] args, boolean space) { + final List completions = new LinkedList<>(); + player.sendMessage("u haef " + args.length + " args and they r "); + for (int i = 0; i < args.length; i++) { + player.sendMessage(i + ": " + args[i]); + } + + switch (args.length - 1) { + case 0: + this.completeNumbers(completions, args[0], 0); + completions.addAll(TabCompletions.completePlayers(args[0], Collections.emptyList())); + break; + case 1: + if (MathMan.isInteger(args[0])) { + break; + } + this.completeNumbers(completions, args[1], 0); + this.completeAreas(completions, args[1]); + break; + case 2: + if (MathMan.isInteger(args[1])) { + break; + } + this.completeNumbers(completions, args[2], 0); + break; + } + + return completions; + } + + private void completeNumbers(final List commands, final String arg, final int start) { + for (int i = 0; i < 10; i++) { + final String command = Integer.toString(start + 1); + if (!command.toLowerCase().startsWith(arg.toLowerCase())) { + continue; + } + commands.add(new Command(this, false, command, "", + RequiredType.NONE, CommandCategory.TELEPORT) {}); + } + } + + private void completeAreas(final List commands, final String arg) { + for (final PlotArea area : PlotSquared.get().getPlotAreas()) { + final String areaName = area.getWorldName() + ";" + area.getId(); + if (!areaName.toLowerCase().startsWith(arg.toLowerCase())) { + continue; + } + commands.add(new Command(this, false, area.getWorldName() + ";" + area.getId(), "", + RequiredType.NONE, CommandCategory.TELEPORT) {}); + } + } + } From 2436a6a402423581e268457b359f6c06bf7c52f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 20:54:10 +0200 Subject: [PATCH 066/121] remove debug, whoops --- Core/src/main/java/com/plotsquared/core/command/Visit.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 2b64746c2..651a1c0b0 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -260,11 +260,6 @@ public class Visit extends Command { public Collection tab(PlotPlayer player, String[] args, boolean space) { final List completions = new LinkedList<>(); - player.sendMessage("u haef " + args.length + " args and they r "); - for (int i = 0; i < args.length; i++) { - player.sendMessage(i + ": " + args[i]); - } - switch (args.length - 1) { case 0: this.completeNumbers(completions, args[0], 0); @@ -289,7 +284,7 @@ public class Visit extends Command { } private void completeNumbers(final List commands, final String arg, final int start) { - for (int i = 0; i < 10; i++) { + for (int i = 0; i < 100; i++) { final String command = Integer.toString(start + 1); if (!command.toLowerCase().startsWith(arg.toLowerCase())) { continue; From 46b68e489d9c90565c0caa877d14f748f3008a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 24 May 2020 21:08:11 +0200 Subject: [PATCH 067/121] Tab complete `/p list` --- .../bukkit/managers/BukkitWorldManager.java | 12 +++++ .../com/plotsquared/core/command/ListCmd.java | 49 +++++++++++++++++++ .../core/util/PlatformWorldManager.java | 9 ++++ 3 files changed, 70 insertions(+) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java index 482d02896..4646868a1 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/managers/BukkitWorldManager.java @@ -36,6 +36,9 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; /** * Default Bukkit world manager. It will handle world creation by @@ -76,4 +79,13 @@ public class BukkitWorldManager implements PlatformWorldManager { return "bukkit"; } + @Override public Collection getWorlds() { + final List worlds = Bukkit.getWorlds(); + final List worldNames = new ArrayList<>(); + for (final World world : worlds) { + worldNames.add(world.getName()); + } + return worldNames; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java index 489208adf..0054df62e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java @@ -42,6 +42,7 @@ import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.StringMan; +import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.query.PlotQuery; import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal3; @@ -49,12 +50,16 @@ import com.plotsquared.core.uuid.UUIDMapping; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; import java.util.List; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Consumer; +import java.util.stream.Collectors; @CommandDeclaration(command = "list", aliases = {"l", "find", "search"}, @@ -397,4 +402,48 @@ public class ListCmd extends SubCommand { }, "/plot list " + args[0], Captions.PLOT_LIST_HEADER_PAGED.getTranslated()); } + @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { + final List completions = new LinkedList<>(); + if (EconHandler.manager != null && Permissions + .hasPermission(player, Captions.PERMISSION_LIST_FOR_SALE)) { + completions.add("forsale"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_MINE)) { + completions.add("mine"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_SHARED)) { + completions.add("shared"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_WORLD)) { + completions.addAll(PlotSquared.imp().getWorldManager().getWorlds()); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_TOP)) { + completions.add("top"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_ALL)) { + completions.add("all"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_UNOWNED)) { + completions.add("unowned"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_DONE)) { + completions.add("done"); + } + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_EXPIRED)) { + completions.add("expired"); + } + + final List commands = new LinkedList<>(); + commands.addAll(completions.stream() + .filter(completion -> completion.toLowerCase().startsWith(args[0].toLowerCase())) + .map(completion -> new Command(null, true, completion, "", RequiredType.NONE, CommandCategory.TELEPORT) {}) + .collect(Collectors.toList())); + + if (Permissions.hasPermission(player, Captions.PERMISSION_LIST_PLAYER) && args[0].length() > 0) { + commands.addAll(TabCompletions.completePlayers(args[0], Collections.emptyList())); + } + + return commands; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/util/PlatformWorldManager.java b/Core/src/main/java/com/plotsquared/core/util/PlatformWorldManager.java index f57e42a21..c304ff04c 100644 --- a/Core/src/main/java/com/plotsquared/core/util/PlatformWorldManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/PlatformWorldManager.java @@ -28,6 +28,8 @@ package com.plotsquared.core.util; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; + /** * This class should be implemented by each platform to allow PlotSquared to interact * with the world management solution used on the server. @@ -62,4 +64,11 @@ public interface PlatformWorldManager { */ String getName(); + /** + * Get the names of all worlds on the server + * + * @return Worlds + */ + Collection getWorlds(); + } From 0021b114def5d6fe380df3fa32780efdaa634fe1 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sun, 24 May 2020 23:24:27 +0100 Subject: [PATCH 068/121] Revert "Slow down queue a bit because 1.13+ performance is bad" This reverts commit bbde2f5e069379a6bb09cca70747dcc7d3c88c4f. --- .../com/plotsquared/core/configuration/Settings.java | 4 ++-- .../com/plotsquared/core/queue/GlobalBlockQueue.java | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 2be87ada3..3fbd71394 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -491,9 +491,9 @@ public class Settings extends Config { @Comment("Settings relating to PlotSquared's GlobalBlockQueue") public static final class QUEUE { - @Comment({"Average time per tick spent completing chunk tasks in ms.", + @Comment({"Average time per tick spent completing chunk tasks in ms. Target average TPS = 20 * 50 / TARGET_TIME.", "Waits (chunk task time / target_time) ticks before completely the next task."}) - public static int TARGET_TIME = 40; + public static int TARGET_TIME = 65; } diff --git a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java index 6abfea8f8..3b63a94c0 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/GlobalBlockQueue.java @@ -57,7 +57,6 @@ public class GlobalBlockQueue { private final RunnableVal2 SET_TASK = new RunnableVal2() { @Override public void run(Long free, LocalBlockQueue queue) { - long t1 = System.currentTimeMillis(); do { boolean more = queue.next(); if (!more) { @@ -67,9 +66,9 @@ public class GlobalBlockQueue { } return; } - } while (((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) - - GlobalBlockQueue.this.last) < free); - lastPeriod = System.currentTimeMillis() - t1; + } while ((lastPeriod = + ((GlobalBlockQueue.this.secondLast = System.currentTimeMillis()) + - GlobalBlockQueue.this.last)) < free); } }; @@ -125,8 +124,8 @@ public class GlobalBlockQueue { lastPeriod -= targetTime; return; } - SET_TASK.value1 = 30 + Math.min( - (30 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = + SET_TASK.value1 = 50 + Math.min( + (50 + GlobalBlockQueue.this.last) - (GlobalBlockQueue.this.last = System.currentTimeMillis()), GlobalBlockQueue.this.secondLast - System.currentTimeMillis()); SET_TASK.value2 = GlobalBlockQueue.this.getNextQueue(); From 31b71ade695016a58fe2b4c29ed9f377c4927e47 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sun, 24 May 2020 23:43:15 +0100 Subject: [PATCH 069/121] * :D --- .../main/java/com/plotsquared/core/configuration/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 3fbd71394..76d384fff 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -491,7 +491,7 @@ public class Settings extends Config { @Comment("Settings relating to PlotSquared's GlobalBlockQueue") public static final class QUEUE { - @Comment({"Average time per tick spent completing chunk tasks in ms. Target average TPS = 20 * 50 / TARGET_TIME.", + @Comment({"Average time per tick spent completing chunk tasks in ms.", "Waits (chunk task time / target_time) ticks before completely the next task."}) public static int TARGET_TIME = 65; } From 4b0df8087844d0d6e91f84fe6c013cb949bc2a86 Mon Sep 17 00:00:00 2001 From: darbyjack Date: Mon, 25 May 2020 00:09:28 -0500 Subject: [PATCH 070/121] Updated PAPI & EssX dependency to ensure compatibility --- Bukkit/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index caafd3ef0..119516422 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -30,9 +30,9 @@ dependencies { compile("com.github.MilkBowl:VaultAPI:1.7") { exclude(module: "bukkit") } - implementation("me.clip:placeholderapi:2.10.4") + implementation("me.clip:placeholderapi:2.10.6") implementation("net.luckperms:api:5.0") - implementation("net.ess3:EssentialsX:2.16.1") + implementation("net.ess3:EssentialsX:2.17.2") compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false } compile 'com.github.pavog:SquirrelID:0.6.1' } From 67fbfb0f2d41b00b96aa11fa6d119868115a8c4a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 25 May 2020 09:13:10 +0000 Subject: [PATCH 071/121] Bump api from 5.0 to 5.1 Bumps [api](https://github.com/lucko/LuckPerms) from 5.0 to 5.1. - [Release notes](https://github.com/lucko/LuckPerms/releases) - [Commits](https://github.com/lucko/LuckPerms/compare/v5.0...v5.1) Signed-off-by: dependabot-preview[bot] --- Bukkit/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index caafd3ef0..391a755dc 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -31,7 +31,7 @@ dependencies { exclude(module: "bukkit") } implementation("me.clip:placeholderapi:2.10.4") - implementation("net.luckperms:api:5.0") + implementation("net.luckperms:api:5.1") implementation("net.ess3:EssentialsX:2.16.1") compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false } compile 'com.github.pavog:SquirrelID:0.6.1' From b9b0d89b5f759354a684cd7a6539ae7e4b883ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Mon, 25 May 2020 15:13:31 +0200 Subject: [PATCH 072/121] Replace the R-tree library with PRTree. Fix SquirrelID shading issues. Bump the version to 5.12.0 --- Bukkit/build.gradle | 9 ++- Bukkit/pom.xml | 18 +++-- Core/build.gradle | 5 +- Core/pom.xml | 6 +- .../plotsquared/core/location/Location.java | 6 ++ .../core/plot/world/ScatteredPlotWorld.java | 44 +++++++----- .../core/util/PlotAreaConverter.java | 68 +++++++++++++++++++ .../com/plotsquared/core/util/RegionUtil.java | 8 +-- build.gradle | 2 +- 9 files changed, 128 insertions(+), 38 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/util/PlotAreaConverter.java diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 9cdb65d18..6995d9034 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -36,7 +36,7 @@ dependencies { implementation("net.ess3:EssentialsX:2.17.2") implementation("net.alpenblock:BungeePerms:4.0-dev-106") compile("se.hyperver.hyperverse:Core:0.6.0-SNAPSHOT"){ transitive = false } - compile 'com.github.pavog:SquirrelID:0.6.1' + compile('com.sk89q:squirrelid:1.0.0-SNAPSHOT'){ transitive = false } } sourceCompatibility = 1.8 @@ -93,15 +93,14 @@ shadowJar { include(dependency("io.papermc:paperlib:1.0.2")) include(dependency("net.kyori:text-adapter-bukkit:3.0.3")) include(dependency("org.bstats:bstats-bukkit:1.7")) - include(dependency("com.github.davidmoten:rtree:0.8.7")) - include(dependency("io.reactivex:rxjava:1.3.8")) - include(dependency("com.github.davidmoten:guava-mini:0.1.1")) - include(dependency("com.github.pavog:SquirrelID:0.6.1")) + include(dependency("org.khelekore:prtree:1.7.0-SNAPSHOT")) + include(dependency("com.sk89q:squirrelid:1.0.0-SNAPSHOT")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") relocate("org.bstats", "com.plotsquared.metrics") relocate('com.sk89q.squirrelid', 'com.plotsquared.squirrelid') + relocate('org.khelekore.prtree', 'com.plotsquared.prtree') archiveFileName = "${project.name}-${parent.version}.jar" destinationDirectory = file "../target" } diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index 42fce3d0a..c2e002a06 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -67,10 +67,16 @@ - com.github.pavog - SquirrelID - 0.6.1 + com.sk89q + squirrelid + 1.0.0-SNAPSHOT compile + + + * + * + + com.sk89q.worldedit @@ -137,19 +143,19 @@ me.clip placeholderapi - 2.10.4 + 2.10.6 runtime net.luckperms api - 5.0 + 5.1 runtime net.ess3 EssentialsX - 2.16.1 + 2.17.2 runtime diff --git a/Core/build.gradle b/Core/build.gradle index 8581a39a4..51f56e187 100644 --- a/Core/build.gradle +++ b/Core/build.gradle @@ -1,5 +1,6 @@ repositories { maven { url = "https://jitpack.io" } + maven { url = "https://mvn.intellectualsites.com/content/repositories/snapshots" } } def textVersion = "3.0.2" @@ -16,7 +17,7 @@ dependencies { testAnnotationProcessor("org.projectlombok:lombok:1.18.8") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.3.72") implementation("org.jetbrains:annotations:19.0.0") - implementation 'com.github.davidmoten:rtree:0.8.7' + implementation("org.khelekore:prtree:1.7.0-SNAPSHOT") } sourceCompatibility = 1.8 @@ -74,7 +75,7 @@ shadowJar { include(dependency("net.kyori:text-serializer-gson:3.0.2")) include(dependency("net.kyori:text-serializer-legacy:3.0.2")) include(dependency("net.kyori:text-serializer-plain:3.0.2")) - include(dependency("com.github.davidmoten:rtree:0.8.7")) + include(dependency("org.khelekore:prtree:1.7.0-SNAPSHOT")) } relocate('net.kyori.text', 'com.plotsquared.formatting.text') relocate("org.json", "com.plotsquared.json") { diff --git a/Core/pom.xml b/Core/pom.xml index 4e53e831a..3260d86a8 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -93,9 +93,9 @@ runtime - com.github.davidmoten - rtree - 0.8.7 + org.khelekore + prtree + 1.7.0-SNAPSHOT runtime diff --git a/Core/src/main/java/com/plotsquared/core/location/Location.java b/Core/src/main/java/com/plotsquared/core/location/Location.java index a6f2c812b..0505137b1 100644 --- a/Core/src/main/java/com/plotsquared/core/location/Location.java +++ b/Core/src/main/java/com/plotsquared/core/location/Location.java @@ -34,6 +34,8 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import lombok.Getter; import lombok.Setter; +import org.khelekore.prtree.MBR; +import org.khelekore.prtree.SimpleMBR; public class Location implements Cloneable, Comparable { @@ -221,6 +223,10 @@ public class Location implements Cloneable, Comparable { return this; } + public MBR toMBR() { + return new SimpleMBR(this.getX(), this.getX(), this.getY(), this.getY(), this.getZ(), this.getZ()); + } + @Override public boolean equals(Object o) { if (o == null) { return false; diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java index 9f245a5ba..40707a8e5 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/ScatteredPlotWorld.java @@ -25,18 +25,18 @@ */ package com.plotsquared.core.plot.world; -import com.github.davidmoten.rtree.Entry; -import com.github.davidmoten.rtree.RTree; -import com.github.davidmoten.rtree.geometry.Geometries; -import com.github.davidmoten.rtree.geometry.Geometry; import com.plotsquared.core.location.Location; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotWorld; +import com.plotsquared.core.util.PlotAreaConverter; import com.plotsquared.core.util.RegionUtil; +import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import rx.Observable; +import org.khelekore.prtree.MBR; +import org.khelekore.prtree.PRTree; +import org.khelekore.prtree.SimpleMBR; import java.util.Collection; import java.util.Collections; @@ -48,9 +48,12 @@ import java.util.List; */ public class ScatteredPlotWorld extends PlotWorld { + private static final PlotAreaConverter MBR_CONVERTER = new PlotAreaConverter(); + private static final int BRANCH_FACTOR = 30; + private final List areas = new LinkedList<>(); private final Object treeLock = new Object(); - private RTree areaTree; + private PRTree areaTree; /** * Create a new plot world with a given world name @@ -66,13 +69,13 @@ public class ScatteredPlotWorld extends PlotWorld { return null; } synchronized (this.treeLock) { - final Observable> area = - areaTree.search(Geometries.point(location.getX(), location.getZ())); - if (area.isEmpty().toBlocking().first()) { - return null; + for (final PlotArea area : this.areaTree.find(location.toMBR())) { + if (area.contains(location)) { + return area; + } } - return area.toBlocking().first().value(); } + return null; } @Override @NotNull public Collection getAreas() { @@ -95,7 +98,17 @@ public class ScatteredPlotWorld extends PlotWorld { } synchronized (this.treeLock) { final List areas = new LinkedList<>(); - this.areaTree.search(RegionUtil.toRectangle(region)).toBlocking().forEach(entry -> areas.add(entry.value())); + + final BlockVector3 min = region.getMinimumPoint(); + final BlockVector3 max = region.getMaximumPoint(); + final MBR mbr = new SimpleMBR(min.getX(), max.getX(), min.getY(), max.getY(), min.getZ(), max.getZ()); + + for (final PlotArea area : this.areaTree.find(mbr)) { + if (RegionUtil.intersects(area.getRegion(), region)) { + areas.add(area); + } + } + return areas; } } @@ -105,11 +118,8 @@ public class ScatteredPlotWorld extends PlotWorld { */ private void buildTree() { synchronized (this.treeLock) { - this.areaTree = RTree.create(); - for (final PlotArea area : areas) { - this.areaTree = this.areaTree.add(area, - RegionUtil.toRectangle(area.getRegion())); - } + this.areaTree = new PRTree<>(MBR_CONVERTER, BRANCH_FACTOR); + this.areaTree.load(this.areas); } } diff --git a/Core/src/main/java/com/plotsquared/core/util/PlotAreaConverter.java b/Core/src/main/java/com/plotsquared/core/util/PlotAreaConverter.java new file mode 100644 index 000000000..b80195c02 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/PlotAreaConverter.java @@ -0,0 +1,68 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util; + +import com.plotsquared.core.plot.PlotArea; +import com.sk89q.worldedit.regions.CuboidRegion; +import org.khelekore.prtree.MBRConverter; + +public class PlotAreaConverter implements MBRConverter { + + public static final int AXIS_X = 0; + public static final int AXIS_Y = 1; + public static final int AXIS_Z = 2; + + @Override public int getDimensions() { + return 3; + } + + @Override public double getMin(final int axis, final PlotArea area) { + final CuboidRegion region = area.getRegion(); + if (axis == AXIS_X) { + return region.getMinimumPoint().getX(); + } else if (axis == AXIS_Y) { + return region.getMinimumPoint().getY(); + } else if (axis == AXIS_Z) { + return region.getMinimumPoint().getZ(); + } else { + throw new IllegalArgumentException("Unknown axis: " + axis); + } + } + + @Override public double getMax(final int axis, final PlotArea area) { + final CuboidRegion region = area.getRegion(); + if (axis == AXIS_X) { + return region.getMaximumPoint().getX(); + } else if (axis == AXIS_Y) { + return region.getMaximumPoint().getY(); + } else if (axis == AXIS_Z) { + return region.getMaximumPoint().getZ(); + } else { + throw new IllegalArgumentException("Unknown axis: " + axis); + } + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java b/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java index 59b14651a..6c16c4a9e 100644 --- a/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/RegionUtil.java @@ -25,14 +25,14 @@ */ package com.plotsquared.core.util; -import com.github.davidmoten.rtree.geometry.Geometries; -import com.github.davidmoten.rtree.geometry.Rectangle; import com.plotsquared.core.plot.Plot; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; +import java.awt.geom.Rectangle2D; + public class RegionUtil { public static CuboidRegion createRegion(int pos1x, int pos2x, int pos1z, int pos2z) { return createRegion(pos1x, pos2x, 0, Plot.MAX_HEIGHT - 1, pos1z, pos2z); @@ -58,10 +58,10 @@ public class RegionUtil { .getY() && y <= max.getY(); } - @NotNull public static Rectangle toRectangle(@NotNull final CuboidRegion region) { + @NotNull public static Rectangle2D toRectangle(@NotNull final CuboidRegion region) { final BlockVector2 min = region.getMinimumPoint().toBlockVector2(); final BlockVector2 max = region.getMaximumPoint().toBlockVector2(); - return Geometries.rectangle(min.getX(), min.getZ(), max.getX(), max.getZ()); + return new Rectangle2D.Double(min.getX(), min.getZ(), max.getX(), max.getZ()); } // Because WE (not fawe) lack this for CuboidRegion diff --git a/build.gradle b/build.gradle index 2b26caee7..4d875660b 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ ext { git = Grgit.open(dir: new File(rootDir.toString() + "/.git")) } -def ver = "5.11.2" +def ver = "5.12.0" def versuffix = "" ext { if (project.hasProperty("versionsuffix")) { From 71e22f41b120fd4868394f45b41c58959b3e9360 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 25 May 2020 09:12:46 +0000 Subject: [PATCH 073/121] Bump json from 20190722 to 20200518 Bumps [json](https://github.com/douglascrockford/JSON-java) from 20190722 to 20200518. - [Release notes](https://github.com/douglascrockford/JSON-java/releases) - [Commits](https://github.com/douglascrockford/JSON-java/commits) Signed-off-by: dependabot-preview[bot] --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4d875660b..0943488d1 100644 --- a/build.gradle +++ b/build.gradle @@ -77,7 +77,7 @@ subprojects { } dependencies { - compile group: 'org.json', name: 'json', version: '20190722' + compile group: 'org.json', name: 'json', version: '20200518' implementation("com.sk89q.worldedit:worldedit-core:7.0.0") { exclude(module: "bukkit-classloader-check") From edbacb8e4743cdc8ec251ae0c17a8e8370825cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Mon, 25 May 2020 20:11:57 +0200 Subject: [PATCH 074/121] Bump dependency version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0943488d1..0422b75a0 100644 --- a/build.gradle +++ b/build.gradle @@ -118,7 +118,7 @@ subprojects { shadowJar { dependencies { - include(dependency("org.json:json:20190722")) + include(dependency("org.json:json:20200518")) include(dependency("net.kyori:text-api:3.0.2")) } relocate("io.papermc.lib", "com.plotsquared.bukkit.paperlib") From 6442922d864647ac2b86fd56116bdc8401f7acec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 27 May 2020 14:08:48 +0200 Subject: [PATCH 075/121] Implement some more generic types to make the player objects easier to work with and also create wrapper objects for fake players (NPCs). Potentially fixes PS-27 --- .../com/plotsquared/bukkit/BukkitMain.java | 9 ++- .../bukkit/listener/PlayerEvents.java | 60 +++++++++---------- .../bukkit/player/BukkitPlayer.java | 18 ++++-- .../bukkit/player/BukkitPlayerManager.java | 10 +++- .../plotsquared/bukkit/util/BukkitUtil.java | 21 ++++--- .../java/com/plotsquared/core/IPlotMain.java | 9 ++- .../com/plotsquared/core/PlotSquared.java | 4 +- .../com/plotsquared/core/command/Add.java | 2 +- .../com/plotsquared/core/command/Alias.java | 2 +- .../com/plotsquared/core/command/Area.java | 2 +- .../com/plotsquared/core/command/Auto.java | 2 +- .../com/plotsquared/core/command/Backup.java | 2 +- .../com/plotsquared/core/command/Buy.java | 2 +- .../com/plotsquared/core/command/Caps.java | 2 +- .../com/plotsquared/core/command/Chat.java | 2 +- .../com/plotsquared/core/command/Claim.java | 2 +- .../com/plotsquared/core/command/Clear.java | 2 +- .../com/plotsquared/core/command/Cluster.java | 2 +- .../plotsquared/core/command/CmdConfirm.java | 6 +- .../com/plotsquared/core/command/Command.java | 4 +- .../com/plotsquared/core/command/Comment.java | 2 +- .../plotsquared/core/command/Condense.java | 2 +- .../com/plotsquared/core/command/Confirm.java | 2 +- .../plotsquared/core/command/Continue.java | 2 +- .../com/plotsquared/core/command/Copy.java | 2 +- .../core/command/CreateRoadSchematic.java | 2 +- .../core/command/DatabaseCommand.java | 2 +- .../com/plotsquared/core/command/Debug.java | 2 +- .../core/command/DebugAllowUnsafe.java | 2 +- .../plotsquared/core/command/DebugExec.java | 4 +- .../core/command/DebugImportWorlds.java | 2 +- .../core/command/DebugLoadTest.java | 2 +- .../plotsquared/core/command/DebugPaste.java | 2 +- .../core/command/DebugRoadRegen.java | 2 +- .../core/command/DebugSaveTest.java | 2 +- .../com/plotsquared/core/command/Delete.java | 2 +- .../com/plotsquared/core/command/Deny.java | 2 +- .../com/plotsquared/core/command/Dislike.java | 2 +- .../com/plotsquared/core/command/Done.java | 2 +- .../plotsquared/core/command/Download.java | 2 +- .../plotsquared/core/command/FlagCommand.java | 2 +- .../com/plotsquared/core/command/Grant.java | 2 +- .../com/plotsquared/core/command/Help.java | 2 +- .../com/plotsquared/core/command/Inbox.java | 2 +- .../com/plotsquared/core/command/Info.java | 2 +- .../com/plotsquared/core/command/Kick.java | 2 +- .../com/plotsquared/core/command/Leave.java | 2 +- .../com/plotsquared/core/command/Like.java | 2 +- .../com/plotsquared/core/command/ListCmd.java | 2 +- .../com/plotsquared/core/command/Load.java | 4 +- .../plotsquared/core/command/MainCommand.java | 2 +- .../com/plotsquared/core/command/Merge.java | 2 +- .../com/plotsquared/core/command/Middle.java | 2 +- .../com/plotsquared/core/command/Move.java | 4 +- .../com/plotsquared/core/command/Music.java | 2 +- .../com/plotsquared/core/command/Near.java | 2 +- .../plotsquared/core/command/PluginCmd.java | 2 +- .../com/plotsquared/core/command/Purge.java | 2 +- .../com/plotsquared/core/command/Rate.java | 2 +- .../core/command/RegenAllRoads.java | 2 +- .../com/plotsquared/core/command/Relight.java | 2 +- .../com/plotsquared/core/command/Reload.java | 2 +- .../com/plotsquared/core/command/Remove.java | 2 +- .../com/plotsquared/core/command/Save.java | 2 +- .../core/command/SchematicCmd.java | 2 +- .../com/plotsquared/core/command/Set.java | 2 +- .../plotsquared/core/command/SetCommand.java | 2 +- .../com/plotsquared/core/command/Setup.java | 2 +- .../plotsquared/core/command/SubCommand.java | 4 +- .../com/plotsquared/core/command/Swap.java | 4 +- .../com/plotsquared/core/command/Target.java | 2 +- .../plotsquared/core/command/Template.java | 2 +- .../com/plotsquared/core/command/Trim.java | 2 +- .../com/plotsquared/core/command/Trust.java | 2 +- .../com/plotsquared/core/command/Unlink.java | 2 +- .../com/plotsquared/core/command/Visit.java | 2 +- .../plotsquared/core/command/WE_Anywhere.java | 2 +- .../core/components/ComponentCommand.java | 2 +- .../core/listener/PlotListener.java | 4 +- .../core/player/ConsolePlayer.java | 6 +- .../plotsquared/core/player/PlotPlayer.java | 6 +- .../java/com/plotsquared/core/plot/Plot.java | 10 ++-- .../plotsquared/core/plot/PlotInventory.java | 14 ++--- .../core/plot/comment/CommentManager.java | 2 +- .../core/plot/expiration/ExpireManager.java | 2 +- .../plotsquared/core/util/Permissions.java | 2 +- .../plotsquared/core/util/PlayerManager.java | 21 ++++++- .../com/plotsquared/core/util/WEManager.java | 2 +- 88 files changed, 203 insertions(+), 155 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 02cf4db04..a9ec5b374 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -156,7 +156,7 @@ import static com.plotsquared.core.util.PremiumVerification.getResourceID; import static com.plotsquared.core.util.PremiumVerification.getUserID; import static com.plotsquared.core.util.ReflectionUtils.getRefClass; -public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain { +public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain { private static final int BSTATS_ID = 1404; @Getter private static WorldEdit worldEdit; @@ -175,8 +175,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain private boolean methodUnloadSetup = false; private boolean metricsStarted; @Getter private BackupManager backupManager; - @Getter private PlatformWorldManager worldManager; - @Getter private final PlayerManager playerManager = new BukkitPlayerManager(); + @Getter private PlatformWorldManager worldManager; + private final BukkitPlayerManager playerManager = new BukkitPlayerManager(); @Override public int[] getServerVersion() { if (this.version == null) { @@ -1079,4 +1079,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain return wePlugin.wrapCommandSender(console); } + @Override @NotNull public PlayerManager, ? extends Player> getPlayerManager() { + return this.playerManager; + } } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 70d3c6d6b..073b7939d 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -695,7 +695,7 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onTeleport(PlayerTeleportEvent event) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); Plot lastPlot = pp.getMeta(PlotPlayer.META_LAST_PLOT); org.bukkit.Location to = event.getTo(); //noinspection ConstantConditions @@ -805,7 +805,7 @@ public class PlayerEvents extends PlotListener implements Listener { int x2; if (MathMan.roundInt(from.getX()) != (x2 = MathMan.roundInt(to.getX()))) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); // Cancel teleport TaskManager.TELEPORT_QUEUE.remove(pp.getName()); // Set last location @@ -865,7 +865,7 @@ public class PlayerEvents extends PlotListener implements Listener { int z2; if (MathMan.roundInt(from.getZ()) != (z2 = MathMan.roundInt(to.getZ()))) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); // Cancel teleport TaskManager.TELEPORT_QUEUE.remove(pp.getName()); // Set last location @@ -929,7 +929,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } - PlotPlayer plotPlayer = BukkitUtil.getPlayer(event.getPlayer()); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(event.getPlayer()); Location location = plotPlayer.getLocation(); PlotArea area = location.getPlotArea(); if (area == null) { @@ -997,7 +997,7 @@ public class PlayerEvents extends PlotListener implements Listener { } Plot plot = area.getPlot(location); if (plot != null) { - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); if (event.getBlock().getY() == 0) { if (!Permissions .hasPermission(plotPlayer, Captions.PERMISSION_ADMIN_DESTROY_GROUNDLEVEL)) { @@ -1046,7 +1046,7 @@ public class PlayerEvents extends PlotListener implements Listener { } return; } - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); if (Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_DESTROY_ROAD)) { return; } @@ -1114,7 +1114,7 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onWorldChanged(PlayerChangedWorldEvent event) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); // Delete last location Plot plot = (Plot) pp.deleteMeta(PlotPlayer.META_LAST_PLOT); pp.deleteMeta(PlotPlayer.META_LOCATION); @@ -1177,14 +1177,14 @@ public class PlayerEvents extends PlotListener implements Listener { if (entity instanceof Player) { Player player = (Player) entity; if (!plot.hasOwner()) { - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); if (plot.getFlag(IceFormFlag.class)) { return; } event.setCancelled(true); return; } - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); if (!plot.isAdded(plotPlayer.getUUID())) { if (plot.getFlag(IceFormFlag.class)) { return; @@ -1297,7 +1297,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } if (!plot.hasOwner()) { - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); if (Permissions .hasPermission(plotPlayer, Captions.PERMISSION_ADMIN_DESTROY_UNOWNED)) { return; @@ -1305,7 +1305,7 @@ public class PlayerEvents extends PlotListener implements Listener { event.setCancelled(true); return; } - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); if (!plot.isAdded(plotPlayer.getUUID())) { List destroy = plot.getFlag(BreakFlag.class); Block block = event.getBlock(); @@ -1320,7 +1320,7 @@ public class PlayerEvents extends PlotListener implements Listener { } return; } - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); if (Permissions.hasPermission(plotPlayer, Captions.PERMISSION_ADMIN_DESTROY_ROAD)) { return; } @@ -1671,7 +1671,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } Player player = (Player) clicker; - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); final PlotInventory inventory = PlotInventory.getOpenPlotInventory(pp); if (inventory != null && event.getRawSlot() == event.getSlot()) { if (!inventory.onClick(event.getSlot())) { @@ -1812,7 +1812,7 @@ public class PlayerEvents extends PlotListener implements Listener { } EntitySpawnListener.testNether(entity); Plot plot = location.getPlotAbs(); - PlotPlayer pp = BukkitUtil.getPlayer(e.getPlayer()); + BukkitPlayer pp = BukkitUtil.getPlayer(e.getPlayer()); if (plot == null) { if (!Permissions.hasPermission(pp, "plots.admin.interact.road")) { MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, "plots.admin.interact.road"); @@ -1881,7 +1881,7 @@ public class PlayerEvents extends PlotListener implements Listener { public void onCancelledInteract(PlayerInteractEvent event) { if (event.isCancelled() && event.getAction() == Action.RIGHT_CLICK_AIR) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); PlotArea area = pp.getPlotAreaAbs(); if (area == null) { return; @@ -1918,7 +1918,7 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler(priority = EventPriority.LOW, ignoreCancelled = true) public void onInteract(PlayerInteractEvent event) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); PlotArea area = pp.getPlotAreaAbs(); if (area == null) { return; @@ -2195,7 +2195,7 @@ public class PlayerEvents extends PlotListener implements Listener { Plot plot = area.getOwnedPlot(location1); if (player != null) { - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); if (plot == null) { if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_BUILD_ROAD)) { MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, @@ -2271,7 +2271,7 @@ public class PlayerEvents extends PlotListener implements Listener { if (area == null) { return; } - PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); + BukkitPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); Plot plot = area.getPlot(location); if (plot == null) { if (Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_BUILD_ROAD)) { @@ -2322,7 +2322,7 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler(priority = EventPriority.MONITOR) public void onLeave(PlayerQuitEvent event) { TaskManager.TELEPORT_QUEUE.remove(event.getPlayer().getName()); - PlotPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); + BukkitPlayer pp = BukkitUtil.getPlayer(event.getPlayer()); pp.unregister(); PlotListener.logout(pp.getUUID()); } @@ -2336,7 +2336,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } Player player = event.getPlayer(); - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); Plot plot = area.getPlot(location); if (plot == null) { if (Permissions.hasPermission(plotPlayer, Captions.PERMISSION_ADMIN_BUILD_ROAD)) { @@ -2409,7 +2409,7 @@ public class PlayerEvents extends PlotListener implements Listener { event.setCancelled(true); return; } - PlotPlayer pp = BukkitUtil.getPlayer(p); + BukkitPlayer pp = BukkitUtil.getPlayer(p); Plot plot = area.getPlot(location); if (plot == null) { if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_BUILD_ROAD)) { @@ -2453,7 +2453,7 @@ public class PlayerEvents extends PlotListener implements Listener { if (area == null) { return; } - PlotPlayer pp = BukkitUtil.getPlayer(p); + BukkitPlayer pp = BukkitUtil.getPlayer(p); Plot plot = area.getPlot(location); if (plot == null) { if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_DESTROY_ROAD)) { @@ -2486,7 +2486,7 @@ public class PlayerEvents extends PlotListener implements Listener { if (area == null) { return; } - PlotPlayer player = BukkitUtil.getPlayer(shooter); + BukkitPlayer player = BukkitUtil.getPlayer(shooter); Plot plot = area.getPlot(BukkitUtil.getLocation(event.getEntity())); if (plot != null) { if (!plot.hasOwner()) { @@ -2521,7 +2521,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } Player p = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(p); + BukkitPlayer pp = BukkitUtil.getPlayer(p); Plot plot = area.getPlot(location); if (plot == null) { if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_INTERACT_ROAD)) { @@ -2595,7 +2595,7 @@ public class PlayerEvents extends PlotListener implements Listener { Entity attacker = event.getAttacker(); if (attacker instanceof Player) { Player p = (Player) attacker; - PlotPlayer pp = BukkitUtil.getPlayer(p); + BukkitPlayer pp = BukkitUtil.getPlayer(p); Plot plot = area.getPlot(location); if (plot == null) { if (!Permissions.hasPermission(pp, "plots.admin.vehicle.break.road")) { @@ -2778,7 +2778,7 @@ public class PlayerEvents extends PlotListener implements Listener { player = null; } if (player != null) { - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); final com.sk89q.worldedit.world.entity.EntityType entityType; @@ -2901,7 +2901,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } Player player = event.getPlayer(); - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); Plot plot = area.getPlot(location); if (plot == null) { if (!Permissions.hasPermission(plotPlayer, "plots.admin.projectile.road")) { @@ -2932,7 +2932,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); Plot plot = area.getPlot(location); if (plot != null) { if ((location.getY() > area.getMaxBuildHeight() || location.getY() < area @@ -3000,7 +3000,7 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler public void onItemDrop(PlayerDropItemEvent event) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); Plot plot = BukkitUtil.getLocation(player).getOwnedPlot(); if (plot == null) { return; @@ -3017,7 +3017,7 @@ public class PlayerEvents extends PlotListener implements Listener { LivingEntity ent = event.getEntity(); if (ent instanceof Player) { Player player = (Player) ent; - PlotPlayer pp = BukkitUtil.getPlayer(player); + BukkitPlayer pp = BukkitUtil.getPlayer(player); Plot plot = BukkitUtil.getLocation(player).getOwnedPlot(); if (plot == null) { return; diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java index 23d856860..acbc31984 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java @@ -63,12 +63,11 @@ import static com.sk89q.worldedit.world.gamemode.GameModes.CREATIVE; import static com.sk89q.worldedit.world.gamemode.GameModes.SPECTATOR; import static com.sk89q.worldedit.world.gamemode.GameModes.SURVIVAL; -public class BukkitPlayer extends PlotPlayer { +public class BukkitPlayer extends PlotPlayer { private static boolean CHECK_EFFECTIVE = true; public final Player player; private boolean offline; - private UUID uuid; private String name; /** @@ -78,20 +77,29 @@ public class BukkitPlayer extends PlotPlayer { * @param player Bukkit player instance */ public BukkitPlayer(@NotNull final Player player) { - this.player = player; - super.populatePersistentMetaMap(); + this(player, false); } public BukkitPlayer(@NotNull final Player player, final boolean offline) { + this(player, offline, true); + } + + public BukkitPlayer(@NotNull final Player player, final boolean offline, final boolean realPlayer) { this.player = player; this.offline = offline; - super.populatePersistentMetaMap(); + if (realPlayer) { + super.populatePersistentMetaMap(); + } } @Override public Actor toActor() { return BukkitAdapter.adapt(player); } + @Override public Player getPlatformPlayer() { + return this.player; + } + @NotNull @Override public Location getLocation() { final Location location = super.getLocation(); return location == null ? BukkitUtil.getLocation(this.player) : location; diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java index cdb770e2f..a15718a5f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayerManager.java @@ -36,7 +36,15 @@ import java.util.UUID; /** * Player manager providing {@link BukkitPlayer Bukkit players} */ -public class BukkitPlayerManager extends PlayerManager { +public class BukkitPlayerManager extends PlayerManager { + + @NotNull @Override public BukkitPlayer getPlayer(@NotNull final Player object) { + try { + return getPlayer(object.getUniqueId()); + } catch (final NoSuchPlayerException exception) { + return new BukkitPlayer(object, object.isOnline(), false); + } + } @Override @NotNull public BukkitPlayer createPlayer(@NotNull final UUID uuid) { final Player player = Bukkit.getPlayer(uuid); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index 8ba3caa9b..b21301251 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -27,6 +27,7 @@ package com.plotsquared.bukkit.util; import com.plotsquared.bukkit.BukkitMain; import com.plotsquared.bukkit.player.BukkitPlayer; +import com.plotsquared.bukkit.player.BukkitPlayerManager; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.location.Location; @@ -35,6 +36,7 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.BlockUtil; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; +import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.StringComparison; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; @@ -112,14 +114,14 @@ public class BukkitUtil extends WorldUtil { private static World lastWorld = null; private static Player lastPlayer = null; - private static PlotPlayer lastPlotPlayer = null; + private static BukkitPlayer lastPlotPlayer = null; public static void removePlayer(String player) { lastPlayer = null; lastPlotPlayer = null; } - public static PlotPlayer getPlayer(@NonNull final OfflinePlayer op) { + public static PlotPlayer getPlayer(@NonNull final OfflinePlayer op) { if (op.isOnline()) { return getPlayer(op.getPlayer()); } @@ -164,7 +166,7 @@ public class BukkitUtil extends WorldUtil { * @return a {@code PlotPlayer} * @see PlotPlayer#wrap(Object) */ - public static PlotPlayer wrapPlayer(OfflinePlayer player) { + public static PlotPlayer wrapPlayer(OfflinePlayer player) { return PlotPlayer.wrap(player); } @@ -176,7 +178,7 @@ public class BukkitUtil extends WorldUtil { * @return a {@code PlotPlayer} * @see PlotPlayer#wrap(Object) */ - public static PlotPlayer wrapPlayer(Player player) { + public static PlotPlayer wrapPlayer(Player player) { return PlotPlayer.wrap(player); } @@ -188,7 +190,7 @@ public class BukkitUtil extends WorldUtil { * @return a {@code PlotPlayer} * @see PlotPlayer#wrap(Object) */ - @Override public PlotPlayer wrapPlayer(UUID uuid) { + @Override public PlotPlayer wrapPlayer(UUID uuid) { return PlotPlayer.wrap(Bukkit.getOfflinePlayer(uuid)); } @@ -199,7 +201,7 @@ public class BukkitUtil extends WorldUtil { * @return the number of allowed plots */ public static int getAllowedPlots(Player player) { - PlotPlayer plotPlayer = PlotPlayer.wrap(player); + PlotPlayer plotPlayer = PlotPlayer.wrap(player); return plotPlayer.getAllowedPlots(); } @@ -225,7 +227,7 @@ public class BukkitUtil extends WorldUtil { if (world == null) { return new HashSet<>(); } - return PlotPlayer.wrap(player).getPlots(world); + return BukkitPlayer.wrap(player).getPlots(world); } /** @@ -263,11 +265,12 @@ public class BukkitUtil extends WorldUtil { MainUtil.sendMessage(BukkitUtil.getPlayer(player), caption); } - public static PlotPlayer getPlayer(@NonNull final Player player) { + public static BukkitPlayer getPlayer(@NonNull final Player player) { if (player == lastPlayer) { return lastPlotPlayer; } - return PlotSquared.imp().getPlayerManager().getPlayer(player.getUniqueId()); + final PlayerManager playerManager = PlotSquared.imp().getPlayerManager(); + return ((BukkitPlayerManager) player).getPlayer(player); } public static Location getLocation(@NonNull final org.bukkit.Location location) { diff --git a/Core/src/main/java/com/plotsquared/core/IPlotMain.java b/Core/src/main/java/com/plotsquared/core/IPlotMain.java index 9e04d85ec..57625ee3f 100644 --- a/Core/src/main/java/com/plotsquared/core/IPlotMain.java +++ b/Core/src/main/java/com/plotsquared/core/IPlotMain.java @@ -50,7 +50,12 @@ import java.io.File; import java.util.List; import java.util.Map; -public interface IPlotMain extends ILogger { +/** + * PlotSquared main utility class + * + * @param

Player type + */ +public interface IPlotMain

extends ILogger { /** * Logs a message to console. @@ -286,6 +291,6 @@ public interface IPlotMain extends ILogger { * * @return Player manager */ - @NotNull PlayerManager getPlayerManager(); + @NotNull PlayerManager, ? extends P> getPlayerManager(); } diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index a33fd502e..3f7f35229 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -141,7 +141,7 @@ public class PlotSquared { private static final Set EMPTY_SET = Collections.unmodifiableSet(Collections.emptySet()); private static PlotSquared instance; // Implementation - public final IPlotMain IMP; + public final IPlotMain IMP; // Current thread private final Thread thread; // UUID pipelines @@ -386,7 +386,7 @@ public class PlotSquared { return PlotSquared.instance; } - @NotNull public static IPlotMain imp() { + @NotNull public static IPlotMain imp() { if (instance != null && instance.IMP != null) { return instance.IMP; } diff --git a/Core/src/main/java/com/plotsquared/core/command/Add.java b/Core/src/main/java/com/plotsquared/core/command/Add.java index 3a3aa7ab7..6d86f7532 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Add.java +++ b/Core/src/main/java/com/plotsquared/core/command/Add.java @@ -56,7 +56,7 @@ public class Add extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, + public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { final Plot plot = check(player.getCurrentPlot(), Captions.NOT_IN_PLOT); diff --git a/Core/src/main/java/com/plotsquared/core/command/Alias.java b/Core/src/main/java/com/plotsquared/core/command/Alias.java index 3f1273014..a10bf8a6e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Alias.java +++ b/Core/src/main/java/com/plotsquared/core/command/Alias.java @@ -45,7 +45,7 @@ import java.util.concurrent.TimeoutException; requiredType = RequiredType.PLAYER) public class Alias extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { if (args.length == 0) { Captions.COMMAND_SYNTAX.send(player, getUsage()); diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index 932bbf0ab..7cdca5c6f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -83,7 +83,7 @@ import java.util.Set; confirmation = true) public class Area extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { if (args.length == 0) { Captions.COMMAND_SYNTAX.send(player, getUsage()); return false; diff --git a/Core/src/main/java/com/plotsquared/core/command/Auto.java b/Core/src/main/java/com/plotsquared/core/command/Auto.java index 518a017d6..9658556d9 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Auto.java +++ b/Core/src/main/java/com/plotsquared/core/command/Auto.java @@ -154,7 +154,7 @@ public class Auto extends SubCommand { () -> autoClaimFromDatabase(player, area, plot.getId(), whenDone)); } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { PlotArea plotarea = player.getApplicablePlotArea(); if (plotarea == null) { if (EconHandler.manager != null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Backup.java b/Core/src/main/java/com/plotsquared/core/command/Backup.java index e06d8208a..944eaaf6b 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Backup.java +++ b/Core/src/main/java/com/plotsquared/core/command/Backup.java @@ -70,7 +70,7 @@ public final class Backup extends Command { } @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { if (args.length == 0 || !Arrays.asList("save", "list", "load") diff --git a/Core/src/main/java/com/plotsquared/core/command/Buy.java b/Core/src/main/java/com/plotsquared/core/command/Buy.java index b986a7983..036e2412f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Buy.java +++ b/Core/src/main/java/com/plotsquared/core/command/Buy.java @@ -54,7 +54,7 @@ public class Buy extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, + public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, final RunnableVal2 whenDone) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Caps.java b/Core/src/main/java/com/plotsquared/core/command/Caps.java index 372e415b8..b56d33dc0 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Caps.java +++ b/Core/src/main/java/com/plotsquared/core/command/Caps.java @@ -50,7 +50,7 @@ import static com.plotsquared.core.util.entity.EntityCategories.CAP_VEHICLE; usage = "/plot caps") public class Caps extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, final String[] args) { + @Override public boolean onCommand(final PlotPlayer player, final String[] args) { final Plot plot = player.getCurrentPlot(); if (plot == null) { return Captions.NOT_IN_PLOT.send(player); diff --git a/Core/src/main/java/com/plotsquared/core/command/Chat.java b/Core/src/main/java/com/plotsquared/core/command/Chat.java index e8c9e395c..3bf04f223 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Chat.java +++ b/Core/src/main/java/com/plotsquared/core/command/Chat.java @@ -37,7 +37,7 @@ import com.plotsquared.core.util.MainUtil; requiredType = RequiredType.PLAYER) public class Chat extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { if (player.getPlotAreaAbs().isForcingPlotChat()) { MainUtil.sendMessage(player, Captions.PLOT_CHAT_FORCED); return true; diff --git a/Core/src/main/java/com/plotsquared/core/command/Claim.java b/Core/src/main/java/com/plotsquared/core/command/Claim.java index 2f4ee7781..488b2dc84 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Claim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Claim.java @@ -54,7 +54,7 @@ import com.plotsquared.core.util.task.TaskManager; usage = "/plot claim") public class Claim extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { String schematic = null; if (args.length >= 1) { schematic = args[0]; diff --git a/Core/src/main/java/com/plotsquared/core/command/Clear.java b/Core/src/main/java/com/plotsquared/core/command/Clear.java index 5e8c2757a..9d8279eda 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Clear.java +++ b/Core/src/main/java/com/plotsquared/core/command/Clear.java @@ -64,7 +64,7 @@ public class Clear extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, + public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { checkTrue(args.length == 0, Captions.COMMAND_SYNTAX, getUsage()); diff --git a/Core/src/main/java/com/plotsquared/core/command/Cluster.java b/Core/src/main/java/com/plotsquared/core/command/Cluster.java index c9ce3d5ef..557ba084b 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Cluster.java +++ b/Core/src/main/java/com/plotsquared/core/command/Cluster.java @@ -54,7 +54,7 @@ import java.util.concurrent.TimeoutException; description = "Manage a plot cluster") public class Cluster extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { // list, create, delete, resize, invite, kick, leave, helpers, tp, sethome if (args.length == 0) { diff --git a/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java b/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java index 8b657992d..f7096834b 100644 --- a/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java +++ b/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java @@ -32,15 +32,15 @@ import com.plotsquared.core.util.task.TaskManager; public class CmdConfirm { - public static CmdInstance getPending(PlotPlayer player) { + public static CmdInstance getPending(PlotPlayer player) { return player.getMeta("cmdConfirm"); } - public static void removePending(PlotPlayer player) { + public static void removePending(PlotPlayer player) { player.deleteMeta("cmdConfirm"); } - public static void addPending(final PlotPlayer player, String commandStr, + public static void addPending(final PlotPlayer player, String commandStr, final Runnable runnable) { removePending(player); if (commandStr != null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Command.java b/Core/src/main/java/com/plotsquared/core/command/Command.java index 6e97eb30a..7238d4566 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Command.java +++ b/Core/src/main/java/com/plotsquared/core/command/Command.java @@ -106,7 +106,7 @@ public abstract class Command { && types[4] == RunnableVal2.class) { Command tmp = new Command(this, true) { @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { try { @@ -300,7 +300,7 @@ public abstract class Command { * @return CompletableFuture true if the command executed fully, false in * any other case */ - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { if (args.length == 0 || args[0] == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Comment.java b/Core/src/main/java/com/plotsquared/core/command/Comment.java index 501ba4247..a5615533f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Comment.java +++ b/Core/src/main/java/com/plotsquared/core/command/Comment.java @@ -46,7 +46,7 @@ import java.util.Locale; permission = "plots.comment") public class Comment extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { if (args.length < 2) { sendMessage(player, Captions.COMMENT_SYNTAX, StringMan.join(CommentManager.inboxes.keySet(), "|")); diff --git a/Core/src/main/java/com/plotsquared/core/command/Condense.java b/Core/src/main/java/com/plotsquared/core/command/Condense.java index f8a65407d..8f792ee7e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Condense.java +++ b/Core/src/main/java/com/plotsquared/core/command/Condense.java @@ -54,7 +54,7 @@ public class Condense extends SubCommand { public static boolean TASK = false; - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { if (args.length != 2 && args.length != 3) { MainUtil.sendMessage(player, getUsage()); return false; diff --git a/Core/src/main/java/com/plotsquared/core/command/Confirm.java b/Core/src/main/java/com/plotsquared/core/command/Confirm.java index 04723ac48..311c1c437 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Confirm.java +++ b/Core/src/main/java/com/plotsquared/core/command/Confirm.java @@ -37,7 +37,7 @@ import com.plotsquared.core.util.task.TaskManager; category = CommandCategory.INFO) public class Confirm extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { CmdInstance command = CmdConfirm.getPending(player); if (command == null) { MainUtil.sendMessage(player, Captions.FAILED_CONFIRM); diff --git a/Core/src/main/java/com/plotsquared/core/command/Continue.java b/Core/src/main/java/com/plotsquared/core/command/Continue.java index d366b2ff6..23f5e93a0 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Continue.java +++ b/Core/src/main/java/com/plotsquared/core/command/Continue.java @@ -44,7 +44,7 @@ import com.plotsquared.core.util.Permissions; requiredType = RequiredType.PLAYER) public class Continue extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { Plot plot = player.getCurrentPlot(); if ((plot == null) || !plot.hasOwner()) { return !sendMessage(player, Captions.NOT_IN_PLOT); diff --git a/Core/src/main/java/com/plotsquared/core/command/Copy.java b/Core/src/main/java/com/plotsquared/core/command/Copy.java index 702255064..6743074ff 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Copy.java +++ b/Core/src/main/java/com/plotsquared/core/command/Copy.java @@ -41,7 +41,7 @@ import com.plotsquared.core.util.Permissions; requiredType = RequiredType.NONE) public class Copy extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { Location location = player.getLocation(); Plot plot1 = location.getPlotAbs(); if (plot1 == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/CreateRoadSchematic.java b/Core/src/main/java/com/plotsquared/core/command/CreateRoadSchematic.java index 258467500..d5800896a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/CreateRoadSchematic.java +++ b/Core/src/main/java/com/plotsquared/core/command/CreateRoadSchematic.java @@ -42,7 +42,7 @@ import com.plotsquared.core.util.MainUtil; usage = "/plot createroadschematic") public class CreateRoadSchematic extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { Location location = player.getLocation(); Plot plot = location.getPlotAbs(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/DatabaseCommand.java b/Core/src/main/java/com/plotsquared/core/command/DatabaseCommand.java index c652957e4..41690b5af 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DatabaseCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/DatabaseCommand.java @@ -74,7 +74,7 @@ public class DatabaseCommand extends SubCommand { }); } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { if (args.length < 1) { MainUtil.sendMessage(player, getUsage()); return false; diff --git a/Core/src/main/java/com/plotsquared/core/command/Debug.java b/Core/src/main/java/com/plotsquared/core/command/Debug.java index e104da337..8a4ef1737 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Debug.java +++ b/Core/src/main/java/com/plotsquared/core/command/Debug.java @@ -48,7 +48,7 @@ import java.util.Map; permission = "plots.admin") public class Debug extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { if (args.length > 0) { if ("player".equalsIgnoreCase(args[0])) { for (Map.Entry meta : player.getMeta().entrySet()) { diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugAllowUnsafe.java b/Core/src/main/java/com/plotsquared/core/command/DebugAllowUnsafe.java index e4de7e351..d424b809f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugAllowUnsafe.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugAllowUnsafe.java @@ -42,7 +42,7 @@ public class DebugAllowUnsafe extends SubCommand { public static final List unsafeAllowed = new ArrayList<>(); - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { if (unsafeAllowed.contains(player.getUUID())) { unsafeAllowed.remove(player.getUUID()); diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java index 9f179803f..381582c57 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java @@ -178,7 +178,7 @@ public class DebugExec extends SubCommand { } } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { List allowed_params = Arrays .asList("analyze", "calibrate-analysis", "remove-flag", "stop-expire", "start-expire", "seen", "list-scripts", "start-rgar", "stop-rgar", "help", "addcmd", "runasync", @@ -312,7 +312,7 @@ public class DebugExec extends SubCommand { new Command(MainCommand.getInstance(), true, args[1].split("\\.")[0], null, RequiredType.NONE, CommandCategory.DEBUG) { @Override - public CompletableFuture execute(PlotPlayer player, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { try { diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java b/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java index 1eedabb71..bdb5a13b2 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugImportWorlds.java @@ -52,7 +52,7 @@ public class DebugImportWorlds extends Command { } @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { // UUID.nameUUIDFromBytes(("OfflinePlayer:" + player.getName()).getBytes(Charsets.UTF_8)) diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugLoadTest.java b/Core/src/main/java/com/plotsquared/core/command/DebugLoadTest.java index 47bf4d6c5..387c5204e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugLoadTest.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugLoadTest.java @@ -37,7 +37,7 @@ import com.plotsquared.core.player.PlotPlayer; requiredType = RequiredType.CONSOLE) public class DebugLoadTest extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { PlotSquared.get().plots_tmp = DBFunc.getPlots(); return true; } diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java b/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java index 0c805d6bc..441fbdd84 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugPaste.java @@ -71,7 +71,7 @@ public class DebugPaste extends SubCommand { return content.toString(); } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { TaskManager.runTaskAsync(() -> { try { diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java b/Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java index 07ce9a516..b20924586 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugRoadRegen.java @@ -46,7 +46,7 @@ import java.util.Arrays; public class DebugRoadRegen extends SubCommand { public static final String USAGE = "/plot debugroadregen "; - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { if (args.length < 1) { MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, DebugRoadRegen.USAGE); return false; diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugSaveTest.java b/Core/src/main/java/com/plotsquared/core/command/DebugSaveTest.java index dc2fc612d..7307ca185 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugSaveTest.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugSaveTest.java @@ -41,7 +41,7 @@ import java.util.ArrayList; description = "This command will force the recreation of all plots in the DB") public class DebugSaveTest extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { ArrayList plots = new ArrayList<>(PlotSquared.get().getPlots()); MainUtil.sendMessage(player, "&6Starting `DEBUGSAVETEST`"); DBFunc.createPlotsAndData(plots, diff --git a/Core/src/main/java/com/plotsquared/core/command/Delete.java b/Core/src/main/java/com/plotsquared/core/command/Delete.java index 1a95046df..6d8ea243e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Delete.java +++ b/Core/src/main/java/com/plotsquared/core/command/Delete.java @@ -53,7 +53,7 @@ public class Delete extends SubCommand { // Note: To delete a specific plot use /plot delete // The syntax also works with any command: /plot - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { Location location = player.getLocation(); final Plot plot = location.getPlotAbs(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Deny.java b/Core/src/main/java/com/plotsquared/core/command/Deny.java index 3cf742f0c..4ed0d0ed5 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Deny.java +++ b/Core/src/main/java/com/plotsquared/core/command/Deny.java @@ -51,7 +51,7 @@ public class Deny extends SubCommand { super(Argument.PlayerName); } - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { Location location = player.getLocation(); Plot plot = location.getPlotAbs(); diff --git a/Core/src/main/java/com/plotsquared/core/command/Dislike.java b/Core/src/main/java/com/plotsquared/core/command/Dislike.java index ee6664f81..410e13b57 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Dislike.java +++ b/Core/src/main/java/com/plotsquared/core/command/Dislike.java @@ -35,7 +35,7 @@ import com.plotsquared.core.player.PlotPlayer; requiredType = RequiredType.PLAYER) public class Dislike extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { return Like.handleLike(player, args, false); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Done.java b/Core/src/main/java/com/plotsquared/core/command/Done.java index 4e9015e04..258454f8a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Done.java +++ b/Core/src/main/java/com/plotsquared/core/command/Done.java @@ -51,7 +51,7 @@ import com.plotsquared.core.util.task.RunnableVal; requiredType = RequiredType.NONE) public class Done extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { Location location = player.getLocation(); final Plot plot = location.getPlotAbs(); if ((plot == null) || !plot.hasOwner()) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Download.java b/Core/src/main/java/com/plotsquared/core/command/Download.java index 25e3c13d7..efd4079d5 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Download.java +++ b/Core/src/main/java/com/plotsquared/core/command/Download.java @@ -50,7 +50,7 @@ import java.net.URL; permission = "plots.download") public class Download extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { String world = player.getLocation().getWorld(); if (!PlotSquared.get().hasPlotArea(world)) { return !sendMessage(player, Captions.NOT_IN_PLOT_WORLD); diff --git a/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java b/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java index 80ee2512a..d6b5a58e8 100644 --- a/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/FlagCommand.java @@ -207,7 +207,7 @@ public final class FlagCommand extends Command { } @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { if (args.length == 0 || !Arrays diff --git a/Core/src/main/java/com/plotsquared/core/command/Grant.java b/Core/src/main/java/com/plotsquared/core/command/Grant.java index 39351c27f..2d41da2e3 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Grant.java +++ b/Core/src/main/java/com/plotsquared/core/command/Grant.java @@ -53,7 +53,7 @@ public class Grant extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, + public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { checkTrue(args.length >= 1 && args.length <= 2, Captions.COMMAND_SYNTAX, getUsage()); diff --git a/Core/src/main/java/com/plotsquared/core/command/Help.java b/Core/src/main/java/com/plotsquared/core/command/Help.java index a1bbdc244..ef4b5a753 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Help.java +++ b/Core/src/main/java/com/plotsquared/core/command/Help.java @@ -52,7 +52,7 @@ public class Help extends Command { } @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { switch (args.length) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Inbox.java b/Core/src/main/java/com/plotsquared/core/command/Inbox.java index 938033758..a042e72cb 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Inbox.java +++ b/Core/src/main/java/com/plotsquared/core/command/Inbox.java @@ -86,7 +86,7 @@ public class Inbox extends SubCommand { MainUtil.sendMessage(player, string.toString()); } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { final Plot plot = player.getCurrentPlot(); if (plot == null) { sendMessage(player, Captions.NOT_IN_PLOT); diff --git a/Core/src/main/java/com/plotsquared/core/command/Info.java b/Core/src/main/java/com/plotsquared/core/command/Info.java index 23c63450b..125d0008d 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Info.java +++ b/Core/src/main/java/com/plotsquared/core/command/Info.java @@ -41,7 +41,7 @@ import com.plotsquared.core.util.task.RunnableVal; category = CommandCategory.INFO) public class Info extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { Plot plot; String arg; if (args.length > 0) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Kick.java b/Core/src/main/java/com/plotsquared/core/command/Kick.java index 69ace1482..0c83fa24e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Kick.java +++ b/Core/src/main/java/com/plotsquared/core/command/Kick.java @@ -53,7 +53,7 @@ public class Kick extends SubCommand { super(Argument.PlayerName); } - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { Location location = player.getLocation(); Plot plot = location.getPlot(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Leave.java b/Core/src/main/java/com/plotsquared/core/command/Leave.java index fdd2d70b4..3a0d7f09d 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Leave.java +++ b/Core/src/main/java/com/plotsquared/core/command/Leave.java @@ -48,7 +48,7 @@ public class Leave extends Command { } @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { final Plot plot = check(player.getCurrentPlot(), Captions.NOT_IN_PLOT); diff --git a/Core/src/main/java/com/plotsquared/core/command/Like.java b/Core/src/main/java/com/plotsquared/core/command/Like.java index 9414985c3..216c6524c 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Like.java +++ b/Core/src/main/java/com/plotsquared/core/command/Like.java @@ -175,7 +175,7 @@ public class Like extends SubCommand { return numLikes / (numLikes + numDislikes); } - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { return handleLike(player, args, true); } diff --git a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java index 0054df62e..811eb88a7 100644 --- a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java @@ -116,7 +116,7 @@ public class ListCmd extends SubCommand { .toString(getArgumentList(player))); } - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { if (args.length < 1) { noArgs(player); return false; diff --git a/Core/src/main/java/com/plotsquared/core/command/Load.java b/Core/src/main/java/com/plotsquared/core/command/Load.java index 58e2197b9..aa952a007 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Load.java +++ b/Core/src/main/java/com/plotsquared/core/command/Load.java @@ -52,7 +52,7 @@ import java.util.List; usage = "/plot load") public class Load extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { String world = player.getLocation().getWorld(); if (!PlotSquared.get().hasPlotArea(world)) { return !sendMessage(player, Captions.NOT_IN_PLOT_WORLD); @@ -152,7 +152,7 @@ public class Load extends SubCommand { return true; } - public void displaySaves(PlotPlayer player) { + public void displaySaves(PlotPlayer player) { List schematics = player.getMeta("plot_schematics"); for (int i = 0; i < Math.min(schematics.size(), 32); i++) { try { diff --git a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java index 133e27ab2..6e1151c4c 100644 --- a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java @@ -217,7 +217,7 @@ public class MainCommand extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, + public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { // Clear perm caching // diff --git a/Core/src/main/java/com/plotsquared/core/command/Merge.java b/Core/src/main/java/com/plotsquared/core/command/Merge.java index 53f88e2e7..962b48163 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Merge.java +++ b/Core/src/main/java/com/plotsquared/core/command/Merge.java @@ -78,7 +78,7 @@ public class Merge extends SubCommand { } } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { Location location = player.getLocationFull(); final Plot plot = location.getPlotAbs(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Middle.java b/Core/src/main/java/com/plotsquared/core/command/Middle.java index 58e7e437b..14c760eef 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Middle.java +++ b/Core/src/main/java/com/plotsquared/core/command/Middle.java @@ -42,7 +42,7 @@ import com.plotsquared.core.plot.Plot; requiredType = RequiredType.PLAYER) public class Middle extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] arguments) { + @Override public boolean onCommand(PlotPlayer player, String[] arguments) { Location location = player.getLocation(); Plot plot = location.getPlot(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Move.java b/Core/src/main/java/com/plotsquared/core/command/Move.java index e95c35a1c..136bbcfaa 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Move.java +++ b/Core/src/main/java/com/plotsquared/core/command/Move.java @@ -47,7 +47,7 @@ import java.util.concurrent.CompletableFuture; public class Move extends SubCommand { @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { Location location = player.getLocation(); @@ -107,7 +107,7 @@ public class Move extends SubCommand { }); } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { return true; } diff --git a/Core/src/main/java/com/plotsquared/core/command/Music.java b/Core/src/main/java/com/plotsquared/core/command/Music.java index 78e0b74e1..91b756a81 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Music.java +++ b/Core/src/main/java/com/plotsquared/core/command/Music.java @@ -55,7 +55,7 @@ public class Music extends SubCommand { "music_disc_far", "music_disc_mall", "music_disc_mellohi", "music_disc_stal", "music_disc_strad", "music_disc_ward", "music_disc_11", "music_disc_wait"); - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { Location location = player.getLocation(); final Plot plot = location.getPlotAbs(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Near.java b/Core/src/main/java/com/plotsquared/core/command/Near.java index a7c020762..20780613a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Near.java +++ b/Core/src/main/java/com/plotsquared/core/command/Near.java @@ -46,7 +46,7 @@ public class Near extends Command { } @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { final Plot plot = check(player.getCurrentPlot(), Captions.NOT_IN_PLOT); diff --git a/Core/src/main/java/com/plotsquared/core/command/PluginCmd.java b/Core/src/main/java/com/plotsquared/core/command/PluginCmd.java index 503e65586..b0bf24d40 100644 --- a/Core/src/main/java/com/plotsquared/core/command/PluginCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/PluginCmd.java @@ -39,7 +39,7 @@ import com.plotsquared.core.util.task.TaskManager; category = CommandCategory.INFO) public class PluginCmd extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { TaskManager.IMP.taskAsync(() -> { MainUtil.sendMessage(player, String.format( "$2>> $1&l" + PlotSquared.imp().getPluginName() + " $2($1Version$2: $1%s$2)", diff --git a/Core/src/main/java/com/plotsquared/core/command/Purge.java b/Core/src/main/java/com/plotsquared/core/command/Purge.java index 50b323300..9a89b2230 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Purge.java +++ b/Core/src/main/java/com/plotsquared/core/command/Purge.java @@ -53,7 +53,7 @@ import java.util.concurrent.atomic.AtomicBoolean; confirmation = true) public class Purge extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { if (args.length == 0) { Captions.COMMAND_SYNTAX.send(player, getUsage()); return false; diff --git a/Core/src/main/java/com/plotsquared/core/command/Rate.java b/Core/src/main/java/com/plotsquared/core/command/Rate.java index 1d80a0c37..23affc37d 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Rate.java +++ b/Core/src/main/java/com/plotsquared/core/command/Rate.java @@ -56,7 +56,7 @@ import java.util.UUID; requiredType = RequiredType.PLAYER) public class Rate extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { if (args.length == 1) { switch (args[0].toLowerCase()) { case "next": { diff --git a/Core/src/main/java/com/plotsquared/core/command/RegenAllRoads.java b/Core/src/main/java/com/plotsquared/core/command/RegenAllRoads.java index c5334241e..69d0022f6 100644 --- a/Core/src/main/java/com/plotsquared/core/command/RegenAllRoads.java +++ b/Core/src/main/java/com/plotsquared/core/command/RegenAllRoads.java @@ -43,7 +43,7 @@ import com.plotsquared.core.util.MainUtil; permission = "plots.regenallroads") public class RegenAllRoads extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { int height = 0; if (args.length == 2) { try { diff --git a/Core/src/main/java/com/plotsquared/core/command/Relight.java b/Core/src/main/java/com/plotsquared/core/command/Relight.java index b41e80baa..4a2475b5f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Relight.java +++ b/Core/src/main/java/com/plotsquared/core/command/Relight.java @@ -47,7 +47,7 @@ public class Relight extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, + public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { final Plot plot = player.getCurrentPlot(); diff --git a/Core/src/main/java/com/plotsquared/core/command/Reload.java b/Core/src/main/java/com/plotsquared/core/command/Reload.java index 2fc594d23..0b8f4b6fe 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Reload.java +++ b/Core/src/main/java/com/plotsquared/core/command/Reload.java @@ -45,7 +45,7 @@ import java.util.Objects; category = CommandCategory.ADMINISTRATION) public class Reload extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { try { // The following won't affect world generation, as that has to be // loaded during startup unfortunately. diff --git a/Core/src/main/java/com/plotsquared/core/command/Remove.java b/Core/src/main/java/com/plotsquared/core/command/Remove.java index 1a079f709..da00e5748 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Remove.java +++ b/Core/src/main/java/com/plotsquared/core/command/Remove.java @@ -50,7 +50,7 @@ public class Remove extends SubCommand { super(Argument.PlayerName); } - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { Location location = player.getLocation(); Plot plot = location.getPlotAbs(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Save.java b/Core/src/main/java/com/plotsquared/core/command/Save.java index 6196f08b7..480167576 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Save.java +++ b/Core/src/main/java/com/plotsquared/core/command/Save.java @@ -49,7 +49,7 @@ import java.util.UUID; permission = "plots.save") public class Save extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { String world = player.getLocation().getWorld(); if (!PlotSquared.get().hasPlotArea(world)) { return !sendMessage(player, Captions.NOT_IN_PLOT_WORLD); diff --git a/Core/src/main/java/com/plotsquared/core/command/SchematicCmd.java b/Core/src/main/java/com/plotsquared/core/command/SchematicCmd.java index 89c29b6c2..66e4a0662 100644 --- a/Core/src/main/java/com/plotsquared/core/command/SchematicCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/SchematicCmd.java @@ -57,7 +57,7 @@ public class SchematicCmd extends SubCommand { private boolean running = false; - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { if (args.length < 1) { sendMessage(player, Captions.SCHEMATIC_MISSING_ARG); return true; 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 bf5285691..ec75fd9eb 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Set.java +++ b/Core/src/main/java/com/plotsquared/core/command/Set.java @@ -176,7 +176,7 @@ public class Set extends SubCommand { return false; } - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { if (args.length == 0) { return noArgs(player); } diff --git a/Core/src/main/java/com/plotsquared/core/command/SetCommand.java b/Core/src/main/java/com/plotsquared/core/command/SetCommand.java index 9531790cb..c487fb0c0 100644 --- a/Core/src/main/java/com/plotsquared/core/command/SetCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/SetCommand.java @@ -36,7 +36,7 @@ import com.plotsquared.core.util.StringMan; public abstract class SetCommand extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { Location location = player.getLocation(); Plot plot = location.getPlotAbs(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Setup.java b/Core/src/main/java/com/plotsquared/core/command/Setup.java index ea76e36cf..c01f604f9 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Setup.java +++ b/Core/src/main/java/com/plotsquared/core/command/Setup.java @@ -90,7 +90,7 @@ public class Setup extends SubCommand { MainUtil.sendMessage(player, message.toString()); } - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { // going through setup SetupObject object = player.getMeta("setup"); if (object == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/SubCommand.java b/Core/src/main/java/com/plotsquared/core/command/SubCommand.java index 4a8d0e9fd..8692d1cae 100644 --- a/Core/src/main/java/com/plotsquared/core/command/SubCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/SubCommand.java @@ -54,11 +54,11 @@ public abstract class SubCommand extends Command { } @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { return CompletableFuture.completedFuture(onCommand(player, args)); } - public abstract boolean onCommand(PlotPlayer player, String[] args); + public abstract boolean onCommand(PlotPlayer player, String[] args); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Swap.java b/Core/src/main/java/com/plotsquared/core/command/Swap.java index d8447c84e..9e7ce5208 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Swap.java +++ b/Core/src/main/java/com/plotsquared/core/command/Swap.java @@ -45,7 +45,7 @@ import java.util.concurrent.CompletableFuture; public class Swap extends SubCommand { @Override - public CompletableFuture execute(PlotPlayer player, String[] args, + public CompletableFuture execute(PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { Location location = player.getLocation(); @@ -93,7 +93,7 @@ public class Swap extends SubCommand { }); } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { return true; } } diff --git a/Core/src/main/java/com/plotsquared/core/command/Target.java b/Core/src/main/java/com/plotsquared/core/command/Target.java index 5edc9b5a5..a70ac3451 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Target.java +++ b/Core/src/main/java/com/plotsquared/core/command/Target.java @@ -45,7 +45,7 @@ public class Target extends SubCommand { super(Argument.PlotID); } - @Override public boolean onCommand(PlotPlayer player, String[] args) { + @Override public boolean onCommand(PlotPlayer player, String[] args) { Location location = player.getLocation(); if (!location.isPlotArea()) { MainUtil.sendMessage(player, Captions.NOT_IN_PLOT_WORLD); diff --git a/Core/src/main/java/com/plotsquared/core/command/Template.java b/Core/src/main/java/com/plotsquared/core/command/Template.java index 373f3b38e..d19fbab51 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Template.java +++ b/Core/src/main/java/com/plotsquared/core/command/Template.java @@ -134,7 +134,7 @@ public class Template extends SubCommand { } } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { if (args.length != 2 && args.length != 3) { if (args.length == 1) { if (args[0].equalsIgnoreCase("export")) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Trim.java b/Core/src/main/java/com/plotsquared/core/command/Trim.java index 4e4e8e900..ad5e5c0fe 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Trim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Trim.java @@ -159,7 +159,7 @@ public class Trim extends SubCommand { return true; } - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { if (args.length == 0) { Captions.COMMAND_SYNTAX.send(player, getUsage()); return false; diff --git a/Core/src/main/java/com/plotsquared/core/command/Trust.java b/Core/src/main/java/com/plotsquared/core/command/Trust.java index 4f9c15e38..1c4064543 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Trust.java +++ b/Core/src/main/java/com/plotsquared/core/command/Trust.java @@ -56,7 +56,7 @@ public class Trust extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, String[] args, + public CompletableFuture execute(final PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) throws CommandException { final Plot currentPlot = player.getCurrentPlot(); diff --git a/Core/src/main/java/com/plotsquared/core/command/Unlink.java b/Core/src/main/java/com/plotsquared/core/command/Unlink.java index d2d5fa8d2..1f309df57 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Unlink.java +++ b/Core/src/main/java/com/plotsquared/core/command/Unlink.java @@ -46,7 +46,7 @@ import com.plotsquared.core.util.task.TaskManager; confirmation = true) public class Unlink extends SubCommand { - @Override public boolean onCommand(final PlotPlayer player, String[] args) { + @Override public boolean onCommand(final PlotPlayer player, String[] args) { Location location = player.getLocation(); final Plot plot = location.getPlotAbs(); if (plot == null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 651a1c0b0..077f1f6de 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -139,7 +139,7 @@ public class Visit extends Command { } @Override - public CompletableFuture execute(final PlotPlayer player, + public CompletableFuture execute(final PlotPlayer player, String[] args, final RunnableVal3 confirm, final RunnableVal2 whenDone) throws CommandException { diff --git a/Core/src/main/java/com/plotsquared/core/command/WE_Anywhere.java b/Core/src/main/java/com/plotsquared/core/command/WE_Anywhere.java index 6ac51f57c..50cda457a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/WE_Anywhere.java +++ b/Core/src/main/java/com/plotsquared/core/command/WE_Anywhere.java @@ -37,7 +37,7 @@ import com.plotsquared.core.player.PlotPlayer; @Deprecated public class WE_Anywhere extends SubCommand { - @Override public boolean onCommand(PlotPlayer player, String[] arguments) { + @Override public boolean onCommand(PlotPlayer player, String[] arguments) { MainCommand.getInstance().toggle.worldedit(this, player, new String[0], null, null); return true; } diff --git a/Core/src/main/java/com/plotsquared/core/components/ComponentCommand.java b/Core/src/main/java/com/plotsquared/core/components/ComponentCommand.java index f79b68063..8c158c417 100644 --- a/Core/src/main/java/com/plotsquared/core/components/ComponentCommand.java +++ b/Core/src/main/java/com/plotsquared/core/components/ComponentCommand.java @@ -46,7 +46,7 @@ public class ComponentCommand extends SubCommand { this.componentPresetManager = componentPresetManager; } - @Override public boolean onCommand(final PlotPlayer player, final String[] args) { + @Override public boolean onCommand(final PlotPlayer player, final String[] args) { final PlotInventory inventory = componentPresetManager.buildInventory(player); if (inventory != null) { inventory.openInventory(); diff --git a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java index 5a4e43142..361a71b28 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -123,7 +123,7 @@ public class PlotListener { }, 20); } - public static boolean plotEntry(final PlotPlayer player, final Plot plot) { + public static boolean plotEntry(final PlotPlayer player, final Plot plot) { if (plot.isDenied(player.getUUID()) && !Permissions .hasPermission(player, "plots.admin.entry.denied")) { return false; @@ -293,7 +293,7 @@ public class PlotListener { return true; } - public static boolean plotExit(final PlotPlayer player, Plot plot) { + public static boolean plotExit(final PlotPlayer player, Plot plot) { Object previous = player.deleteMeta(PlotPlayer.META_LAST_PLOT); PlotSquared.get().getEventDispatcher().callLeave(player, plot); if (plot.hasOwner()) { diff --git a/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java b/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java index bf295c9d7..9a97800e7 100644 --- a/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java @@ -41,7 +41,7 @@ import org.jetbrains.annotations.NotNull; import java.util.UUID; -public class ConsolePlayer extends PlotPlayer { +public class ConsolePlayer extends PlotPlayer { private static ConsolePlayer instance; @@ -71,6 +71,10 @@ public class ConsolePlayer extends PlotPlayer { return PlotSquared.get().IMP.getConsole(); } + @Override public Actor getPlatformPlayer() { + return this.toActor(); + } + @Override public boolean canTeleport(@NotNull Location location) { return true; } diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java index 586809880..1a4e668c5 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -68,7 +68,7 @@ import java.util.stream.Collectors; /** * The abstract class supporting {@code BukkitPlayer} and {@code SpongePlayer}. */ -public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { +public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer { public static final String META_LAST_PLOT = "lastplot"; public static final String META_LOCATION = "location"; @@ -103,12 +103,14 @@ public abstract class PlotPlayer implements CommandCaller, OfflinePlotPlayer { * @param player * @return */ - public static PlotPlayer wrap(Object player) { + public static PlotPlayer wrap(Object player) { return PlotSquared.get().IMP.wrapPlayer(player); } public abstract Actor toActor(); + public abstract P getPlatformPlayer(); + /** * Set some session only metadata for this player. * diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index df9ee12c4..5def886a8 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -399,9 +399,9 @@ public class Plot { * * @return list of PlotPlayer(s) or an empty list */ - public List getPlayersInPlot() { - final List players = new ArrayList<>(); - for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { + public List> getPlayersInPlot() { + final List> players = new ArrayList<>(); + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { if (this.equals(player.getCurrentPlot())) { players.add(player); } @@ -1323,8 +1323,8 @@ public class Plot { return false; } for (Plot current : getConnectedPlots()) { - List players = current.getPlayersInPlot(); - for (PlotPlayer pp : players) { + List> players = current.getPlayersInPlot(); + for (PlotPlayer pp : players) { PlotListener.plotExit(pp, current); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotInventory.java b/Core/src/main/java/com/plotsquared/core/plot/PlotInventory.java index 1a3abd5e0..88f9c100c 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotInventory.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotInventory.java @@ -33,40 +33,40 @@ import lombok.NonNull; public class PlotInventory { private static final String META_KEY = "inventory"; - public final PlotPlayer player; + public final PlotPlayer player; public final int size; private final PlotItemStack[] items; private String title; private boolean open = false; - public PlotInventory(PlotPlayer player) { + public PlotInventory(PlotPlayer player) { this.size = 4; this.title = null; this.player = player; this.items = InventoryUtil.manager.getItems(player); } - public PlotInventory(PlotPlayer player, int size, String name) { + public PlotInventory(PlotPlayer player, int size, String name) { this.size = size; this.title = name == null ? "" : name; this.player = player; this.items = new PlotItemStack[size * 9]; } - public static boolean hasPlotInventoryOpen(@NonNull final PlotPlayer plotPlayer) { + public static boolean hasPlotInventoryOpen(@NonNull final PlotPlayer plotPlayer) { return getOpenPlotInventory(plotPlayer) != null; } - public static PlotInventory getOpenPlotInventory(@NonNull final PlotPlayer plotPlayer) { + public static PlotInventory getOpenPlotInventory(@NonNull final PlotPlayer plotPlayer) { return plotPlayer.getMeta(META_KEY, null); } - public static void setPlotInventoryOpen(@NonNull final PlotPlayer plotPlayer, + public static void setPlotInventoryOpen(@NonNull final PlotPlayer plotPlayer, @NonNull final PlotInventory plotInventory) { plotPlayer.setMeta(META_KEY, plotInventory); } - public static void removePlotInventoryOpen(@NonNull final PlotPlayer plotPlayer) { + public static void removePlotInventoryOpen(@NonNull final PlotPlayerplotPlayer) { plotPlayer.deleteMeta(META_KEY); } 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 1e945a8bb..141d729c7 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 @@ -75,7 +75,7 @@ import java.util.concurrent.atomic.AtomicInteger; }, 20); } - public static long getTimestamp(PlotPlayer player, String inbox) { + public static long getTimestamp(PlotPlayer player, String inbox) { return player.getMeta("inbox:" + inbox, player.getLastPlayed()); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java index 16d4ee41f..88d167a50 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java @@ -83,7 +83,7 @@ public class ExpireManager { this.tasks.add(task); } - public void handleJoin(PlotPlayer pp) { + public void handleJoin(PlotPlayer pp) { storeDate(pp.getUUID(), System.currentTimeMillis()); if (plotsToDelete != null && !plotsToDelete.isEmpty()) { for (Plot plot : pp.getPlots()) { diff --git a/Core/src/main/java/com/plotsquared/core/util/Permissions.java b/Core/src/main/java/com/plotsquared/core/util/Permissions.java index 186439fc9..34754e7c8 100644 --- a/Core/src/main/java/com/plotsquared/core/util/Permissions.java +++ b/Core/src/main/java/com/plotsquared/core/util/Permissions.java @@ -61,7 +61,7 @@ public class Permissions { * @param permission * @return */ - public static boolean hasPermission(PlotPlayer player, String permission) { + public static boolean hasPermission(PlotPlayer player, String permission) { if (!Settings.Enabled_Components.PERMISSION_CACHE) { return hasPermission((CommandCaller) player, permission); } diff --git a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java index 473826b2d..a5f8add50 100644 --- a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java @@ -39,7 +39,7 @@ import java.util.UUID; /** * Manages player instances */ -public abstract class PlayerManager

{ +public abstract class PlayerManager

, T> { private final Map playerMap = new HashMap<>(); private final Object playerLock = new Object(); @@ -77,6 +77,18 @@ public abstract class PlayerManager

+ * The method will throw an exception if there is no such + * player online. + * + * @param object Platform player object + * @return Player object + */ + @NotNull public abstract P getPlayer(@NotNull final T object); + /** * Get a plot player from a UUID. This method requires * that the caller actually knows that the player exists. @@ -106,7 +118,7 @@ public abstract class PlayerManager

getMask(PlotPlayer player) { + public static HashSet getMask(PlotPlayer player) { HashSet regions = new HashSet<>(); UUID uuid = player.getUUID(); Location location = player.getLocation(); From f1b79a3b0d82b429107a7f87e1bc35427b474285 Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Wed, 27 May 2020 22:20:13 +0200 Subject: [PATCH 076/121] Add more documentation to the settings.yml Apparently gradle wants to update the poms so here we go --- Bukkit/pom.xml | 4 +- Core/pom.xml | 2 +- .../core/configuration/Settings.java | 59 ++++++++++++------- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index c2e002a06..b94221c89 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -9,7 +9,7 @@ org.json json - 20190722 + 20200518 compile @@ -21,7 +21,7 @@ com.plotsquared PlotSquared-Core - 5.11.2 + 5.12.0 compile diff --git a/Core/pom.xml b/Core/pom.xml index 3260d86a8..d69f10a99 100644 --- a/Core/pom.xml +++ b/Core/pom.xml @@ -9,7 +9,7 @@ org.json json - 20190722 + 20200518 compile diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 78b7c6e37..dc10790d8 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -40,13 +40,14 @@ public class Settings extends Config { NOTE: Fields are saved in declaration order, classes in reverse order */ - @Comment("The first value is not configurable") // This is a comment + @Comment("This value is not configurable. It shows the platform you are using.") // This is a comment @Final public static String PLATFORM; // These values are set from P2 before loading - @Comment("Show additional information in console") public static boolean DEBUG = false; - @Comment({"The big annoying text that appears when you enter a plot", - "For a single plot: `/plot flag set titles false`", "For just you: `/plot toggle titles`", - "For all plots: Add `titles: false` in the worlds.yml flags block"}) public static boolean + @Comment({"Show additional information in console. It helps us at IntellectualSites to find out more about an issue.", + "Leave it off if you don't need it, it can spam your console."}) public static boolean DEBUG = false; + @Comment({"The big text that appears when you enter a plot.", + "For a single plot set `/plot flag set titles false` to disable it.", "For just you run `/plot toggle titles` to disable it.", + "For all plots: Add `titles: false` in the worlds.yml flags block to disable it."}) public static boolean TITLES = true; @Create // This value will be generated automatically @@ -207,7 +208,7 @@ public class Settings extends Config { public List WORLDS = new ArrayList<>(Collections.singletonList("*")); - @Comment("See: https://wiki.intellectualsites.com/en/plotsquared/optimization/plot-analysis") + @Comment("See: https://wiki.intellectualsites.com/en/plotsquared/optimization/plot-analysis for a description of each value.") public static final class CALIBRATION { public int VARIETY = 0; public int VARIETY_SD = 0; @@ -223,6 +224,8 @@ public class Settings extends Config { } + @Comment({"Chunk processor related settings", + "See https://wiki.intellectualsites.com/en/plotsquared/optimization/chunk-processor for more information."}) public static class Chunk_Processor { @Comment("Auto trim will not save chunks which aren't claimed") public static boolean AUTO_TRIM = false; @@ -232,6 +235,8 @@ public class Settings extends Config { } + @Comment({"UUID settings", + "DO NOT EDIT them unless you know what you are doing."}) public static class UUID { @Comment("Force using offline UUIDs (it usually detects the right mode)") public static boolean OFFLINE = false; @@ -259,7 +264,8 @@ public class Settings extends Config { public static final class General { @Comment("Display scientific numbers (4.2E8)") public static boolean SCIENTIFIC = false; @Comment("Replace wall when merging") public static boolean MERGE_REPLACE_WALL = true; - @Comment("Blocks that may not be used in plot components") public static List + @Comment({"Blocks that may not be used in plot components", + "Checkout the wiki article regarding plot components before modifying: https://wiki.intellectualsites.com/en/plotsquared/installation/plot-components"}) public static List INVALID_BLOCKS = Arrays.asList( // Acacia Stuff "acacia_button", "acacia_fence_gate", "acacia_door", "acacia_pressure_plate", @@ -373,7 +379,8 @@ public class Settings extends Config { } - @Comment("Schematic Settings") + @Comment({"Schematic Settings", + "See https://wiki.intellectualsites.com/en/plotsquared/schematics/on-claim for more information."}) public static final class Schematics { @Comment( "Whether schematic based generation should paste schematic on top of plots, or from Y=1") @@ -390,6 +397,7 @@ public class Settings extends Config { } + @Comment("Schematic and Asset interface related settings") public static class Web { @Comment({"The web interface for schematics", " - All schematics are anonymous and private", " - Downloads can be deleted by the user", @@ -402,8 +410,9 @@ public class Settings extends Config { } + @Comment("Misc settings") public static final class Done { - @Comment("Require a plot marked as done to download") public static boolean + @Comment("Require a plot marked as done to download (/plot download)") public static boolean REQUIRED_FOR_DOWNLOAD = false; @Comment("Only plots marked as done can be rated") public static boolean REQUIRED_FOR_RATINGS = false; @@ -414,6 +423,7 @@ public class Settings extends Config { } + @Comment("Chat related settings") public static final class Chat { @Comment("Sometimes console color doesn't work, you can disable it here") public static boolean CONSOLE_COLOR = true; @@ -421,7 +431,7 @@ public class Settings extends Config { } - @Comment("Relating to how many plots someone can claim ") + @Comment("Relating to how many plots someone can claim") public static final class Limit { @Comment("Should the limit be global (over multiple worlds)") public static boolean GLOBAL = false; @@ -432,9 +442,10 @@ public class Settings extends Config { } - @Comment("Backup related settings") + @Comment({"Backup related settings", + "See https://wiki.intellectualsites.com/en/plotsquared/backups for more information."}) public static final class Backup { - @Comment("Automatically backup plots when destructive commands are performed") + @Comment("Automatically backup plots when destructive commands are performed, e.g. /plot clear") public static boolean AUTOMATIC_BACKUPS = true; @Comment("Maximum amount of backups associated with a plot") public static int BACKUP_LIMIT = 3; @@ -443,12 +454,14 @@ public class Settings extends Config { } + @Comment("Confirmation timeout related settings") public static final class Confirmation { @Comment("Timeout before a confirmation prompt expires") public static int CONFIRMATION_TIMEOUT_SECONDS = 20; } + @Comment("Teleportation related settings") public static final class Teleport { @Comment("Teleport to your plot on death") public static boolean ON_DEATH = false; @Comment("Teleport to your plot on login") public static boolean ON_LOGIN = false; @@ -461,6 +474,7 @@ public class Settings extends Config { } + @Comment("Redstone related settings") public static final class Redstone { @Comment("Disable redstone in unoccupied plots") public static boolean DISABLE_UNOCCUPIED = false; @@ -472,12 +486,14 @@ public class Settings extends Config { } + @Comment("Claim related settings") public static final class Claim { @Comment("The max plots claimed in a single `/plot auto ` command") public static int MAX_AUTO_AREA = 4; } + @Comment("Rating related settings") public static final class Ratings { @Comment("Replace the rating system with a like system. Will add /plot like/dislike," + " and remove the rating command") public static boolean USE_LIKES = false; @@ -528,27 +544,28 @@ public class Settings extends Config { true; @Comment("Allow WorldEdit to be restricted to plots") public static boolean WORLDEDIT_RESTRICTIONS = true; - @Comment("Allow economy to be used") public static boolean ECONOMY = true; + @Comment("Allow economy to be used to sell, claim or buy plots.") public static boolean ECONOMY = true; @Comment("Expiry will clear old or simplistic plots") public static boolean PLOT_EXPIRY = false; @Comment("Processes chunks (trimming, or entity/tile limits) ") public static boolean CHUNK_PROCESSOR = false; - @Comment("Kill mobs on roads") public static boolean KILL_ROAD_MOBS = false; - @Comment("Kill items on roads") public static boolean KILL_ROAD_ITEMS = false; - @Comment("Kill vehicles on roads") public static boolean KILL_ROAD_VEHICLES = false; - @Comment("Notify a player of any missed comments upon plot entry") public static boolean + @Comment("Kill mobs on roads (Chicken, Cow, etc.)") public static boolean KILL_ROAD_MOBS = false; + @Comment("Kill items on roads (Stick, Paper, etc.)") public static boolean KILL_ROAD_ITEMS = false; + @Comment("Kill vehicles on roads (Boat, Minecart, etc.)") public static boolean KILL_ROAD_VEHICLES = false; + @Comment("Notify a player of any missed plot comments upon plot entry") public static boolean COMMENT_NOTIFIER = false; @Comment("Let players claim entire worlds with PlotSquared") public static boolean WORLDS = false; @Comment("Actively purge invalid database entries") public static boolean DATABASE_PURGER = false; - @Comment("Delete plots when a player is banned") public static boolean BAN_DELETER = false; - @Comment("Allows PlaceholderAPI placeholders to be used in captions, flags, etc") + @Comment({"Delete plots when a player is banned.", + "Note: This only works with the /minecraft:ban command. Any punishment plugin like LiteBans is not supported."}) public static boolean BAN_DELETER = false; + @Comment("Allows PlaceholderAPI placeholders to be used in captions, flags, etc.") public static boolean EXTERNAL_PLACEHOLDERS = true; @Comment("Make road regeneration persistent across restarts") public static boolean PERSISTENT_ROAD_REGEN = false; - @Comment("Plot component preset GUI") - public static boolean COMPONENT_PRESETS = true; + @Comment({"Enable the `/plot component` preset GUI", + "Read more about components here: https://wiki.intellectualsites.com/en/plotsquared/installation/plot-components"}) public static boolean COMPONENT_PRESETS = true; @Comment("Use UUID cache to complete usernames") public static boolean EXTENDED_USERNAME_COMPLETION = true; } From 2c74d2479fcd77092a1ad63a18d9ab31e9fb01fe Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Tue, 2 Jun 2020 17:06:33 +0200 Subject: [PATCH 077/121] Exchange website url --- Bukkit/src/main/resources/plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bukkit/src/main/resources/plugin.yml b/Bukkit/src/main/resources/plugin.yml index 05d2aa6e2..ff6442591 100644 --- a/Bukkit/src/main/resources/plugin.yml +++ b/Bukkit/src/main/resources/plugin.yml @@ -5,7 +5,7 @@ version: "${version}" load: STARTUP description: "Easy, yet powerful Plot World generation and management." authors: [Citymonstret, Empire92, MattBDev, dordsor21, NotMyFault, SirYwell] -website: https://github.com/IntellectualSites/ +website: https://www.spigotmc.org/resources/77506/ softdepend: [Vault, PlaceholderAPI] loadbefore: [MultiWorld, Multiverse-Core] depend: [WorldEdit] From 86746e784340b1a4cfd2d05e840d4c1fb84ae1b7 Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Wed, 3 Jun 2020 21:18:46 +0200 Subject: [PATCH 078/121] Fixed https://issues.intellectualsites.com/issue/PS-26 --- .../main/java/com/plotsquared/bukkit/listener/PlayerEvents.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 073b7939d..5a047b5c6 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -1216,7 +1216,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } switch (event.getSource().getType()) { - case GRASS: + case GRASS_BLOCK: if (!plot.getFlag(GrassGrowFlag.class)) { event.setCancelled(true); } From 950640a557b1dd2623c8170629b89716b38f546b Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Thu, 4 Jun 2020 11:29:02 +0200 Subject: [PATCH 079/121] Revert "Don't send chat spy to message sender" This reverts commit a37ab10414e529d79d213d5adb66c49fe91abb71. Let's not break plotchat when plotspy is enabled --- .../java/com/plotsquared/bukkit/listener/PlayerEvents.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 5a047b5c6..734816707 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -979,9 +979,6 @@ public class PlayerEvents extends PlotListener implements Listener { .replace("%plot_id%", id.x + ";" + id.y).replace("%sender%", sender) .replace("%msg%", message); for (Player player : spies) { - if (player.equals(event.getPlayer())) { - continue; - } player.sendMessage(spyMessage); } } From d12ecc861632c56e30780f6a4ac642e5461710d4 Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Thu, 4 Jun 2020 11:41:20 +0200 Subject: [PATCH 080/121] Softdepend on new complementary UUID services --- Bukkit/src/main/resources/plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bukkit/src/main/resources/plugin.yml b/Bukkit/src/main/resources/plugin.yml index ff6442591..41967220c 100644 --- a/Bukkit/src/main/resources/plugin.yml +++ b/Bukkit/src/main/resources/plugin.yml @@ -6,7 +6,7 @@ load: STARTUP description: "Easy, yet powerful Plot World generation and management." authors: [Citymonstret, Empire92, MattBDev, dordsor21, NotMyFault, SirYwell] website: https://www.spigotmc.org/resources/77506/ -softdepend: [Vault, PlaceholderAPI] +softdepend: [Vault, PlaceholderAPI, Essentials, LuckPerms, BungeePerms] loadbefore: [MultiWorld, Multiverse-Core] depend: [WorldEdit] database: false From c5bfde330f99005d4eaf7e10da3c1c930ff35966 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sun, 31 May 2020 23:55:59 +0200 Subject: [PATCH 081/121] First draft of redesigned setup processing --- .../core/configuration/ConfigurationNode.java | 21 ++- .../generator/IndependentPlotGenerator.java | 10 + .../plotsquared/core/plot/PlotAreaType.java | 18 +- .../plotsquared/core/plot/SetupObject.java | 4 + .../core/setup/CommonSetupSteps.java | 176 ++++++++++++++++++ .../core/setup/PlotAreaBuilder.java | 20 ++ .../core/setup/SettingsNodeStep.java | 45 +++++ .../core/setup/SettingsNodesWrapper.java | 27 +++ .../plotsquared/core/setup/SetupProcess.java | 34 ++++ .../com/plotsquared/core/setup/SetupStep.java | 40 ++++ 10 files changed, 384 insertions(+), 11 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java create mode 100644 Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java create mode 100644 Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java create mode 100644 Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java create mode 100644 Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java create mode 100644 Core/src/main/java/com/plotsquared/core/setup/SetupStep.java diff --git a/Core/src/main/java/com/plotsquared/core/configuration/ConfigurationNode.java b/Core/src/main/java/com/plotsquared/core/configuration/ConfigurationNode.java index c936245b3..cd3d524a8 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/ConfigurationNode.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/ConfigurationNode.java @@ -28,9 +28,11 @@ package com.plotsquared.core.configuration; import com.plotsquared.core.plot.BlockBucket; import com.plotsquared.core.util.StringMan; import com.sk89q.worldedit.world.block.BlockState; +import lombok.Getter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -38,19 +40,26 @@ import java.util.List; */ public class ConfigurationNode { - private final String constant; + @Getter private final String constant; private final Object defaultValue; - private final String description; + @Getter private final String description; private final ConfigurationUtil.SettingValue type; + @Getter private final Collection suggestions; private Object value; public ConfigurationNode(String constant, Object defaultValue, String description, ConfigurationUtil.SettingValue type) { + this(constant, defaultValue, description, type, new ArrayList<>()); + } + + public ConfigurationNode(String constant, Object defaultValue, String description, + ConfigurationUtil.SettingValue type, Collection suggestions) { this.constant = constant; this.defaultValue = defaultValue; this.description = description; this.value = defaultValue; this.type = type; + this.suggestions = suggestions; } public ConfigurationUtil.SettingValue getType() { @@ -97,18 +106,10 @@ public class ConfigurationNode { return this.value; } - public String getConstant() { - return this.constant; - } - public Object getDefaultValue() { if (this.defaultValue instanceof Object[]) { return StringMan.join((Object[]) this.defaultValue, ","); } return this.defaultValue; } - - public String getDescription() { - return this.description; - } } diff --git a/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java b/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java index 915f22940..b2e1278ab 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java +++ b/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java @@ -30,6 +30,7 @@ import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.queue.ScopedLocalBlockQueue; +import com.plotsquared.core.setup.SetupProcess; /** * This class allows for implementation independent world generation. @@ -74,9 +75,18 @@ public abstract class IndependentPlotGenerator { * * @param setup */ + @Deprecated public void processSetup(SetupObject setup) { } + /** + * If any additional setup options need to be changed before world creation. + * - e.g. If setup doesn't support some standard options + * + * @param setupProcess the setup process to modify + */ + public void processSetup(SetupProcess setupProcess) { } + /** * It is preferred for the PlotArea object to do most of the initialization necessary. * diff --git a/Core/src/main/java/com/plotsquared/core/plot/PlotAreaType.java b/Core/src/main/java/com/plotsquared/core/plot/PlotAreaType.java index 60c9fc7f0..9ed4cb0f0 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotAreaType.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotAreaType.java @@ -25,6 +25,10 @@ */ package com.plotsquared.core.plot; +import com.plotsquared.core.configuration.Caption; +import com.plotsquared.core.configuration.Captions; +import lombok.Getter; + import java.util.Map; import java.util.Optional; import java.util.function.Function; @@ -32,11 +36,23 @@ import java.util.stream.Collectors; import java.util.stream.Stream; public enum PlotAreaType { - NORMAL, AUGMENTED, PARTIAL; + NORMAL(Captions.PLOT_AREA_TYPE_NORMAL), + AUGMENTED(Captions.PLOT_AREA_TYPE_AUGMENTED), + PARTIAL(Captions.PLOT_AREA_TYPE_PARTIAL); + + @Getter private final Caption description; private static final Map types = Stream.of(values()) .collect(Collectors.toMap(e -> e.toString().toLowerCase(), Function.identity())); + PlotAreaType(Caption description) { + this.description = description; + } + + public static Map getDescriptionMap() { + return Stream.of(values()).collect(Collectors.toMap(e -> e, PlotAreaType::getDescription)); + } + public static Optional fromString(String typeName) { return Optional.ofNullable(types.get(typeName.toLowerCase())); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/SetupObject.java b/Core/src/main/java/com/plotsquared/core/plot/SetupObject.java index 8ac5d5cb0..bfca8fe5e 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/SetupObject.java +++ b/Core/src/main/java/com/plotsquared/core/plot/SetupObject.java @@ -28,6 +28,10 @@ package com.plotsquared.core.plot; import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.util.SetupUtils; +/** + * @deprecated will be removed in v6 + */ +@Deprecated public class SetupObject { /** diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java new file mode 100644 index 000000000..0908b250c --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -0,0 +1,176 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.configuration.Caption; +import com.plotsquared.core.configuration.Captions; +import com.plotsquared.core.configuration.ConfigurationNode; +import com.plotsquared.core.generator.GeneratorWrapper; +import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.PlotAreaTerrainType; +import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.SetupUtils; +import com.plotsquared.core.util.StringMan; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Collectors; + +import static com.plotsquared.core.util.MainUtil.sendMessage; + +public enum CommonSetupSteps implements SetupStep { + GENERATOR(Captions.SETUP_INIT) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { + if (!SetupUtils.generators.containsKey(arg)) { + String prefix = "\n&8 - &7"; + sendMessage(plotPlayer, Captions.SETUP_WORLD_GENERATOR_ERROR + prefix + StringMan + .join(SetupUtils.generators.keySet(), prefix) + .replaceAll(PlotSquared.imp().getPluginName(), + "&2" + PlotSquared.imp().getPluginName())); + sendMessage(plotPlayer, Captions.SETUP_INIT); + return this; // invalid input -> same setup step + } + builder.generatorName(arg); + sendMessage(plotPlayer, Captions.SETUP_WORLD_TYPE); + return CommonSetupSteps.PLOT_AREA_TYPE; // proceed with next step + } + + @Override public @NotNull Collection getSuggestions() { + return Collections.unmodifiableSet(SetupUtils.generators.keySet()); + } + + @Override @Nullable public String getDefaultValue() { + return PlotSquared.imp().getPluginName(); + } + }, + PLOT_AREA_TYPE(PlotAreaType.class, Captions.SETUP_WORLD_TYPE) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { + boolean withNormal = SetupUtils.generators.get(builder.generatorName()).isFull(); + Optional plotAreaType = PlotAreaType.fromString(arg); + if (!plotAreaType.isPresent()) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_TYPE_ERROR); + PlotAreaType.getDescriptionMap().forEach((type, caption) -> { + if (!withNormal && type == PlotAreaType.NORMAL) { + return; // skip + } + String color = type == PlotAreaType.NORMAL ? "&2" : "&7"; + MainUtil.sendMessage(plotPlayer, "&8 - " + color + type + + " &8-&7 " + caption.getTranslated()); + }); + return this; + } + builder.plotAreaType(plotAreaType.get()); + // object.type = plotAreaType.get(); + GeneratorWrapper gen = SetupUtils.generators.get(builder.generatorName()); + if (builder.plotAreaType() == PlotAreaType.NORMAL) { + if (builder.settingsNodesWrapper() == null) { + builder.plotManager(builder.generatorName()); + builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); + // TODO reimplement SetupUtils.generators.get(object.plotManager).getPlotGenerator() + // .processSetup(process); + } + if (!builder.settingsNodesWrapper().hasNext()) { + // MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME); + // object.setup_index = 0; TODO what did that do? + return WORLD_NAME; // skip + } + SettingsNodeStep next = builder.settingsNodesWrapper().next(); + ConfigurationNode step = next.getConfigurationNode(); + sendMessage(plotPlayer, Captions.SETUP_STEP, next.getId() + 1, + step.getDescription(), step.getType().getType(), + String.valueOf(step.getDefaultValue())); + return next; + } else { + if (gen.isFull()) { + builder.plotManager(builder.generatorName()); + builder.generatorName(null); + builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); + // TODO reimplement SetupUtils.generators.get(object.plotManager).getPlotGenerator() + // .processSetup(process); + } else { + builder.plotManager(PlotSquared.imp().getPluginName()); + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WRONG_GENERATOR); + builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); + // TODO why is processSetup not called here? + } + if (builder.plotAreaType() == PlotAreaType.PARTIAL) { + // MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_NAME); + // TODO return step area id + return null; + } else { + // MainUtil.sendMessage(plotPlayer, Captions.SETUP_PARTIAL_AREA); + return TERRAIN_TYPE; + } + } + } + + @Nullable @Override public String getDefaultValue() { + return PlotAreaType.NORMAL.toString(); // TODO toLowerCase here? + } + }, + TERRAIN_TYPE(PlotAreaTerrainType.class, Captions.SETUP_PARTIAL_AREA) { + @Override + public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + return null; + } + + @Override + public @Nullable String getDefaultValue() { + return PlotAreaTerrainType.NONE.toString(); // TODO toLowerCase here? + } + }, + WORLD_NAME(Captions.SETUP_WORLD_NAME) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + return null; + } + + @Nullable @Override public String getDefaultValue() { + return null; + } + }; + + @Getter @NotNull private final Collection suggestions; + private final Caption description; + + /** + * + * @param suggestions the input suggestions for this step + * @param description the caption describing this step + */ + CommonSetupSteps(@NotNull Collection suggestions, Caption description) { + this.suggestions = suggestions; + this.description = description; + } + + CommonSetupSteps(Caption description) { + this.description = description; + this.suggestions = Collections.emptyList(); + } + + > CommonSetupSteps(Class argumentType, Caption description) { + this(enumToStrings(argumentType), description); + } + + + + private static > Collection enumToStrings(Class type) { + return Arrays.stream(type.getEnumConstants()).map(e -> e.toString().toLowerCase()).collect(Collectors.toList()); + } + + private static SettingsNodesWrapper wrap(String plotManager) { + return new SettingsNodesWrapper(SetupUtils.generators.get(plotManager).getPlotGenerator() + .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) + .getSettingNodes()); + } + + @Override + public void announce(PlotPlayer plotPlayer) { + MainUtil.sendMessage(plotPlayer, this.description); + } +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java new file mode 100644 index 000000000..fe4f755c1 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java @@ -0,0 +1,20 @@ +package com.plotsquared.core.setup; + + +import com.plotsquared.core.plot.PlotAreaTerrainType; +import com.plotsquared.core.plot.PlotAreaType; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Accessors(fluent = true) +public class PlotAreaBuilder { + @Getter @Setter private String generatorName; + @Getter @Setter private String plotManager; + @Getter @Setter private PlotAreaType plotAreaType; + @Getter @Setter private PlotAreaTerrainType terrainType; + @Getter @Setter private String worldName; + @Getter @Setter private String areaName; + @Getter @Setter private SettingsNodesWrapper settingsNodesWrapper; + +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java new file mode 100644 index 000000000..ffcb43cc5 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -0,0 +1,45 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.configuration.Captions; +import com.plotsquared.core.configuration.ConfigurationNode; +import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.util.MainUtil; +import lombok.Getter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public class SettingsNodeStep implements SetupStep { + @Getter private final ConfigurationNode configurationNode; + @Getter private final int id; + private final SettingsNodesWrapper wrapper; + + public SettingsNodeStep(ConfigurationNode configurationNode, int id, SettingsNodesWrapper wrapper) { + this.configurationNode = configurationNode; + this.id = id; + this.wrapper = wrapper; + } + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + if (this.configurationNode.isValid(argument)) { + this.configurationNode.setValue(argument); + } + return wrapper.next(); + } + + @NotNull @Override public Collection getSuggestions() { + return this.configurationNode.getSuggestions(); + } + + @Nullable @Override public String getDefaultValue() { + return String.valueOf(this.configurationNode.getDefaultValue()); + } + + @Override + public void announce(PlotPlayer plotPlayer) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_STEP, this.getId() + 1, + this.configurationNode.getDescription(), this.configurationNode.getType().getType(), + String.valueOf(this.configurationNode.getDefaultValue())); + } +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java new file mode 100644 index 000000000..896419ddb --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java @@ -0,0 +1,27 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.configuration.ConfigurationNode; + +public class SettingsNodesWrapper { + private final ConfigurationNode[] settingsNodes; + private int current; + + public SettingsNodesWrapper(ConfigurationNode[] settingsNodes) { + this.settingsNodes = settingsNodes; + this.current = 0; + } + + + public SettingsNodeStep next() { + if (this.settingsNodes.length <= this.current) { + throw new IllegalStateException("No step left"); + } else { + int temp = this.current; + this.current++; + return new SettingsNodeStep(this.settingsNodes[temp], temp, this); + } + } + public boolean hasNext() { + return this.current < this.settingsNodes.length; + } +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java new file mode 100644 index 000000000..721f427ec --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java @@ -0,0 +1,34 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.player.PlotPlayer; + +import java.util.ArrayDeque; +import java.util.Queue; + +public class SetupProcess { + private final PlotAreaBuilder builder; + private final Queue history; + private SetupStep current; + + public SetupProcess() { + this.builder = new PlotAreaBuilder(); + this.history = new ArrayDeque<>(); + this.current = CommonSetupSteps.GENERATOR; + } + + public SetupStep getCurrentStep() { + return this.current; + } + + public void handleInput(PlotPlayer plotPlayer, String argument) { + // TODO null check? + this.current = this.current.handleInput(plotPlayer, this.builder, argument); + } + + public void back() { + if (!this.history.isEmpty()) { + this.current.onBack(this.builder); + this.current = this.history.poll(); + } + } +} diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java new file mode 100644 index 000000000..ef7908cf9 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java @@ -0,0 +1,40 @@ +package com.plotsquared.core.setup; + +import com.plotsquared.core.player.PlotPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public interface SetupStep { + + /** + * Handles the input for this setup step. + * + * @param plotPlayer the plot player executing the command + * @param builder the plot area builder to work on + * @param argument the argument given as input + * @return the next step if input was valid, this setup step otherwise + */ + SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument); + + @NotNull Collection getSuggestions(); + + @Nullable String getDefaultValue(); + + /** + * Announces this step to the player. + * + * @param plotPlayer the player to announce this step to. + */ + void announce(PlotPlayer plotPlayer); + + /** + * This method is called when the SetupProcess reverts to a previous step. + * + * @param builder the builder associated with the setup process. + */ + default void onBack(PlotAreaBuilder builder) { + + } +} From b15c48e07481286c48bd2890fe7024999f7cc35a Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Tue, 2 Jun 2020 18:28:14 +0200 Subject: [PATCH 082/121] Implement setup steps --- .../com/plotsquared/core/command/Setup.java | 43 ++++- .../core/configuration/Captions.java | 6 + .../core/setup/CommonSetupSteps.java | 150 +++++++++++++++--- .../core/setup/PlotAreaBuilder.java | 21 +++ .../core/setup/SettingsNodeStep.java | 2 +- .../core/setup/SettingsNodesWrapper.java | 7 +- .../plotsquared/core/setup/SetupProcess.java | 16 +- .../com/plotsquared/core/setup/SetupStep.java | 2 +- .../com/plotsquared/core/util/SetupUtils.java | 3 + 9 files changed, 216 insertions(+), 34 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Setup.java b/Core/src/main/java/com/plotsquared/core/command/Setup.java index c01f604f9..97aa5350e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Setup.java +++ b/Core/src/main/java/com/plotsquared/core/command/Setup.java @@ -29,6 +29,7 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.configuration.ConfigurationUtil; +import com.plotsquared.core.configuration.StaticCaption; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.player.PlotPlayer; @@ -38,6 +39,8 @@ import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.plot.message.PlotMessage; +import com.plotsquared.core.setup.SetupProcess; +import com.plotsquared.core.setup.SetupStep; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; @@ -91,6 +94,42 @@ public class Setup extends SubCommand { } @Override public boolean onCommand(PlotPlayer player, String[] args) { + SetupProcess process = player.getMeta("setup"); + if (process == null) { + if (args.length > 0) { + // TODO use old behaviour? + MainUtil.sendMessage(player, "Use /plot setup to start the setup"); + return true; + } + process = new SetupProcess(); + player.setMeta("setup", process); + SetupUtils.manager.updateGenerators(); + com.plotsquared.core.setup.SetupStep step = process.getCurrentStep(); + // TODO generalize? + step.announce(player); + displayGenerators(player); + return true; + } + if (args.length == 1) { + if ("back".equalsIgnoreCase(args[0])) { + process.back(); + process.getCurrentStep().announce(player); + } else if ("cancel".equalsIgnoreCase(args[0])) { + player.deleteMeta("setup"); + } else { + process.handleInput(player, args[0]); + } + return true; + } else { + process.getCurrentStep().announce(player); + // TODO return only + if (true) { + return true; + } + } + + + // going through setup SetupObject object = player.getMeta("setup"); if (object == null) { @@ -354,7 +393,7 @@ public class Setup extends SubCommand { } - private static final class StepPickGenerator extends SetupStep { + /*private static final class StepPickGenerator extends SetupStep { @Getter private String generator; @@ -481,6 +520,6 @@ public class Setup extends SubCommand { } } - } + }*/ } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 26515db06..778423635 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -319,6 +319,7 @@ public enum Captions implements Caption { REMOVED_GRANTED_PLOT("$2You used %s0 plot grant(s), you've got $1%s1 $2left", "Economy"), // // + SETUP_NOT_STARTED("$7No setup started. Use $2/plot setup $7to start a setup process.", "Setup"), SETUP_INIT("$1Usage: $2/plot setup ", "Setup"), SETUP_STEP("$3[$1Step %s0$3] $1%s1 $2- $1Expecting: $2%s2 $1Default: $2%s3", "Setup"), SETUP_INVALID_ARG("$2%s0 is not a valid argument for step %s1. To cancel setup use: $1/plot setup cancel", "Setup"), @@ -357,6 +358,11 @@ public enum Captions implements Caption { SETUP_AREA_MAX_PLOT_ID_ERROR("$7You must choose a valid maximum Plot Id!", "Setup"), SETUP_AREA_PLOT_ID_GREATER_THAN_MINIMUM("$7The max PlotId must be greater than the minimum!", "Setup"), // + // + PLOT_AREA_TYPE_NORMAL("Standard plot generation", "PlotAreaType"), + PLOT_AREA_TYPE_AUGMENTED("Plot generation with vanilla terrain", "PlotAreaType"), + PLOT_AREA_TYPE_PARTIAL("Vanilla with clusters of plots", "PlotAreaType"), + // // SCHEMATIC_TOO_LARGE("$2The plot is too large for this action!", "Schematics"), SCHEMATIC_MISSING_ARG("$2You need to specify an argument. Possible values: $1save$2, $1paste $2, $1exportall$2, $1list", "Schematics"), diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java index 0908b250c..34869d15f 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -4,13 +4,17 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Caption; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.ConfigurationNode; +import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.StringMan; +import com.plotsquared.core.util.WorldUtil; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,7 +28,7 @@ import java.util.stream.Collectors; import static com.plotsquared.core.util.MainUtil.sendMessage; public enum CommonSetupSteps implements SetupStep { - GENERATOR(Captions.SETUP_INIT) { + CHOOSE_GENERATOR(Captions.SETUP_INIT) { @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { if (!SetupUtils.generators.containsKey(arg)) { @@ -38,18 +42,19 @@ public enum CommonSetupSteps implements SetupStep { } builder.generatorName(arg); sendMessage(plotPlayer, Captions.SETUP_WORLD_TYPE); - return CommonSetupSteps.PLOT_AREA_TYPE; // proceed with next step + return CommonSetupSteps.CHOOSE_PLOT_AREA_TYPE; // proceed with next step } - @Override public @NotNull Collection getSuggestions() { + @NotNull @Override public Collection getSuggestions() { return Collections.unmodifiableSet(SetupUtils.generators.keySet()); } - @Override @Nullable public String getDefaultValue() { + @Nullable @Override public String getDefaultValue() { return PlotSquared.imp().getPluginName(); } }, - PLOT_AREA_TYPE(PlotAreaType.class, Captions.SETUP_WORLD_TYPE) { + CHOOSE_PLOT_AREA_TYPE(PlotAreaType.class, Captions.SETUP_WORLD_TYPE) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { boolean withNormal = SetupUtils.generators.get(builder.generatorName()).isFull(); Optional plotAreaType = PlotAreaType.fromString(arg); @@ -78,7 +83,7 @@ public enum CommonSetupSteps implements SetupStep { if (!builder.settingsNodesWrapper().hasNext()) { // MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME); // object.setup_index = 0; TODO what did that do? - return WORLD_NAME; // skip + return CHOOSE_WORLD_NAME; // skip } SettingsNodeStep next = builder.settingsNodesWrapper().next(); ConfigurationNode step = next.getConfigurationNode(); @@ -105,7 +110,7 @@ public enum CommonSetupSteps implements SetupStep { return null; } else { // MainUtil.sendMessage(plotPlayer, Captions.SETUP_PARTIAL_AREA); - return TERRAIN_TYPE; + return CHOOSE_TERRAIN_TYPE; } } } @@ -114,19 +119,116 @@ public enum CommonSetupSteps implements SetupStep { return PlotAreaType.NORMAL.toString(); // TODO toLowerCase here? } }, - TERRAIN_TYPE(PlotAreaTerrainType.class, Captions.SETUP_PARTIAL_AREA) { - @Override - public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { - return null; + CHOOSE_AREA_ID(Captions.SETUP_AREA_NAME) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + if (!StringMan.isAlphanumericUnd(argument)) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_NON_ALPHANUMERICAL); + return this; + } + for (PlotArea area : PlotSquared.get().getPlotAreas()) { + if (area.getId() != null && area.getId().equalsIgnoreCase(argument)) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_INVALID_ID); + return this; + } + } + builder.areaName(argument); + return CHOOSE_MINIMUM_PLOT_ID; } - @Override - public @Nullable String getDefaultValue() { + @Nullable @Override public String getDefaultValue() { + return null; + } + }, + CHOOSE_MINIMUM_PLOT_ID(Captions.SETUP_AREA_MIN_PLOT_ID) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + try { + builder.minimumId(PlotId.fromString(argument)); + } catch (IllegalArgumentException ignored) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_MIN_PLOT_ID_ERROR); + return this; + } catch (IllegalStateException ignored) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_PLOT_ID_GREATER_THAN_MINIMUM); + return this; + } + return CHOOSE_MAXIMUM_PLOT_ID; + } + + @Override public String getDefaultValue() { + return "0;0"; + } + }, + CHOOSE_MAXIMUM_PLOT_ID(Captions.SETUP_AREA_MAX_PLOT_ID) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + try { + builder.maximumId(PlotId.fromString(argument)); + } catch (IllegalArgumentException ignored) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_MAX_PLOT_ID_ERROR); + return this; + } catch (IllegalStateException ignored) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_PLOT_ID_GREATER_THAN_MINIMUM); + return this; + } + return CHOOSE_TERRAIN_TYPE; + } + + @Override public String getDefaultValue() { + return "0;0"; + } + }, + CHOOSE_TERRAIN_TYPE(PlotAreaTerrainType.class, Captions.SETUP_PARTIAL_AREA) { + + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + Optional optTerrain; + if (!(optTerrain = PlotAreaTerrainType.fromString(argument)) + .isPresent()) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_PARTIAL_AREA_ERROR, Captions.SETUP_PARTIAL_AREA); + return this; + } + builder.terrainType(optTerrain.get()); + if (builder.settingsNodesWrapper() == null) { + builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); + } + SettingsNodesWrapper wrapper = builder.settingsNodesWrapper(); + // TODO return CHOOSE_WORLD_NAME if !hasNext + return wrapper.hasNext() ? wrapper.next() : wrapper.getAfterwards(); + } + + @Nullable @Override public String getDefaultValue() { return PlotAreaTerrainType.NONE.toString(); // TODO toLowerCase here? } }, - WORLD_NAME(Captions.SETUP_WORLD_NAME) { + CHOOSE_WORLD_NAME(Captions.SETUP_WORLD_NAME) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + if (!isValidWorldName(argument)) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME_FORMAT + argument); + return this; + } + if (WorldUtil.IMP.isWorld(argument)) { + if (PlotSquared.get().hasPlotArea(argument)) { + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME_TAKEN); + return this; + } + MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_APPLY_PLOTSQUARED); + } + builder.worldName(argument); + plotPlayer.deleteMeta("setup"); + String world; + if (builder.setupManager() == null) { + world = SetupUtils.manager.setupWorld(builder); + } else { + world = builder.setupManager().setupWorld(builder); + } + try { + plotPlayer.teleport(WorldUtil.IMP.getSpawn(world), TeleportCause.COMMAND); + } catch (Exception e) { + plotPlayer.sendMessage("&cAn error occurred. See console for more information"); + e.printStackTrace(); + } + sendMessage(plotPlayer, Captions.SETUP_FINISHED, builder.worldName()); return null; } @@ -143,21 +245,24 @@ public enum CommonSetupSteps implements SetupStep { * @param suggestions the input suggestions for this step * @param description the caption describing this step */ - CommonSetupSteps(@NotNull Collection suggestions, Caption description) { + CommonSetupSteps(@NotNull Collection suggestions, @NotNull Caption description) { this.suggestions = suggestions; this.description = description; } - CommonSetupSteps(Caption description) { + CommonSetupSteps(@NotNull Caption description) { this.description = description; this.suggestions = Collections.emptyList(); } - > CommonSetupSteps(Class argumentType, Caption description) { + > CommonSetupSteps(@NotNull Class argumentType, Caption description) { this(enumToStrings(argumentType), description); } - + @Override + public void announce(PlotPlayer plotPlayer) { + MainUtil.sendMessage(plotPlayer, this.description); + } private static > Collection enumToStrings(Class type) { return Arrays.stream(type.getEnumConstants()).map(e -> e.toString().toLowerCase()).collect(Collectors.toList()); @@ -166,11 +271,12 @@ public enum CommonSetupSteps implements SetupStep { private static SettingsNodesWrapper wrap(String plotManager) { return new SettingsNodesWrapper(SetupUtils.generators.get(plotManager).getPlotGenerator() .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) - .getSettingNodes()); + .getSettingNodes(), CHOOSE_WORLD_NAME); } - @Override - public void announce(PlotPlayer plotPlayer) { - MainUtil.sendMessage(plotPlayer, this.description); + private static boolean isValidWorldName(String s) { + return s.chars().allMatch((i) -> { + return i == 95 || i == 45 || i >= 97 && i <= 122 || i >= 48 && i <= 57 || i == 46; + }); } } diff --git a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java index fe4f755c1..956a5f847 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java +++ b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java @@ -3,6 +3,8 @@ package com.plotsquared.core.setup; import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; +import com.plotsquared.core.plot.PlotId; +import com.plotsquared.core.util.SetupUtils; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; @@ -15,6 +17,25 @@ public class PlotAreaBuilder { @Getter @Setter private PlotAreaTerrainType terrainType; @Getter @Setter private String worldName; @Getter @Setter private String areaName; + @Getter private PlotId minimumId; + @Getter private PlotId maximumId; @Getter @Setter private SettingsNodesWrapper settingsNodesWrapper; + @Getter @Setter private SetupUtils setupManager; + + public void minimumId(PlotId minimumId) { + if (this.maximumId != null + && (minimumId.getX() >= this.maximumId.getX() || minimumId.getY() >= this.maximumId.getY())) { + throw new IllegalStateException("minId >= maxId"); + } + this.minimumId = minimumId; + } + + public void maximumId(PlotId maximumId) { + if (this.minimumId != null + && (this.minimumId.getX() <= maximumId.getX() || this.minimumId.getY() <= maximumId.getY())) { + throw new IllegalStateException("maxId <= minId"); + } + this.maximumId = maximumId; + } } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java index ffcb43cc5..b4f4a94c5 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -25,7 +25,7 @@ public class SettingsNodeStep implements SetupStep { if (this.configurationNode.isValid(argument)) { this.configurationNode.setValue(argument); } - return wrapper.next(); + return this.wrapper.hasNext() ? wrapper.next() : wrapper.getAfterwards(); } @NotNull @Override public Collection getSuggestions() { diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java index 896419ddb..a967d8ea1 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java @@ -1,13 +1,16 @@ package com.plotsquared.core.setup; import com.plotsquared.core.configuration.ConfigurationNode; +import lombok.Getter; public class SettingsNodesWrapper { - private final ConfigurationNode[] settingsNodes; + @Getter private final ConfigurationNode[] settingsNodes; + @Getter private final SetupStep afterwards; private int current; - public SettingsNodesWrapper(ConfigurationNode[] settingsNodes) { + public SettingsNodesWrapper(ConfigurationNode[] settingsNodes, SetupStep afterwards) { this.settingsNodes = settingsNodes; + this.afterwards = afterwards; this.current = 0; } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java index 721f427ec..0086189ce 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java @@ -2,18 +2,17 @@ package com.plotsquared.core.setup; import com.plotsquared.core.player.PlotPlayer; -import java.util.ArrayDeque; -import java.util.Queue; +import java.util.Stack; public class SetupProcess { private final PlotAreaBuilder builder; - private final Queue history; + private final Stack history; private SetupStep current; public SetupProcess() { this.builder = new PlotAreaBuilder(); - this.history = new ArrayDeque<>(); - this.current = CommonSetupSteps.GENERATOR; + this.history = new Stack<>(); + this.current = CommonSetupSteps.CHOOSE_GENERATOR; } public SetupStep getCurrentStep() { @@ -21,14 +20,19 @@ public class SetupProcess { } public void handleInput(PlotPlayer plotPlayer, String argument) { + SetupStep previous = this.current; // TODO null check? this.current = this.current.handleInput(plotPlayer, this.builder, argument); + // push previous step into history + if (this.current != previous && this.current != null) { + this.history.push(previous); + } } public void back() { if (!this.history.isEmpty()) { this.current.onBack(this.builder); - this.current = this.history.poll(); + this.current = this.history.pop(); } } } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java index ef7908cf9..787c4ac03 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java @@ -16,7 +16,7 @@ public interface SetupStep { * @param argument the argument given as input * @return the next step if input was valid, this setup step otherwise */ - SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument); + SetupStep handleInput(final PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument); @NotNull Collection getSuggestions(); diff --git a/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java b/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java index 477c99715..73e6ccfaa 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java +++ b/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java @@ -28,6 +28,7 @@ package com.plotsquared.core.util; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.SetupObject; +import com.plotsquared.core.setup.PlotAreaBuilder; import java.util.HashMap; @@ -43,5 +44,7 @@ public abstract class SetupUtils { public abstract String setupWorld(final SetupObject object); + public abstract String setupWorld(final PlotAreaBuilder builder); + public abstract void unload(String world, boolean save); } From 5165c439fc5b3a9468bb72d99c700146a3260c7a Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Wed, 3 Jun 2020 01:50:10 +0200 Subject: [PATCH 083/121] Add tab completion and fix minor bugs --- .../bukkit/util/BukkitSetupUtils.java | 115 ++++++++++++++++++ .../plotsquared/bukkit/util/BukkitUtil.java | 2 +- .../com/plotsquared/core/command/Setup.java | 20 ++- .../core/setup/CommonSetupSteps.java | 41 ++----- .../core/setup/PlotAreaBuilder.java | 2 +- .../core/setup/SettingsNodeStep.java | 24 +++- .../plotsquared/core/setup/SetupProcess.java | 2 +- .../com/plotsquared/core/setup/SetupStep.java | 25 +++- .../plotsquared/core/util/TabCompletions.java | 20 +++ 9 files changed, 213 insertions(+), 38 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitSetupUtils.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitSetupUtils.java index af529c251..ce893aeee 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitSetupUtils.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitSetupUtils.java @@ -33,6 +33,7 @@ import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.SetupObject; +import com.plotsquared.core.setup.PlotAreaBuilder; import com.plotsquared.core.util.SetupUtils; import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; @@ -209,6 +210,120 @@ public class BukkitSetupUtils extends SetupUtils { return object.world; } + @Override + public String setupWorld(PlotAreaBuilder builder) { + SetupUtils.manager.updateGenerators(); + ConfigurationNode[] steps = builder.settingsNodesWrapper() == null ? + new ConfigurationNode[0] : builder.settingsNodesWrapper().getSettingsNodes(); + String world = builder.worldName(); + PlotAreaType type = builder.plotAreaType(); + String worldPath = "worlds." + builder.worldName(); + switch (type) { + case PARTIAL: { + if (builder.areaName() != null) { + if (!PlotSquared.get().worlds.contains(worldPath)) { + PlotSquared.get().worlds.createSection(worldPath); + } + ConfigurationSection worldSection = + PlotSquared.get().worlds.getConfigurationSection(worldPath); + String areaName = builder.areaName() + "-" + builder.minimumId() + "-" + builder.maximumId(); + String areaPath = "areas." + areaName; + if (!worldSection.contains(areaPath)) { + worldSection.createSection(areaPath); + } + ConfigurationSection areaSection = + worldSection.getConfigurationSection(areaPath); + HashMap options = new HashMap<>(); + for (ConfigurationNode step : steps) { + options.put(step.getConstant(), step.getValue()); + } + options.put("generator.type", builder.plotAreaType().toString()); + options.put("generator.terrain", builder.terrainType().toString()); + options.put("generator.plugin", builder.plotManager()); + if (builder.generatorName() != null && !builder.generatorName() + .equals(builder.plotManager())) { + options.put("generator.init", builder.generatorName()); + } + for (Entry entry : options.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (worldSection.contains(key)) { + Object current = worldSection.get(key); + if (!Objects.equals(value, current)) { + areaSection.set(key, value); + } + } else { + worldSection.set(key, value); + } + } + } + GeneratorWrapper gen = SetupUtils.generators.get(builder.generatorName()); + if (gen != null && gen.isFull()) { + builder.generatorName(null); + } + break; + } + case AUGMENTED: { + if (!builder.plotManager().endsWith(":single")) { + if (!PlotSquared.get().worlds.contains(worldPath)) { + PlotSquared.get().worlds.createSection(worldPath); + } + if (steps.length != 0) { + ConfigurationSection worldSection = + PlotSquared.get().worlds.getConfigurationSection(worldPath); + for (ConfigurationNode step : steps) { + worldSection.set(step.getConstant(), step.getValue()); + } + } + PlotSquared.get().worlds + .set("worlds." + world + ".generator.type", builder.plotAreaType().toString()); + PlotSquared.get().worlds + .set("worlds." + world + ".generator.terrain", builder.terrainType().toString()); + PlotSquared.get().worlds + .set("worlds." + world + ".generator.plugin", builder.plotManager()); + if (builder.generatorName() != null && !builder.generatorName() + .equals(builder.plotManager())) { + PlotSquared.get().worlds + .set("worlds." + world + ".generator.init", builder.generatorName()); + } + } + GeneratorWrapper gen = SetupUtils.generators.get(builder.generatorName()); + if (gen != null && gen.isFull()) { + builder.generatorName(null); + } + break; + } + case NORMAL: { + if (steps.length != 0) { + if (!PlotSquared.get().worlds.contains(worldPath)) { + PlotSquared.get().worlds.createSection(worldPath); + } + ConfigurationSection worldSection = + PlotSquared.get().worlds.getConfigurationSection(worldPath); + for (ConfigurationNode step : steps) { + worldSection.set(step.getConstant(), step.getValue()); + } + } + break; + } + } + + try { + PlotSquared.get().worlds.save(PlotSquared.get().worldsFile); + } catch (IOException e) { + e.printStackTrace(); + } + + Objects.requireNonNull(PlotSquared.imp()).getWorldManager() + .handleWorldCreation(builder.worldName(), builder.generatorName()); + + if (Bukkit.getWorld(world) != null) { + return world; + } + + return builder.worldName(); + } + @Override public String getGenerator(PlotArea plotArea) { if (SetupUtils.generators.isEmpty()) { updateGenerators(); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index b21301251..b771c5e45 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -270,7 +270,7 @@ public class BukkitUtil extends WorldUtil { return lastPlotPlayer; } final PlayerManager playerManager = PlotSquared.imp().getPlayerManager(); - return ((BukkitPlayerManager) player).getPlayer(player); + return ((BukkitPlayerManager) playerManager).getPlayer(player); } public static Location getLocation(@NonNull final org.bukkit.Location location) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Setup.java b/Core/src/main/java/com/plotsquared/core/command/Setup.java index 97aa5350e..db3d750bd 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Setup.java +++ b/Core/src/main/java/com/plotsquared/core/command/Setup.java @@ -57,6 +57,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -98,14 +99,13 @@ public class Setup extends SubCommand { if (process == null) { if (args.length > 0) { // TODO use old behaviour? - MainUtil.sendMessage(player, "Use /plot setup to start the setup"); + MainUtil.sendMessage(player, Captions.SETUP_NOT_STARTED); return true; } process = new SetupProcess(); player.setMeta("setup", process); SetupUtils.manager.updateGenerators(); com.plotsquared.core.setup.SetupStep step = process.getCurrentStep(); - // TODO generalize? step.announce(player); displayGenerators(player); return true; @@ -116,8 +116,12 @@ public class Setup extends SubCommand { process.getCurrentStep().announce(player); } else if ("cancel".equalsIgnoreCase(args[0])) { player.deleteMeta("setup"); + MainUtil.sendMessage(player, Captions.SETUP_CANCELLED); } else { process.handleInput(player, args[0]); + if (process.getCurrentStep() != null) { + process.getCurrentStep().announce(player); + } } return true; } else { @@ -392,6 +396,18 @@ public class Setup extends SubCommand { return false; } + @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { + SetupProcess process = (SetupProcess) player.getMeta("setup"); // TODO use generics -> auto cast + if (process == null) { + return Collections.emptyList(); + } + // player already provided too many arguments + if (args.length > 1 || (args.length == 1 && space)) { + return Collections.emptyList(); + } + SetupStep setupStep = process.getCurrentStep(); + return setupStep.createSuggestions(player, space ? "" : args[0]); + } /*private static final class StepPickGenerator extends SetupStep { diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java index 34869d15f..4b0a6c7a6 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -3,7 +3,6 @@ package com.plotsquared.core.setup; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Caption; import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.player.PlotPlayer; @@ -30,18 +29,16 @@ import static com.plotsquared.core.util.MainUtil.sendMessage; public enum CommonSetupSteps implements SetupStep { CHOOSE_GENERATOR(Captions.SETUP_INIT) { - @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { if (!SetupUtils.generators.containsKey(arg)) { String prefix = "\n&8 - &7"; sendMessage(plotPlayer, Captions.SETUP_WORLD_GENERATOR_ERROR + prefix + StringMan .join(SetupUtils.generators.keySet(), prefix) .replaceAll(PlotSquared.imp().getPluginName(), "&2" + PlotSquared.imp().getPluginName())); - sendMessage(plotPlayer, Captions.SETUP_INIT); return this; // invalid input -> same setup step } builder.generatorName(arg); - sendMessage(plotPlayer, Captions.SETUP_WORLD_TYPE); return CommonSetupSteps.CHOOSE_PLOT_AREA_TYPE; // proceed with next step } @@ -55,7 +52,7 @@ public enum CommonSetupSteps implements SetupStep { }, CHOOSE_PLOT_AREA_TYPE(PlotAreaType.class, Captions.SETUP_WORLD_TYPE) { - @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String arg) { boolean withNormal = SetupUtils.generators.get(builder.generatorName()).isFull(); Optional plotAreaType = PlotAreaType.fromString(arg); if (!plotAreaType.isPresent()) { @@ -71,7 +68,6 @@ public enum CommonSetupSteps implements SetupStep { return this; } builder.plotAreaType(plotAreaType.get()); - // object.type = plotAreaType.get(); GeneratorWrapper gen = SetupUtils.generators.get(builder.generatorName()); if (builder.plotAreaType() == PlotAreaType.NORMAL) { if (builder.settingsNodesWrapper() == null) { @@ -81,16 +77,10 @@ public enum CommonSetupSteps implements SetupStep { // .processSetup(process); } if (!builder.settingsNodesWrapper().hasNext()) { - // MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME); // object.setup_index = 0; TODO what did that do? - return CHOOSE_WORLD_NAME; // skip + return builder.settingsNodesWrapper().getAfterwards(); // skip } - SettingsNodeStep next = builder.settingsNodesWrapper().next(); - ConfigurationNode step = next.getConfigurationNode(); - sendMessage(plotPlayer, Captions.SETUP_STEP, next.getId() + 1, - step.getDescription(), step.getType().getType(), - String.valueOf(step.getDefaultValue())); - return next; + return builder.settingsNodesWrapper().next(); } else { if (gen.isFull()) { builder.plotManager(builder.generatorName()); @@ -105,23 +95,20 @@ public enum CommonSetupSteps implements SetupStep { // TODO why is processSetup not called here? } if (builder.plotAreaType() == PlotAreaType.PARTIAL) { - // MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_NAME); - // TODO return step area id - return null; + return CHOOSE_AREA_ID; } else { - // MainUtil.sendMessage(plotPlayer, Captions.SETUP_PARTIAL_AREA); return CHOOSE_TERRAIN_TYPE; } } } @Nullable @Override public String getDefaultValue() { - return PlotAreaType.NORMAL.toString(); // TODO toLowerCase here? + return PlotAreaType.NORMAL.toString(); } }, CHOOSE_AREA_ID(Captions.SETUP_AREA_NAME) { - @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { if (!StringMan.isAlphanumericUnd(argument)) { MainUtil.sendMessage(plotPlayer, Captions.SETUP_AREA_NON_ALPHANUMERICAL); return this; @@ -142,7 +129,7 @@ public enum CommonSetupSteps implements SetupStep { }, CHOOSE_MINIMUM_PLOT_ID(Captions.SETUP_AREA_MIN_PLOT_ID) { - @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { try { builder.minimumId(PlotId.fromString(argument)); } catch (IllegalArgumentException ignored) { @@ -161,7 +148,7 @@ public enum CommonSetupSteps implements SetupStep { }, CHOOSE_MAXIMUM_PLOT_ID(Captions.SETUP_AREA_MAX_PLOT_ID) { - @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { try { builder.maximumId(PlotId.fromString(argument)); } catch (IllegalArgumentException ignored) { @@ -180,7 +167,7 @@ public enum CommonSetupSteps implements SetupStep { }, CHOOSE_TERRAIN_TYPE(PlotAreaTerrainType.class, Captions.SETUP_PARTIAL_AREA) { - @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { Optional optTerrain; if (!(optTerrain = PlotAreaTerrainType.fromString(argument)) .isPresent()) { @@ -192,17 +179,16 @@ public enum CommonSetupSteps implements SetupStep { builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); } SettingsNodesWrapper wrapper = builder.settingsNodesWrapper(); - // TODO return CHOOSE_WORLD_NAME if !hasNext return wrapper.hasNext() ? wrapper.next() : wrapper.getAfterwards(); } @Nullable @Override public String getDefaultValue() { - return PlotAreaTerrainType.NONE.toString(); // TODO toLowerCase here? + return PlotAreaTerrainType.NONE.toString(); } }, CHOOSE_WORLD_NAME(Captions.SETUP_WORLD_NAME) { - @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { if (!isValidWorldName(argument)) { MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_NAME_FORMAT + argument); return this; @@ -259,8 +245,7 @@ public enum CommonSetupSteps implements SetupStep { this(enumToStrings(argumentType), description); } - @Override - public void announce(PlotPlayer plotPlayer) { + @Override public void announce(PlotPlayer plotPlayer) { MainUtil.sendMessage(plotPlayer, this.description); } diff --git a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java index 956a5f847..c6c6ea494 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java +++ b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java @@ -32,7 +32,7 @@ public class PlotAreaBuilder { public void maximumId(PlotId maximumId) { if (this.minimumId != null - && (this.minimumId.getX() <= maximumId.getX() || this.minimumId.getY() <= maximumId.getY())) { + && (maximumId.getX() <= this.minimumId.getX() || maximumId.getY() <= this.minimumId.getY())) { throw new IllegalStateException("maxId <= minId"); } this.maximumId = maximumId; diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java index b4f4a94c5..55d78722d 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -1,14 +1,18 @@ package com.plotsquared.core.setup; +import com.plotsquared.core.command.Command; +import com.plotsquared.core.command.RequiredType; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.ConfigurationNode; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.TabCompletions; import lombok.Getter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; +import java.util.Collections; public class SettingsNodeStep implements SetupStep { @Getter private final ConfigurationNode configurationNode; @@ -21,7 +25,7 @@ public class SettingsNodeStep implements SetupStep { this.wrapper = wrapper; } - @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { + @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { if (this.configurationNode.isValid(argument)) { this.configurationNode.setValue(argument); } @@ -36,10 +40,24 @@ public class SettingsNodeStep implements SetupStep { return String.valueOf(this.configurationNode.getDefaultValue()); } - @Override - public void announce(PlotPlayer plotPlayer) { + @Override public void announce(PlotPlayer plotPlayer) { MainUtil.sendMessage(plotPlayer, Captions.SETUP_STEP, this.getId() + 1, this.configurationNode.getDescription(), this.configurationNode.getType().getType(), String.valueOf(this.configurationNode.getDefaultValue())); } + + @Override public Collection createSuggestions(PlotPlayer plotPlayer, String argument) { + switch (this.configurationNode.getType().getType()) { + case "BLOCK_BUCKET": + return TabCompletions.completePatterns(argument); + case "INTEGER": + if (getDefaultValue() != null && getDefaultValue().startsWith(argument)) { + return Collections.singletonList(new Command(null, false, + getDefaultValue(), "", RequiredType.NONE, null) {}); + } + case "BOOLEAN": + return TabCompletions.completeBoolean(argument); + } + return Collections.emptyList(); + } } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java index 0086189ce..93d7b9593 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java @@ -19,7 +19,7 @@ public class SetupProcess { return this.current; } - public void handleInput(PlotPlayer plotPlayer, String argument) { + public void handleInput(PlotPlayer plotPlayer, String argument) { SetupStep previous = this.current; // TODO null check? this.current = this.current.handleInput(plotPlayer, this.builder, argument); diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java index 787c4ac03..8ea5db0a0 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java @@ -1,10 +1,14 @@ package com.plotsquared.core.setup; +import com.plotsquared.core.command.Command; +import com.plotsquared.core.command.RequiredType; import com.plotsquared.core.player.PlotPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; public interface SetupStep { @@ -16,7 +20,7 @@ public interface SetupStep { * @param argument the argument given as input * @return the next step if input was valid, this setup step otherwise */ - SetupStep handleInput(final PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument); + SetupStep handleInput(final PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument); @NotNull Collection getSuggestions(); @@ -27,7 +31,24 @@ public interface SetupStep { * * @param plotPlayer the player to announce this step to. */ - void announce(PlotPlayer plotPlayer); + void announce(PlotPlayer plotPlayer); + + /** + * Creates a collection of suggestions for the current input. + * + * @param plotPlayer the player to receive the suggestions. + * @param argument the argument already typed. + * @return a collection of suggestions. + */ + default Collection createSuggestions(final PlotPlayer plotPlayer, String argument) { + List result = new ArrayList<>(getSuggestions().size()); + for (String suggestion : getSuggestions()) { + if (suggestion.startsWith(argument)) { + result.add(new Command(null, false, suggestion, "", RequiredType.NONE, null) {}); + } + } + return result; + } /** * This method is called when the SetupProcess reverts to a previous step. diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java index 0369ad730..91454b3bb 100644 --- a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java +++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java @@ -38,7 +38,9 @@ import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.concurrent.TimeUnit; @@ -53,6 +55,11 @@ public class TabCompletions { private final Cache> cachedCompletionValues = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); + private final Command booleanTrueCompletion = new Command(null, false, "true", "", + RequiredType.NONE, null) {}; + private final Command booleanFalseCompletion = new Command(null, false, "false", "", + RequiredType.NONE, null) {}; + /** * Get a list of tab completions corresponding to player names. This uses the UUID pipeline * cache, so it will complete will all names known to PlotSquared @@ -109,4 +116,17 @@ public class TabCompletions { }).collect(Collectors.toList()); } + @NotNull public List completeBoolean(@NotNull final String input) { + if (input.isEmpty()) { + return Arrays.asList(booleanTrueCompletion, booleanFalseCompletion); + } + if ("true".startsWith(input)) { + return Collections.singletonList(booleanTrueCompletion); + } + if ("false".startsWith(input)) { + return Collections.singletonList(booleanFalseCompletion); + } + return Collections.emptyList(); + } + } From ae1427b189aa3760f26930cd9e31b41f36d7837d Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Fri, 5 Jun 2020 02:19:37 +0200 Subject: [PATCH 084/121] Remove usage of SetupObject --- .../com/plotsquared/bukkit/BukkitMain.java | 19 +- .../com/plotsquared/core/command/Area.java | 62 ++- .../com/plotsquared/core/command/Setup.java | 439 +----------------- .../plotsquared/core/command/Template.java | 19 +- .../core/plot/world/SinglePlotArea.java | 21 +- .../core/setup/CommonSetupSteps.java | 6 +- .../core/setup/PlotAreaBuilder.java | 25 +- .../core/setup/SettingsNodeStep.java | 2 +- .../core/setup/SettingsNodesWrapper.java | 27 +- .../com/plotsquared/core/util/SetupUtils.java | 1 + 10 files changed, 114 insertions(+), 507 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index a9ec5b374..582f94746 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -81,12 +81,13 @@ import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotId; -import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.plot.message.PlainChatManager; import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.SinglePlotArea; import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.queue.QueueProvider; +import com.plotsquared.core.setup.PlotAreaBuilder; +import com.plotsquared.core.setup.SettingsNodesWrapper; import com.plotsquared.core.util.ChatManager; import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ConsoleColors; @@ -992,14 +993,14 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< ConfigurationSection worldConfig = PlotSquared.get().worlds.getConfigurationSection("worlds." + worldName); String manager = worldConfig.getString("generator.plugin", getPluginName()); - SetupObject setup = new SetupObject(); - setup.plotManager = manager; - setup.setupGenerator = worldConfig.getString("generator.init", manager); - setup.type = MainUtil.getType(worldConfig); - setup.terrain = MainUtil.getTerrain(worldConfig); - setup.step = new ConfigurationNode[0]; - setup.world = worldName; - SetupUtils.manager.setupWorld(setup); + PlotAreaBuilder builder = new PlotAreaBuilder() + .plotManager(manager) + .generatorName(worldConfig.getString("generator.init", manager)) + .plotAreaType(MainUtil.getType(worldConfig)) + .terrainType(MainUtil.getTerrain(worldConfig)) + .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)) + .worldName(worldName); + SetupUtils.manager.setupWorld(builder); world = Bukkit.getWorld(worldName); } else { try { diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index 7cdca5c6f..696cf1459 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -39,8 +39,8 @@ import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotId; -import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.plot.message.PlotMessage; +import com.plotsquared.core.setup.PlotAreaBuilder; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; @@ -186,20 +186,15 @@ public class Area extends SubCommand { final BlockVector3 singlePos1 = selectedRegion.getMinimumPoint(); // Now the schematic is saved, which is wonderful! - final SetupObject singleSetup = new SetupObject(); - singleSetup.world = hybridPlotWorld.getWorldName(); - singleSetup.id = hybridPlotWorld.getId(); - singleSetup.terrain = hybridPlotWorld.getTerrain(); - singleSetup.type = hybridPlotWorld.getType(); - singleSetup.plotManager = PlotSquared.imp().getPluginName(); - singleSetup.setupGenerator = PlotSquared.imp().getPluginName(); - singleSetup.step = hybridPlotWorld.getSettingNodes(); - singleSetup.max = plotId; - singleSetup.min = plotId; + PlotAreaBuilder singleBuilder = PlotAreaBuilder.ofPlotArea(hybridPlotWorld) + .plotManager(PlotSquared.imp().getPluginName()) + .generatorName(PlotSquared.imp().getPluginName()) + .maximumId(plotId) + .minimumId(plotId); // TODO will throw exception right now Runnable singleRun = () -> { final String path = "worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld.getId() + '-' - + singleSetup.min + '-' + singleSetup.max; + + singleBuilder.minimumId() + '-' + singleBuilder.maximumId(); final int offsetX = singlePos1.getX(); final int offsetZ = singlePos1.getZ(); if (offsetX != 0) { @@ -210,7 +205,7 @@ public class Area extends SubCommand { PlotSquared.get().worlds .set(path + ".road.offset.z", offsetZ); } - final String world = SetupUtils.manager.setupWorld(singleSetup); + final String world = SetupUtils.manager.setupWorld(singleBuilder); if (WorldUtil.IMP.isWorld(world)) { PlotSquared.get().loadWorld(world, null); MainUtil.sendMessage(player, Captions.SINGLE_AREA_CREATED); @@ -286,19 +281,14 @@ public class Area extends SubCommand { .send(player, areas.iterator().next().toString()); return false; } - final SetupObject object = new SetupObject(); - object.world = area.getWorldName(); - object.id = area.getId(); - object.terrain = area.getTerrain(); - object.type = area.getType(); - object.min = new PlotId(1, 1); - object.max = new PlotId(numX, numZ); - object.plotManager = PlotSquared.imp().getPluginName(); - object.setupGenerator = PlotSquared.imp().getPluginName(); - object.step = area.getSettingNodes(); + PlotAreaBuilder builder = PlotAreaBuilder.ofPlotArea(area) + .plotManager(PlotSquared.imp().getPluginName()) + .generatorName(PlotSquared.imp().getPluginName()) + .minimumId(new PlotId(1, 1)) + .maximumId(new PlotId(numX, numZ)); final String path = "worlds." + area.getWorldName() + ".areas." + area.getId() + '-' - + object.min + '-' + object.max; + + builder.minimumId() + '-' + builder.maximumId(); Runnable run = () -> { if (offsetX != 0) { PlotSquared.get().worlds @@ -308,7 +298,7 @@ public class Area extends SubCommand { PlotSquared.get().worlds .set(path + ".road.offset.z", offsetZ); } - final String world = SetupUtils.manager.setupWorld(object); + final String world = SetupUtils.manager.setupWorld(builder); if (WorldUtil.IMP.isWorld(world)) { PlotSquared.get().loadWorld(world, null); Captions.SETUP_FINISHED.send(player); @@ -346,9 +336,9 @@ public class Area extends SubCommand { } else { id = null; } - final SetupObject object = new SetupObject(); - object.world = split[0]; - final HybridPlotWorld pa = new HybridPlotWorld(object.world, id, + PlotAreaBuilder builder = new PlotAreaBuilder(); + builder.worldName(split[0]); + final HybridPlotWorld pa = new HybridPlotWorld(builder.worldName(), id, PlotSquared.get().IMP.getDefaultGenerator(), null, null); PlotArea other = PlotSquared.get().getPlotArea(pa.getWorldName(), id); if (other != null && Objects.equals(pa.getId(), other.getId())) { @@ -410,13 +400,13 @@ public class Area extends SubCommand { pa.setTerrain(PlotAreaTerrainType.fromString(pair[1]) .orElseThrow(() -> new IllegalArgumentException( pair[1] + " is not a valid terrain."))); - object.terrain = pa.getTerrain(); + builder.terrainType(pa.getTerrain()); break; case "type": pa.setType(PlotAreaType.fromString(pair[1]).orElseThrow( () -> new IllegalArgumentException( pair[1] + " is not a valid type."))); - object.type = pa.getType(); + builder.plotAreaType(pa.getType()); break; default: Captions.COMMAND_SYNTAX.send(player, getCommandString() @@ -438,9 +428,9 @@ public class Area extends SubCommand { PlotSquared.get().worlds.getConfigurationSection(path); pa.saveConfiguration(section); pa.loadConfiguration(section); - object.plotManager = PlotSquared.imp().getPluginName(); - object.setupGenerator = PlotSquared.imp().getPluginName(); - String world = SetupUtils.manager.setupWorld(object); + builder.plotManager(PlotSquared.imp().getPluginName()); + builder.generatorName(PlotSquared.imp().getPluginName()); + String world = SetupUtils.manager.setupWorld(builder); if (WorldUtil.IMP.isWorld(world)) { Captions.SETUP_FINISHED.send(player); player.teleport(WorldUtil.IMP.getSpawn(world), @@ -475,9 +465,9 @@ public class Area extends SubCommand { TeleportCause.COMMAND); } } else { - object.terrain = PlotAreaTerrainType.NONE; - object.type = PlotAreaType.NORMAL; - SetupUtils.manager.setupWorld(object); + builder.terrainType(PlotAreaTerrainType.NONE); + builder.plotAreaType(PlotAreaType.NORMAL); + SetupUtils.manager.setupWorld(builder); player.teleport(WorldUtil.IMP.getSpawn(pa.getWorldName()), TeleportCause.COMMAND); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Setup.java b/Core/src/main/java/com/plotsquared/core/command/Setup.java index db3d750bd..238f1bd5a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Setup.java +++ b/Core/src/main/java/com/plotsquared/core/command/Setup.java @@ -27,43 +27,19 @@ package com.plotsquared.core.command; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; -import com.plotsquared.core.configuration.ConfigurationNode; -import com.plotsquared.core.configuration.ConfigurationUtil; -import com.plotsquared.core.configuration.StaticCaption; -import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.GeneratorWrapper; import com.plotsquared.core.player.PlotPlayer; -import com.plotsquared.core.plot.PlotArea; -import com.plotsquared.core.plot.PlotAreaTerrainType; -import com.plotsquared.core.plot.PlotAreaType; -import com.plotsquared.core.plot.PlotId; -import com.plotsquared.core.plot.SetupObject; -import com.plotsquared.core.plot.message.PlotMessage; import com.plotsquared.core.setup.SetupProcess; import com.plotsquared.core.setup.SetupStep; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SetupUtils; -import com.plotsquared.core.util.StringMan; -import com.plotsquared.core.util.WorldUtil; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.ToString; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Map.Entry; -import java.util.Optional; -import java.util.UUID; @CommandDeclaration(command = "setup", permission = "plots.admin.command.setup", @@ -72,14 +48,12 @@ import java.util.UUID; aliases = {"create"}, category = CommandCategory.ADMINISTRATION) public class Setup extends SubCommand { + private static final Collection specialCommands = Arrays.asList( + new Command(null, false, "back", "", RequiredType.NONE, null) {}, + new Command(null, false, "cancel", "", RequiredType.NONE, null) {}); - private static boolean d(String s) { - return s.chars().allMatch((i) -> { - return i == 95 || i == 45 || i >= 97 && i <= 122 || i >= 48 && i <= 57 || i == 46; - }); - } - public void displayGenerators(PlotPlayer player) { + public void displayGenerators(PlotPlayer player) { StringBuilder message = new StringBuilder(); message.append("&6What generator do you want?"); for (Entry> entry : SetupUtils.generators.entrySet()) { @@ -105,7 +79,7 @@ public class Setup extends SubCommand { process = new SetupProcess(); player.setMeta("setup", process); SetupUtils.manager.updateGenerators(); - com.plotsquared.core.setup.SetupStep step = process.getCurrentStep(); + SetupStep step = process.getCurrentStep(); step.announce(player); displayGenerators(player); return true; @@ -123,277 +97,11 @@ public class Setup extends SubCommand { process.getCurrentStep().announce(player); } } - return true; } else { process.getCurrentStep().announce(player); - // TODO return only - if (true) { - return true; - } } + return true; - - - // going through setup - SetupObject object = player.getMeta("setup"); - if (object == null) { - object = new SetupObject(); - player.setMeta("setup", object); - SetupUtils.manager.updateGenerators(); - sendMessage(player, Captions.SETUP_INIT); - displayGenerators(player); - return false; - } - if (args.length == 1) { - if (args[0].equalsIgnoreCase("cancel")) { - player.deleteMeta("setup"); - MainUtil.sendMessage(player, Captions.SETUP_CANCELLED); - return false; - } - if (args[0].equalsIgnoreCase("back")) { - if (object.setup_index > 0) { - object.setup_index--; - ConfigurationNode node = object.step[object.setup_index]; - sendMessage(player, Captions.SETUP_STEP, object.setup_index + 1, - node.getDescription(), node.getType().getType(), - String.valueOf(node.getDefaultValue())); - return false; - } else if (object.current > 0) { - object.current--; - } - } - } - int index = object.current; - switch (index) { - case 0: // choose generator - if (args.length != 1 || !SetupUtils.generators.containsKey(args[0])) { - String prefix = "\n&8 - &7"; - MainUtil.sendMessage(player, - Captions.SETUP_WORLD_GENERATOR_ERROR + prefix + StringMan - .join(SetupUtils.generators.keySet(), prefix) - .replaceAll(PlotSquared.imp().getPluginName(), - "&2" + PlotSquared.imp().getPluginName())); - sendMessage(player, Captions.SETUP_INIT); - return false; - } - object.setupGenerator = args[0]; - object.current++; - MainUtil.sendMessage(player, Captions.SETUP_WORLD_TYPE); - break; - case 1: // choose world type - List allTypes = Arrays.asList("normal", "augmented", "partial"); - List allDesc = Arrays - .asList("Standard plot generation", "Plot generation with vanilla terrain", - "Vanilla with clusters of plots"); - ArrayList types = new ArrayList<>(); - if (SetupUtils.generators.get(object.setupGenerator).isFull()) { - types.add("normal"); - } - types.add("augmented"); - types.add("partial"); - Optional plotAreaType; - if (args.length != 1 || !(plotAreaType = PlotAreaType.fromString(args[0])) - .isPresent()) { - MainUtil.sendMessage(player, Captions.SETUP_WORLD_TYPE_ERROR); - for (String type : types) { - int i = allTypes.indexOf(type); - if (type.equals("normal")) { - MainUtil - .sendMessage(player, "&8 - &2" + type + " &8-&7 " + allDesc.get(i)); - } else { - MainUtil - .sendMessage(player, "&8 - &7" + type + " &8-&7 " + allDesc.get(i)); - } - } - return false; - } - object.type = plotAreaType.orElse(PlotAreaType.NORMAL); - GeneratorWrapper gen = SetupUtils.generators.get(object.setupGenerator); - if (object.type == PlotAreaType.NORMAL) { - object.current = 6; - if (object.step == null) { - object.plotManager = object.setupGenerator; - object.step = - SetupUtils.generators.get(object.plotManager).getPlotGenerator() - .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) - .getSettingNodes(); - SetupUtils.generators.get(object.plotManager).getPlotGenerator() - .processSetup(object); - } - if (object.step.length == 0) { - MainUtil.sendMessage(player, Captions.SETUP_WORLD_NAME); - object.setup_index = 0; - return true; - } - ConfigurationNode step = object.step[object.setup_index]; - sendMessage(player, Captions.SETUP_STEP, object.setup_index + 1, - step.getDescription(), step.getType().getType(), - String.valueOf(step.getDefaultValue())); - } else { - if (gen.isFull()) { - object.plotManager = object.setupGenerator; - object.setupGenerator = null; - object.step = - SetupUtils.generators.get(object.plotManager).getPlotGenerator() - .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) - .getSettingNodes(); - SetupUtils.generators.get(object.plotManager).getPlotGenerator() - .processSetup(object); - } else { - object.plotManager = PlotSquared.imp().getPluginName(); - MainUtil.sendMessage(player, Captions.SETUP_WRONG_GENERATOR); - object.step = - SetupUtils.generators.get(object.plotManager).getPlotGenerator() - .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) - .getSettingNodes(); - } - if (object.type == PlotAreaType.PARTIAL) { - MainUtil.sendMessage(player, Captions.SETUP_AREA_NAME); - object.current++; - } else { - MainUtil.sendMessage(player, Captions.SETUP_PARTIAL_AREA); - object.current = 5; - } - } - break; - case 2: // area id - if (!StringMan.isAlphanumericUnd(args[0])) { - MainUtil.sendMessage(player, Captions.SETUP_AREA_NON_ALPHANUMERICAL); - return false; - } - for (PlotArea area : PlotSquared.get().getPlotAreas()) { - if (area.getId() != null && area.getId().equalsIgnoreCase(args[0])) { - MainUtil.sendMessage(player, Captions.SETUP_AREA_INVALID_ID); - return false; - } - } - object.id = args[0]; - object.current++; - MainUtil.sendMessage(player, Captions.SETUP_AREA_MIN_PLOT_ID); - break; - case 3: // min - try { - object.min = PlotId.fromString(args[0]); - } catch (IllegalArgumentException ignored) { - MainUtil.sendMessage(player, Captions.SETUP_AREA_MIN_PLOT_ID_ERROR); - return false; - } - object.current++; - MainUtil.sendMessage(player, Captions.SETUP_AREA_MAX_PLOT_ID); - break; - case 4: - // max - PlotId id; - try { - id = PlotId.fromString(args[0]); - } catch (IllegalArgumentException ignored) { - MainUtil.sendMessage(player, Captions.SETUP_AREA_MAX_PLOT_ID_ERROR); - return false; - } - if (id.x <= object.min.x || id.y <= object.min.y) { - MainUtil.sendMessage(player, Captions.SETUP_AREA_PLOT_ID_GREATER_THAN_MINIMUM); - return false; - } - object.max = id; - object.current++; - MainUtil.sendMessage(player, Captions.SETUP_PARTIAL_AREA); - break; - case 5: { // Choose terrain - Optional optTerrain; - if (args.length != 1 || !(optTerrain = PlotAreaTerrainType.fromString(args[0])) - .isPresent()) { - MainUtil.sendMessage(player, Captions.SETUP_PARTIAL_AREA_ERROR, - Captions.SETUP_PARTIAL_AREA); - return false; - } - object.terrain = optTerrain.get(); - object.current++; - if (object.step == null) { - object.step = SetupUtils.generators.get(object.plotManager).getPlotGenerator() - .getNewPlotArea("CheckingPlotSquaredGenerator", null, null, null) - .getSettingNodes(); - } - ConfigurationNode step = object.step[object.setup_index]; - sendMessage(player, Captions.SETUP_STEP, object.setup_index + 1, - step.getDescription(), step.getType().getType(), - String.valueOf(step.getDefaultValue())); - break; - } - case 6: // world setup - if (object.setup_index == object.step.length) { - MainUtil.sendMessage(player, Captions.SETUP_WORLD_NAME); - object.setup_index = 0; - object.current++; - return true; - } - ConfigurationNode step = object.step[object.setup_index]; - if (args.length < 1) { - sendMessage(player, Captions.SETUP_STEP, object.setup_index + 1, - step.getDescription(), step.getType().getType(), - String.valueOf(step.getDefaultValue())); - return false; - } - - boolean valid = false; - try { - valid = step.isValid(args[0]); - } catch (final ConfigurationUtil.UnsafeBlockException e) { - Captions.NOT_ALLOWED_BLOCK.send(player, e.getUnsafeBlock().toString()); - } - if (valid) { - step.setValue(args[0]); - Object value = step.getValue(); - sendMessage(player, Captions.SETUP_VALID_ARG, step.getConstant(), value); - object.setup_index++; - if (object.setup_index == object.step.length) { - onCommand(player, args); - return false; - } - step = object.step[object.setup_index]; - sendMessage(player, Captions.SETUP_STEP, object.setup_index + 1, - step.getDescription(), step.getType().getType(), - String.valueOf(step.getDefaultValue())); - return false; - } else { - sendMessage(player, Captions.SETUP_INVALID_ARG, args[0], step.getConstant()); - sendMessage(player, Captions.SETUP_STEP, object.setup_index + 1, - step.getDescription(), step.getType().getType(), - String.valueOf(step.getDefaultValue())); - return false; - } - case 7: - if (args.length != 1) { - MainUtil.sendMessage(player, Captions.SETUP_WORLD_NAME_ERROR); - return false; - } - if (!d(args[0])) { - MainUtil.sendMessage(player, Captions.SETUP_WORLD_NAME_FORMAT + args[0]); - return false; - } - if (WorldUtil.IMP.isWorld(args[0])) { - if (PlotSquared.get().hasPlotArea(args[0])) { - MainUtil.sendMessage(player, Captions.SETUP_WORLD_NAME_TAKEN); - return false; - } - MainUtil.sendMessage(player, Captions.SETUP_WORLD_APPLY_PLOTSQUARED); - } - object.world = args[0]; - player.deleteMeta("setup"); - String world; - if (object.setupManager == null) { - world = SetupUtils.manager.setupWorld(object); - } else { - world = object.setupManager.setupWorld(object); - } - try { - player.teleport(WorldUtil.IMP.getSpawn(world), TeleportCause.COMMAND); - } catch (Exception e) { - player.sendMessage("&cAn error occurred. See console for more information"); - e.printStackTrace(); - } - sendMessage(player, Captions.SETUP_FINISHED, object.world); - } - return false; } @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { @@ -406,136 +114,15 @@ public class Setup extends SubCommand { return Collections.emptyList(); } SetupStep setupStep = process.getCurrentStep(); - return setupStep.createSuggestions(player, space ? "" : args[0]); + List commands = new ArrayList<>(setupStep.createSuggestions(player, space ? "" : args[0])); + tryAddSubCommand("back", args[0], commands); + tryAddSubCommand("cancel", args[0], commands); + return commands; } - /*private static final class StepPickGenerator extends SetupStep { - - @Getter private String generator; - - public StepPickGenerator() { - super("generator"); - } - - @Override public Collection showDescriptionMessage() { - SetupUtils.manager.updateGenerators(); - final List messages = new ArrayList<>(); - messages.add(new PlotMessage("What generator do you want?").color("$6")); - for (Entry> entry : SetupUtils.generators.entrySet()) { - final PlotMessage plotMessage = new PlotMessage(" - ").color("$8"); - if (entry.getKey().equals(PlotSquared.imp().getPluginName())) { - plotMessage.text(entry.getKey()).color("$8").tooltip("Select this generator") - .color("$2").command("/plot setup generator " + entry.getKey()) - .text(" (Default Generator)").color("$7"); - } else if (entry.getValue().isFull()) { - plotMessage.text(entry.getKey()).color("$8").tooltip("Select this generator") - .color("$7").command("/plot setup generator " + entry.getKey()) - .text(" (Plot Generator)").color("$7"); - } else { - plotMessage.text(entry.getKey()).color("$8").tooltip("Select this generator") - .color("$7").command("/plot setup generator " + entry.getKey()) - .text(" (Unknown Structure)").color("$7"); - } - messages.add(plotMessage); - } - return messages; - } - - @Override public boolean parseInput(String input) { - this.generator = input.toLowerCase(); - return true; - } - - @Nullable @Override public String getDefault() { - return null; + private void tryAddSubCommand(String subCommand, String argument, List suggestions) { + if (!argument.isEmpty() && subCommand.startsWith(argument)) { + suggestions.add(new Command(null, false, subCommand, "", RequiredType.NONE, null) {}); } } - - - private static final class StepWorldType extends SetupStep { - - private static final Map WORLD_TYPES = new HashMap<>(); - - static { - WORLD_TYPES.put("default", "Standard plot generation"); - WORLD_TYPES.put("augmented", "Plot generation with vanilla terrain"); - WORLD_TYPES.put("partial", "Vanilla clusters of plots"); - } - - @Getter private String worldType; - - public StepWorldType() { - super("type"); - } - - @Override public Collection showDescriptionMessage() { - final List messages = new ArrayList<>(); - messages.add(new PlotMessage("What world type do you want?").color("$6")); - for (final Map.Entry worldType : WORLD_TYPES.entrySet()) { - messages.add(new PlotMessage(" - ").color("$8").text(worldType.getKey()) - .color(worldType.getKey().equals(getDefault()) ? "$2" : "$7") - .tooltip("Select this world type") - .command("/plot setup type " + worldType.getKey()) - .text(" (" + worldType.getValue() + ")").color("$7")); - } - return messages; - } - - @Override public boolean parseInput(String input) { - if (!WORLD_TYPES.containsKey(input.toLowerCase())) { - return false; - } - this.worldType = input.toLowerCase(); - return true; - } - - @Override public String getDefault() { - return "default"; - } - } - - - @ToString - @EqualsAndHashCode(of = "uuid") - @AllArgsConstructor - private static class SetupContext { - - private final UUID uuid; - - @Getter private String step; - - } - - - @RequiredArgsConstructor(access = AccessLevel.PROTECTED) - private abstract static class SetupStep { - - private final String stepName; - - public abstract Collection showDescriptionMessage(); - - public abstract boolean parseInput(String input); - - public final PlotMessage getUsage() { - return new PlotMessage("Usage: ").color("$1") - .text("/plot setup " + this.stepName + " ").color("$2").suggest( - "/plot setup " + this.stepName + (this.getDefault() != null ? - this.getDefault() : - "")); - } - - @Nullable public abstract String getDefault(); - - public void sendToPlayer(@NonNull final PlotPlayer plotPlayer) { - new PlotMessage("Setup Step: ").color("$6").text(this.stepName).color("$7") - .send(plotPlayer); - this.getUsage().send(plotPlayer); - this.showDescriptionMessage().forEach(plotMessage -> plotMessage.send(plotPlayer)); - if (this.getDefault() != null) { - new PlotMessage("Default: ").color("$6").text(this.getDefault()).color("$7"); - } - } - - }*/ - } diff --git a/Core/src/main/java/com/plotsquared/core/command/Template.java b/Core/src/main/java/com/plotsquared/core/command/Template.java index d19fbab51..02bc7af4d 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Template.java +++ b/Core/src/main/java/com/plotsquared/core/command/Template.java @@ -36,8 +36,9 @@ import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotManager; -import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.queue.GlobalBlockQueue; +import com.plotsquared.core.setup.PlotAreaBuilder; +import com.plotsquared.core.setup.SettingsNodesWrapper; import com.plotsquared.core.util.FileBytes; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SetupUtils; @@ -181,15 +182,15 @@ public class Template extends SubCommand { String manager = worldConfig.getString("generator.plugin", PlotSquared.imp().getPluginName()); String generator = worldConfig.getString("generator.init", manager); - SetupObject setup = new SetupObject(); - setup.type = MainUtil.getType(worldConfig); - setup.terrain = MainUtil.getTerrain(worldConfig); + PlotAreaBuilder builder = new PlotAreaBuilder() + .plotAreaType(MainUtil.getType(worldConfig)) + .terrainType(MainUtil.getTerrain(worldConfig)) + .plotManager(manager) + .generatorName(generator) + .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)) + .worldName(world); - setup.plotManager = manager; - setup.setupGenerator = generator; - setup.step = new ConfigurationNode[0]; - setup.world = world; - SetupUtils.manager.setupWorld(setup); + SetupUtils.manager.setupWorld(builder); GlobalBlockQueue.IMP.addEmptyTask(() -> { MainUtil.sendMessage(player, "Done!"); player.teleport(WorldUtil.IMP.getSpawn(world), TeleportCause.COMMAND); diff --git a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java index da1613cee..a212a0506 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java +++ b/Core/src/main/java/com/plotsquared/core/plot/world/SinglePlotArea.java @@ -38,8 +38,9 @@ import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.PlotManager; import com.plotsquared.core.plot.PlotSettings; -import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.plot.flag.FlagContainer; +import com.plotsquared.core.setup.PlotAreaBuilder; +import com.plotsquared.core.setup.SettingsNodesWrapper; import com.plotsquared.core.util.SetupUtils; import com.plotsquared.core.util.WorldUtil; import com.plotsquared.core.util.task.RunnableVal; @@ -78,13 +79,13 @@ public class SinglePlotArea extends GridPlotWorld { if (WorldUtil.IMP.isWorld(worldName)) { return; } - SetupObject setup = new SetupObject(); - setup.plotManager = "PlotSquared:single"; - setup.setupGenerator = "PlotSquared:single"; - setup.type = getType(); - setup.terrain = getTerrain(); - setup.step = new ConfigurationNode[0]; - setup.world = worldName; + PlotAreaBuilder builder = new PlotAreaBuilder() + .plotManager("PlotSquared:single") + .generatorName("PlotSquared:single") + .plotAreaType(getType()) + .terrainType(getTerrain()) + .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)) + .worldName(worldName); File container = PlotSquared.imp().getWorldContainer(); File destination = new File(container, worldName); @@ -96,7 +97,7 @@ public class SinglePlotArea extends GridPlotWorld { } } // Duplicate 0;0 - if (setup.type != PlotAreaType.NORMAL) { + if (builder.plotAreaType() != PlotAreaType.NORMAL) { if (!destination.exists()) { File src = new File(container, "0.0"); if (src.exists()) { @@ -132,7 +133,7 @@ public class SinglePlotArea extends GridPlotWorld { return; } - SetupUtils.manager.setupWorld(setup); + SetupUtils.manager.setupWorld(builder); } }); // String worldName = plot.getWorldName(); diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java index 4b0a6c7a6..f299f0b42 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -76,11 +76,11 @@ public enum CommonSetupSteps implements SetupStep { // TODO reimplement SetupUtils.generators.get(object.plotManager).getPlotGenerator() // .processSetup(process); } - if (!builder.settingsNodesWrapper().hasNext()) { + if (!builder.settingsNodesWrapper().hasStep()) { // object.setup_index = 0; TODO what did that do? return builder.settingsNodesWrapper().getAfterwards(); // skip } - return builder.settingsNodesWrapper().next(); + return builder.settingsNodesWrapper().first(); } else { if (gen.isFull()) { builder.plotManager(builder.generatorName()); @@ -179,7 +179,7 @@ public enum CommonSetupSteps implements SetupStep { builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); } SettingsNodesWrapper wrapper = builder.settingsNodesWrapper(); - return wrapper.hasNext() ? wrapper.next() : wrapper.getAfterwards(); + return wrapper.hasStep() ? wrapper.first() : wrapper.getAfterwards(); } @Nullable @Override public String getDefaultValue() { diff --git a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java index c6c6ea494..bae262df1 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java +++ b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java @@ -1,6 +1,8 @@ package com.plotsquared.core.setup; +import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaTerrainType; import com.plotsquared.core.plot.PlotAreaType; import com.plotsquared.core.plot.PlotId; @@ -22,20 +24,35 @@ public class PlotAreaBuilder { @Getter @Setter private SettingsNodesWrapper settingsNodesWrapper; @Getter @Setter private SetupUtils setupManager; - public void minimumId(PlotId minimumId) { + public static PlotAreaBuilder ofPlotArea(PlotArea area) { + return new PlotAreaBuilder() + .worldName(area.getWorldName()) + .areaName(area.getId()) + .plotAreaType(area.getType()) + .terrainType(area.getTerrain()) + .generatorName(area.getGenerator().getName()) + .plotManager(PlotSquared.imp().getPluginName()) + .minimumId(area.getMin()) + .maximumId(area.getMax()) + .settingsNodesWrapper(new SettingsNodesWrapper(area.getSettingNodes(), null)); + } + + public PlotAreaBuilder minimumId(PlotId minimumId) { if (this.maximumId != null - && (minimumId.getX() >= this.maximumId.getX() || minimumId.getY() >= this.maximumId.getY())) { + && (minimumId.getX() > this.maximumId.getX() || minimumId.getY() > this.maximumId.getY())) { throw new IllegalStateException("minId >= maxId"); } this.minimumId = minimumId; + return this; } - public void maximumId(PlotId maximumId) { + public PlotAreaBuilder maximumId(PlotId maximumId) { if (this.minimumId != null - && (maximumId.getX() <= this.minimumId.getX() || maximumId.getY() <= this.minimumId.getY())) { + && (maximumId.getX() < this.minimumId.getX() || maximumId.getY() < this.minimumId.getY())) { throw new IllegalStateException("maxId <= minId"); } this.maximumId = maximumId; + return this; } } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java index 55d78722d..e5f3da3bd 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -29,7 +29,7 @@ public class SettingsNodeStep implements SetupStep { if (this.configurationNode.isValid(argument)) { this.configurationNode.setValue(argument); } - return this.wrapper.hasNext() ? wrapper.next() : wrapper.getAfterwards(); + return this.wrapper.hasNext(this.id) ? wrapper.next(this.id) : wrapper.getAfterwards(); } @NotNull @Override public Collection getSuggestions() { diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java index a967d8ea1..2c0fd0b0f 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java @@ -6,25 +6,34 @@ import lombok.Getter; public class SettingsNodesWrapper { @Getter private final ConfigurationNode[] settingsNodes; @Getter private final SetupStep afterwards; - private int current; public SettingsNodesWrapper(ConfigurationNode[] settingsNodes, SetupStep afterwards) { this.settingsNodes = settingsNodes; this.afterwards = afterwards; - this.current = 0; } - public SettingsNodeStep next() { - if (this.settingsNodes.length <= this.current) { + public SettingsNodeStep next(int current) { + if (this.settingsNodes.length <= current + 1) { throw new IllegalStateException("No step left"); } else { - int temp = this.current; - this.current++; - return new SettingsNodeStep(this.settingsNodes[temp], temp, this); + return new SettingsNodeStep(this.settingsNodes[current + 1], current + 1, this); } } - public boolean hasNext() { - return this.current < this.settingsNodes.length; + + public SettingsNodeStep first() { + if (this.settingsNodes.length == 0) { + throw new IllegalStateException("No step left"); + } else { + return new SettingsNodeStep(this.settingsNodes[0], 0, this); + } + } + + public boolean hasNext(int current) { + return current + 1 < this.settingsNodes.length; + } + + public boolean hasStep() { + return this.settingsNodes.length > 0; } } diff --git a/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java b/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java index 73e6ccfaa..cae6f2ae1 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java +++ b/Core/src/main/java/com/plotsquared/core/util/SetupUtils.java @@ -42,6 +42,7 @@ public abstract class SetupUtils { public abstract String getGenerator(final PlotArea plotArea); + @Deprecated public abstract String setupWorld(final SetupObject object); public abstract String setupWorld(final PlotAreaBuilder builder); From 67b80bb8e8502a9653243873c05287ce76880aa4 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Fri, 5 Jun 2020 13:59:03 +0200 Subject: [PATCH 085/121] Fix /plot setup back --- .../core/setup/CommonSetupSteps.java | 8 ++---- .../core/setup/SettingsNodeStep.java | 10 +++++--- .../core/setup/SettingsNodesWrapper.java | 25 ++----------------- 3 files changed, 11 insertions(+), 32 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java index f299f0b42..39dc2dd1b 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -76,11 +76,7 @@ public enum CommonSetupSteps implements SetupStep { // TODO reimplement SetupUtils.generators.get(object.plotManager).getPlotGenerator() // .processSetup(process); } - if (!builder.settingsNodesWrapper().hasStep()) { - // object.setup_index = 0; TODO what did that do? - return builder.settingsNodesWrapper().getAfterwards(); // skip - } - return builder.settingsNodesWrapper().first(); + return builder.settingsNodesWrapper().getFirstStep(); } else { if (gen.isFull()) { builder.plotManager(builder.generatorName()); @@ -179,7 +175,7 @@ public enum CommonSetupSteps implements SetupStep { builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); } SettingsNodesWrapper wrapper = builder.settingsNodesWrapper(); - return wrapper.hasStep() ? wrapper.first() : wrapper.getAfterwards(); + return wrapper.getFirstStep(); } @Nullable @Override public String getDefaultValue() { diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java index e5f3da3bd..ec384884e 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -17,19 +17,23 @@ import java.util.Collections; public class SettingsNodeStep implements SetupStep { @Getter private final ConfigurationNode configurationNode; @Getter private final int id; - private final SettingsNodesWrapper wrapper; + private final SetupStep next; public SettingsNodeStep(ConfigurationNode configurationNode, int id, SettingsNodesWrapper wrapper) { this.configurationNode = configurationNode; this.id = id; - this.wrapper = wrapper; + if (wrapper.getSettingsNodes().length > id + 1) { + this.next = new SettingsNodeStep(wrapper.getSettingsNodes()[id + 1], id + 1, wrapper); + } else { + this.next = wrapper.getAfterwards(); + } } @Override public SetupStep handleInput(PlotPlayer plotPlayer, PlotAreaBuilder builder, String argument) { if (this.configurationNode.isValid(argument)) { this.configurationNode.setValue(argument); } - return this.wrapper.hasNext(this.id) ? wrapper.next(this.id) : wrapper.getAfterwards(); + return this.next; } @NotNull @Override public Collection getSuggestions() { diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java index 2c0fd0b0f..cdcb74bce 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java @@ -12,28 +12,7 @@ public class SettingsNodesWrapper { this.afterwards = afterwards; } - - public SettingsNodeStep next(int current) { - if (this.settingsNodes.length <= current + 1) { - throw new IllegalStateException("No step left"); - } else { - return new SettingsNodeStep(this.settingsNodes[current + 1], current + 1, this); - } - } - - public SettingsNodeStep first() { - if (this.settingsNodes.length == 0) { - throw new IllegalStateException("No step left"); - } else { - return new SettingsNodeStep(this.settingsNodes[0], 0, this); - } - } - - public boolean hasNext(int current) { - return current + 1 < this.settingsNodes.length; - } - - public boolean hasStep() { - return this.settingsNodes.length > 0; + public SetupStep getFirstStep() { + return this.settingsNodes.length == 0 ? this.afterwards : new SettingsNodeStep(this.settingsNodes[0], 0, this); } } From e3fbb32399c2dae1c48506a828a80f13883b1b0b Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Fri, 5 Jun 2020 14:05:30 +0200 Subject: [PATCH 086/121] Formatting and documentation --- .../com/plotsquared/bukkit/util/BukkitSetupUtils.java | 5 ++--- .../com/plotsquared/core/setup/SettingsNodeStep.java | 3 +++ .../com/plotsquared/core/setup/SettingsNodesWrapper.java | 9 +++++++++ .../java/com/plotsquared/core/setup/SetupProcess.java | 5 ++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitSetupUtils.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitSetupUtils.java index ce893aeee..53185b608 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitSetupUtils.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitSetupUtils.java @@ -98,7 +98,7 @@ public class BukkitSetupUtils extends SetupUtils { Bukkit.unloadWorld(world, false); } - @Override public String setupWorld(SetupObject object) { + @Deprecated @Override public String setupWorld(SetupObject object) { SetupUtils.manager.updateGenerators(); ConfigurationNode[] steps = object.step == null ? new ConfigurationNode[0] : object.step; String world = object.world; @@ -210,8 +210,7 @@ public class BukkitSetupUtils extends SetupUtils { return object.world; } - @Override - public String setupWorld(PlotAreaBuilder builder) { + @Override public String setupWorld(PlotAreaBuilder builder) { SetupUtils.manager.updateGenerators(); ConfigurationNode[] steps = builder.settingsNodesWrapper() == null ? new ConfigurationNode[0] : builder.settingsNodesWrapper().getSettingsNodes(); diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java index ec384884e..6d2976d3e 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -14,6 +14,9 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; +/** + * A SettingsNodeStep is a step wrapping a {@link ConfigurationNode}. + */ public class SettingsNodeStep implements SetupStep { @Getter private final ConfigurationNode configurationNode; @Getter private final int id; diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java index cdcb74bce..f34cf91d9 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java @@ -3,6 +3,9 @@ package com.plotsquared.core.setup; import com.plotsquared.core.configuration.ConfigurationNode; import lombok.Getter; +/** + * This class wraps an array of {@link ConfigurationNode}s. + */ public class SettingsNodesWrapper { @Getter private final ConfigurationNode[] settingsNodes; @Getter private final SetupStep afterwards; @@ -12,6 +15,12 @@ public class SettingsNodesWrapper { this.afterwards = afterwards; } + /** + * Returns the first step of this wrapper or the step or the + * {@code afterwards} step if no step is available. + * + * @return the first step or {@code afterwards}. + */ public SetupStep getFirstStep() { return this.settingsNodes.length == 0 ? this.afterwards : new SettingsNodeStep(this.settingsNodes[0], 0, this); } diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java index 93d7b9593..ae4fcd7fe 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java @@ -4,6 +4,10 @@ import com.plotsquared.core.player.PlotPlayer; import java.util.Stack; +/** + * This class keeps track of a setup process. + * It holds the history and the current setup state. + */ public class SetupProcess { private final PlotAreaBuilder builder; private final Stack history; @@ -21,7 +25,6 @@ public class SetupProcess { public void handleInput(PlotPlayer plotPlayer, String argument) { SetupStep previous = this.current; - // TODO null check? this.current = this.current.handleInput(plotPlayer, this.builder, argument); // push previous step into history if (this.current != previous && this.current != null) { From b6f1610a7ed125f7d854995245014b184efb461e Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Fri, 5 Jun 2020 14:06:43 +0200 Subject: [PATCH 087/121] Provide no suggestions instead of player names for commands --- Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java index 20ab45529..1f5b0de02 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitCommand.java @@ -78,6 +78,6 @@ public class BukkitCommand implements CommandExecutor, TabCompleter { for (com.plotsquared.core.command.Command o : objects) { result.add(o.toString()); } - return result.isEmpty() ? null : result; + return result; } } From 033b87deb57d74c56d4a5331ab72a14013297380 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Fri, 5 Jun 2020 14:13:03 +0200 Subject: [PATCH 088/121] Resolve TODOs --- .../src/main/java/com/plotsquared/core/command/Setup.java | 1 - .../core/generator/IndependentPlotGenerator.java | 5 +++-- .../java/com/plotsquared/core/setup/CommonSetupSteps.java | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Setup.java b/Core/src/main/java/com/plotsquared/core/command/Setup.java index 238f1bd5a..8f5f9574a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Setup.java +++ b/Core/src/main/java/com/plotsquared/core/command/Setup.java @@ -72,7 +72,6 @@ public class Setup extends SubCommand { SetupProcess process = player.getMeta("setup"); if (process == null) { if (args.length > 0) { - // TODO use old behaviour? MainUtil.sendMessage(player, Captions.SETUP_NOT_STARTED); return true; } diff --git a/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java b/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java index b2e1278ab..324f6d8d4 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java +++ b/Core/src/main/java/com/plotsquared/core/generator/IndependentPlotGenerator.java @@ -30,6 +30,7 @@ import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotId; import com.plotsquared.core.plot.SetupObject; import com.plotsquared.core.queue.ScopedLocalBlockQueue; +import com.plotsquared.core.setup.PlotAreaBuilder; import com.plotsquared.core.setup.SetupProcess; /** @@ -83,9 +84,9 @@ public abstract class IndependentPlotGenerator { * If any additional setup options need to be changed before world creation. * - e.g. If setup doesn't support some standard options * - * @param setupProcess the setup process to modify + * @param builder the area builder to modify */ - public void processSetup(SetupProcess setupProcess) { } + public void processAreaSetup(PlotAreaBuilder builder) { } /** * It is preferred for the PlotArea object to do most of the initialization necessary. diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java index 39dc2dd1b..bd73bb74a 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -73,8 +73,8 @@ public enum CommonSetupSteps implements SetupStep { if (builder.settingsNodesWrapper() == null) { builder.plotManager(builder.generatorName()); builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); - // TODO reimplement SetupUtils.generators.get(object.plotManager).getPlotGenerator() - // .processSetup(process); + SetupUtils.generators.get(builder.plotManager()).getPlotGenerator() + .processAreaSetup(builder); } return builder.settingsNodesWrapper().getFirstStep(); } else { @@ -82,8 +82,8 @@ public enum CommonSetupSteps implements SetupStep { builder.plotManager(builder.generatorName()); builder.generatorName(null); builder.settingsNodesWrapper(CommonSetupSteps.wrap(builder.plotManager())); - // TODO reimplement SetupUtils.generators.get(object.plotManager).getPlotGenerator() - // .processSetup(process); + SetupUtils.generators.get(builder.plotManager()).getPlotGenerator() + .processAreaSetup(builder); } else { builder.plotManager(PlotSquared.imp().getPluginName()); MainUtil.sendMessage(plotPlayer, Captions.SETUP_WRONG_GENERATOR); From 8c0f581ff03cf84ea30f89f16a156e5f3d363a46 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Fri, 5 Jun 2020 14:25:54 +0200 Subject: [PATCH 089/121] Add missing license headers to new files --- .../core/setup/CommonSetupSteps.java | 25 +++++++++++++++++++ .../core/setup/PlotAreaBuilder.java | 25 +++++++++++++++++++ .../core/setup/SettingsNodeStep.java | 25 +++++++++++++++++++ .../core/setup/SettingsNodesWrapper.java | 25 +++++++++++++++++++ .../plotsquared/core/setup/SetupProcess.java | 25 +++++++++++++++++++ .../com/plotsquared/core/setup/SetupStep.java | 25 +++++++++++++++++++ 6 files changed, 150 insertions(+) diff --git a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java index bd73bb74a..0a8c7ba9a 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -1,3 +1,28 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.setup; import com.plotsquared.core.PlotSquared; diff --git a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java index bae262df1..d59e2d8f0 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java +++ b/Core/src/main/java/com/plotsquared/core/setup/PlotAreaBuilder.java @@ -1,3 +1,28 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.setup; diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java index 6d2976d3e..d216f067c 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodeStep.java @@ -1,3 +1,28 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.setup; import com.plotsquared.core.command.Command; diff --git a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java index f34cf91d9..153ec7d86 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SettingsNodesWrapper.java @@ -1,3 +1,28 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.setup; import com.plotsquared.core.configuration.ConfigurationNode; diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java index ae4fcd7fe..7af19aefb 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupProcess.java @@ -1,3 +1,28 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.setup; import com.plotsquared.core.player.PlotPlayer; diff --git a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java index 8ea5db0a0..5befafc81 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java +++ b/Core/src/main/java/com/plotsquared/core/setup/SetupStep.java @@ -1,3 +1,28 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.setup; import com.plotsquared.core.command.Command; From bb298ab660e4299baa2bc414f25f1605368d13c0 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Fri, 5 Jun 2020 14:43:53 +0200 Subject: [PATCH 090/121] Remove leftover TODO --- Core/src/main/java/com/plotsquared/core/command/Area.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Area.java b/Core/src/main/java/com/plotsquared/core/command/Area.java index 696cf1459..383076f0d 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -190,7 +190,7 @@ public class Area extends SubCommand { .plotManager(PlotSquared.imp().getPluginName()) .generatorName(PlotSquared.imp().getPluginName()) .maximumId(plotId) - .minimumId(plotId); // TODO will throw exception right now + .minimumId(plotId); Runnable singleRun = () -> { final String path = "worlds." + hybridPlotWorld.getWorldName() + ".areas." + hybridPlotWorld.getId() + '-' From a3586791b5deb2e54a22a332761105c15a782e9d Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Tue, 9 Jun 2020 12:39:27 +0200 Subject: [PATCH 091/121] Remove unused code and use less aggressive colors --- Core/src/main/java/com/plotsquared/core/command/Setup.java | 5 ----- .../java/com/plotsquared/core/configuration/Captions.java | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Setup.java b/Core/src/main/java/com/plotsquared/core/command/Setup.java index 8f5f9574a..bdcd20697 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Setup.java +++ b/Core/src/main/java/com/plotsquared/core/command/Setup.java @@ -35,7 +35,6 @@ import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.SetupUtils; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -48,10 +47,6 @@ import java.util.Map.Entry; aliases = {"create"}, category = CommandCategory.ADMINISTRATION) public class Setup extends SubCommand { - private static final Collection specialCommands = Arrays.asList( - new Command(null, false, "back", "", RequiredType.NONE, null) {}, - new Command(null, false, "cancel", "", RequiredType.NONE, null) {}); - public void displayGenerators(PlotPlayer player) { StringBuilder message = new StringBuilder(); diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 778423635..99123b334 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -319,7 +319,7 @@ public enum Captions implements Caption { REMOVED_GRANTED_PLOT("$2You used %s0 plot grant(s), you've got $1%s1 $2left", "Economy"), // // - SETUP_NOT_STARTED("$7No setup started. Use $2/plot setup $7to start a setup process.", "Setup"), + SETUP_NOT_STARTED("$1No setup started. Use $2/plot setup $1to start a setup process.", "Setup"), SETUP_INIT("$1Usage: $2/plot setup ", "Setup"), SETUP_STEP("$3[$1Step %s0$3] $1%s1 $2- $1Expecting: $2%s2 $1Default: $2%s3", "Setup"), SETUP_INVALID_ARG("$2%s0 is not a valid argument for step %s1. To cancel setup use: $1/plot setup cancel", "Setup"), From 3e2e61d2be893691757f4191b15adaf07737c777 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 13 Jun 2020 15:53:03 +0200 Subject: [PATCH 092/121] Re-introduce online mode --- .../bukkit/uuid/OfflinePlayerUUIDService.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java index 9c9f02344..3789de0c7 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java @@ -60,12 +60,19 @@ public class OfflinePlayerUUIDService implements UUIDService { @Override @NotNull public List getUUIDs(@NotNull final List usernames) { final List wrappers = new ArrayList<>(usernames.size()); for (final String username : usernames) { - if (Settings.UUID.FORCE_LOWERCASE) { - wrappers.add(new UUIDMapping(UUID.nameUUIDFromBytes(("OfflinePlayer:" + - username.toLowerCase()).getBytes(Charsets.UTF_8)), username)); + if (Settings.UUID.OFFLINE) { + if (Settings.UUID.FORCE_LOWERCASE) { + wrappers.add(new UUIDMapping(UUID.nameUUIDFromBytes(("OfflinePlayer:" + + username.toLowerCase()).getBytes(Charsets.UTF_8)), username)); + } else { + wrappers.add(new UUIDMapping(UUID.nameUUIDFromBytes(("OfflinePlayer:" + + username).getBytes(Charsets.UTF_8)), username)); + } } else { - wrappers.add(new UUIDMapping(UUID.nameUUIDFromBytes(("OfflinePlayer:" + - username).getBytes(Charsets.UTF_8)), username)); + final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(username); + if (offlinePlayer.hasPlayedBefore()) { + wrappers.add(new UUIDMapping(offlinePlayer.getUniqueId(), offlinePlayer.getName())); + } } } return wrappers; From 6259287dffe03e6b0ccd29a2a485aa07aa8b71e6 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 13 Jun 2020 15:54:38 +0200 Subject: [PATCH 093/121] Add tab completion for /plot --- .../com/plotsquared/core/command/Deny.java | 7 ++ .../com/plotsquared/core/command/Kick.java | 13 +++ .../com/plotsquared/core/command/Remove.java | 13 +++ .../plotsquared/core/util/TabCompletions.java | 105 +++++++++++++----- 4 files changed, 112 insertions(+), 26 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Deny.java b/Core/src/main/java/com/plotsquared/core/command/Deny.java index 4ed0d0ed5..1cb862304 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Deny.java +++ b/Core/src/main/java/com/plotsquared/core/command/Deny.java @@ -33,9 +33,12 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.WorldUtil; import com.sk89q.worldedit.world.gamemode.GameModes; +import java.util.Collection; +import java.util.Collections; import java.util.UUID; import java.util.concurrent.TimeoutException; @@ -112,6 +115,10 @@ public class Deny extends SubCommand { return true; } + @Override public Collection tab(final PlotPlayer player, final String[] args, final boolean space) { + return TabCompletions.completePlayers(String.join(",", args).trim(), Collections.emptyList()); + } + private void handleKick(PlotPlayer player, Plot plot) { if (player == null) { return; diff --git a/Core/src/main/java/com/plotsquared/core/command/Kick.java b/Core/src/main/java/com/plotsquared/core/command/Kick.java index 0c83fa24e..6dc3aaa97 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Kick.java +++ b/Core/src/main/java/com/plotsquared/core/command/Kick.java @@ -33,8 +33,11 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.TabCompletions; import com.plotsquared.core.util.WorldUtil; +import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.UUID; @@ -122,4 +125,14 @@ public class Kick extends SubCommand { return true; } + + @Override public Collection tab(final PlotPlayer player, final String[] args, final boolean space) { + Location location = player.getLocation(); + Plot plot = location.getPlotAbs(); + if (plot == null) { + return Collections.emptyList(); + } + return TabCompletions.completePlayersInPlot(plot, String.join(",", args).trim(), + Collections.singletonList(player.getName())); + } } diff --git a/Core/src/main/java/com/plotsquared/core/command/Remove.java b/Core/src/main/java/com/plotsquared/core/command/Remove.java index da00e5748..871bd2b60 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Remove.java +++ b/Core/src/main/java/com/plotsquared/core/command/Remove.java @@ -33,7 +33,10 @@ import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.TabCompletions; +import java.util.Collection; +import java.util.Collections; import java.util.UUID; import java.util.concurrent.TimeoutException; @@ -120,4 +123,14 @@ public class Remove extends SubCommand { return true; } + @Override public Collection tab(final PlotPlayer player, final String[] args, final boolean space) { + Location location = player.getLocation(); + Plot plot = location.getPlotAbs(); + if (plot == null) { + return Collections.emptyList(); + } + return TabCompletions.completeAddedPlayers(plot, String.join(",", args).trim(), + Collections.singletonList(player.getName())); + } + } diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java index 91454b3bb..bb6c74bd4 100644 --- a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java +++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java @@ -33,6 +33,7 @@ import com.plotsquared.core.command.CommandCategory; import com.plotsquared.core.command.RequiredType; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.player.PlotPlayer; +import com.plotsquared.core.plot.Plot; import com.plotsquared.core.uuid.UUIDMapping; import lombok.experimental.UtilityClass; import org.jetbrains.annotations.NotNull; @@ -43,7 +44,9 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.UUID; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; import java.util.stream.Collectors; /** @@ -70,35 +73,37 @@ public class TabCompletions { */ @NotNull public List completePlayers(@NotNull final String input, @NotNull final List existing) { - List players; - if (Settings.Enabled_Components.EXTENDED_USERNAME_COMPLETION) { - players = cachedCompletionValues.getIfPresent("players"); - if (players == null) { - final Collection mappings = - PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); - players = new ArrayList<>(mappings.size()); - for (final UUIDMapping mapping : mappings) { - players.add(mapping.getUsername()); - } - cachedCompletionValues.put("players", players); - } - } else { - final Collection onlinePlayers = PlotSquared.imp().getPlayerManager().getPlayers(); - players = new ArrayList<>(onlinePlayers.size()); - for (final PlotPlayer player : onlinePlayers) { + return completePlayers("players", input, existing, uuid -> true); + } + + /** + * Get a list of tab completions corresponding to player names added to the given plot. + * + * @param plot Plot to complete added players for + * @param input Command input + * @param existing Players that should not be included in completions + * @return List of completions + */ + @NotNull public List completeAddedPlayers(@NotNull final Plot plot, @NotNull final String input, + @NotNull final List existing) { + return completePlayers("added" + plot, input, existing, + uuid -> plot.getMembers().contains(uuid) + || plot.getTrusted().contains(uuid) + || plot.getDenied().contains(uuid)); + } + + @NotNull public List completePlayersInPlot(@NotNull final Plot plot, @NotNull final String input, + @NotNull final List existing) { + List players = cachedCompletionValues.getIfPresent("inPlot" + plot); + if (players == null) { + final List> inPlot = plot.getPlayersInPlot(); + players = new ArrayList<>(inPlot.size()); + for (PlotPlayer player : inPlot) { players.add(player.getName()); } + cachedCompletionValues.put("inPlot" + plot, players); } - final String processedInput = input.toLowerCase(Locale.ENGLISH); - return players.stream() - .filter(player -> player.toLowerCase(Locale.ENGLISH).startsWith(processedInput)) - .filter(player -> !existing.contains(player)).map( - player -> new Command(null, false, player, "", RequiredType.NONE, - CommandCategory.INFO) { - }) - /* If there are more than 200 suggestions, just send the first 200 */ - .limit(200) - .collect(Collectors.toList()); + return filterCached(players, input, existing); } /** @@ -129,4 +134,52 @@ public class TabCompletions { return Collections.emptyList(); } + /** + * @param cacheIdentifier Cache key + * @param input Command input + * @param existing Players that should not be included in completions + * @param uuidFilter Filter applied before caching values + * @return List of completions + */ + private List completePlayers(@NotNull final String cacheIdentifier, @NotNull final String input, + @NotNull final List existing, + @NotNull final Predicate uuidFilter) { + List players; + if (Settings.Enabled_Components.EXTENDED_USERNAME_COMPLETION) { + players = cachedCompletionValues.getIfPresent(cacheIdentifier); + if (players == null) { + final Collection mappings = + PlotSquared.get().getImpromptuUUIDPipeline().getAllImmediately(); + players = new ArrayList<>(mappings.size()); + for (final UUIDMapping mapping : mappings) { + if (uuidFilter.test(mapping.getUuid())) { + players.add(mapping.getUsername()); + } + } + cachedCompletionValues.put(cacheIdentifier, players); + } + } else { + final Collection> onlinePlayers = PlotSquared.imp().getPlayerManager().getPlayers(); + players = new ArrayList<>(onlinePlayers.size()); + for (final PlotPlayer player : onlinePlayers) { + if (uuidFilter.test(player.getUUID())) { + players.add(player.getName()); + } + } + } + return filterCached(players, input, existing); + } + + private List filterCached(Collection playerNames, String input, List existing) { + final String processedInput = input.toLowerCase(Locale.ENGLISH); + return playerNames.stream().filter(player -> player.toLowerCase(Locale.ENGLISH).startsWith(processedInput)) + .filter(player -> !existing.contains(player)).map( + player -> new Command(null, false, player, "", RequiredType.NONE, + CommandCategory.INFO) { + }) + /* If there are more than 200 suggestions, just send the first 200 */ + .limit(200) + .collect(Collectors.toList()); + } + } From cb969e37a654c070d46fb55581dda88f0c3768cc Mon Sep 17 00:00:00 2001 From: PureGero Date: Tue, 16 Jun 2020 01:44:05 +1000 Subject: [PATCH 094/121] Don't teleport players; Fixes PS-14 --- .../plotsquared/bukkit/listener/EntitySpawnListener.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntitySpawnListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntitySpawnListener.java index e094baf9c..0bf5e75e8 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntitySpawnListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/EntitySpawnListener.java @@ -100,15 +100,15 @@ public class EntitySpawnListener implements Listener { if (!originWorld.equals(world)) { if (!ignoreTP) { if (!world.getName().equalsIgnoreCase(originWorld + "_the_end")) { + if (entity.getType() == EntityType.PLAYER) { + return; + } try { ignoreTP = true; PaperLib.teleportAsync(entity, origin); } finally { ignoreTP = false; } - if (entity.getType() == EntityType.PLAYER) { - return; - } if (entity.getLocation().getWorld().equals(world)) { entity.remove(); } From d07d32e28be2d75feb7d88b5b41c24b17f1a1c79 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 20 Jun 2020 00:14:04 +0200 Subject: [PATCH 095/121] Generate plot blocks on correct height when removing intersection Fixes PS-46 --- .../core/generator/ClassicPlotManager.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java index 52557144e..46333a84c 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java +++ b/Core/src/main/java/com/plotsquared/core/generator/ClassicPlotManager.java @@ -455,17 +455,17 @@ public class ClassicPlotManager extends SquarePlotManager { int sz = location.getZ() + 1; int ez = sz + classicPlotWorld.ROAD_WIDTH - 1; LocalBlockQueue queue = classicPlotWorld.getQueue(false); - queue.setCuboid( - new Location(classicPlotWorld.getWorldName(), sx, classicPlotWorld.ROAD_HEIGHT + 1, sz), - new Location(classicPlotWorld.getWorldName(), ex, - classicPlotWorld.getPlotManager().getWorldHeight(), ez), - BlockTypes.AIR.getDefaultState()); + queue.setCuboid(new Location(classicPlotWorld.getWorldName(), sx, + Math.min(classicPlotWorld.PLOT_HEIGHT, classicPlotWorld.ROAD_HEIGHT) + 1, sz), + new Location(classicPlotWorld.getWorldName(), ex, + classicPlotWorld.getPlotManager().getWorldHeight(), ez), + BlockTypes.AIR.getDefaultState()); queue.setCuboid(new Location(classicPlotWorld.getWorldName(), sx, 1, sz), - new Location(classicPlotWorld.getWorldName(), ex, classicPlotWorld.ROAD_HEIGHT - 1, ez), + new Location(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT - 1, ez), classicPlotWorld.MAIN_BLOCK.toPattern()); queue.setCuboid( - new Location(classicPlotWorld.getWorldName(), sx, classicPlotWorld.ROAD_HEIGHT, sz), - new Location(classicPlotWorld.getWorldName(), ex, classicPlotWorld.ROAD_HEIGHT, ez), + new Location(classicPlotWorld.getWorldName(), sx, classicPlotWorld.PLOT_HEIGHT, sz), + new Location(classicPlotWorld.getWorldName(), ex, classicPlotWorld.PLOT_HEIGHT, ez), classicPlotWorld.TOP_BLOCK.toPattern()); return queue.enqueue(); } From 1dcf8d3995ecdc5753c877a74f27f8a666844e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Sun, 21 Jun 2020 15:50:49 +0200 Subject: [PATCH 096/121] Progress on the debug logging API --- .../bukkit/listener/PlayerEvents.java | 10 ++++ .../plotsquared/core/command/SetCommand.java | 2 +- .../com/plotsquared/core/command/Toggle.java | 28 ++++++--- .../core/configuration/Captions.java | 5 ++ .../plotsquared/core/player/PlotPlayer.java | 57 ++++++++++++++++++- .../java/com/plotsquared/core/plot/Plot.java | 15 +++++ .../com/plotsquared/core/util/EntityUtil.java | 1 + .../plotsquared/core/util/PlayerManager.java | 2 +- 8 files changed, 109 insertions(+), 11 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 734816707..2ac326b93 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -401,6 +401,7 @@ public class PlayerEvents extends PlotListener implements Listener { } if (!plot.getFlag(RedstoneFlag.class)) { event.setCancelled(true); + plot.debug("Prevented comparator update because redstone = false"); } return; } @@ -423,6 +424,7 @@ public class PlayerEvents extends PlotListener implements Listener { } if (plot.getFlag(DisablePhysicsFlag.class)) { event.setCancelled(true); + plot.debug("Prevented block physics because disable-physics = true"); } return; } @@ -460,6 +462,7 @@ public class PlayerEvents extends PlotListener implements Listener { Plot newPlot = area.getOwnedPlotAbs(location); if (!plot.equals(newPlot)) { event.setCancelled(true); + plot.debug("Prevented piston update because of invalid edge piston detection"); return; } } @@ -2959,6 +2962,8 @@ public class PlayerEvents extends PlotListener implements Listener { MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, Captions.PERMISSION_ADMIN_BUILD_OTHER); event.setCancelled(true); + plot.debug(player.getName() + " could not place " + event.getBlock().getType() + + " because of the place flag"); return; } } else if (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot)) { @@ -2973,6 +2978,7 @@ public class PlayerEvents extends PlotListener implements Listener { Block block = event.getBlockPlaced(); if (block.getType().hasGravity()) { sendBlockChange(block.getLocation(), block.getBlockData()); + plot.debug(event.getBlock().getType() + " did not fall because of disable-physics = true"); } } } else if (!Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_BUILD_ROAD)) { @@ -2991,6 +2997,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } if (plot.getFlag(InvincibleFlag.class)) { + plot.debug(event.getEntity().getName() + " could not take damage because invincible = true"); event.setCancelled(true); } } @@ -3005,6 +3012,7 @@ public class PlayerEvents extends PlotListener implements Listener { UUID uuid = pp.getUUID(); if (!plot.isAdded(uuid)) { if (!plot.getFlag(ItemDropFlag.class)) { + plot.debug(player.getName() + " could not drop item because of item-drop = false"); event.setCancelled(true); } } @@ -3021,6 +3029,7 @@ public class PlayerEvents extends PlotListener implements Listener { } UUID uuid = pp.getUUID(); if (!plot.isAdded(uuid) && plot.getFlag(DropProtectionFlag.class)) { + plot.debug(player.getName() + " could not pick up item because of drop-protection = true"); event.setCancelled(true); } } @@ -3029,6 +3038,7 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler public void onDeath(final PlayerDeathEvent event) { final Plot plot = BukkitUtil.getPlayer(event.getEntity()).getCurrentPlot(); if (plot != null && plot.getFlag(KeepInventoryFlag.class)) { + plot.debug(event.getEntity().getName() + " kept their inventory because of keep-inventory = true"); event.setKeepInventory(true); } } diff --git a/Core/src/main/java/com/plotsquared/core/command/SetCommand.java b/Core/src/main/java/com/plotsquared/core/command/SetCommand.java index c487fb0c0..aede7e779 100644 --- a/Core/src/main/java/com/plotsquared/core/command/SetCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/SetCommand.java @@ -52,7 +52,7 @@ public abstract class SetCommand extends SubCommand { return false; } } - if (!plot.isOwner(player.getUUID()) && !plot.getTrusted().contains(player.getUUID())) { + if (!plot.isOwner(player.getUUID())) { if (!Permissions.hasPermission(player, CaptionUtility .format(player, Captions.PERMISSION_ADMIN_COMMAND.getTranslated(), getFullId()))) { MainUtil.sendMessage(player, Captions.NO_PERMISSION, CaptionUtility diff --git a/Core/src/main/java/com/plotsquared/core/command/Toggle.java b/Core/src/main/java/com/plotsquared/core/command/Toggle.java index 8bb25014c..c0085fb6c 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Toggle.java +++ b/Core/src/main/java/com/plotsquared/core/command/Toggle.java @@ -47,7 +47,7 @@ public class Toggle extends Command { aliases = {"spy"}, permission = "plots.admin.command.chat", description = "Toggle plot chat spy") - public void chatspy(Command command, PlotPlayer player, String[] args, + public void chatspy(Command command, PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { if (toggle(player, "chatspy")) { @@ -61,7 +61,7 @@ public class Toggle extends Command { aliases = {"we", "wea"}, permission = "plots.worldedit.bypass", description = "Toggle worldedit area restrictions") - public void worldedit(Command command, PlotPlayer player, String[] args, + public void worldedit(Command command, PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { if (toggle(player, "worldedit")) { @@ -74,7 +74,7 @@ public class Toggle extends Command { @CommandDeclaration(command = "chat", permission = "plots.toggle.chat", description = "Toggle plot chat") - public void chat(Command command, PlotPlayer player, String[] args, + public void chat(Command command, PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { if (toggle(player, "chat")) { @@ -87,7 +87,7 @@ public class Toggle extends Command { @CommandDeclaration(command = "clear-confirmation", permission = "plots.admin.command.autoclear", description = "Toggle autoclear confirmation") - public void clearConfirmation(Command command, PlotPlayer player, String[] args, + public void clearConfirmation(Command command, PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { if (toggle(player, "ignoreExpireTask")) { @@ -100,7 +100,7 @@ public class Toggle extends Command { @CommandDeclaration(command = "titles", permission = "plots.toggle.titles", description = "Toggle plot title messages") - public void titles(Command command, PlotPlayer player, String[] args, + public void titles(Command command, PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { if (toggle(player, "disabletitles")) { @@ -113,7 +113,7 @@ public class Toggle extends Command { @CommandDeclaration(command = "time", permission = "plots.toggle.time", description = "Toggle plot time settings") - public void time(Command command, PlotPlayer player, String[] args, + public void time(Command command, PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { if (toggle(player, "disabletime")) { @@ -123,7 +123,21 @@ public class Toggle extends Command { } } - public boolean toggle(PlotPlayer player, String key) { + @CommandDeclaration(command = "debug", + permission = "plots.toggle.debug", + description = "Toggle plot debugging") + public void debug(Command command, PlotPlayer player, String[] args, + RunnableVal3 confirm, + RunnableVal2 whenDone) { + if (toggle(player, "debug")) { + MainUtil.sendMessage(player, Captions.TOGGLE_ENABLED, command.toString()); + } else { + MainUtil.sendMessage(player, Captions.TOGGLE_DISABLED, command.toString()); + } + player.refreshDebug(); + } + + public boolean toggle(PlotPlayer player, String key) { if (player.getAttribute(key)) { player.removeAttribute(key); return true; diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 99123b334..03f08cda9 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -190,6 +190,7 @@ public enum Captions implements Caption { PERMISSION_BACKUP_LOAD("plots.backup.load", "static.permissions"), PERMISSION_ADMIN_BACKUP_OTHER("plots.admin.backup.other", "static.permissions"), PERMISSION_ADMIN_ALLOW_UNSAFE("plots.admin.unsafe", "static.permissions"), + PERMISSION_ADMIN_DEBUG_OTHER("plots.admin.debug.other", "static.permissions"), // // EXPIRED_CONFIRM("$2Confirmation has expired, please run the command again!", "Confirm"), @@ -803,6 +804,10 @@ public enum Captions implements Caption { SINGLE_AREA_CREATED("$1The area was created successfully!", "Single"), // + // + PLOT_DEBUG("$1Plot Debug ($2%plot%$1): %message%", "Plot-Debug"), + // + /** * Legacy Configuration Conversion */ diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java index 1a4e668c5..568498786 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -56,8 +56,11 @@ import lombok.NonNull; import org.jetbrains.annotations.NotNull; import java.nio.ByteBuffer; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -72,12 +75,17 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer public static final String META_LAST_PLOT = "lastplot"; public static final String META_LOCATION = "location"; + + // Used to track debug mode + private static final Set> debugModeEnabled = Collections.synchronizedSet(new HashSet<>()); + private static final Map converters = new HashMap<>(); private Map metaMap = new HashMap<>(); /** * The metadata map. */ private ConcurrentHashMap meta; + private int hash; public static PlotPlayer from(@NonNull final T object) { if (!converters.containsKey(object.getClass())) { @@ -93,6 +101,19 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer converters.put(clazz, converter); } + public static Collection> getDebugModePlayerInPlot(@NotNull final Plot plot) { + if (debugModeEnabled.isEmpty()) { + return Collections.emptyList(); + } + final Collection> players = new LinkedList<>(); + for (final PlotPlayer player : debugModeEnabled) { + if (player.getCurrentPlot().equals(plot)) { + players.add(player); + } + } + return players; + } + /** * Efficiently wrap a Player, or OfflinePlayer object to get a PlotPlayer (or fetch if it's already cached)
* - Accepts sponge/bukkit Player (online) @@ -519,6 +540,15 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer */ public abstract void kick(String message); + public void refreshDebug() { + final boolean debug = this.getAttribute("debug"); + if (debug && !debugModeEnabled.contains(this)) { + debugModeEnabled.add(this); + } else if (!debug) { + debugModeEnabled.remove(this); + } + } + /** * Called when this player quits. */ @@ -556,6 +586,8 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer } PlotSquared.imp().getPlayerManager().removePlayer(this); PlotSquared.get().IMP.unregister(this); + + debugModeEnabled.remove(this); } /** @@ -603,6 +635,10 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer return; } + if (PlotPlayer.this.getAttribute("debug")) { + debugModeEnabled.add(PlotPlayer.this); + } + if (!Settings.Teleport.ON_LOGIN) { return; } @@ -693,10 +729,27 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer public abstract void stopSpectating(); + public boolean hasDebugMode() { + return this.getAttribute("debug"); + } + + @Override public int hashCode() { + if (this.hash == 0 || this.hash == 485) { + this.hash = 485 + this.getUUID().hashCode(); + } + return this.hash; + } + + @Override public boolean equals(final Object obj) { + if (!(obj instanceof PlotPlayer)) { + return false; + } + final PlotPlayer other = (PlotPlayer) obj; + return this.getUUID().equals(other.getUUID()); + } + /** * The amount of money this Player has. - * - * @return */ public double getMoney() { return EconHandler.manager == null ? 0 : EconHandler.manager.getMoney(this); diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 5def886a8..85410628c 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -2924,6 +2924,21 @@ public class Plot { }, 1); } + public void debug(@NotNull final String message) { + final Collection> players = PlotPlayer.getDebugModePlayerInPlot(this); + if (players.isEmpty()) { + return; + } + final String string = Captions.PLOT_DEBUG.getTranslated().replace("%plot%", this.toString()) + .replace("%message%", message); + for (final PlotPlayer player : players) { + if (isOwner(player.getUUID()) || + Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_DEBUG_OTHER)) { + player.sendMessage(string); + } + } + } + /** * Gets all the corners of the plot (supports non-rectangular shapes). * diff --git a/Core/src/main/java/com/plotsquared/core/util/EntityUtil.java b/Core/src/main/java/com/plotsquared/core/util/EntityUtil.java index 91eb4e99d..9bbc4e1aa 100644 --- a/Core/src/main/java/com/plotsquared/core/util/EntityUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/EntityUtil.java @@ -90,6 +90,7 @@ public final class EntityUtil { if (mobs[i] >= cap) { plot.setMeta("EntityCount", mobs); plot.setMeta("EntityCountTime", System.currentTimeMillis()); + plot.debug("Prevented spawning of mob because it would exceed " + flag.getName()); return true; } } diff --git a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java index a5f8add50..4af113ca6 100644 --- a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java @@ -49,7 +49,7 @@ public abstract class PlayerManager

, T> { * * @param plotPlayer Player to remove */ - public void removePlayer(@NotNull final PlotPlayer plotPlayer) { + public void removePlayer(@NotNull final PlotPlayer plotPlayer) { synchronized (playerLock) { this.playerMap.remove(plotPlayer.getUUID()); } From 2d6e6ceaeb189be67095a7c4a55ca8e526ce9a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Mon, 22 Jun 2020 15:45:57 +0200 Subject: [PATCH 097/121] Improve documentation of BukkitMain#wrapPlayer and improve generic types --- .../com/plotsquared/bukkit/BukkitMain.java | 100 ++++++++++++------ .../plotsquared/bukkit/util/BukkitUtil.java | 2 +- .../java/com/plotsquared/core/IPlotMain.java | 3 +- .../plotsquared/core/player/PlotPlayer.java | 4 +- 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 582f94746..c423d8102 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -235,11 +235,12 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< PlotSquared.log(Captions.PREFIX + "&6Couldn't verify purchase :("); } - final UUIDPipeline impromptuPipeline = PlotSquared.get().getImpromptuUUIDPipeline(); + final UUIDPipeline impromptuPipeline = PlotSquared.get().getImpromptuUUIDPipeline(); final UUIDPipeline backgroundPipeline = PlotSquared.get().getBackgroundUUIDPipeline(); // Services are accessed in order - final CacheUUIDService cacheUUIDService = new CacheUUIDService(Settings.UUID.UUID_CACHE_SIZE); + final CacheUUIDService cacheUUIDService = + new CacheUUIDService(Settings.UUID.UUID_CACHE_SIZE); impromptuPipeline.registerService(cacheUUIDService); backgroundPipeline.registerService(cacheUUIDService); impromptuPipeline.registerConsumer(cacheUUIDService); @@ -261,7 +262,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< final SQLiteUUIDService sqLiteUUIDService = new SQLiteUUIDService("user_cache.db"); final SQLiteUUIDService legacyUUIDService; - if (Settings.UUID.LEGACY_DATABASE_SUPPORT && MainUtil.getFile(PlotSquared.get().IMP.getDirectory(), "usercache.db").exists()) { + if (Settings.UUID.LEGACY_DATABASE_SUPPORT && MainUtil + .getFile(PlotSquared.get().IMP.getDirectory(), "usercache.db").exists()) { legacyUUIDService = new SQLiteUUIDService("usercache.db"); } else { legacyUUIDService = null; @@ -270,7 +272,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< final LuckPermsUUIDService luckPermsUUIDService; if (Bukkit.getPluginManager().getPlugin("LuckPerms") != null) { luckPermsUUIDService = new LuckPermsUUIDService(); - PlotSquared.log(Captions.PREFIX + "(UUID) Using LuckPerms as a complementary UUID service"); + PlotSquared + .log(Captions.PREFIX + "(UUID) Using LuckPerms as a complementary UUID service"); } else { luckPermsUUIDService = null; } @@ -278,15 +281,17 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< final BungeePermsUUIDService bungeePermsUUIDService; if (Bukkit.getPluginManager().getPlugin("BungeePerms") != null) { bungeePermsUUIDService = new BungeePermsUUIDService(); - PlotSquared.log(Captions.PREFIX + "(UUID) Using BungeePerms as a complementary UUID service"); + PlotSquared + .log(Captions.PREFIX + "(UUID) Using BungeePerms as a complementary UUID service"); } else { bungeePermsUUIDService = null; } - + final EssentialsUUIDService essentialsUUIDService; if (Bukkit.getPluginManager().getPlugin("Essentials") != null) { essentialsUUIDService = new EssentialsUUIDService(); - PlotSquared.log(Captions.PREFIX + "(UUID) Using Essentials as a complementary UUID service"); + PlotSquared + .log(Captions.PREFIX + "(UUID) Using Essentials as a complementary UUID service"); } else { essentialsUUIDService = null; } @@ -297,7 +302,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< final PaperUUIDService paperUUIDService = new PaperUUIDService(); impromptuPipeline.registerService(paperUUIDService); backgroundPipeline.registerService(paperUUIDService); - PlotSquared.log(Captions.PREFIX + "(UUID) Using Paper as a complementary UUID service"); + PlotSquared + .log(Captions.PREFIX + "(UUID) Using Paper as a complementary UUID service"); } impromptuPipeline.registerService(sqLiteUUIDService); @@ -324,9 +330,11 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< backgroundPipeline.registerService(essentialsUUIDService); } - final SquirrelIdUUIDService impromptuMojangService = new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT); + final SquirrelIdUUIDService impromptuMojangService = + new SquirrelIdUUIDService(Settings.UUID.IMPROMPTU_LIMIT); impromptuPipeline.registerService(impromptuMojangService); - final SquirrelIdUUIDService backgroundMojangService = new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT); + final SquirrelIdUUIDService backgroundMojangService = + new SquirrelIdUUIDService(Settings.UUID.BACKGROUND_LIMIT); backgroundPipeline.registerService(backgroundMojangService); } else { impromptuPipeline.registerService(sqLiteUUIDService); @@ -381,8 +389,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< this.worldManager = new BukkitWorldManager(); } - PlotSquared.log(Captions.PREFIX.getTranslated() + "Using platform world manager: " + - this.worldManager.getName()); + PlotSquared.log( + Captions.PREFIX.getTranslated() + "Using platform world manager: " + this.worldManager + .getName()); } private void unload() { @@ -465,7 +474,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< } private void startUuidCatching(@NotNull final SQLiteUUIDService sqLiteUUIDService, - @NotNull final CacheUUIDService cacheUUIDService) { + @NotNull final CacheUUIDService cacheUUIDService) { // Load all uuids into a big chunky boi queue final Queue uuidQueue = new LinkedBlockingQueue<>(); PlotSquared.get().forEachPlotRaw(plot -> { @@ -480,7 +489,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< } } }); - PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) " + uuidQueue.size() + " UUIDs will be cached."); + PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) " + uuidQueue.size() + + " UUIDs will be cached."); Executors.newSingleThreadScheduledExecutor().schedule(() -> { // Begin by reading all the SQLite cache at once @@ -488,7 +498,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< // Now fetch names for all known UUIDs final int totalSize = uuidQueue.size(); int read = 0; - PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) PlotSquared will fetch UUIDs in groups of " + PlotSquared.log(Captions.PREFIX.getTranslated() + + "(UUID) PlotSquared will fetch UUIDs in groups of " + Settings.UUID.BACKGROUND_LIMIT); final List uuidList = new ArrayList<>(Settings.UUID.BACKGROUND_LIMIT); @@ -505,7 +516,8 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< // fresh batch secondRun = false; // Populate the request list - for (int i = 0; i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) { + for (int i = 0; + i < Settings.UUID.BACKGROUND_LIMIT && !uuidQueue.isEmpty(); i++) { uuidList.add(uuidQueue.poll()); read++; } @@ -520,13 +532,15 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< uuidList.clear(); // Print progress final double percentage = ((double) read / (double) totalSize) * 100.0D; - PlotSquared.log(Captions.PREFIX.getTranslated() + String.format("(UUID) PlotSquared has cached %.1f%% of UUIDs", percentage)); + PlotSquared.log(Captions.PREFIX.getTranslated() + String + .format("(UUID) PlotSquared has cached %.1f%% of UUIDs", percentage)); } catch (final InterruptedException | ExecutionException e) { PlotSquared.log("Failed to retrieve that batch. Will try again."); e.printStackTrace(); } } - PlotSquared.log(Captions.PREFIX.getTranslated() + "(UUID) PlotSquared has cached all UUIDs"); + PlotSquared + .log(Captions.PREFIX.getTranslated() + "(UUID) PlotSquared has cached all UUIDs"); }, 10, TimeUnit.SECONDS); } @@ -903,8 +917,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< return new BukkitUtil(); } - @Override @Nullable - public GeneratorWrapper getGenerator(@NonNull final String world, + @Override @Nullable public GeneratorWrapper getGenerator(@NonNull final String world, @Nullable final String name) { if (name == null) { return null; @@ -955,7 +968,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< metrics.addCustomChart(new Metrics.SimplePie("premium", () -> PremiumVerification.isPremium() ? "Premium" : "Non-Premium")); metrics.addCustomChart(new Metrics.SimplePie("worldedit_implementation", - () -> Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null ? "FastAsyncWorldEdit" : "WorldEdit")); + () -> Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null ? + "FastAsyncWorldEdit" : + "WorldEdit")); } @Override public ChunkManager initChunkManager() { @@ -993,13 +1008,12 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< ConfigurationSection worldConfig = PlotSquared.get().worlds.getConfigurationSection("worlds." + worldName); String manager = worldConfig.getString("generator.plugin", getPluginName()); - PlotAreaBuilder builder = new PlotAreaBuilder() - .plotManager(manager) - .generatorName(worldConfig.getString("generator.init", manager)) - .plotAreaType(MainUtil.getType(worldConfig)) - .terrainType(MainUtil.getTerrain(worldConfig)) - .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)) - .worldName(worldName); + PlotAreaBuilder builder = new PlotAreaBuilder().plotManager(manager) + .generatorName(worldConfig.getString("generator.init", manager)) + .plotAreaType(MainUtil.getType(worldConfig)) + .terrainType(MainUtil.getTerrain(worldConfig)) + .settingsNodesWrapper(new SettingsNodesWrapper(new ConfigurationNode[0], null)) + .worldName(worldName); SetupUtils.manager.setupWorld(builder); world = Bukkit.getWorld(worldName); } else { @@ -1028,7 +1042,22 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< return new BukkitSchematicHandler(); } - @Override @Nullable public PlotPlayer wrapPlayer(final Object player) { + /** + * Attempt to retrieve a {@link PlotPlayer} from a player identifier. + * This method accepts: + * - {@link Player} objects, + * - {@link OfflinePlayer} objects, + * - {@link String} usernames for online players, and + * - {@link UUID} UUIDs for online players + *

+ * In the case of offline players, a fake {@link Player} instance will be created. + * This is a rather expensive operation, and should be avoided if possible. + * + * @param player The player to convert to a PlotPlayer + * @return The plot player instance that corresponds to the identifier, or null + * if no such player object could be created + */ + @Override @Nullable public PlotPlayer wrapPlayer(final Object player) { if (player instanceof Player) { return BukkitUtil.getPlayer((Player) player); } @@ -1036,10 +1065,12 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< return BukkitUtil.getPlayer((OfflinePlayer) player); } if (player instanceof String) { - return PlotSquared.imp().getPlayerManager().getPlayerIfExists((String) player); + return (PlotPlayer) PlotSquared.imp().getPlayerManager() + .getPlayerIfExists((String) player); } if (player instanceof UUID) { - return PlotSquared.imp().getPlayerManager().getPlayerIfExists((UUID) player); + return (PlotPlayer) PlotSquared.imp().getPlayerManager() + .getPlayerIfExists((UUID) player); } return null; } @@ -1057,8 +1088,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< } } - @Override - public GeneratorWrapper wrapPlotGenerator(@Nullable final String world, + @Override public GeneratorWrapper wrapPlotGenerator(@Nullable final String world, @NonNull final IndependentPlotGenerator generator) { return new BukkitPlotGenerator(world, generator); } @@ -1080,7 +1110,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< return wePlugin.wrapCommandSender(console); } - @Override @NotNull public PlayerManager, ? extends Player> getPlayerManager() { + @Override @NotNull + public PlayerManager, ? extends Player> getPlayerManager() { return this.playerManager; } + } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index b771c5e45..d73a11a54 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -121,7 +121,7 @@ public class BukkitUtil extends WorldUtil { lastPlotPlayer = null; } - public static PlotPlayer getPlayer(@NonNull final OfflinePlayer op) { + public static PlotPlayer getPlayer(@NonNull final OfflinePlayer op) { if (op.isOnline()) { return getPlayer(op.getPlayer()); } diff --git a/Core/src/main/java/com/plotsquared/core/IPlotMain.java b/Core/src/main/java/com/plotsquared/core/IPlotMain.java index 57625ee3f..eb70402f6 100644 --- a/Core/src/main/java/com/plotsquared/core/IPlotMain.java +++ b/Core/src/main/java/com/plotsquared/core/IPlotMain.java @@ -45,6 +45,7 @@ import com.plotsquared.core.util.logger.ILogger; import com.plotsquared.core.util.task.TaskManager; import com.sk89q.worldedit.extension.platform.Actor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.List; @@ -84,7 +85,7 @@ public interface IPlotMain

extends ILogger { * @param player The player to convert to a PlotPlayer * @return A PlotPlayer */ - PlotPlayer wrapPlayer(Object player); + @Nullable PlotPlayer

wrapPlayer(Object player); /** * Completely shuts down the plugin. diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java index 568498786..47470d80e 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -121,8 +121,8 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer * - Accepts UUID * - Accepts bukkit OfflinePlayer (offline) * - * @param player - * @return + * @param player Player object to wrap + * @return Wrapped player */ public static PlotPlayer wrap(Object player) { return PlotSquared.get().IMP.wrapPlayer(player); From 14baead342b999dd4bff75a24d93fee5bf23ac5b Mon Sep 17 00:00:00 2001 From: EpiCanard Date: Tue, 23 Jun 2020 01:20:17 +0200 Subject: [PATCH 098/121] Add placeholder to get the value of a plot flag --- .../bukkit/placeholder/Placeholders.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java index 0ae44fbcb..39de8a7fd 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java @@ -29,6 +29,8 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.flag.GlobalFlagContainer; +import com.plotsquared.core.plot.flag.PlotFlag; import me.clip.placeholderapi.PlaceholderAPIPlugin; import me.clip.placeholderapi.expansion.PlaceholderExpansion; import org.bukkit.Bukkit; @@ -36,9 +38,13 @@ import org.bukkit.entity.Player; import java.util.Set; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class Placeholders extends PlaceholderExpansion { + private Pattern flagPattern = Pattern.compile("currentplot_flag_(.+)"); + public Placeholders() { } @@ -59,7 +65,7 @@ public class Placeholders extends PlaceholderExpansion { } @Override public String getVersion() { - return "2.4"; + return "2.5"; } @Override public String onPlaceholderRequest(Player p, String identifier) { @@ -124,7 +130,7 @@ public class Placeholders extends PlaceholderExpansion { return ""; } - String name = PlotSquared.get().getImpromptuUUIDPipeline() .getSingle(uid, + String name = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(uid, Settings.UUID.BLOCKING_TIMEOUT); if (name != null) { @@ -181,6 +187,31 @@ public class Placeholders extends PlaceholderExpansion { default: break; } + final Matcher matcher = this.flagPattern.matcher(identifier); + if (matcher.find()) { + return getFlag(plot, matcher.group(1)); + } + return ""; + } + + /** + * Return the flag value from its name on the current plot. + * If the flag doesn't exist it return an empty string. + * If the flag exists but it is not set on current plot it return the default value. + * + * @param plot Current plot where the player is + * @param flagName Name of flag to get from current plot + * @return The value of flag serialized in string + */ + private String getFlag(final Plot plot, final String flagName) { + final PlotFlag flag = GlobalFlagContainer.getInstance().getFlagFromString(flagName); + if (flag != null) { + return plot.getFlags().stream() + .filter(pflag -> pflag.getName().equals(flagName)).findFirst() + .map(PlotFlag::getValue) + .map(Object::toString) + .orElseGet(() -> plot.getFlagContainer().getFlagErased(flag.getClass()).toString()); + } return ""; } } From 2b4e2fc793d69b3bc2ee7d5f615cf1bade40924f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 23 Jun 2020 11:39:45 +0200 Subject: [PATCH 099/121] Add plot debugging and make tab completable aliases configurable --- .../bukkit/listener/PaperListener.java | 9 ++- .../bukkit/listener/PlayerEvents.java | 65 ++++++++++++++++--- .../com/plotsquared/core/command/Debug.java | 7 ++ .../com/plotsquared/core/command/Toggle.java | 2 +- .../core/configuration/Captions.java | 2 +- .../core/configuration/Settings.java | 2 + .../plotsquared/core/player/PlotPlayer.java | 8 ++- .../java/com/plotsquared/core/plot/Plot.java | 2 +- 8 files changed, 78 insertions(+), 19 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java index ec5384ab5..a512189f7 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PaperListener.java @@ -60,7 +60,6 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.projectiles.ProjectileSource; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Locale; @@ -280,7 +279,7 @@ public class PaperListener implements Listener { } final int tileEntityCount = event.getBlock().getChunk().getTileEntities(false).length; if (tileEntityCount >= Settings.Chunk_Processor.MAX_TILES) { - final PlotPlayer plotPlayer = BukkitUtil.getPlayer(event.getPlayer()); + final PlotPlayer plotPlayer = BukkitUtil.getPlayer(event.getPlayer()); Captions.TILE_ENTITY_CAP_REACHED.send(plotPlayer, Settings.Chunk_Processor.MAX_TILES); event.setCancelled(true); event.setBuild(false); @@ -309,7 +308,7 @@ public class PaperListener implements Listener { if (!PlotSquared.get().hasPlotArea(location.getWorld())) { return; } - PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); + PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); Plot plot = location.getOwnedPlot(); if (plot != null && !plot.isAdded(pp.getUUID())) { entity.remove(); @@ -334,14 +333,14 @@ public class PaperListener implements Listener { final String[] unprocessedArgs = buffer.split(Pattern.quote(" ")); if (unprocessedArgs.length == 1) { return; // We don't do anything in this case - } else if (!Arrays.asList("plot", "plots", "p", "plotsquared", "plot2", "p2", "ps", "2", "plotme", "plotz", "ap") + } else if (!Settings.Enabled_Components.TAB_COMPLETED_ALIASES .contains(unprocessedArgs[0].toLowerCase(Locale.ENGLISH))) { return; } final String[] args = new String[unprocessedArgs.length - 1]; System.arraycopy(unprocessedArgs, 1, args, 0, args.length); try { - final PlotPlayer player = BukkitUtil.getPlayer((Player) event.getSender()); + final PlotPlayer player = BukkitUtil.getPlayer((Player) event.getSender()); final Collection objects = MainCommand.getInstance().tab(player, args, buffer.endsWith(" ")); if (objects == null) { return; diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 2ac326b93..f94c54638 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -253,7 +253,7 @@ public class PlayerEvents extends PlotListener implements Listener { int z = bloc.getBlockZ(); int distance = Bukkit.getViewDistance() * 16; - for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { Location location = player.getLocation(); if (location.getWorld().equals(world)) { if (16 * Math.abs(location.getX() - x) / 16 > distance @@ -313,7 +313,7 @@ public class PlayerEvents extends PlotListener implements Listener { Location location = BukkitUtil.getLocation(e.getEntity()); if (location.isPlotArea()) { if (e.getEntity() instanceof Player) { - PlotPlayer player = BukkitUtil.getPlayer((Player) e.getEntity()); + PlotPlayer player = BukkitUtil.getPlayer((Player) e.getEntity()); Plot plot = player.getCurrentPlot(); if (plot != null) { if (!plot.isAdded(player.getUUID())) { @@ -346,6 +346,7 @@ public class PlayerEvents extends PlotListener implements Listener { } if (!plot.getFlag(RedstoneFlag.class)) { event.setNewCurrent(0); + plot.debug("Redstone event was cancelled because redstone = false"); return; } if (Settings.Redstone.DISABLE_OFFLINE) { @@ -372,12 +373,13 @@ public class PlayerEvents extends PlotListener implements Listener { } if (disable) { event.setNewCurrent(0); + plot.debug("Redstone event was cancelled because no trusted player was in the plot"); return; } } } if (Settings.Redstone.DISABLE_UNOCCUPIED) { - for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { + for (final PlotPlayer player : PlotSquared.imp().getPlayerManager().getPlayers()) { if (plot.equals(player.getCurrentPlot())) { return; } @@ -484,7 +486,7 @@ public class PlayerEvents extends PlotListener implements Listener { if (!PlotSquared.get().hasPlotArea(location.getWorld())) { return; } - PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); + PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); Plot plot = location.getOwnedPlot(); if (plot != null && !plot.isAdded(pp.getUUID())) { entity.remove(); @@ -505,7 +507,7 @@ public class PlayerEvents extends PlotListener implements Listener { Plot plot = area.getPlot(location); ProjectileSource shooter = entity.getShooter(); if (shooter instanceof Player) { - PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); + PlotPlayer pp = BukkitUtil.getPlayer((Player) shooter); if (plot == null) { if (!Permissions.hasPermission(pp, Captions.PERMISSION_PROJECTILE_UNOWNED)) { entity.remove(); @@ -547,7 +549,7 @@ public class PlayerEvents extends PlotListener implements Listener { return; } Player player = event.getPlayer(); - PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); + PlotPlayer plotPlayer = BukkitUtil.getPlayer(player); Location location = plotPlayer.getLocation(); PlotArea area = location.getPlotArea(); if (area == null) { @@ -652,7 +654,7 @@ public class PlayerEvents extends PlotListener implements Listener { public void onConnect(PlayerJoinEvent event) { final Player player = event.getPlayer(); BukkitUtil.removePlayer(player.getName()); - final PlotPlayer pp = BukkitUtil.getPlayer(player); + final PlotPlayer pp = BukkitUtil.getPlayer(player); Location location = pp.getLocation(); PlotArea area = location.getPlotArea(); @@ -691,7 +693,7 @@ public class PlayerEvents extends PlotListener implements Listener { @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void playerRespawn(PlayerRespawnEvent event) { Player player = event.getPlayer(); - PlotPlayer pp = BukkitUtil.getPlayer(player); + PlotPlayer pp = BukkitUtil.getPlayer(player); PlotSquared.get().getEventDispatcher().doRespawnTask(pp); } @@ -958,7 +960,7 @@ public class PlayerEvents extends PlotListener implements Listener { Set recipients = event.getRecipients(); recipients.clear(); Set spies = new HashSet<>(); - for (final PlotPlayer pp : PlotSquared.imp().getPlayerManager().getPlayers()) { + for (final PlotPlayer pp : PlotSquared.imp().getPlayerManager().getPlayers()) { if (pp.getAttribute("chatspy")) { spies.add(((BukkitPlayer) pp).player); } else { @@ -1106,6 +1108,8 @@ public class PlayerEvents extends PlotListener implements Listener { } } return; + } else { + plot.debug("Explosion was cancelled because explosion = false"); } } event.setCancelled(true); @@ -1150,6 +1154,7 @@ public class PlayerEvents extends PlotListener implements Listener { if (area != null) { Plot plot = area.getOwnedPlot(location); if (plot != null && plot.getFlag(MobPlaceFlag.class)) { + plot.debug(e.getType() + " could not change block because mob-place = false"); return; } event.setCancelled(true); @@ -1179,6 +1184,7 @@ public class PlayerEvents extends PlotListener implements Listener { if (!plot.hasOwner()) { BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); if (plot.getFlag(IceFormFlag.class)) { + plot.debug("Ice could not be formed because ice-form = false"); return; } event.setCancelled(true); @@ -1187,6 +1193,7 @@ public class PlayerEvents extends PlotListener implements Listener { BukkitPlayer plotPlayer = BukkitUtil.getPlayer(player); if (!plot.isAdded(plotPlayer.getUUID())) { if (plot.getFlag(IceFormFlag.class)) { + plot.debug("Ice could not be formed because ice-form = false"); return; } event.setCancelled(true); @@ -1218,21 +1225,25 @@ public class PlayerEvents extends PlotListener implements Listener { switch (event.getSource().getType()) { case GRASS_BLOCK: if (!plot.getFlag(GrassGrowFlag.class)) { + plot.debug("Grass could not grow because grass-grow = false"); event.setCancelled(true); } break; case MYCELIUM: if (!plot.getFlag(MycelGrowFlag.class)) { + plot.debug("Mycelium could not grow because mycel-grow = false"); event.setCancelled(true); } break; case VINE: if (!plot.getFlag(VineGrowFlag.class)) { + plot.debug("Vine could not grow because vine-grow = false"); event.setCancelled(true); } break; case KELP: if (!plot.getFlag(KelpGrowFlag.class)) { + plot.debug("Kelp could not grow because kelp-grow = false"); event.setCancelled(true); } break; @@ -1259,6 +1270,7 @@ public class PlayerEvents extends PlotListener implements Listener { case SNOW: case SNOW_BLOCK: if (!plot.getFlag(SnowFormFlag.class)) { + plot.debug("Snow could not form because snow-form = false"); event.setCancelled(true); } return; @@ -1266,6 +1278,7 @@ public class PlayerEvents extends PlotListener implements Listener { case FROSTED_ICE: case PACKED_ICE: if (!plot.getFlag(IceFormFlag.class)) { + plot.debug("Ice could not form because ice-form = false"); event.setCancelled(true); } } @@ -1315,6 +1328,8 @@ public class PlayerEvents extends PlotListener implements Listener { .hasPermission(plotPlayer, Captions.PERMISSION_ADMIN_DESTROY_OTHER)) { return; } + plot.debug(player.getName() + " could not break " + block.getType() + + " because it was not in the break flag"); event.setCancelled(true); return; } @@ -1343,16 +1358,19 @@ public class PlayerEvents extends PlotListener implements Listener { switch (block.getType()) { case ICE: if (!plot.getFlag(IceMeltFlag.class)) { + plot.debug("Ice could not melt because ice-melt = false"); event.setCancelled(true); } break; case SNOW: if (!plot.getFlag(SnowMeltFlag.class)) { + plot.debug("Snow could not melt because snow-melt = false"); event.setCancelled(true); } break; case FARMLAND: if (!plot.getFlag(SoilDryFlag.class)) { + plot.debug("Soil could not dry because soil-dry = false"); event.setCancelled(true); } break; @@ -1372,6 +1390,7 @@ public class PlayerEvents extends PlotListener implements Listener { case FIRE_CORAL_FAN: case HORN_CORAL_FAN: if (!plot.getFlag(CoralDryFlag.class)) { + plot.debug("Coral could not dry because coral-dry = false"); event.setCancelled(true); } break; @@ -1390,6 +1409,7 @@ public class PlayerEvents extends PlotListener implements Listener { if (plot != null && plot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.DISABLED && event .getBlock().isLiquid()) { + plot.debug("Liquid could now flow because liquid-flow = disabled"); event.setCancelled(true); return; } @@ -1413,11 +1433,13 @@ public class PlayerEvents extends PlotListener implements Listener { return; } if (plot.getFlag(DisablePhysicsFlag.class)) { + plot.debug(event.getBlock().getType() + " could not update because disable-physics = true"); event.setCancelled(true); return; } if (plot.getFlag(LiquidFlowFlag.class) == LiquidFlowFlag.FlowStatus.DISABLED && event .getBlock().isLiquid()) { + plot.debug("Liquid could not flow because liquid-flow = disabled"); event.setCancelled(true); } } else if (!area.contains(fLocation.getX(), fLocation.getZ()) || !Objects @@ -1698,6 +1720,7 @@ public class PlayerEvents extends PlotListener implements Listener { !Permissions.hasPermission(pp, Captions.PERMISSION_ADMIN_INTERACT_OTHER)) { final ItemStack newStack = new ItemStack(newItem.getType(), newItem.getAmount()); event.setCursor(newStack); + plot.debug(player.getName() + " could not creative-copy an item because prevent-creative-copy = true"); } return; } @@ -1845,6 +1868,7 @@ public class PlayerEvents extends PlotListener implements Listener { MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, "plots.admin.interact.other"); e.setCancelled(true); + plot.debug(pp.getName() + " could not interact with " + entity.getType() + " bcause misc-interact = false"); } } } @@ -1872,6 +1896,9 @@ public class PlayerEvents extends PlotListener implements Listener { Plot plot = area.getOwnedPlot(location); if (plot == null || !plot.getFlag(ExplosionFlag.class)) { event.setCancelled(true); + if (plot != null) { + plot.debug("Explosion was cancelled because explosion = false"); + } } event.blockList().removeIf( blox -> !plot.equals(area.getOwnedPlot(BukkitUtil.getLocation(blox.getLocation())))); @@ -2137,6 +2164,7 @@ public class PlayerEvents extends PlotListener implements Listener { Plot plot = area.getOwnedPlotAbs(location); if (plot == null || plot.getFlag(DisablePhysicsFlag.class)) { event.setCancelled(true); + plot.debug("Falling block event was cancelled because disable-physics = true"); return; } if (event.getTo().hasGravity()) { @@ -2172,6 +2200,7 @@ public class PlayerEvents extends PlotListener implements Listener { Plot plot = location.getOwnedPlot(); if (plot == null || !plot.getFlag(BlockBurnFlag.class)) { + plot.debug("Block burning was cancelled because block-burn = false"); event.setCancelled(true); } @@ -2225,6 +2254,7 @@ public class PlayerEvents extends PlotListener implements Listener { if (ignitingEntity != null) { if (!plot.getFlag(BlockIgnitionFlag.class)) { event.setCancelled(true); + plot.debug("Block ignition was cancelled because block-ignition = false"); return; } if (igniteCause == BlockIgniteEvent.IgniteCause.FIREBALL) { @@ -2475,6 +2505,7 @@ public class PlayerEvents extends PlotListener implements Listener { MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, Captions.PERMISSION_ADMIN_DESTROY_OTHER); event.setCancelled(true); + plot.debug(p.getName() + " could not break hanging entity because hanging-break = false"); } } } else if (remover instanceof Projectile) { @@ -2503,6 +2534,7 @@ public class PlayerEvents extends PlotListener implements Listener { MainUtil.sendMessage(player, Captions.NO_PERMISSION_EVENT, Captions.PERMISSION_ADMIN_DESTROY_OTHER); event.setCancelled(true); + plot.debug(player.getName() + " could not break hanging entity because hanging-break = false"); } } } @@ -2621,6 +2653,7 @@ public class PlayerEvents extends PlotListener implements Listener { MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, "plots.admin.vehicle.break.other"); event.setCancelled(true); + plot.debug(pp.getName() + " could not break vehicle because vehicle-break = false"); } } } @@ -2815,6 +2848,9 @@ public class PlayerEvents extends PlotListener implements Listener { if (!Permissions.hasPermission(plotPlayer, "plots.admin.destroy." + stub)) { MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT, "plots.admin.destroy." + stub); + if (plot != null) { + plot.debug(player.getName() + " could not break armor stand because misc-break = false"); + } return false; } } else if (EntityCategories.HOSTILE.contains(entityType)) { @@ -2825,6 +2861,9 @@ public class PlayerEvents extends PlotListener implements Listener { if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + if (plot != null) { + plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR hostile-attack = false"); + } return false; } } else if (EntityCategories.TAMEABLE.contains(entityType)) { // victim is tameable @@ -2835,6 +2874,9 @@ public class PlayerEvents extends PlotListener implements Listener { if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + if (plot != null) { + plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR tamned-attack = false"); + } return false; } } else if (EntityCategories.PLAYER.contains(entityType)) { @@ -2843,6 +2885,7 @@ public class PlayerEvents extends PlotListener implements Listener { .hasPermission(plotPlayer, "plots.admin.pvp." + stub)) { MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT, "plots.admin.pvp." + stub); + plot.debug(player.getName() + " could not attack " + entityType + " because pve = false"); return false; } else { return true; @@ -2856,6 +2899,7 @@ public class PlayerEvents extends PlotListener implements Listener { } else if (EntityCategories.ANIMAL.contains(entityType)) { // victim is animal if (plot != null && (plot.getFlag(AnimalAttackFlag.class) || plot .getFlag(PveFlag.class) || plot.isAdded(plotPlayer.getUUID()))) { + plot.debug(player.getName() + " could not attack " + entityType + " because pve = false OR animal-attack = false"); return true; } if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { @@ -2874,6 +2918,9 @@ public class PlayerEvents extends PlotListener implements Listener { if (!Permissions.hasPermission(plotPlayer, "plots.admin.pve." + stub)) { MainUtil.sendMessage(plotPlayer, Captions.NO_PERMISSION_EVENT, "plots.admin.pve." + stub); + if (plot != null) { + plot.debug(player.getName() + " could not attack " + entityType + " because pve = false"); + } return false; } } diff --git a/Core/src/main/java/com/plotsquared/core/command/Debug.java b/Core/src/main/java/com/plotsquared/core/command/Debug.java index 8a4ef1737..91997a4ec 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Debug.java +++ b/Core/src/main/java/com/plotsquared/core/command/Debug.java @@ -72,6 +72,13 @@ public class Debug extends SubCommand { MainUtil.sendMessage(player, String.format("There are %d cached UUIDs", mappings.size())); return true; } + if (args.length > 0 && "debug-players".equalsIgnoreCase(args[0])) { + MainUtil.sendMessage(player, "Player in debug mode: " ); + for (final PlotPlayer pp : PlotPlayer.getDebugModePlayers()) { + MainUtil.sendMessage(player, "- " + pp.getName()); + } + return true; + } if (args.length > 0 && "entitytypes".equalsIgnoreCase(args[0])) { EntityCategories.init(); player.sendMessage(Captions.PREFIX.getTranslated() + "§cEntity Categories: "); diff --git a/Core/src/main/java/com/plotsquared/core/command/Toggle.java b/Core/src/main/java/com/plotsquared/core/command/Toggle.java index c0085fb6c..e9e46ac7a 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Toggle.java +++ b/Core/src/main/java/com/plotsquared/core/command/Toggle.java @@ -129,7 +129,7 @@ public class Toggle extends Command { public void debug(Command command, PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 whenDone) { - if (toggle(player, "debug")) { + if (!toggle(player, "debug")) { MainUtil.sendMessage(player, Captions.TOGGLE_ENABLED, command.toString()); } else { MainUtil.sendMessage(player, Captions.TOGGLE_DISABLED, command.toString()); diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 03f08cda9..03874da48 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -805,7 +805,7 @@ public enum Captions implements Caption { // // - PLOT_DEBUG("$1Plot Debug ($2%plot%$1): %message%", "Plot-Debug"), + PLOT_DEBUG("$2Plot Debug ($1%plot%$2): %message%", "Plot-Debug"), // /** diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index dc10790d8..7b0196412 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -568,6 +568,8 @@ public class Settings extends Config { "Read more about components here: https://wiki.intellectualsites.com/en/plotsquared/installation/plot-components"}) public static boolean COMPONENT_PRESETS = true; @Comment("Use UUID cache to complete usernames") public static boolean EXTENDED_USERNAME_COMPLETION = true; + @Comment("Command aliases that will be tab completed") + public static List TAB_COMPLETED_ALIASES = Arrays.asList("plot", "plots", "p", "plotsquared", "plot2", "p2", "ps", "2", "plotme", "plotz", "ap"); } } diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java index 47470d80e..a9af02b65 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -87,7 +87,7 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer private ConcurrentHashMap meta; private int hash; - public static PlotPlayer from(@NonNull final T object) { + public static PlotPlayer from(@NonNull final T object) { if (!converters.containsKey(object.getClass())) { throw new IllegalArgumentException(String .format("There is no registered PlotPlayer converter for type %s", @@ -101,7 +101,11 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer converters.put(clazz, converter); } - public static Collection> getDebugModePlayerInPlot(@NotNull final Plot plot) { + public static Collection> getDebugModePlayers() { + return Collections.unmodifiableCollection(debugModeEnabled); + } + + public static Collection> getDebugModePlayersInPlot(@NotNull final Plot plot) { if (debugModeEnabled.isEmpty()) { return Collections.emptyList(); } diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 85410628c..83e616e9f 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -2925,7 +2925,7 @@ public class Plot { } public void debug(@NotNull final String message) { - final Collection> players = PlotPlayer.getDebugModePlayerInPlot(this); + final Collection> players = PlotPlayer.getDebugModePlayersInPlot(this); if (players.isEmpty()) { return; } From f4724a3c87d8513bd3a21be00eb8cde012a5149e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 23 Jun 2020 11:45:04 +0200 Subject: [PATCH 100/121] Fix expiration flag commands --- .../core/plot/expiration/ExpireManager.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java index 88d167a50..532134536 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java +++ b/Core/src/main/java/com/plotsquared/core/plot/expiration/ExpireManager.java @@ -151,11 +151,11 @@ public class ExpireManager { //.text("\n - ").color("$3").text("Delete all (/plot delete expired)").color("$2").command("/plot delete expired") .text("\n - ").color("$3").text("Delete this (/plot delete)") .color("$2").command("/plot delete").tooltip("/plot delete") - .text("\n - ").color("$3").text("Remind later (/plot set keep 1d)") - .color("$2").command("/plot set keep 1d").tooltip("/plot set keep 1d") - .text("\n - ").color("$3").text("Keep this (/plot set keep true)") - .color("$2").command("/plot set keep true") - .tooltip("/plot set keep true").text("\n - ").color("$3") + .text("\n - ").color("$3").text("Remind later (/plot flag set keep 1d)") + .color("$2").command("/plot flag set keep 1d").tooltip("/plot flag set keep 1d") + .text("\n - ").color("$3").text("Keep this (/plot flag set keep true)") + .color("$2").command("/plot flag set keep true") + .tooltip("/plot flag set keep true").text("\n - ").color("$3") .text("Don't show me this").color("$2") .command("/plot toggle clear-confirmation") .tooltip("/plot toggle clear-confirmation"); From c52603921db067a215d2a58f9878765efcfcd45e Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Tue, 23 Jun 2020 13:13:01 +0200 Subject: [PATCH 101/121] Bump version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 0422b75a0..03053e64a 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ ext { git = Grgit.open(dir: new File(rootDir.toString() + "/.git")) } -def ver = "5.12.0" +def ver = "5.12.1" def versuffix = "" ext { if (project.hasProperty("versionsuffix")) { From 55cf34508a045b1d3239c0af3cc0cd6060218e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Tue, 23 Jun 2020 18:36:53 +0200 Subject: [PATCH 102/121] Fix issue where old player objects were not cleaned up properly. This is caused by an issue with the event order in Spigot (and Spigot derivatives), so the fix is rather hacky. --- .../com/plotsquared/bukkit/BukkitMain.java | 15 ++++++++++- .../bukkit/listener/PlayerEvents.java | 4 +-- .../plotsquared/bukkit/util/BukkitUtil.java | 4 ++- .../java/com/plotsquared/core/plot/Plot.java | 25 ++++++++++--------- .../plotsquared/core/util/PlayerManager.java | 16 ++++++++++-- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index c423d8102..1a40c51d5 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -392,6 +392,19 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< PlotSquared.log( Captions.PREFIX.getTranslated() + "Using platform world manager: " + this.worldManager .getName()); + + // Clean up potential memory leak + Bukkit.getScheduler().runTaskTimer(this, () -> { + try { + for (final PlotPlayer player : this.getPlayerManager().getPlayers()) { + if (player.getPlatformPlayer() == null || !player.getPlatformPlayer().isOnline()) { + this.getPlayerManager().removePlayer(player); + } + } + } catch (final Exception e) { + getLogger().warning("Failed to clean up players: " + e.getMessage()); + } + }, 100L, 100L); } private void unload() { @@ -982,7 +995,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< } @Override public void unregister(@NonNull final PlotPlayer player) { - BukkitUtil.removePlayer(player.getName()); + BukkitUtil.removePlayer(player.getUUID()); } @Override public void registerChunkProcessor() { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index f94c54638..643f80611 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -650,10 +650,10 @@ public class PlayerEvents extends PlotListener implements Listener { PlotSquared.get().getImpromptuUUIDPipeline().storeImmediately(event.getName(), uuid); } - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onConnect(PlayerJoinEvent event) { final Player player = event.getPlayer(); - BukkitUtil.removePlayer(player.getName()); + BukkitUtil.removePlayer(player.getUniqueId()); final PlotPlayer pp = BukkitUtil.getPlayer(player); Location location = pp.getLocation(); diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java index d73a11a54..5acdde298 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitUtil.java @@ -116,9 +116,11 @@ public class BukkitUtil extends WorldUtil { private static Player lastPlayer = null; private static BukkitPlayer lastPlotPlayer = null; - public static void removePlayer(String player) { + public static void removePlayer(UUID uuid) { lastPlayer = null; lastPlotPlayer = null; + // Make sure that it's removed internally + PlotSquared.imp().getPlayerManager().removePlayer(uuid); } public static PlotPlayer getPlayer(@NonNull final OfflinePlayer op) { diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 83e616e9f..0d756ac6c 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -2917,7 +2917,7 @@ public class Plot { */ public void reEnter() { TaskManager.runTaskLater(() -> { - for (PlotPlayer pp : Plot.this.getPlayersInPlot()) { + for (PlotPlayer pp : Plot.this.getPlayersInPlot()) { PlotListener.plotExit(pp, Plot.this); PlotListener.plotEntry(pp, Plot.this); } @@ -2925,18 +2925,19 @@ public class Plot { } public void debug(@NotNull final String message) { - final Collection> players = PlotPlayer.getDebugModePlayersInPlot(this); - if (players.isEmpty()) { - return; - } - final String string = Captions.PLOT_DEBUG.getTranslated().replace("%plot%", this.toString()) - .replace("%message%", message); - for (final PlotPlayer player : players) { - if (isOwner(player.getUUID()) || - Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_DEBUG_OTHER)) { - player.sendMessage(string); + try { + final Collection> players = PlotPlayer.getDebugModePlayersInPlot(this); + if (players.isEmpty()) { + return; } - } + final String string = + Captions.PLOT_DEBUG.getTranslated().replace("%plot%", this.toString()).replace("%message%", message); + for (final PlotPlayer player : players) { + if (isOwner(player.getUUID()) || Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_DEBUG_OTHER)) { + player.sendMessage(string); + } + } + } catch (final Exception ignored) {} } /** diff --git a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java index 4af113ca6..8c4ec1bea 100644 --- a/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/PlayerManager.java @@ -30,6 +30,7 @@ import com.plotsquared.core.player.PlotPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -55,6 +56,17 @@ public abstract class PlayerManager

, T> { } } + /** + * Remove a player from the player map + * + * @param uuid Player to remove + */ + public void removePlayer(@NotNull final UUID uuid) { + synchronized (playerLock) { + this.playerMap.remove(uuid); + } + } + /** * Get the player from its UUID if it is stored in the player map. * @@ -110,7 +122,7 @@ public abstract class PlayerManager

, T> { } } - @NotNull protected abstract P createPlayer(@NotNull final UUID uuid); + @NotNull public abstract P createPlayer(@NotNull final UUID uuid); /** * Get an an offline player object from the player's UUID @@ -134,7 +146,7 @@ public abstract class PlayerManager

, T> { * @return Unmodifiable collection of players */ public Collection

getPlayers() { - return Collections.unmodifiableCollection(this.playerMap.values()); + return Collections.unmodifiableCollection(new ArrayList<>(this.playerMap.values())); } From 29080de86008ccae6808ca5f181618055fb7f3a0 Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Tue, 23 Jun 2020 23:57:27 +0200 Subject: [PATCH 103/121] 5.12.2 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 03053e64a..635cd7ea4 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ ext { git = Grgit.open(dir: new File(rootDir.toString() + "/.git")) } -def ver = "5.12.1" +def ver = "5.12.2" def versuffix = "" ext { if (project.hasProperty("versionsuffix")) { From 7fbac4f2868b331df7ab07414986ed5c099d8b01 Mon Sep 17 00:00:00 2001 From: EpiCanard Date: Wed, 24 Jun 2020 00:51:27 +0200 Subject: [PATCH 104/121] Add a second placeholder to support only local flag of current plot --- .../bukkit/placeholder/Placeholders.java | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java index 39de8a7fd..ce2445052 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java @@ -38,13 +38,9 @@ import org.bukkit.entity.Player; import java.util.Set; import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class Placeholders extends PlaceholderExpansion { - private Pattern flagPattern = Pattern.compile("currentplot_flag_(.+)"); - public Placeholders() { } @@ -130,8 +126,8 @@ public class Placeholders extends PlaceholderExpansion { return ""; } - String name = PlotSquared.get().getImpromptuUUIDPipeline().getSingle(uid, - Settings.UUID.BLOCKING_TIMEOUT); + String name = PlotSquared.get().getImpromptuUUIDPipeline() + .getSingle(uid, Settings.UUID.BLOCKING_TIMEOUT); if (name != null) { return name; @@ -187,31 +183,40 @@ public class Placeholders extends PlaceholderExpansion { default: break; } - final Matcher matcher = this.flagPattern.matcher(identifier); - if (matcher.find()) { - return getFlag(plot, matcher.group(1)); + if (identifier.startsWith("currentplot_localflag_")) { + final String[] splitValues = identifier.split("currentplot_localflag_"); + return (splitValues.length >= 2) ? getFlagValue(plot, splitValues[1], false) : ""; + } + if (identifier.startsWith("currentplot_flag_")) { + final String[] splitValues = identifier.split("currentplot_flag_"); + return (splitValues.length >= 2) ? getFlagValue(plot, splitValues[1], true) : ""; } return ""; } /** * Return the flag value from its name on the current plot. - * If the flag doesn't exist it return an empty string. - * If the flag exists but it is not set on current plot it return the default value. + * If the flag doesn't exist it returns an empty string. + * If the flag exists but it is not set on current plot and the parameter inherit is set to true, + * it returns the default value. * * @param plot Current plot where the player is * @param flagName Name of flag to get from current plot + * @param inherit Define if it returns only the flag set on currentplot or also inherited flag * @return The value of flag serialized in string */ - private String getFlag(final Plot plot, final String flagName) { + private String getFlagValue(final Plot plot, final String flagName, final boolean inherit) { final PlotFlag flag = GlobalFlagContainer.getInstance().getFlagFromString(flagName); - if (flag != null) { - return plot.getFlags().stream() - .filter(pflag -> pflag.getName().equals(flagName)).findFirst() - .map(PlotFlag::getValue) - .map(Object::toString) - .orElseGet(() -> plot.getFlagContainer().getFlagErased(flag.getClass()).toString()); + if (flag == null) { + return ""; } - return ""; + + if (inherit) { + return plot.getFlag(flag).toString(); + } else { + final PlotFlag plotFlag = plot.getFlagContainer().queryLocal(flag.getClass()); + return (plotFlag != null) ? plotFlag.getValue().toString() : ""; + } + } } From 159b35c717fde43210e5d2bcbf11f45504a04841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 24 Jun 2020 08:05:06 +0200 Subject: [PATCH 105/121] Fix OfflinePlayerUUIDService breaking when no worlds have been loaded. --- .../bukkit/uuid/OfflinePlayerUUIDService.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java index 3789de0c7..7b904e627 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/uuid/OfflinePlayerUUIDService.java @@ -44,15 +44,19 @@ import java.util.UUID; public class OfflinePlayerUUIDService implements UUIDService { @Override @NotNull public List getNames(@NotNull final List uuids) { - if (Settings.UUID.FORCE_LOWERCASE) { + if (Settings.UUID.FORCE_LOWERCASE || Bukkit.getWorlds().isEmpty()) { return Collections.emptyList(); // This is useless now } final List wrappers = new ArrayList<>(uuids.size()); for (final UUID uuid : uuids) { final OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); - if (offlinePlayer.hasPlayedBefore()) { - wrappers.add(new UUIDMapping(uuid, offlinePlayer.getName())); - } + try { + if (offlinePlayer.hasPlayedBefore()) { + wrappers.add(new UUIDMapping(uuid, offlinePlayer.getName())); + } + } catch (final Exception ignored) {} /* This can be safely ignored. If this happens, it is + probably because it's called before the worlds have + been loaded. This is bad, but does not break anything */ } return wrappers; } From f6f26c6102d9c36426a892a59a1c5d375221327d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 24 Jun 2020 08:31:23 +0200 Subject: [PATCH 106/121] Fix issue where numbers were sometimes parsed as usernames when they shouldn't be. This commit also fixes an issue where "Not a valid plot ID" was sent twice. --- Bukkit/pom.xml | 2 +- .../com/plotsquared/core/command/Visit.java | 18 ++++++++++++++---- .../com/plotsquared/core/util/MainUtil.java | 3 ++- .../core/uuid/CacheUUIDService.java | 18 ++++++++++++++++++ .../plotsquared/core/uuid/UUIDPipeline.java | 16 ++++++++++++++++ .../com/plotsquared/core/uuid/UUIDService.java | 11 +++++++++++ build.gradle | 2 +- 7 files changed, 63 insertions(+), 7 deletions(-) diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index b94221c89..d01f91307 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -21,7 +21,7 @@ com.plotsquared PlotSquared-Core - 5.12.0 + 5.12.2 compile diff --git a/Core/src/main/java/com/plotsquared/core/command/Visit.java b/Core/src/main/java/com/plotsquared/core/command/Visit.java index 077f1f6de..f5243b4ba 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Visit.java +++ b/Core/src/main/java/com/plotsquared/core/command/Visit.java @@ -40,6 +40,7 @@ import com.plotsquared.core.util.query.PlotQuery; import com.plotsquared.core.util.query.SortingStrategy; import com.plotsquared.core.util.task.RunnableVal2; import com.plotsquared.core.util.task.RunnableVal3; +import com.plotsquared.core.uuid.UUIDMapping; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -193,7 +194,18 @@ public class Visit extends Command { case 1: final String[] finalArgs = args; int finalPage = page; - if (args[0].length() >= 2 && !args[0].contains(";") && !args[0].contains(",")) { + // Try to determine whether the given argument is a username + // or an ordinal + boolean isNumber = false; + if (args[0].length() < 2) { + isNumber = true; + } else if (args[0].length() <= 4 && MathMan.isInteger(args[0])) { + // Check if it's an all-digit username that is stored in cache + final UUIDMapping mapping = PlotSquared.get().getImpromptuUUIDPipeline().getImmediately(args[0]); + // If no UUID could be found, then we assume it's a number and not a username + isNumber = mapping == null; + } + if (!isNumber && args[0].length() >= 2 && !args[0].contains(";") && !args[0].contains(",")) { PlotSquared.get().getImpromptuUUIDPipeline().getSingle(args[0], (uuid, throwable) -> { if (throwable instanceof TimeoutException) { // The request timed out @@ -240,9 +252,7 @@ public class Visit extends Command { } else { // Try to parse a plot final Plot plot = MainUtil.getPlotFromString(player, finalArgs[0], true); - if (plot == null) { - MainUtil.sendMessage(player, Captions.NOT_VALID_PLOT_ID); - } else { + if (plot != null) { this.visit(player, PlotQuery.newQuery().withPlot(plot), null, confirm, whenDone, 1); } } diff --git a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java index 8546298b6..9e2a78853 100644 --- a/Core/src/main/java/com/plotsquared/core/util/MainUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/MainUtil.java @@ -55,6 +55,7 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.world.biome.BiomeType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -515,7 +516,7 @@ public class MainUtil { * @param message If a message should be sent to the player if a plot cannot be found * @return The plot if only 1 result is found, or null */ - public static Plot getPlotFromString(PlotPlayer player, String arg, boolean message) { + @Nullable public static Plot getPlotFromString(PlotPlayer player, String arg, boolean message) { if (arg == null) { if (player == null) { if (message) { diff --git a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java index 484146dae..563618afa 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/CacheUUIDService.java @@ -28,9 +28,11 @@ package com.plotsquared.core.uuid; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.UUID; import java.util.function.Consumer; @@ -81,4 +83,20 @@ public class CacheUUIDService implements UUIDService, Consumer @Override public boolean canBeSynchronous() { return true; } + + @Override @Nullable public UUIDMapping getImmediately(@NotNull final Object object) { + final List list; + if (object instanceof String) { + list = getUUIDs(Collections.singletonList((String) object)); + } else if (object instanceof UUID) { + list = getNames(Collections.singletonList((UUID) object)); + } else { + list = Collections.emptyList(); + } + if (list.isEmpty()) { + return null; + } + return list.get(0); + } + } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java index 8c8baa06d..997cdfdc1 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDPipeline.java @@ -405,4 +405,20 @@ public class UUIDPipeline { return mappings; } + /** + * Get a single UUID mapping immediately, if possible + * + * @param object Username ({@link String}) or {@link UUID} + * @return Mapping, if it could be found immediately + */ + @Nullable public final UUIDMapping getImmediately(@NotNull final Object object) { + for (final UUIDService uuidService : this.getServiceListInstance()) { + final UUIDMapping mapping = uuidService.getImmediately(object); + if (mapping != null) { + return mapping; + } + } + return null; + } + } diff --git a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java index 3b6419bd6..f6fe86f11 100644 --- a/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java +++ b/Core/src/main/java/com/plotsquared/core/uuid/UUIDService.java @@ -26,6 +26,7 @@ package com.plotsquared.core.uuid; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; @@ -75,4 +76,14 @@ public interface UUIDService { return false; } + /** + * Get a single UUID mapping immediately, if possible + * + * @param object Username ({@link String}) or {@link UUID} + * @return Mapping, if it could be found immediately + */ + default @Nullable UUIDMapping getImmediately(@NotNull final Object object) { + return null; + } + } diff --git a/build.gradle b/build.gradle index 03053e64a..635cd7ea4 100644 --- a/build.gradle +++ b/build.gradle @@ -30,7 +30,7 @@ ext { git = Grgit.open(dir: new File(rootDir.toString() + "/.git")) } -def ver = "5.12.1" +def ver = "5.12.2" def versuffix = "" ext { if (project.hasProperty("versionsuffix")) { From efab6e92f76eaccb62247aac2bac10f3659539f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 24 Jun 2020 13:44:06 +0200 Subject: [PATCH 107/121] Lower tab completion cache time and fix "Invalid player" message for `/plot kick` --- .../main/java/com/plotsquared/core/command/Kick.java | 10 +++++----- .../java/com/plotsquared/core/util/TabCompletions.java | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Kick.java b/Core/src/main/java/com/plotsquared/core/command/Kick.java index 6dc3aaa97..911ea9810 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Kick.java +++ b/Core/src/main/java/com/plotsquared/core/command/Kick.java @@ -72,12 +72,12 @@ public class Kick extends SubCommand { if (throwable instanceof TimeoutException) { MainUtil.sendMessage(player, Captions.FETCHING_PLAYERS_TIMEOUT); } else if (throwable != null || uuids.isEmpty()) { - MainUtil.sendMessage(player, Captions.INVALID_PLAYER); + MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); } else { - Set players = new HashSet<>(); + Set> players = new HashSet<>(); for (UUID uuid : uuids) { if (uuid == DBFunc.EVERYONE) { - for (PlotPlayer pp : plot.getPlayersInPlot()) { + for (PlotPlayer pp : plot.getPlayersInPlot()) { if (pp == player || Permissions .hasPermission(pp, Captions.PERMISSION_ADMIN_ENTRY_DENIED)) { continue; @@ -86,7 +86,7 @@ public class Kick extends SubCommand { } continue; } - PlotPlayer pp = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); + PlotPlayer pp = PlotSquared.imp().getPlayerManager().getPlayerIfExists(uuid); if (pp != null) { players.add(pp); } @@ -96,7 +96,7 @@ public class Kick extends SubCommand { MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); return; } - for (PlotPlayer player2 : players) { + for (PlotPlayer player2 : players) { if (!plot.equals(player2.getCurrentPlot())) { MainUtil.sendMessage(player, Captions.INVALID_PLAYER, args[0]); return; diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java index bb6c74bd4..dbf053c52 100644 --- a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java +++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java @@ -56,7 +56,7 @@ import java.util.stream.Collectors; public class TabCompletions { private final Cache> cachedCompletionValues = - CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).build(); + CacheBuilder.newBuilder().expireAfterWrite(15, TimeUnit.SECONDS).build(); private final Command booleanTrueCompletion = new Command(null, false, "true", "", RequiredType.NONE, null) {}; From f64026af1ae80cfb262b3425c43bd69c1c265a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Wed, 24 Jun 2020 15:26:06 +0200 Subject: [PATCH 108/121] Only initialise EconHandler when economy is enabled and stop accessing the static instance directly. --- .../bukkit/player/BukkitPlayer.java | 4 +- .../bukkit/util/BukkitEconHandler.java | 18 ++++----- .../com/plotsquared/core/PlotSquared.java | 3 +- .../com/plotsquared/core/command/Auto.java | 10 ++--- .../com/plotsquared/core/command/Buy.java | 4 +- .../com/plotsquared/core/command/Claim.java | 6 +-- .../plotsquared/core/command/DebugExec.java | 2 +- .../com/plotsquared/core/command/Delete.java | 4 +- .../com/plotsquared/core/command/ListCmd.java | 6 +-- .../plotsquared/core/command/MainCommand.java | 12 +++--- .../com/plotsquared/core/command/Merge.java | 18 ++++----- .../components/ComponentPresetManager.java | 8 ++-- .../plotsquared/core/player/PlotPlayer.java | 10 ++--- .../plotsquared/core/util/EconHandler.java | 38 +++++++++++++------ build.gradle | 2 + 15 files changed, 80 insertions(+), 65 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java index acbc31984..643039600 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java @@ -155,8 +155,8 @@ public class BukkitPlayer extends PlotPlayer { } @Override public boolean hasPermission(final String permission) { - if (this.offline && EconHandler.manager != null) { - return EconHandler.manager.hasPermission(getName(), permission); + if (this.offline && EconHandler.getEconHandler() != null) { + return EconHandler.getEconHandler().hasPermission(getName(), permission); } return this.player.hasPermission(permission); } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java index 1efd7fea5..b8387efed 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java @@ -48,28 +48,26 @@ public class BukkitEconHandler extends EconHandler { return this.econ != null && this.perms != null; } - private boolean setupPermissions() { + private void setupPermissions() { RegisteredServiceProvider permissionProvider = Bukkit.getServer().getServicesManager().getRegistration(Permission.class); if (permissionProvider != null) { this.perms = permissionProvider.getProvider(); } - return this.perms != null; } - private boolean setupEconomy() { + private void setupEconomy() { if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { - return false; + return; } RegisteredServiceProvider economyProvider = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); if (economyProvider != null) { this.econ = economyProvider.getProvider(); } - return this.econ != null; } - @Override public double getMoney(PlotPlayer player) { + @Override public double getMoney(PlotPlayer player) { double bal = super.getMoney(player); if (Double.isNaN(bal)) { return this.econ.getBalance(((BukkitPlayer) player).player); @@ -77,11 +75,11 @@ public class BukkitEconHandler extends EconHandler { return bal; } - @Override public void withdrawMoney(PlotPlayer player, double amount) { + @Override public void withdrawMoney(PlotPlayer player, double amount) { this.econ.withdrawPlayer(((BukkitPlayer) player).player, amount); } - @Override public void depositMoney(PlotPlayer player, double amount) { + @Override public void depositMoney(PlotPlayer player, double amount) { this.econ.depositPlayer(((BukkitPlayer) player).player, amount); } @@ -93,11 +91,11 @@ public class BukkitEconHandler extends EconHandler { return this.perms.playerHas(world, Bukkit.getOfflinePlayer(player), perm); } - @Override public double getBalance(PlotPlayer player) { + @Override public double getBalance(PlotPlayer player) { return this.econ.getBalance(player.getName()); } - public void setPermission(String world, String player, String perm, boolean value) { + @Deprecated public void setPermission(String world, String player, String perm, boolean value) { if (value) { this.perms.playerAdd(world, player, perm); } else { diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index 3f7f35229..30d738afc 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -304,8 +304,7 @@ public class PlotSquared { } // Economy if (Settings.Enabled_Components.ECONOMY) { - TaskManager - .runTask(() -> EconHandler.manager = PlotSquared.this.IMP.getEconomyHandler()); + TaskManager.runTask(() -> EconHandler.initializeEconHandler()); } if (Settings.Enabled_Components.COMPONENT_PRESETS) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Auto.java b/Core/src/main/java/com/plotsquared/core/command/Auto.java index 9658556d9..4c75de3f8 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Auto.java +++ b/Core/src/main/java/com/plotsquared/core/command/Auto.java @@ -157,9 +157,9 @@ public class Auto extends SubCommand { @Override public boolean onCommand(final PlotPlayer player, String[] args) { PlotArea plotarea = player.getApplicablePlotArea(); if (plotarea == null) { - if (EconHandler.manager != null) { + if (EconHandler.getEconHandler() != null) { for (PlotArea area : PlotSquared.get().getPlotAreaManager().getAllPlotAreas()) { - if (EconHandler.manager + if (EconHandler.getEconHandler() .hasPermission(area.getWorldName(), player.getName(), "plots.auto")) { if (plotarea != null) { plotarea = null; @@ -253,18 +253,18 @@ public class Auto extends SubCommand { return true; } } - if (EconHandler.manager != null && plotarea.useEconomy()) { + if (EconHandler.getEconHandler() != null && plotarea.useEconomy()) { Expression costExp = plotarea.getPrices().get("claim"); double cost = costExp.evaluate((double) (Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(plotarea.getWorldName()))); cost = (size_x * size_z) * cost; if (cost > 0d) { - if (!force && EconHandler.manager.getMoney(player) < cost) { + if (!force && EconHandler.getEconHandler().getMoney(player) < cost) { sendMessage(player, Captions.CANNOT_AFFORD_PLOT, "" + cost); return true; } - EconHandler.manager.withdrawMoney(player, cost); + EconHandler.getEconHandler().withdrawMoney(player, cost); sendMessage(player, Captions.REMOVED_BALANCE, cost + ""); } } diff --git a/Core/src/main/java/com/plotsquared/core/command/Buy.java b/Core/src/main/java/com/plotsquared/core/command/Buy.java index 036e2412f..337801385 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Buy.java +++ b/Core/src/main/java/com/plotsquared/core/command/Buy.java @@ -58,7 +58,7 @@ public class Buy extends Command { RunnableVal3 confirm, final RunnableVal2 whenDone) { - check(EconHandler.manager, Captions.ECON_DISABLED); + check(EconHandler.getEconHandler(), Captions.ECON_DISABLED); final Plot plot; if (args.length != 0) { checkTrue(args.length == 1, Captions.COMMAND_SYNTAX, getUsage()); @@ -82,7 +82,7 @@ public class Buy extends Command { confirm.run(this, () -> { Captions.REMOVED_BALANCE.send(player, price); - EconHandler.manager.depositMoney(PlotSquared.imp().getPlayerManager().getOfflinePlayer(plot.getOwnerAbs()), price); + EconHandler.getEconHandler().depositMoney(PlotSquared.imp().getPlayerManager().getOfflinePlayer(plot.getOwnerAbs()), price); PlotPlayer owner = PlotSquared.imp().getPlayerManager().getPlayerIfExists(plot.getOwnerAbs()); if (owner != null) { diff --git a/Core/src/main/java/com/plotsquared/core/command/Claim.java b/Core/src/main/java/com/plotsquared/core/command/Claim.java index 488b2dc84..481a25bf5 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Claim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Claim.java @@ -105,14 +105,14 @@ public class Claim extends SubCommand { } } } - if ((EconHandler.manager != null) && area.useEconomy() && !force) { + if ((EconHandler.getEconHandler() != null) && area.useEconomy() && !force) { Expression costExr = area.getPrices().get("claim"); double cost = costExr.evaluate((double) currentPlots); if (cost > 0d) { - if (EconHandler.manager.getMoney(player) < cost) { + if (EconHandler.getEconHandler().getMoney(player) < cost) { return sendMessage(player, Captions.CANNOT_AFFORD_PLOT, "" + cost); } - EconHandler.manager.withdrawMoney(player, cost); + EconHandler.getEconHandler().withdrawMoney(player, cost); sendMessage(player, Captions.REMOVED_BALANCE, cost + ""); } } diff --git a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java index 381582c57..3d6af68f1 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java @@ -166,7 +166,7 @@ public class DebugExec extends SubCommand { this.scope.put("BlockManager", WorldUtil.IMP); this.scope.put("SetupUtils", SetupUtils.manager); this.scope.put("EventUtil", PlotSquared.get().getEventDispatcher()); - this.scope.put("EconHandler", EconHandler.manager); + this.scope.put("EconHandler", EconHandler.getEconHandler()); this.scope.put("DBFunc", DBFunc.dbManager); this.scope.put("HybridUtils", HybridUtils.manager); this.scope.put("IMP", PlotSquared.get().IMP); diff --git a/Core/src/main/java/com/plotsquared/core/command/Delete.java b/Core/src/main/java/com/plotsquared/core/command/Delete.java index 6d8ea243e..5f8178e06 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Delete.java +++ b/Core/src/main/java/com/plotsquared/core/command/Delete.java @@ -86,11 +86,11 @@ public class Delete extends SubCommand { final long start = System.currentTimeMillis(); boolean result = plot.deletePlot(() -> { plot.removeRunning(); - if ((EconHandler.manager != null) && plotArea.useEconomy()) { + if ((EconHandler.getEconHandler() != null) && plotArea.useEconomy()) { Expression valueExr = plotArea.getPrices().get("sell"); double value = plots.size() * valueExr.evaluate((double) currentPlots); if (value > 0d) { - EconHandler.manager.depositMoney(player, value); + EconHandler.getEconHandler().depositMoney(player, value); sendMessage(player, Captions.ADDED_BALANCE, String.valueOf(value)); } } diff --git a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java index 811eb88a7..a08de0cd0 100644 --- a/Core/src/main/java/com/plotsquared/core/command/ListCmd.java +++ b/Core/src/main/java/com/plotsquared/core/command/ListCmd.java @@ -71,7 +71,7 @@ public class ListCmd extends SubCommand { private String[] getArgumentList(PlotPlayer player) { List args = new ArrayList<>(); - if (EconHandler.manager != null && Permissions + if (EconHandler.getEconHandler() != null && Permissions .hasPermission(player, Captions.PERMISSION_LIST_FOR_SALE)) { args.add("forsale"); } @@ -264,7 +264,7 @@ public class ListCmd extends SubCommand { Captions.PERMISSION_LIST_FOR_SALE); return false; } - if (EconHandler.manager == null) { + if (EconHandler.getEconHandler() == null) { break; } plotConsumer.accept(PlotQuery.newQuery().allPlots().thatPasses(plot -> plot.getFlag(PriceFlag.class) > 0)); @@ -404,7 +404,7 @@ public class ListCmd extends SubCommand { @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { final List completions = new LinkedList<>(); - if (EconHandler.manager != null && Permissions + if (EconHandler.getEconHandler() != null && Permissions .hasPermission(player, Captions.PERMISSION_LIST_FOR_SALE)) { completions.add("forsale"); } diff --git a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java index 6e1151c4c..a5c42b117 100644 --- a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java @@ -164,14 +164,14 @@ public class MainCommand extends Command { public void run(final Command cmd, final Runnable success, final Runnable failure) { if (cmd.hasConfirmation(player)) { CmdConfirm.addPending(player, cmd.getUsage(), () -> { - if (EconHandler.manager != null) { + if (EconHandler.getEconHandler() != null) { PlotArea area = player.getApplicablePlotArea(); if (area != null) { Expression priceEval = area.getPrices().get(cmd.getFullId()); Double price = priceEval != null ? priceEval.evaluate(0d) : 0d; if (price != null - && EconHandler.manager.getMoney(player) < price) { + && EconHandler.getEconHandler().getMoney(player) < price) { if (failure != null) { failure.run(); } @@ -185,12 +185,12 @@ public class MainCommand extends Command { }); return; } - if (EconHandler.manager != null) { + if (EconHandler.getEconHandler() != null) { PlotArea area = player.getApplicablePlotArea(); if (area != null) { Expression priceEval = area.getPrices().get(cmd.getFullId()); Double price = priceEval != null ? priceEval.evaluate(0d) : 0d; - if (price != 0d && EconHandler.manager.getMoney(player) < price) { + if (price != 0d && EconHandler.getEconHandler().getMoney(player) < price) { if (failure != null) { failure.run(); } @@ -252,14 +252,14 @@ public class MainCommand extends Command { if ("f".equals(args[0].substring(1))) { confirm = new RunnableVal3() { @Override public void run(Command cmd, Runnable success, Runnable failure) { - if (EconHandler.manager != null) { + if (EconHandler.getEconHandler() != null) { PlotArea area = player.getApplicablePlotArea(); if (area != null) { Expression priceEval = area.getPrices().get(cmd.getFullId()); Double price = priceEval != null ? priceEval.evaluate(0d) : 0d; if (price != 0d - && EconHandler.manager.getMoney(player) < price) { + && EconHandler.getEconHandler().getMoney(player) < price) { if (failure != null) { failure.run(); } diff --git a/Core/src/main/java/com/plotsquared/core/command/Merge.java b/Core/src/main/java/com/plotsquared/core/command/Merge.java index 962b48163..33754c4b8 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Merge.java +++ b/Core/src/main/java/com/plotsquared/core/command/Merge.java @@ -156,8 +156,8 @@ public class Merge extends SubCommand { return true; } if (plot.autoMerge(Direction.ALL, maxSize, uuid, terrain)) { - if (EconHandler.manager != null && plotArea.useEconomy() && price > 0d) { - EconHandler.manager.withdrawMoney(player, price); + if (EconHandler.getEconHandler() != null && plotArea.useEconomy() && price > 0d) { + EconHandler.getEconHandler().withdrawMoney(player, price); sendMessage(player, Captions.REMOVED_BALANCE, String.valueOf(price)); } MainUtil.sendMessage(player, Captions.SUCCESS_MERGE); @@ -174,8 +174,8 @@ public class Merge extends SubCommand { uuid = plot.getOwnerAbs(); } } - if (!force && EconHandler.manager != null && plotArea.useEconomy() && price > 0d - && EconHandler.manager.getMoney(player) < price) { + if (!force && EconHandler.getEconHandler() != null && plotArea.useEconomy() && price > 0d + && EconHandler.getEconHandler().getMoney(player) < price) { sendMessage(player, Captions.CANNOT_AFFORD_MERGE, String.valueOf(price)); return false; } @@ -192,8 +192,8 @@ public class Merge extends SubCommand { return true; } if (plot.autoMerge(direction, maxSize - size, uuid, terrain)) { - if (EconHandler.manager != null && plotArea.useEconomy() && price > 0d) { - EconHandler.manager.withdrawMoney(player, price); + if (EconHandler.getEconHandler() != null && plotArea.useEconomy() && price > 0d) { + EconHandler.getEconHandler().withdrawMoney(player, price); sendMessage(player, Captions.REMOVED_BALANCE, String.valueOf(price)); } MainUtil.sendMessage(player, Captions.SUCCESS_MERGE); @@ -226,12 +226,12 @@ public class Merge extends SubCommand { sendMessage(accepter, Captions.MERGE_NOT_VALID); return; } - if (EconHandler.manager != null && plotArea.useEconomy() && price > 0d) { - if (!force && EconHandler.manager.getMoney(player) < price) { + if (EconHandler.getEconHandler() != null && plotArea.useEconomy() && price > 0d) { + if (!force && EconHandler.getEconHandler().getMoney(player) < price) { sendMessage(player, Captions.CANNOT_AFFORD_MERGE, String.valueOf(price)); return; } - EconHandler.manager.withdrawMoney(player, price); + EconHandler.getEconHandler().withdrawMoney(player, price); sendMessage(player, Captions.REMOVED_BALANCE, String.valueOf(price)); } MainUtil.sendMessage(player, Captions.SUCCESS_MERGE); diff --git a/Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java b/Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java index 80ae1deb4..fb10eff9b 100644 --- a/Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java +++ b/Core/src/main/java/com/plotsquared/core/components/ComponentPresetManager.java @@ -170,12 +170,12 @@ public class ComponentPresetManager { return false; } - if (componentPreset.getCost() > 0.0D && EconHandler.manager != null && plot.getArea().useEconomy()) { - if (EconHandler.manager.getMoney(player) < componentPreset.getCost()) { + if (componentPreset.getCost() > 0.0D && EconHandler.getEconHandler() != null && plot.getArea().useEconomy()) { + if (EconHandler.getEconHandler().getMoney(player) < componentPreset.getCost()) { Captions.PRESET_CANNOT_AFFORD.send(player); return false; } else { - EconHandler.manager.withdrawMoney(player, componentPreset.getCost()); + EconHandler.getEconHandler().withdrawMoney(player, componentPreset.getCost()); Captions.REMOVED_BALANCE.send(player, componentPreset.getCost() + ""); } } @@ -196,7 +196,7 @@ public class ComponentPresetManager { for (int i = 0; i < allowedPresets.size(); i++) { final ComponentPreset preset = allowedPresets.get(i); final List lore = new ArrayList<>(); - if (preset.getCost() > 0 && EconHandler.manager != null && plot.getArea().useEconomy()){ + if (preset.getCost() > 0 && EconHandler.getEconHandler() != null && plot.getArea().useEconomy()){ lore.add(Captions.PRESET_LORE_COST.getTranslated().replace("%cost%", String.format("%.2f", preset.getCost()))); } diff --git a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java index a9af02b65..13efa6bfb 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -756,18 +756,18 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer * The amount of money this Player has. */ public double getMoney() { - return EconHandler.manager == null ? 0 : EconHandler.manager.getMoney(this); + return EconHandler.getEconHandler() == null ? 0 : EconHandler.getEconHandler().getMoney(this); } public void withdraw(double amount) { - if (EconHandler.manager != null) { - EconHandler.manager.withdrawMoney(this, amount); + if (EconHandler.getEconHandler() != null) { + EconHandler.getEconHandler().withdrawMoney(this, amount); } } public void deposit(double amount) { - if (EconHandler.manager != null) { - EconHandler.manager.depositMoney(this, amount); + if (EconHandler.getEconHandler() != null) { + EconHandler.getEconHandler().depositMoney(this, amount); } } diff --git a/Core/src/main/java/com/plotsquared/core/util/EconHandler.java b/Core/src/main/java/com/plotsquared/core/util/EconHandler.java index 15180e68e..bedbda228 100644 --- a/Core/src/main/java/com/plotsquared/core/util/EconHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/EconHandler.java @@ -25,36 +25,52 @@ */ package com.plotsquared.core.util; +import com.plotsquared.core.IPlotMain; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.player.ConsolePlayer; import com.plotsquared.core.player.OfflinePlotPlayer; import com.plotsquared.core.player.PlotPlayer; +import org.jetbrains.annotations.Nullable; public abstract class EconHandler { - public static EconHandler manager; - private static boolean initialized; + /** + * @deprecated This will be made private in the future + */ + @Deprecated public static EconHandler manager; - public static EconHandler getEconHandler() { - if (initialized) { - return manager; + /** + * Initialize the economy handler using + * {@link IPlotMain#getEconomyHandler()} + */ + public static void initializeEconHandler() { + if (manager != null) { + return; } - initialized = true; - return manager = PlotSquared.get().IMP.getEconomyHandler(); + manager = PlotSquared.get().IMP.getEconomyHandler(); } - public double getMoney(PlotPlayer player) { + /** + * Return the econ handler instance, if one exists + * + * @return Economy handler instance + */ + @Nullable public static EconHandler getEconHandler() { + return manager; + } + + public double getMoney(PlotPlayer player) { if (player instanceof ConsolePlayer) { return Double.MAX_VALUE; } return getBalance(player); } - public abstract double getBalance(PlotPlayer player); + public abstract double getBalance(PlotPlayer player); - public abstract void withdrawMoney(PlotPlayer player, double amount); + public abstract void withdrawMoney(PlotPlayer player, double amount); - public abstract void depositMoney(PlotPlayer player, double amount); + public abstract void depositMoney(PlotPlayer player, double amount); public abstract void depositMoney(OfflinePlotPlayer player, double amount); diff --git a/build.gradle b/build.gradle index 635cd7ea4..c55d34847 100644 --- a/build.gradle +++ b/build.gradle @@ -76,6 +76,8 @@ subprojects { delete("../target") } + javadoc.options.encoding = 'UTF-8' + dependencies { compile group: 'org.json', name: 'json', version: '20200518' From e833403e3c473542ec3fe52573de59c23d38aaf4 Mon Sep 17 00:00:00 2001 From: EpiCanard Date: Thu, 25 Jun 2020 14:08:44 +0200 Subject: [PATCH 109/121] Replace split with substring for placeholders --- .../bukkit/placeholder/Placeholders.java | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java index ce2445052..5457dbe0f 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/placeholder/Placeholders.java @@ -72,20 +72,20 @@ public class Placeholders extends PlaceholderExpansion { } if (identifier.startsWith("has_plot_")) { - if (identifier.split("has_plot_").length != 2) + identifier = identifier.substring("has_plot_".length()); + if (identifier.isEmpty()) return ""; - identifier = identifier.split("has_plot_")[1]; return pl.getPlotCount(identifier) > 0 ? PlaceholderAPIPlugin.booleanTrue() : PlaceholderAPIPlugin.booleanFalse(); } if (identifier.startsWith("plot_count_")) { - if (identifier.split("plot_count_").length != 2) + identifier = identifier.substring("plot_count_".length()); + if (identifier.isEmpty()) return ""; - identifier = identifier.split("plot_count_")[1]; return String.valueOf(pl.getPlotCount(identifier)); } @@ -184,12 +184,11 @@ public class Placeholders extends PlaceholderExpansion { break; } if (identifier.startsWith("currentplot_localflag_")) { - final String[] splitValues = identifier.split("currentplot_localflag_"); - return (splitValues.length >= 2) ? getFlagValue(plot, splitValues[1], false) : ""; + return getFlagValue(plot, identifier.substring("currentplot_localflag_".length()), + false); } if (identifier.startsWith("currentplot_flag_")) { - final String[] splitValues = identifier.split("currentplot_flag_"); - return (splitValues.length >= 2) ? getFlagValue(plot, splitValues[1], true) : ""; + return getFlagValue(plot, identifier.substring("currentplot_flag_".length()), true); } return ""; } @@ -206,10 +205,11 @@ public class Placeholders extends PlaceholderExpansion { * @return The value of flag serialized in string */ private String getFlagValue(final Plot plot, final String flagName, final boolean inherit) { - final PlotFlag flag = GlobalFlagContainer.getInstance().getFlagFromString(flagName); - if (flag == null) { + if (flagName.isEmpty()) + return ""; + final PlotFlag flag = GlobalFlagContainer.getInstance().getFlagFromString(flagName); + if (flag == null) return ""; - } if (inherit) { return plot.getFlag(flag).toString(); @@ -217,6 +217,5 @@ public class Placeholders extends PlaceholderExpansion { final PlotFlag plotFlag = plot.getFlagContainer().queryLocal(flag.getClass()); return (plotFlag != null) ? plotFlag.getValue().toString() : ""; } - } } From 38425a1eaed2749bbe11982332a8bfcca48281e5 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Fri, 26 Jun 2020 13:49:17 +0200 Subject: [PATCH 110/121] Update world border on Plot#claim (Fixes PS-13) --- Core/src/main/java/com/plotsquared/core/plot/Plot.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/main/java/com/plotsquared/core/plot/Plot.java b/Core/src/main/java/com/plotsquared/core/plot/Plot.java index 0d756ac6c..46ce9f24c 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/Plot.java +++ b/Core/src/main/java/com/plotsquared/core/plot/Plot.java @@ -1751,6 +1751,7 @@ public class Plot { } } else { area.addPlot(this); + updateWorldBorder(); } setSign(player.getName()); MainUtil.sendMessage(player, Captions.CLAIMED); From cb04c183a823f0491c73a29483c979f14ffcaad2 Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Fri, 26 Jun 2020 20:38:30 -0400 Subject: [PATCH 111/121] Update to 1.16.1 --- Bukkit/build.gradle | 4 ++-- Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java | 2 +- .../java/com/plotsquared/bukkit/listener/PlayerEvents.java | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 6995d9034..6b011faf7 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -22,9 +22,9 @@ dependencies { implementation(project(":PlotSquared-Core")) compile("org.bstats:bstats-bukkit:1.7") compile(project(":PlotSquared-Core")) - compile("com.destroystokyo.paper:paper-api:1.15.2-R0.1-SNAPSHOT") + compile("com.destroystokyo.paper:paper-api:1.16.1-R0.1-SNAPSHOT") //implementation 'com.onarandombox.multiversecore:Multiverse-Core:3.0.0-SNAPSHOT' - implementation("org.spigotmc:spigot-api:1.15.2-R0.1-SNAPSHOT") + implementation("org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT") compile(group: "com.sk89q.worldedit", name: "worldedit-bukkit", version: "7.0.1") compile("io.papermc:paperlib:1.0.2") implementation("net.kyori:text-adapter-bukkit:3.0.3") diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 1a40c51d5..ca21d9a3d 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -123,6 +123,7 @@ import org.bukkit.World; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.PluginCommand; import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.Listener; @@ -790,7 +791,6 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< case MUSHROOM_COW: case OCELOT: case PIG: - case PIG_ZOMBIE: case RABBIT: case SHEEP: case SILVERFISH: diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java index 643f80611..c8c16a4c6 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -1389,6 +1389,11 @@ public class PlayerEvents extends PlotListener implements Listener { case BUBBLE_CORAL_FAN: case FIRE_CORAL_FAN: case HORN_CORAL_FAN: + case BRAIN_CORAL_WALL_FAN: + case BUBBLE_CORAL_WALL_FAN: + case FIRE_CORAL_WALL_FAN: + case HORN_CORAL_WALL_FAN: + case TUBE_CORAL_WALL_FAN: if (!plot.getFlag(CoralDryFlag.class)) { plot.debug("Coral could not dry because coral-dry = false"); event.setCancelled(true); From 9c3d2cfb0212dc5d3b463c0dc15642701df7603b Mon Sep 17 00:00:00 2001 From: MeFisto94 Date: Wed, 24 Jun 2020 17:33:49 +0200 Subject: [PATCH 112/121] Move the caching and static accessors from EconHandler to PlotMain --- .../com/plotsquared/bukkit/BukkitMain.java | 11 +++++++++- .../bukkit/util/BukkitEconHandler.java | 1 + .../java/com/plotsquared/core/IPlotMain.java | 4 ++-- .../plotsquared/core/util/EconHandler.java | 21 +++++++++++-------- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index 1a40c51d5..a0f19cb6e 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -178,6 +178,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< @Getter private BackupManager backupManager; @Getter private PlatformWorldManager worldManager; private final BukkitPlayerManager playerManager = new BukkitPlayerManager(); + private EconHandler econ; @Override public int[] getServerVersion() { if (this.version == null) { @@ -902,8 +903,16 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< } @Override public EconHandler getEconomyHandler() { + if (econ != null) { + if (econ.init() /* is inited*/) { + return econ; + } else { + return null; + } + } + try { - BukkitEconHandler econ = new BukkitEconHandler(); + econ = new BukkitEconHandler(); if (econ.init()) { return econ; } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java index b8387efed..642ed3c63 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java @@ -40,6 +40,7 @@ public class BukkitEconHandler extends EconHandler { private Economy econ; private Permission perms; + @Override public boolean init() { if (this.econ == null || this.perms == null) { setupPermissions(); diff --git a/Core/src/main/java/com/plotsquared/core/IPlotMain.java b/Core/src/main/java/com/plotsquared/core/IPlotMain.java index eb70402f6..4dc293c6d 100644 --- a/Core/src/main/java/com/plotsquared/core/IPlotMain.java +++ b/Core/src/main/java/com/plotsquared/core/IPlotMain.java @@ -174,11 +174,11 @@ public interface IPlotMain

extends ILogger { boolean initWorldEdit(); /** - * Gets the economy provider. + * Gets the economy provider, if there is one * * @return the PlotSquared economy manager */ - EconHandler getEconomyHandler(); + @Nullable EconHandler getEconomyHandler(); /** * Gets the {@link QueueProvider} class. diff --git a/Core/src/main/java/com/plotsquared/core/util/EconHandler.java b/Core/src/main/java/com/plotsquared/core/util/EconHandler.java index bedbda228..1064b0800 100644 --- a/Core/src/main/java/com/plotsquared/core/util/EconHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/EconHandler.java @@ -35,18 +35,17 @@ import org.jetbrains.annotations.Nullable; public abstract class EconHandler { /** - * @deprecated This will be made private in the future + * @deprecated This will be removed in the future, + * call {@link IPlotMain#getEconomyHandler()} instead. */ - @Deprecated public static EconHandler manager; + @Deprecated @Nullable public static EconHandler manager; /** - * Initialize the economy handler using - * {@link IPlotMain#getEconomyHandler()} + * Initialize the economy handler using {@link IPlotMain#getEconomyHandler()} + * @deprecated Call {@link #init} instead or use {@link IPlotMain#getEconomyHandler()} + * which does this already. */ - public static void initializeEconHandler() { - if (manager != null) { - return; - } + @Deprecated public static void initializeEconHandler() { manager = PlotSquared.get().IMP.getEconomyHandler(); } @@ -54,11 +53,15 @@ public abstract class EconHandler { * Return the econ handler instance, if one exists * * @return Economy handler instance + * @deprecated Call {@link IPlotMain#getEconomyHandler()} instead */ - @Nullable public static EconHandler getEconHandler() { + @Deprecated @Nullable public static EconHandler getEconHandler() { + manager = PlotSquared.get().IMP.getEconomyHandler(); return manager; } + public abstract boolean init(); + public double getMoney(PlotPlayer player) { if (player instanceof ConsolePlayer) { return Double.MAX_VALUE; From 02f3c3ef50684f254a86916c86ff8d75079cae08 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Sat, 27 Jun 2020 20:38:55 +0100 Subject: [PATCH 113/121] Fix my stupid mistake of using lamdas not creating nested classes when creating schematics. "this" doesn't work like that. Cheers Java. --- .../core/util/SchematicHandler.java | 197 ++++++++++-------- 1 file changed, 105 insertions(+), 92 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java index 547741e6f..92b1b2ef4 100644 --- a/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/SchematicHandler.java @@ -130,8 +130,7 @@ public abstract class SchematicHandler { name = plot.getId().x + ";" + plot.getId().y + ',' + plot.getArea() + ',' + owner; } else { - name = namingScheme - .replaceAll("%id%", plot.getId().toString()) + name = namingScheme.replaceAll("%id%", plot.getId().toString()) .replaceAll("%idx%", plot.getId().x + "") .replaceAll("%idy%", plot.getId().y + "") .replaceAll("%world%", plot.getArea().toString()); @@ -566,100 +565,114 @@ public abstract class SchematicHandler { final int p2z = pos2.getZ(); final int ey = pos2.getY(); Iterator yiter = IntStream.range(sy, ey + 1).iterator(); - final Runnable yTask = () -> { - long ystart = System.currentTimeMillis(); - while (yiter.hasNext() && System.currentTimeMillis() - ystart < 20) { - final int y = yiter.next(); - Iterator ziter = IntStream.range(p1z, p2z + 1).iterator(); - final Runnable zTask = () -> { - long zstart = System.currentTimeMillis(); - while (ziter.hasNext() - && System.currentTimeMillis() - zstart < 20) { - final int z = ziter.next(); - Iterator xiter = - IntStream.range(p1x, p2x + 1).iterator(); - final Runnable xTask = () -> { - long xstart = System.currentTimeMillis(); - final int ry = y - sy; - final int rz = z - p1z; - while (xiter.hasNext() - && System.currentTimeMillis() - xstart < 20) { - final int x = xiter.next(); - final int rx = x - p1x; - BlockVector3 point = BlockVector3.at(x, y, z); - BaseBlock block = - cuboidRegion.getWorld().getFullBlock(point); - if (block.getNbtData() != null) { - Map values = new HashMap<>(); - for (Map.Entry entry : block - .getNbtData().getValue().entrySet()) { - values.put(entry.getKey(), entry.getValue()); + final Runnable yTask = new Runnable() { + @Override public void run() { + long ystart = System.currentTimeMillis(); + while (yiter.hasNext() && System.currentTimeMillis() - ystart < 20) { + final int y = yiter.next(); + Iterator ziter = IntStream.range(p1z, p2z + 1).iterator(); + final Runnable zTask = new Runnable() { + @Override public void run() { + long zstart = System.currentTimeMillis(); + while (ziter.hasNext() + && System.currentTimeMillis() - zstart < 20) { + final int z = ziter.next(); + Iterator xiter = + IntStream.range(p1x, p2x + 1).iterator(); + final Runnable xTask = new Runnable() { + @Override public void run() { + long xstart = System.currentTimeMillis(); + final int ry = y - sy; + final int rz = z - p1z; + while (xiter.hasNext() + && System.currentTimeMillis() - xstart + < 20) { + final int x = xiter.next(); + final int rx = x - p1x; + BlockVector3 point = + BlockVector3.at(x, y, z); + BaseBlock block = cuboidRegion.getWorld() + .getFullBlock(point); + if (block.getNbtData() != null) { + Map values = + new HashMap<>(); + for (Map.Entry entry : block + .getNbtData().getValue() + .entrySet()) { + values.put(entry.getKey(), + entry.getValue()); + } + // Remove 'id' if it exists. We want 'Id' + values.remove("id"); + + // Positions are kept in NBT, we don't want that. + values.remove("x"); + values.remove("y"); + values.remove("z"); + + values.put("Id", + new StringTag(block.getNbtId())); + values.put("Pos", new IntArrayTag( + new int[] {rx, ry, rz})); + + tileEntities + .add(new CompoundTag(values)); + } + String blockKey = + block.toImmutableState().getAsString(); + int blockId; + if (palette.containsKey(blockKey)) { + blockId = palette.get(blockKey); + } else { + blockId = palette.size(); + palette.put(blockKey, palette.size()); + } + + while ((blockId & -128) != 0) { + buffer.write(blockId & 127 | 128); + blockId >>>= 7; + } + buffer.write(blockId); + + if (ry > 0) { + continue; + } + BlockVector2 pt = BlockVector2.at(x, z); + BiomeType biome = + cuboidRegion.getWorld().getBiome(pt); + String biomeStr = biome.getId(); + int biomeId; + if (biomePalette.containsKey(biomeStr)) { + biomeId = biomePalette.get(biomeStr); + } else { + biomeId = biomePalette.size(); + biomePalette.put(biomeStr, biomeId); + } + while ((biomeId & -128) != 0) { + biomeBuffer.write(biomeId & 127 | 128); + biomeId >>>= 7; + } + biomeBuffer.write(biomeId); + } + if (xiter.hasNext()) { + this.run(); + } } - // Remove 'id' if it exists. We want 'Id' - values.remove("id"); - - // Positions are kept in NBT, we don't want that. - values.remove("x"); - values.remove("y"); - values.remove("z"); - - values.put("Id", new StringTag(block.getNbtId())); - values.put("Pos", - new IntArrayTag(new int[] {rx, ry, rz})); - - tileEntities.add(new CompoundTag(values)); - } - String blockKey = - block.toImmutableState().getAsString(); - int blockId; - if (palette.containsKey(blockKey)) { - blockId = palette.get(blockKey); - } else { - blockId = palette.size(); - palette.put(blockKey, palette.size()); - } - - while ((blockId & -128) != 0) { - buffer.write(blockId & 127 | 128); - blockId >>>= 7; - } - buffer.write(blockId); - - if (ry > 0) { - continue; - } - BlockVector2 pt = BlockVector2.at(x, z); - BiomeType biome = cuboidRegion.getWorld().getBiome(pt); - String biomeStr = biome.getId(); - int biomeId; - if (biomePalette.containsKey(biomeStr)) { - biomeId = biomePalette.get(biomeStr); - } else { - biomeId = biomePalette.size(); - biomePalette.put(biomeStr, biomeId); - } - while ((biomeId & -128) != 0) { - biomeBuffer.write(biomeId & 127 | 128); - biomeId >>>= 7; - } - biomeBuffer.write(biomeId); + }; + xTask.run(); } - if (xiter.hasNext()) { + if (ziter.hasNext()) { this.run(); } - }; - xTask.run(); - } - if (ziter.hasNext()) { - this.run(); - } - }; - zTask.run(); - } - if (yiter.hasNext()) { - TaskManager.runTaskLater(this, 1); - } else { - regionTask.run(); + } + }; + zTask.run(); + } + if (yiter.hasNext()) { + TaskManager.runTaskLater(this, 1); + } else { + regionTask.run(); + } } }; yTask.run(); From 74876f9e64191281deba2295f8ad3a0beb0dcdb8 Mon Sep 17 00:00:00 2001 From: Carter Date: Sat, 27 Jun 2020 15:40:20 -0400 Subject: [PATCH 114/121] Get biome data from correct schematic for intersections (Fixes PS-50) --- .../java/com/plotsquared/core/generator/HybridPlotWorld.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java index 49a5c0da4..e322072df 100644 --- a/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java +++ b/Core/src/main/java/com/plotsquared/core/generator/HybridPlotWorld.java @@ -335,7 +335,7 @@ public class HybridPlotWorld extends ClassicPlotWorld { (short) (z - shift), id, false, h2); } } - BiomeType biome = blockArrayClipboard1 + BiomeType biome = blockArrayClipboard2 .getBiome(BlockVector2.at(x + min.getBlockX(), z + min.getBlockZ())); addOverlayBiome((short) (x - shift), (short) (z - shift), biome); } From 181c5b134f284d52d8dd8cad0b8290951a96420f Mon Sep 17 00:00:00 2001 From: NotMyFault Date: Sat, 27 Jun 2020 21:48:15 +0200 Subject: [PATCH 115/121] Update old links --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 60cba3066..f55841917 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,10 +2,10 @@ -**Fixes #{issue number}** +**Fixes {Link to issue}** ## Description From e139550949a52ebfabc6de4307f4ea4d1595d82b Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 27 Jun 2020 23:07:20 +0200 Subject: [PATCH 116/121] Make cache expiration configurable --- .../java/com/plotsquared/core/configuration/Settings.java | 7 +++++++ .../java/com/plotsquared/core/util/TabCompletions.java | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java index 7b0196412..80d103882 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Settings.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Settings.java @@ -527,6 +527,13 @@ public class Settings extends Config { public static int TARGET_TIME = 65; } + @Comment("Settings related to tab completion") + public static final class Tab_Completions { + @Comment({"The time in seconds how long tab completions should remain in cache.", + "0 will disable caching. Lower values may be less performant."}) + public static int CACHE_EXPIRATION = 15; + } + @Comment({"Enable or disable parts of the plugin", "Note: A cache will use some memory if enabled"}) diff --git a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java index dbf053c52..56a3ff8fa 100644 --- a/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java +++ b/Core/src/main/java/com/plotsquared/core/util/TabCompletions.java @@ -56,7 +56,9 @@ import java.util.stream.Collectors; public class TabCompletions { private final Cache> cachedCompletionValues = - CacheBuilder.newBuilder().expireAfterWrite(15, TimeUnit.SECONDS).build(); + CacheBuilder.newBuilder() + .expireAfterWrite(Settings.Tab_Completions.CACHE_EXPIRATION, TimeUnit.SECONDS) + .build(); private final Command booleanTrueCompletion = new Command(null, false, "true", "", RequiredType.NONE, null) {}; From bd9bdc9e034ef5750d66efa0e799f50f2334cf65 Mon Sep 17 00:00:00 2001 From: MeFisto94 Date: Thu, 25 Jun 2020 00:19:58 +0200 Subject: [PATCH 117/121] Separate the Vault Permission Handling from the Economy Handling --- .../com/plotsquared/bukkit/BukkitMain.java | 25 +++++++- .../bukkit/util/BukkitEconHandler.java | 36 ++++------- .../bukkit/util/BukkitPermHandler.java | 59 +++++++++++++++++++ .../java/com/plotsquared/core/IPlotMain.java | 8 +++ .../plotsquared/core/util/EconHandler.java | 10 +++- .../plotsquared/core/util/PermHandler.java | 37 ++++++++++++ 6 files changed, 149 insertions(+), 26 deletions(-) create mode 100644 Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitPermHandler.java create mode 100644 Core/src/main/java/com/plotsquared/core/util/PermHandler.java diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index a0f19cb6e..b313098a8 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -45,6 +45,7 @@ import com.plotsquared.bukkit.util.BukkitChatManager; import com.plotsquared.bukkit.util.BukkitChunkManager; import com.plotsquared.bukkit.util.BukkitEconHandler; import com.plotsquared.bukkit.util.BukkitInventoryUtil; +import com.plotsquared.bukkit.util.BukkitPermHandler; import com.plotsquared.bukkit.util.BukkitRegionManager; import com.plotsquared.bukkit.util.BukkitSetupUtils; import com.plotsquared.bukkit.util.BukkitTaskManager; @@ -94,6 +95,7 @@ import com.plotsquared.core.util.ConsoleColors; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.InventoryUtil; import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.PermHandler; import com.plotsquared.core.util.PlatformWorldManager; import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.PremiumVerification; @@ -179,6 +181,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< @Getter private PlatformWorldManager worldManager; private final BukkitPlayerManager playerManager = new BukkitPlayerManager(); private EconHandler econ; + private PermHandler perm; @Override public int[] getServerVersion() { if (this.version == null) { @@ -904,7 +907,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< @Override public EconHandler getEconomyHandler() { if (econ != null) { - if (econ.init() /* is inited*/) { + if (econ.init() /* is inited */) { return econ; } else { return null; @@ -922,6 +925,26 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< return null; } + @Override public PermHandler getPermissionHandler() { + if (perm != null) { + if (perm.init() /* is inited */) { + return perm; + } else { + return null; + } + } + + try { + perm = new BukkitPermHandler(); + if (perm.init()) { + return perm; + } + } catch (Throwable ignored) { + PlotSquared.debug("No permissions detected!"); + } + return null; + } + @Override public QueueProvider initBlockQueue() { //TODO Figure out why this code is still here yet isn't being called anywhere. // try { diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java index 642ed3c63..e71c48158 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitEconHandler.java @@ -27,34 +27,25 @@ package com.plotsquared.bukkit.util; import com.plotsquared.bukkit.player.BukkitOfflinePlayer; import com.plotsquared.bukkit.player.BukkitPlayer; +import com.plotsquared.core.PlotSquared; import com.plotsquared.core.player.OfflinePlotPlayer; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.EconHandler; +import com.plotsquared.core.util.PermHandler; import net.milkbowl.vault.economy.Economy; -import net.milkbowl.vault.permission.Permission; import org.bukkit.Bukkit; import org.bukkit.plugin.RegisteredServiceProvider; public class BukkitEconHandler extends EconHandler { private Economy econ; - private Permission perms; @Override public boolean init() { - if (this.econ == null || this.perms == null) { - setupPermissions(); + if (this.econ == null) { setupEconomy(); } - return this.econ != null && this.perms != null; - } - - private void setupPermissions() { - RegisteredServiceProvider permissionProvider = - Bukkit.getServer().getServicesManager().getRegistration(Permission.class); - if (permissionProvider != null) { - this.perms = permissionProvider.getProvider(); - } + return this.econ != null; } private void setupEconomy() { @@ -88,20 +79,19 @@ public class BukkitEconHandler extends EconHandler { this.econ.depositPlayer(((BukkitOfflinePlayer) player).player, amount); } - @Override public boolean hasPermission(String world, String player, String perm) { - return this.perms.playerHas(world, Bukkit.getOfflinePlayer(player), perm); + /** + * @deprecated Use {@link PermHandler#hasPermission(String, String, String)} instead + */ + @Deprecated @Override public boolean hasPermission(String world, String player, String perm) { + if (PlotSquared.imp().getPermissionHandler() != null) { + return PlotSquared.imp().getPermissionHandler().hasPermission(world, player, perm); + } else { + return false; + } } @Override public double getBalance(PlotPlayer player) { return this.econ.getBalance(player.getName()); } - @Deprecated public void setPermission(String world, String player, String perm, boolean value) { - if (value) { - this.perms.playerAdd(world, player, perm); - } else { - this.perms.playerRemove(world, player, perm); - } - } - } diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitPermHandler.java b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitPermHandler.java new file mode 100644 index 000000000..fee00a66d --- /dev/null +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/util/BukkitPermHandler.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.bukkit.util; + +import com.plotsquared.core.util.PermHandler; +import net.milkbowl.vault.permission.Permission; +import org.bukkit.Bukkit; +import org.bukkit.plugin.RegisteredServiceProvider; + +public class BukkitPermHandler extends PermHandler { + + private Permission perms; + + @Override + public boolean init() { + if (this.perms == null) { + setupPermissions(); + } + return this.perms != null; + } + + private void setupPermissions() { + if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { + return; + } + RegisteredServiceProvider permissionProvider = + Bukkit.getServer().getServicesManager().getRegistration(Permission.class); + if (permissionProvider != null) { + this.perms = permissionProvider.getProvider(); + } + } + + @Override public boolean hasPermission(String world, String player, String perm) { + return this.perms.playerHas(world, Bukkit.getOfflinePlayer(player), perm); + } +} diff --git a/Core/src/main/java/com/plotsquared/core/IPlotMain.java b/Core/src/main/java/com/plotsquared/core/IPlotMain.java index 4dc293c6d..a38045acb 100644 --- a/Core/src/main/java/com/plotsquared/core/IPlotMain.java +++ b/Core/src/main/java/com/plotsquared/core/IPlotMain.java @@ -35,6 +35,7 @@ import com.plotsquared.core.util.ChatManager; import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.InventoryUtil; +import com.plotsquared.core.util.PermHandler; import com.plotsquared.core.util.PlatformWorldManager; import com.plotsquared.core.util.PlayerManager; import com.plotsquared.core.util.RegionManager; @@ -180,6 +181,13 @@ public interface IPlotMain

extends ILogger { */ @Nullable EconHandler getEconomyHandler(); + /** + * Gets the permission provider, if there is one + * + * @return the PlotSquared permission manager + */ + @Nullable PermHandler getPermissionHandler(); + /** * Gets the {@link QueueProvider} class. */ diff --git a/Core/src/main/java/com/plotsquared/core/util/EconHandler.java b/Core/src/main/java/com/plotsquared/core/util/EconHandler.java index 1064b0800..a593e0cb0 100644 --- a/Core/src/main/java/com/plotsquared/core/util/EconHandler.java +++ b/Core/src/main/java/com/plotsquared/core/util/EconHandler.java @@ -77,9 +77,15 @@ public abstract class EconHandler { public abstract void depositMoney(OfflinePlotPlayer player, double amount); - public abstract boolean hasPermission(String world, String player, String perm); + /** + * @deprecated Use {@link PermHandler#hasPermission(String, String, String)} instead + */ + @Deprecated public abstract boolean hasPermission(String world, String player, String perm); - public boolean hasPermission(String player, String perm) { + /** + * @deprecated Use {@link PermHandler#hasPermission(String, String)} instead + */ + @Deprecated public boolean hasPermission(String player, String perm) { return hasPermission(null, player, perm); } } diff --git a/Core/src/main/java/com/plotsquared/core/util/PermHandler.java b/Core/src/main/java/com/plotsquared/core/util/PermHandler.java new file mode 100644 index 000000000..1dec45fd4 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/PermHandler.java @@ -0,0 +1,37 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.util; + +public abstract class PermHandler { + + public abstract boolean init(); + + public abstract boolean hasPermission(String world, String player, String perm); + + public boolean hasPermission(String player, String perm) { + return hasPermission(null, player, perm); + } +} From 3a2e932d171a51f23af96bd90a7020dd2211ffde Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Sun, 28 Jun 2020 18:45:40 -0400 Subject: [PATCH 118/121] Add missing mobs from 1.13.2+ --- .../com/plotsquared/bukkit/BukkitMain.java | 214 +++++++++--------- 1 file changed, 110 insertions(+), 104 deletions(-) diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java index ca21d9a3d..95ceed2de 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/BukkitMain.java @@ -627,46 +627,46 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< Iterator iterator = entities.iterator(); while (iterator.hasNext()) { Entity entity = iterator.next(); - switch (entity.getType()) { - case EGG: - case FISHING_HOOK: - case ENDER_SIGNAL: - case AREA_EFFECT_CLOUD: - case EXPERIENCE_ORB: - case LEASH_HITCH: - case FIREWORK: - case LIGHTNING: - case WITHER_SKULL: - case UNKNOWN: - case PLAYER: + switch (entity.getType().toString()) { + case "EGG": + case "FISHING_HOOK": + case "ENDER_SIGNAL": + case "AREA_EFFECT_CLOUD": + case "EXPERIENCE_ORB": + case "LEASH_HITCH": + case "FIREWORK": + case "LIGHTNING": + case "WITHER_SKULL": + case "UNKNOWN": + case "PLAYER": // non moving / unmovable continue; - case THROWN_EXP_BOTTLE: - case SPLASH_POTION: - case SNOWBALL: - case SHULKER_BULLET: - case SPECTRAL_ARROW: - case ENDER_PEARL: - case ARROW: - case LLAMA_SPIT: - case TRIDENT: + case "THROWN_EXP_BOTTLE": + case "SPLASH_POTION": + case "SNOWBALL": + case "SHULKER_BULLET": + case "SPECTRAL_ARROW": + case "ENDER_PEARL": + case "ARROW": + case "LLAMA_SPIT": + case "TRIDENT": // managed elsewhere | projectile continue; - case ITEM_FRAME: - case PAINTING: + case "ITEM_FRAME": + case "PAINTING": // Not vehicles continue; - case ARMOR_STAND: + case "ARMOR_STAND": // Temporarily classify as vehicle - case MINECART: - case MINECART_CHEST: - case MINECART_COMMAND: - case MINECART_FURNACE: - case MINECART_HOPPER: - case MINECART_MOB_SPAWNER: - case ENDER_CRYSTAL: - case MINECART_TNT: - case BOAT: + case "MINECART": + case "MINECART_CHEST": + case "MINECART_COMMAND": + case "MINECART_FURNACE": + case "MINECART_HOPPER": + case "MINECART_MOB_SPAWNER": + case "ENDER_CRYSTAL": + case "MINECART_TNT": + case "BOAT": if (Settings.Enabled_Components.KILL_ROAD_VEHICLES) { com.plotsquared.core.location.Location location = BukkitUtil.getLocation(entity.getLocation()); @@ -695,10 +695,10 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< } } continue; - case SMALL_FIREBALL: - case FIREBALL: - case DRAGON_FIREBALL: - case DROPPED_ITEM: + case "SMALL_FIREBALL": + case "FIREBALL": + case "DRAGON_FIREBALL": + case "DROPPED_ITEM": if (Settings.Enabled_Components.KILL_ROAD_ITEMS && plotArea .getOwnedPlotAbs(BukkitUtil.getLocation(entity.getLocation())) == null) { @@ -706,11 +706,11 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< } // dropped item continue; - case PRIMED_TNT: - case FALLING_BLOCK: + case "PRIMED_TNT": + case "FALLING_BLOCK": // managed elsewhere continue; - case SHULKER: + case "SHULKER": if (Settings.Enabled_Components.KILL_ROAD_MOBS) { LivingEntity livingEntity = (LivingEntity) entity; List meta = entity.getMetadata("shulkerPlot"); @@ -758,70 +758,76 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain< } } continue; - case LLAMA: - case DONKEY: - case MULE: - case ZOMBIE_HORSE: - case SKELETON_HORSE: - case HUSK: - case ELDER_GUARDIAN: - case WITHER_SKELETON: - case STRAY: - case ZOMBIE_VILLAGER: - case EVOKER: - case EVOKER_FANGS: - case VEX: - case VINDICATOR: - case POLAR_BEAR: - case BAT: - case BLAZE: - case CAVE_SPIDER: - case CHICKEN: - case COW: - case CREEPER: - case ENDERMAN: - case ENDERMITE: - case ENDER_DRAGON: - case GHAST: - case GIANT: - case GUARDIAN: - case HORSE: - case IRON_GOLEM: - case MAGMA_CUBE: - case MUSHROOM_COW: - case OCELOT: - case PIG: - case RABBIT: - case SHEEP: - case SILVERFISH: - case SKELETON: - case SLIME: - case SNOWMAN: - case SPIDER: - case SQUID: - case VILLAGER: - case WITCH: - case WITHER: - case WOLF: - case ZOMBIE: - case PARROT: - case SALMON: - case DOLPHIN: - case TROPICAL_FISH: - case DROWNED: - case COD: - case TURTLE: - case PUFFERFISH: - case PHANTOM: - case ILLUSIONER: - case CAT: - case PANDA: - case FOX: - case PILLAGER: - case TRADER_LLAMA: - case WANDERING_TRADER: - case RAVAGER: - //case BEE: + case "ZOMBIFIED_PIGLIN": + case "LLAMA": + case "DONKEY": + case "MULE": + case "ZOMBIE_HORSE": + case "SKELETON_HORSE": + case "HUSK": + case "ELDER_GUARDIAN": + case "WITHER_SKELETON": + case "STRAY": + case "ZOMBIE_VILLAGER": + case "EVOKER": + case "EVOKER_FANGS": + case "VEX": + case "VINDICATOR": + case "POLAR_BEAR": + case "BAT": + case "BLAZE": + case "CAVE_SPIDER": + case "CHICKEN": + case "COW": + case "CREEPER": + case "ENDERMAN": + case "ENDERMITE": + case "ENDER_DRAGON": + case "GHAST": + case "GIANT": + case "GUARDIAN": + case "HORSE": + case "IRON_GOLEM": + case "MAGMA_CUBE": + case "MUSHROOM_COW": + case "OCELOT": + case "PIG": + case "PIG_ZOMBIE": + case "RABBIT": + case "SHEEP": + case "SILVERFISH": + case "SKELETON": + case "SLIME": + case "SNOWMAN": + case "SPIDER": + case "SQUID": + case "VILLAGER": + case "WITCH": + case "WITHER": + case "WOLF": + case "ZOMBIE": + case "PARROT": + case "SALMON": + case "DOLPHIN": + case "TROPICAL_FISH": + case "DROWNED": + case "COD": + case "TURTLE": + case "PUFFERFISH": + case "PHANTOM": + case "ILLUSIONER": + case "CAT": + case "PANDA": + case "FOX": + case "PILLAGER": + case "TRADER_LLAMA": + case "WANDERING_TRADER": + case "RAVAGER": + case "BEE": + case "HOGLIN": + case "PIGLIN": + case "ZOGLIN": + break; default: { if (Settings.Enabled_Components.KILL_ROAD_MOBS) { Location location = entity.getLocation(); From fa2ad8ab22a32b8d690cb66941f1a15dc9277ae4 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Mon, 29 Jun 2020 13:48:18 +0200 Subject: [PATCH 119/121] Improve plot alias command (tab complete, admin permission) fixes PS-63 --- .../com/plotsquared/core/command/Alias.java | 79 +++++++++++++------ .../core/configuration/Captions.java | 2 + .../core/util/query/PlotQuery.java | 24 ++++++ 3 files changed, 80 insertions(+), 25 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/command/Alias.java b/Core/src/main/java/com/plotsquared/core/command/Alias.java index a10bf8a6e..59c0da49c 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Alias.java +++ b/Core/src/main/java/com/plotsquared/core/command/Alias.java @@ -33,17 +33,24 @@ import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.Permissions; +import com.plotsquared.core.util.query.PlotQuery; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.concurrent.TimeoutException; -@CommandDeclaration(command = "setalias", +@CommandDeclaration(command = "alias", permission = "plots.alias", description = "Set the plot name", usage = "/plot alias ", - aliases = {"alias", "sa", "name", "rename", "setname", "seta", "nameplot"}, + aliases = {"setalias", "sa", "name", "rename", "setname", "seta", "nameplot"}, category = CommandCategory.SETTINGS, requiredType = RequiredType.PLAYER) public class Alias extends SubCommand { + private static final Command SET_COMMAND = new Command(null, false, "set", null, RequiredType.NONE, null) {}; + private static final Command REMOVE_COMMAND = new Command(null, false, "remove", null, RequiredType.NONE, null) {}; @Override public boolean onCommand(PlotPlayer player, String[] args) { @@ -63,13 +70,11 @@ public class Alias extends SubCommand { return false; } - if (!plot.isOwner(player.getUUID())) { - MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); - return false; - } - boolean result = false; + boolean owner = plot.isOwner(player.getUUID()); + boolean permission; + boolean admin; switch (args[0].toLowerCase()) { case "set": if (args.length != 2) { @@ -77,18 +82,34 @@ public class Alias extends SubCommand { return false; } - if (canExecuteCommand(player, Captions.PERMISSION_ALIAS_SET, false) - || canExecuteCommand(player, Captions.PERMISSION_ALIAS_SET_OBSOLETE, false)) { + permission = isPermitted(player, Captions.PERMISSION_ALIAS_SET) + || isPermitted(player, Captions.PERMISSION_ALIAS_SET_OBSOLETE); + admin = isPermitted(player, Captions.PERMISSION_ADMIN_ALIAS_SET); + if (!admin && !owner) { + MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); + return false; + } + if (permission) { // is either admin or owner setAlias(player, plot, args[1]); return true; } else { - MainUtil.sendMessage(player, Captions.NO_PERMISSION); + MainUtil.sendMessage(player, Captions.NO_PERMISSION, + Captions.PERMISSION_ALIAS_SET.getTranslated()); } break; case "remove": - if (canExecuteCommand(player, Captions.PERMISSION_ALIAS_REMOVE, true)) { + permission = isPermitted(player, Captions.PERMISSION_ALIAS_REMOVE); + admin = isPermitted(player, Captions.PERMISSION_ADMIN_ALIAS_REMOVE); + if (!admin && !owner) { + MainUtil.sendMessage(player, Captions.NO_PLOT_PERMS); + return false; + } + if (permission) { result = removeAlias(player, plot); + } else { + MainUtil.sendMessage(player, Captions.NO_PERMISSION, + Captions.PERMISSION_ALIAS_REMOVE.getTranslated()); } break; default: @@ -99,6 +120,20 @@ public class Alias extends SubCommand { return result; } + @Override + public Collection tab(PlotPlayer player, String[] args, boolean space) { + final List commands = new ArrayList<>(2); + if (args.length == 1) { + if ("set".startsWith(args[0])) { + commands.add(SET_COMMAND); + } + if ("remove".startsWith(args[0])) { + commands.add(REMOVE_COMMAND); + } + return commands; + } + return Collections.emptySet(); + } private void setAlias(PlotPlayer player, Plot plot, String alias) { if (alias.isEmpty()) { @@ -110,11 +145,11 @@ public class Alias extends SubCommand { } else if (MathMan.isInteger(alias)) { Captions.NOT_VALID_VALUE.send(player); } else { - for (Plot p : PlotSquared.get().getPlots(plot.getArea())) { - if (p.getAlias().equalsIgnoreCase(alias)) { - MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); - return; - } + if (PlotQuery.newQuery().inArea(plot.getArea()) + .withAlias(alias) + .anyMatch()) { + MainUtil.sendMessage(player, Captions.ALIAS_IS_TAKEN); + return; } PlotSquared.get().getImpromptuUUIDPipeline().getSingle(alias, ((uuid, throwable) -> { if (throwable instanceof TimeoutException) { @@ -130,19 +165,13 @@ public class Alias extends SubCommand { } } - private boolean removeAlias(PlotPlayer player, Plot plot) { + private boolean removeAlias(PlotPlayer player, Plot plot) { plot.setAlias(null); MainUtil.sendMessage(player, Captions.ALIAS_REMOVED.getTranslated()); return true; } - private boolean canExecuteCommand(PlotPlayer player, Captions caption, boolean sendMessage) { - if (!Permissions.hasPermission(player, caption)) { - if (sendMessage) { - MainUtil.sendMessage(player, Captions.NO_PERMISSION); - } - return false; - } - return true; + private boolean isPermitted(PlotPlayer player, Captions caption) { + return Permissions.hasPermission(player, caption); } } diff --git a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java index 03874da48..dbcf463ac 100644 --- a/Core/src/main/java/com/plotsquared/core/configuration/Captions.java +++ b/Core/src/main/java/com/plotsquared/core/configuration/Captions.java @@ -182,7 +182,9 @@ public enum Captions implements Caption { PERMISSION_HOME("plots.home", "static.permissions"), PERMISSION_ALIAS_SET_OBSOLETE("plots.set.alias", "static.permissions"), // Note this is for backwards compatibility PERMISSION_ALIAS_SET("plots.alias.set", "static.permissions"), + PERMISSION_ADMIN_ALIAS_SET("plots.admin.alias.set", "static.permissions"), PERMISSION_ALIAS_REMOVE("plots.alias.remove", "static.permissions"), + PERMISSION_ADMIN_ALIAS_REMOVE("plots.admin.alias.remove", "static.permissions"), PERMISSION_ADMIN_CHAT_BYPASS("plots.admin.chat.bypass", "static.permissions"), PERMISSION_BACKUP("plots.backup", "static.permissions"), PERMISSION_BACKUP_SAVE("plots.backup.save", "static.permissions"), diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 40d883062..27b4352eb 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -376,6 +376,30 @@ public final class PlotQuery { return this.asList(); } + /** + * Get whether any provided plot matches the given filters. + * If no plot was provided, false will be returned. + * + * @return true if any provided plot matches the filters. + */ + public boolean anyMatch() { + if (this.filters.isEmpty()) { + return !this.plotProvider.getPlots().isEmpty(); + } else { + final Collection plots = this.plotProvider.getPlots(); + outer: for (final Plot plot : plots) { + // a plot must pass all filters to match the criteria + for (final PlotFilter filter : this.filters) { + if (!filter.accepts(plot)) { + continue outer; + } + } + return true; // a plot passed all filters, so we have a match + } + return false; + } + } + @NotNull private PlotQuery addFilter(@NotNull final PlotFilter filter) { this.filters.add(filter); return this; From 49c35ec084f861ad1017d7b0e47aaaaa27fe3a1b Mon Sep 17 00:00:00 2001 From: MattBDev <4009945+MattBDev@users.noreply.github.com> Date: Mon, 29 Jun 2020 22:05:32 -0400 Subject: [PATCH 120/121] Resolve NMF's concerns --- Bukkit/build.gradle | 5 +- Bukkit/pom.xml | 12 +- .../entity/ReplicatingEntityWrapper.java | 338 +++++++++--------- 3 files changed, 185 insertions(+), 170 deletions(-) diff --git a/Bukkit/build.gradle b/Bukkit/build.gradle index 6b011faf7..61ae5e54f 100644 --- a/Bukkit/build.gradle +++ b/Bukkit/build.gradle @@ -25,7 +25,10 @@ dependencies { compile("com.destroystokyo.paper:paper-api:1.16.1-R0.1-SNAPSHOT") //implementation 'com.onarandombox.multiversecore:Multiverse-Core:3.0.0-SNAPSHOT' implementation("org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT") - compile(group: "com.sk89q.worldedit", name: "worldedit-bukkit", version: "7.0.1") + compile(group: "com.sk89q.worldedit", name: "worldedit-bukkit", version: "7.1.0") { + exclude(module: "bukkit") + + } compile("io.papermc:paperlib:1.0.2") implementation("net.kyori:text-adapter-bukkit:3.0.3") compile("com.github.MilkBowl:VaultAPI:1.7") { diff --git a/Bukkit/pom.xml b/Bukkit/pom.xml index d01f91307..d70af5d57 100644 --- a/Bukkit/pom.xml +++ b/Bukkit/pom.xml @@ -27,14 +27,20 @@ com.destroystokyo.paper paper-api - 1.15.2-R0.1-SNAPSHOT + 1.16.1-R0.1-SNAPSHOT compile com.sk89q.worldedit worldedit-bukkit - 7.0.1 + 7.1.0 compile + + + bukkit + * + + io.papermc @@ -131,7 +137,7 @@ org.spigotmc spigot-api - 1.15.2-R0.1-SNAPSHOT + 1.16.1-R0.1-SNAPSHOT runtime diff --git a/Bukkit/src/main/java/com/plotsquared/bukkit/entity/ReplicatingEntityWrapper.java b/Bukkit/src/main/java/com/plotsquared/bukkit/entity/ReplicatingEntityWrapper.java index f0ef20fba..83740e9db 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/entity/ReplicatingEntityWrapper.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/entity/ReplicatingEntityWrapper.java @@ -103,51 +103,51 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { if (!entity.hasGravity()) { this.noGravity = true; } - switch (entity.getType()) { - case BOAT: + switch (entity.getType().toString()) { + case "BOAT": Boat boat = (Boat) entity; this.dataByte = getOrdinal(TreeSpecies.values(), boat.getWoodType()); return; - case ARROW: - case EGG: - case ENDER_CRYSTAL: - case ENDER_PEARL: - case ENDER_SIGNAL: - case EXPERIENCE_ORB: - case FALLING_BLOCK: - case FIREBALL: - case FIREWORK: - case FISHING_HOOK: - case LEASH_HITCH: - case LIGHTNING: - case MINECART: - case MINECART_COMMAND: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - case PLAYER: - case PRIMED_TNT: - case SLIME: - case SMALL_FIREBALL: - case SNOWBALL: - case MINECART_FURNACE: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case WITHER_SKULL: - case UNKNOWN: - case SPECTRAL_ARROW: - case SHULKER_BULLET: - case DRAGON_FIREBALL: - case AREA_EFFECT_CLOUD: - case TRIDENT: - case LLAMA_SPIT: + case "ARROW": + case "EGG": + case "ENDER_CRYSTAL": + case "ENDER_PEARL": + case "ENDER_SIGNAL": + case "EXPERIENCE_ORB": + case "FALLING_BLOCK": + case "FIREBALL": + case "FIREWORK": + case "FISHING_HOOK": + case "LEASH_HITCH": + case "LIGHTNING": + case "MINECART": + case "MINECART_COMMAND": + case "MINECART_MOB_SPAWNER": + case "MINECART_TNT": + case "PLAYER": + case "PRIMED_TNT": + case "SLIME": + case "SMALL_FIREBALL": + case "SNOWBALL": + case "MINECART_FURNACE": + case "SPLASH_POTION": + case "THROWN_EXP_BOTTLE": + case "WITHER_SKULL": + case "UNKNOWN": + case "SPECTRAL_ARROW": + case "SHULKER_BULLET": + case "DRAGON_FIREBALL": + case "AREA_EFFECT_CLOUD": + case "TRIDENT": + case "LLAMA_SPIT": // Do this stuff later return; // MISC // - case DROPPED_ITEM: + case "DROPPED_ITEM": Item item = (Item) entity; this.stack = item.getItemStack(); return; - case ITEM_FRAME: + case "ITEM_FRAME": this.x = Math.floor(this.x); this.y = Math.floor(this.y); this.z = Math.floor(this.z); @@ -155,7 +155,7 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { this.dataByte = getOrdinal(Rotation.values(), itemFrame.getRotation()); this.stack = itemFrame.getItem().clone(); return; - case PAINTING: + case "PAINTING": this.x = Math.floor(this.x); this.y = Math.floor(this.y); this.z = Math.floor(this.z); @@ -170,18 +170,18 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { return; // END MISC // // INVENTORY HOLDER // - case MINECART_CHEST: - case MINECART_HOPPER: + case "MINECART_CHEST": + case "MINECART_HOPPER": storeInventory((InventoryHolder) entity); return; // START LIVING ENTITY // // START AGEABLE // // START TAMEABLE // - case HORSE: - case DONKEY: - case LLAMA: - case MULE: - case SKELETON_HORSE: + case "HORSE": + case "DONKEY": + case "LLAMA": + case "MULE": + case "SKELETON_HORSE": AbstractHorse horse = (AbstractHorse) entity; this.horse = new HorseStats(); this.horse.jump = horse.getJumpStrength(); @@ -199,15 +199,15 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { storeInventory(horse); return; // END INVENTORY HOLDER // - case WOLF: - case OCELOT: + case "WOLF": + case "OCELOT": storeTameable((Tameable) entity); storeAgeable((Ageable) entity); storeLiving((LivingEntity) entity); return; // END TAMEABLE // //todo fix sheep - case SHEEP: + case "SHEEP": Sheep sheep = (Sheep) entity; if (sheep.isSheared()) { this.dataByte = (byte) 1; @@ -218,23 +218,23 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { storeAgeable(sheep); storeLiving(sheep); return; - case VILLAGER: - case CHICKEN: - case COW: - case MUSHROOM_COW: - case PIG: - case TURTLE: - case POLAR_BEAR: + case "VILLAGER": + case "CHICKEN": + case "COW": + case "MUSHROOM_COW": + case "PIG": + case "TURTLE": + case "POLAR_BEAR": storeAgeable((Ageable) entity); storeLiving((LivingEntity) entity); return; - case RABBIT: + case "RABBIT": this.dataByte = getOrdinal(Rabbit.Type.values(), ((Rabbit) entity).getRabbitType()); storeAgeable((Ageable) entity); storeLiving((LivingEntity) entity); return; // END AGEABLE // - case ARMOR_STAND: + case "ARMOR_STAND": ArmorStand stand = (ArmorStand) entity; this.inventory = new ItemStack[] {stand.getItemInHand().clone(), stand.getHelmet().clone(), @@ -286,42 +286,45 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { this.stand.small = true; } return; - case ENDERMITE: + case "ENDERMITE": return; - case BAT: + case "BAT": if (((Bat) entity).isAwake()) { this.dataByte = (byte) 1; } else { this.dataByte = (byte) 0; } return; - case ENDER_DRAGON: + case "ENDER_DRAGON": EnderDragon entity1 = (EnderDragon) entity; this.dataByte = (byte) entity1.getPhase().ordinal(); return; - case SKELETON: - case WITHER_SKELETON: - case GUARDIAN: - case ELDER_GUARDIAN: - case GHAST: - case MAGMA_CUBE: - case SQUID: - case PIG_ZOMBIE: - case ZOMBIE: - case WITHER: - case WITCH: - case SPIDER: - case CAVE_SPIDER: - case SILVERFISH: - case GIANT: - case ENDERMAN: - case CREEPER: - case BLAZE: - case SHULKER: - case SNOWMAN: + case "SKELETON": + case "WITHER_SKELETON": + case "GUARDIAN": + case "ELDER_GUARDIAN": + case "GHAST": + case "MAGMA_CUBE": + case "SQUID": + case "PIG_ZOMBIE": + case "HOGLIN": + case "ZOMBIFIED_PIGLIN": + case "PIGLIN": + case "ZOMBIE": + case "WITHER": + case "WITCH": + case "SPIDER": + case "CAVE_SPIDER": + case "SILVERFISH": + case "GIANT": + case "ENDERMAN": + case "CREEPER": + case "BLAZE": + case "SHULKER": + case "SNOWMAN": storeLiving((LivingEntity) entity); return; - case IRON_GOLEM: + case "IRON_GOLEM": if (((IronGolem) entity).isPlayerCreated()) { this.dataByte = (byte) 1; } else { @@ -463,16 +466,16 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { return null; } Entity entity; - switch (this.getType()) { - case DROPPED_ITEM: + switch (this.getType().toString()) { + case "DROPPED_ITEM": return world.dropItem(location, this.stack); - case PLAYER: - case LEASH_HITCH: + case "PLAYER": + case "LEASH_HITCH": return null; - case ITEM_FRAME: + case "ITEM_FRAME": entity = world.spawn(location, ItemFrame.class); break; - case PAINTING: + case "PAINTING": entity = world.spawn(location, Painting.class); break; default: @@ -504,73 +507,73 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { if (this.noGravity) { entity.setGravity(false); } - switch (entity.getType()) { - case BOAT: + switch (entity.getType().toString()) { + case "BOAT": Boat boat = (Boat) entity; boat.setWoodType(TreeSpecies.values()[dataByte]); return entity; - case SLIME: + case "SLIME": ((Slime) entity).setSize(this.dataByte); return entity; - case ARROW: - case EGG: - case ENDER_CRYSTAL: - case ENDER_PEARL: - case ENDER_SIGNAL: - case DROPPED_ITEM: - case EXPERIENCE_ORB: - case FALLING_BLOCK: - case FIREBALL: - case FIREWORK: - case FISHING_HOOK: - case LEASH_HITCH: - case LIGHTNING: - case MINECART: - case MINECART_COMMAND: - case MINECART_MOB_SPAWNER: - case MINECART_TNT: - case PLAYER: - case PRIMED_TNT: - case SMALL_FIREBALL: - case SNOWBALL: - case SPLASH_POTION: - case THROWN_EXP_BOTTLE: - case SPECTRAL_ARROW: - case SHULKER_BULLET: - case AREA_EFFECT_CLOUD: - case DRAGON_FIREBALL: - case WITHER_SKULL: - case MINECART_FURNACE: - case LLAMA_SPIT: - case TRIDENT: - case UNKNOWN: + case "ARROW": + case "EGG": + case "ENDER_CRYSTAL": + case "ENDER_PEARL": + case "ENDER_SIGNAL": + case "DROPPED_ITEM": + case "EXPERIENCE_ORB": + case "FALLING_BLOCK": + case "FIREBALL": + case "FIREWORK": + case "FISHING_HOOK": + case "LEASH_HITCH": + case "LIGHTNING": + case "MINECART": + case "MINECART_COMMAND": + case "MINECART_MOB_SPAWNER": + case "MINECART_TNT": + case "PLAYER": + case "PRIMED_TNT": + case "SMALL_FIREBALL": + case "SNOWBALL": + case "SPLASH_POTION": + case "THROWN_EXP_BOTTLE": + case "SPECTRAL_ARROW": + case "SHULKER_BULLET": + case "AREA_EFFECT_CLOUD": + case "DRAGON_FIREBALL": + case "WITHER_SKULL": + case "MINECART_FURNACE": + case "LLAMA_SPIT": + case "TRIDENT": + case "UNKNOWN": // Do this stuff later return entity; // MISC // - case ITEM_FRAME: + case "ITEM_FRAME": ItemFrame itemframe = (ItemFrame) entity; itemframe.setRotation(Rotation.values()[this.dataByte]); itemframe.setItem(this.stack); return entity; - case PAINTING: + case "PAINTING": Painting painting = (Painting) entity; painting.setFacingDirection(BlockFace.values()[this.dataByte], true); painting.setArt(Art.getByName(this.dataString), true); return entity; // END MISC // // INVENTORY HOLDER // - case MINECART_CHEST: - case MINECART_HOPPER: + case "MINECART_CHEST": + case "MINECART_HOPPER": restoreInventory((InventoryHolder) entity); return entity; // START LIVING ENTITY // // START AGEABLE // // START TAMEABLE // - case HORSE: - case LLAMA: - case SKELETON_HORSE: - case DONKEY: - case MULE: + case "HORSE": + case "LLAMA": + case "SKELETON_HORSE": + case "DONKEY": + case "MULE": AbstractHorse horse = (AbstractHorse) entity; horse.setJumpStrength(this.horse.jump); if (horse instanceof ChestedHorse) { @@ -586,14 +589,14 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { restoreInventory(horse); return entity; // END INVENTORY HOLDER // - case WOLF: - case OCELOT: + case "WOLF": + case "OCELOT": restoreTameable((Tameable) entity); restoreAgeable((Ageable) entity); restoreLiving((LivingEntity) entity); return entity; // END AGEABLE // - case SHEEP: + case "SHEEP": Sheep sheep = (Sheep) entity; if (this.dataByte == 1) { sheep.setSheared(true); @@ -604,25 +607,25 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { restoreAgeable(sheep); restoreLiving(sheep); return sheep; - case VILLAGER: - case CHICKEN: - case COW: - case TURTLE: - case POLAR_BEAR: - case MUSHROOM_COW: - case PIG: + case "VILLAGER": + case "CHICKEN": + case "COW": + case "TURTLE": + case "POLAR_BEAR": + case "MUSHROOM_COW": + case "PIG": restoreAgeable((Ageable) entity); restoreLiving((LivingEntity) entity); return entity; // END AGEABLE // - case RABBIT: + case "RABBIT": if (this.dataByte != 0) { ((Rabbit) entity).setRabbitType(Rabbit.Type.values()[this.dataByte]); } restoreAgeable((Ageable) entity); restoreLiving((LivingEntity) entity); return entity; - case ARMOR_STAND: + case "ARMOR_STAND": // CHECK positions ArmorStand stand = (ArmorStand) entity; if (this.inventory[0] != null) { @@ -688,42 +691,45 @@ public final class ReplicatingEntityWrapper extends EntityWrapper { } restoreLiving(stand); return stand; - case BAT: + case "BAT": if (this.dataByte != 0) { ((Bat) entity).setAwake(true); } restoreLiving((LivingEntity) entity); return entity; - case ENDER_DRAGON: + case "ENDER_DRAGON": if (this.dataByte != 0) { ((EnderDragon) entity).setPhase(EnderDragon.Phase.values()[this.dataByte]); } restoreLiving((LivingEntity) entity); return entity; - case ENDERMITE: - case GHAST: - case MAGMA_CUBE: - case SQUID: - case PIG_ZOMBIE: - case ZOMBIE: - case WITHER: - case WITCH: - case SPIDER: - case CAVE_SPIDER: - case SILVERFISH: - case GIANT: - case ENDERMAN: - case CREEPER: - case BLAZE: - case SNOWMAN: - case SHULKER: - case GUARDIAN: - case ELDER_GUARDIAN: - case SKELETON: - case WITHER_SKELETON: + case "ENDERMITE": + case "GHAST": + case "MAGMA_CUBE": + case "SQUID": + case "PIG_ZOMBIE": + case "HOGLIN": + case "PIGLIN": + case "ZOMBIFIED_PIGLIN": + case "ZOMBIE": + case "WITHER": + case "WITCH": + case "SPIDER": + case "CAVE_SPIDER": + case "SILVERFISH": + case "GIANT": + case "ENDERMAN": + case "CREEPER": + case "BLAZE": + case "SNOWMAN": + case "SHULKER": + case "GUARDIAN": + case "ELDER_GUARDIAN": + case "SKELETON": + case "WITHER_SKELETON": restoreLiving((LivingEntity) entity); return entity; - case IRON_GOLEM: + case "IRON_GOLEM": if (this.dataByte != 0) { ((IronGolem) entity).setPlayerCreated(true); } From cbe8875b94c19e25159e3262e23ba998b4a26621 Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Wed, 1 Jul 2020 11:59:28 +0200 Subject: [PATCH 121/121] Bump gradle version --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4c5803d13..bb8b2fc26 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists