From d8e5daf12bf711373cd24d7437e326143ddd77a2 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 23 Jul 2020 18:04:01 +0100 Subject: [PATCH 01/10] Fix missing Main->Chunk Util change --- .../com/plotsquared/bukkit/queue/BukkitLocalQueue.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 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 fa6ccd69d..a1bf7bee7 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/queue/BukkitLocalQueue.java @@ -29,7 +29,7 @@ import com.plotsquared.bukkit.schematic.StateWrapper; import com.plotsquared.bukkit.util.BukkitBlockUtil; import com.plotsquared.core.queue.BasicLocalBlockQueue; import com.plotsquared.core.util.BlockUtil; -import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.ChunkUtil; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; @@ -48,8 +48,8 @@ import org.bukkit.block.Biome; import org.bukkit.block.Block; import org.bukkit.block.Container; import org.bukkit.block.data.BlockData; -import javax.annotation.Nonnull; +import javax.annotation.Nonnull; import java.util.concurrent.ExecutionException; import java.util.function.Consumer; @@ -125,9 +125,9 @@ public class BukkitLocalQueue extends BasicLocalBlockQueue { for (int j = 0; j < blocksLayer.length; j++) { if (blocksLayer[j] != null) { BaseBlock block = blocksLayer[j]; - int x = MainUtil.x_loc[layer][j]; - int y = MainUtil.y_loc[layer][j]; - int z = MainUtil.z_loc[layer][j]; + int x = ChunkUtil.getX(j); + int y = ChunkUtil.getY(layer, j); + int z = ChunkUtil.getZ(j); BlockData blockData = BukkitAdapter.adapt(block); From 4d4f7556070a4aaacb471c4842a7a8f365698346 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 23 Jul 2020 18:06:14 +0100 Subject: [PATCH 02/10] 6.0.0-SUPER-SNAPSHOT --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index eacbc0fc2..806f85e47 100644 --- a/build.gradle +++ b/build.gradle @@ -30,8 +30,8 @@ ext { git = Grgit.open(dir: new File(rootDir.toString() + "/.git")) } -def ver = "5.12.5" -def versuffix = "" +def ver = "6.0.0" +def versuffix = "SUPER-SNAPSHOT" ext { if (project.hasProperty("versionsuffix")) { versuffix = "-$versionsuffix" From a1da452c415963222e3cca7904c7d079220171e1 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 23 Jul 2020 18:09:37 +0100 Subject: [PATCH 03/10] Fix build properly --- .../core/queue/BasicLocalBlockQueue.java | 6 ++--- .../com/plotsquared/core/util/ChunkUtil.java | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java b/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java index 03aa8b437..487cfaf7a 100644 --- a/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java +++ b/Core/src/main/java/com/plotsquared/core/queue/BasicLocalBlockQueue.java @@ -25,7 +25,7 @@ */ package com.plotsquared.core.queue; -import com.plotsquared.core.util.MainUtil; +import com.plotsquared.core.util.ChunkUtil; import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.task.TaskManager; @@ -262,8 +262,8 @@ public abstract class BasicLocalBlockQueue extends LocalBlockQueue { } private void setInternal(final int x, final int y, final int z, final BaseBlock baseBlock) { - final int i = MainUtil.CACHE_I[y][x][z]; - final int j = MainUtil.CACHE_J[y][x][z]; + final int i = y >> 4; + final int j = ChunkUtil.getJ(x, y, z); BaseBlock[] array = baseblocks[i]; if (array == null) { array = (baseblocks[i] = new BaseBlock[4096]); diff --git a/Core/src/main/java/com/plotsquared/core/util/ChunkUtil.java b/Core/src/main/java/com/plotsquared/core/util/ChunkUtil.java index 3e89c630a..6c1a1415d 100644 --- a/Core/src/main/java/com/plotsquared/core/util/ChunkUtil.java +++ b/Core/src/main/java/com/plotsquared/core/util/ChunkUtil.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.util; import lombok.experimental.UtilityClass; From 2575787bd08c683186ae92426d431440e0ef3991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 23 Jul 2020 18:30:50 +0200 Subject: [PATCH 04/10] Add LockRepository --- .../core/synchronization/LockKey.java | 92 ++++++++++++++ .../core/synchronization/LockRepository.java | 116 ++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 Core/src/main/java/com/plotsquared/core/synchronization/LockKey.java create mode 100644 Core/src/main/java/com/plotsquared/core/synchronization/LockRepository.java diff --git a/Core/src/main/java/com/plotsquared/core/synchronization/LockKey.java b/Core/src/main/java/com/plotsquared/core/synchronization/LockKey.java new file mode 100644 index 000000000..0062d4da6 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/synchronization/LockKey.java @@ -0,0 +1,92 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.synchronization; + +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Key used to access {@link java.util.concurrent.locks.Lock locks} + * from a {@link LockRepository} + */ +public final class LockKey { + + private static final Map keyMap = new HashMap<>(); + private static final Object keyLock = new Object(); + + private final String key; + + private LockKey(@Nonnull final String key) { + this.key = Preconditions.checkNotNull(key, "Key may not be null"); + } + + /** + * Get a new named lock key + * + * @param key Key name + * @return Lock key instance + */ + @Nonnull public static LockKey of(@Nonnull final String key) { + synchronized (keyLock) { + return keyMap.computeIfAbsent(key, LockKey::new); + } + } + + /** + * Get all currently recognized lock keys + * + * @return Currently recognized lock keys + */ + @Nonnull static Collection recognizedKeys() { + return Collections.unmodifiableCollection(keyMap.values()); + } + + @Override public String toString() { + return "LockKey{" + "key='" + key + '\'' + '}'; + } + + @Override public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final LockKey lockKey = (LockKey) o; + return Objects.equal(this.key, lockKey.key); + } + + @Override public int hashCode() { + return Objects.hashCode(this.key); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/synchronization/LockRepository.java b/Core/src/main/java/com/plotsquared/core/synchronization/LockRepository.java new file mode 100644 index 000000000..373f3694c --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/synchronization/LockRepository.java @@ -0,0 +1,116 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.synchronization; + +import com.google.common.util.concurrent.Striped; + +import javax.annotation.Nonnull; +import java.util.concurrent.locks.Lock; +import java.util.function.Consumer; + +/** + * A repository for keyed {@link java.util.concurrent.locks.Lock locks} + */ +public final class LockRepository { + + private final Striped striped; + + public LockRepository() { + this.striped = Striped.lock(LockKey.recognizedKeys().size()); + } + + /** + * Get the lock corresponding to the given lock key + * + * @param key Lock key + * @return Lock + */ + @Nonnull public Lock getLock(@Nonnull final LockKey key) { + return this.striped.get(key); + } + + /** + * Consume a lock + * + * @param key Lock key + * @param consumer Lock consumer + */ + public void useLock(@Nonnull final LockKey key, @Nonnull final Consumer consumer) { + consumer.accept(this.getLock(key)); + } + + /** + * Wait for the lock to become available, and run + * the given runnable, then unlock the lock. This is + * a blocking method. + * + * @param key Lock key + * @param runnable Action to run when the lock is available + */ + public void useLock(@Nonnull final LockKey key, @Nonnull final Runnable runnable) { + this.useLock(key, lock -> { + lock.lock(); + runnable.run(); + lock.unlock(); + }); + } + + /** + * Wait for a lock to be available, lock it and return + * an {@link AutoCloseable} instance that locks the key. + *

+ * This is meant to be used with try-with-resources, like such: + *

{@code
+     * try (final LockAccess lockAccess = lockRepository.lock(LockKey.of("your.key"))) {
+     *      // use lock
+     * }
+     * }
+ * + * @param key Lock key + * @return Lock access. Must be closed. + */ + @Nonnull public LockAccess lock(@Nonnull final LockKey key) { + final Lock lock = this.getLock(key); + lock.lock(); + return new LockAccess(lock); + } + + + public static class LockAccess implements AutoCloseable { + + private final Lock lock; + + private LockAccess(@Nonnull final Lock lock) { + this.lock = lock; + } + + @Override public void close() { + this.lock.unlock(); + } + + } + +} From 555860cf838b6e0747fc879b33c7ba14d751c6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 23 Jul 2020 19:18:21 +0200 Subject: [PATCH 05/10] Add managed persistent meta data access --- .../com/plotsquared/core/command/Auto.java | 41 +++---- .../com/plotsquared/core/command/Claim.java | 86 +++++++------- .../com/plotsquared/core/command/Grant.java | 62 +++++----- .../core/listener/PlotListener.java | 31 ++--- .../core/player/MetaDataAccess.java | 101 +++++++++++++++++ .../plotsquared/core/player/MetaDataKey.java | 107 ++++++++++++++++++ .../core/player/PersistentMetaDataAccess.java | 57 ++++++++++ .../core/player/PlayerMetaDataKeys.java | 36 ++++++ .../plotsquared/core/player/PlotPlayer.java | 63 ++++++++++- 9 files changed, 474 insertions(+), 110 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java create mode 100644 Core/src/main/java/com/plotsquared/core/player/MetaDataKey.java create mode 100644 Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java create mode 100644 Core/src/main/java/com/plotsquared/core/player/PlayerMetaDataKeys.java 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 ea6a6cf6c..46be2c3e5 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Auto.java +++ b/Core/src/main/java/com/plotsquared/core/command/Auto.java @@ -26,7 +26,6 @@ package com.plotsquared.core.command; import com.google.common.collect.Lists; -import com.google.common.primitives.Ints; import com.google.inject.Inject; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.CaptionUtility; @@ -37,6 +36,8 @@ import com.plotsquared.core.events.PlayerAutoPlotEvent; import com.plotsquared.core.events.PlotAutoMergeEvent; import com.plotsquared.core.events.Result; import com.plotsquared.core.events.TeleportCause; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -91,27 +92,29 @@ public class Auto extends SubCommand { } int diff = allowedPlots - currentPlots; if (diff - sizeX * sizeZ < 0) { - if (player.hasPersistentMeta("grantedPlots")) { - int grantedPlots = Ints.fromByteArray(player.getPersistentMeta("grantedPlots")); - if (diff < 0 && grantedPlots < sizeX * sizeZ) { - MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); - return false; - } else if (diff >= 0 && grantedPlots + diff < sizeX * sizeZ) { - MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); - return false; - } else { - int left = grantedPlots + diff < 0 ? 0 : diff - sizeX * sizeZ; - if (left == 0) { - player.removePersistentMeta("grantedPlots"); + try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData( + PlayerMetaDataKeys.GRANTED_PLOTS)) { + if (metaDataAccess.has()) { + int grantedPlots = metaDataAccess.get().orElse(0); + if (diff < 0 && grantedPlots < sizeX * sizeZ) { + MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); + return false; + } else if (diff >= 0 && grantedPlots + diff < sizeX * sizeZ) { + MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); + return false; } else { - player.setPersistentMeta("grantedPlots", Ints.toByteArray(left)); + int left = grantedPlots + diff < 0 ? 0 : diff - sizeX * sizeZ; + if (left == 0) { + metaDataAccess.remove(); + } else { + metaDataAccess.set(left); + } + MainUtil.sendMessage(player, Captions.REMOVED_GRANTED_PLOT, "" + (grantedPlots - left), "" + left); } - MainUtil.sendMessage(player, Captions.REMOVED_GRANTED_PLOT, - "" + (grantedPlots - left), "" + left); + } else { + MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); + return false; } - } else { - MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); - return false; } } 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 bb3ae02c3..c9bfb4c8f 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Claim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Claim.java @@ -25,7 +25,6 @@ */ package com.plotsquared.core.command; -import com.google.common.primitives.Ints; import com.google.inject.Inject; import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.Captions; @@ -36,6 +35,8 @@ import com.plotsquared.core.events.PlotMergeEvent; import com.plotsquared.core.events.Result; import com.plotsquared.core.location.Direction; import com.plotsquared.core.location.Location; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -85,54 +86,57 @@ public class Claim extends SubCommand { int currentPlots = Settings.Limit.GLOBAL ? player.getPlotCount() : player.getPlotCount(location.getWorldName()); - int grants = 0; - if (currentPlots >= player.getAllowedPlots() && !force) { - if (player.hasPersistentMeta("grantedPlots")) { - grants = Ints.fromByteArray(player.getPersistentMeta("grantedPlots")); - if (grants <= 0) { - player.removePersistentMeta("grantedPlots"); + + final PlotArea area = plot.getArea(); + + try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.GRANTED_PLOTS)) { + int grants = 0; + if (currentPlots >= player.getAllowedPlots() && !force) { + if (metaDataAccess.has()) { + grants = metaDataAccess.get().orElse(0); + if (grants <= 0) { + metaDataAccess.remove(); + return sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); + } + } else { return sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); } - } else { - return sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); } - } - if (!plot.canClaim(player)) { - return sendMessage(player, Captions.PLOT_IS_CLAIMED); - } - final PlotArea area = plot.getArea(); - if (schematic != null && !schematic.isEmpty()) { - if (area.isSchematicClaimSpecify()) { - if (!area.hasSchematic(schematic)) { - return sendMessage(player, Captions.SCHEMATIC_INVALID, - "non-existent: " + schematic); - } - if (!Permissions.hasPermission(player, CaptionUtility - .format(player, Captions.PERMISSION_CLAIM_SCHEMATIC.getTranslated(), schematic)) - && !Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_SCHEMATIC) && !force) { - return sendMessage(player, Captions.NO_SCHEMATIC_PERMISSION, schematic); + + if (!plot.canClaim(player)) { + return sendMessage(player, Captions.PLOT_IS_CLAIMED); + } + if (schematic != null && !schematic.isEmpty()) { + if (area.isSchematicClaimSpecify()) { + if (!area.hasSchematic(schematic)) { + return sendMessage(player, Captions.SCHEMATIC_INVALID, "non-existent: " + schematic); + } + if (!Permissions.hasPermission(player, CaptionUtility.format(player, Captions.PERMISSION_CLAIM_SCHEMATIC.getTranslated(), + schematic)) && !Permissions.hasPermission(player, Captions.PERMISSION_ADMIN_COMMAND_SCHEMATIC) + && !force) { + return sendMessage(player, Captions.NO_SCHEMATIC_PERMISSION, schematic); + } } } - } - if ((this.econHandler != null) && area.useEconomy() && !force) { - Expression costExr = area.getPrices().get("claim"); - double cost = costExr.evaluate((double) currentPlots); - if (cost > 0d) { - if (this.econHandler.getMoney(player) < cost) { - return sendMessage(player, Captions.CANNOT_AFFORD_PLOT, "" + cost); + if ((this.econHandler != null) && area.useEconomy() && !force) { + Expression costExr = area.getPrices().get("claim"); + double cost = costExr.evaluate((double) currentPlots); + if (cost > 0d) { + if (this.econHandler.getMoney(player) < cost) { + return sendMessage(player, Captions.CANNOT_AFFORD_PLOT, "" + cost); + } + this.econHandler.withdrawMoney(player, cost); + sendMessage(player, Captions.REMOVED_BALANCE, cost + ""); } - this.econHandler.withdrawMoney(player, cost); - sendMessage(player, Captions.REMOVED_BALANCE, cost + ""); } - } - if (grants > 0) { - if (grants == 1) { - player.removePersistentMeta("grantedPlots"); - } else { - player.setPersistentMeta("grantedPlots", Ints.toByteArray(grants - 1)); + if (grants > 0) { + if (grants == 1) { + metaDataAccess.remove(); + } else { + metaDataAccess.set(grants - 1); + } + sendMessage(player, Captions.REMOVED_GRANTED_PLOT, "1", (grants - 1)); } - sendMessage(player, Captions.REMOVED_GRANTED_PLOT, "1", (grants - 1)); } int border = area.getBorder(); if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !force) { 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 ab1ef00d4..429e97168 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Grant.java +++ b/Core/src/main/java/com/plotsquared/core/command/Grant.java @@ -30,6 +30,8 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.database.DBFunc; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.Permissions; @@ -42,7 +44,6 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeoutException; -import java.util.function.Consumer; @CommandDeclaration(command = "grant", category = CommandCategory.CLAIMING, @@ -80,41 +81,40 @@ public class Grant extends Command { MainUtil.sendMessage(player, Captions.INVALID_PLAYER); } else { final UUID uuid = uuids.toArray(new UUID[0])[0]; - final Consumer result = 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.platform().getPlayerManager().getPlayerIfExists(uuid); - if (online != null) { - online.setPersistentMeta(key, rawData); - } else { - DBFunc.addPersistentMeta(uuid, key, rawData, replace); - } - } - }; PlotPlayer pp = PlotSquared.platform().getPlayerManager().getPlayerIfExists(uuid); if (pp != null) { - result.accept(player.getPersistentMeta("grantedPlots")); + try (final MetaDataAccess access = player.accessPersistentMetaData( + PlayerMetaDataKeys.GRANTED_PLOTS)) { + if (args[0].equalsIgnoreCase("check")) { + Captions.GRANTED_PLOTS.send(player, access.get().orElse(0)); + } else { + access.set(access.get().orElse(0) + 1); + } + } } else { DBFunc.getPersistentMeta(uuid, new RunnableVal>() { @Override public void run(Map value) { - result.accept(value.get("grantedPlots")); + final byte[] array = value.get("grantedPlots"); + 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); + DBFunc.addPersistentMeta(uuid, key, rawData, replace); + } } }); } 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 2579976a4..9fcaad2de 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -26,12 +26,13 @@ package com.plotsquared.core.listener; import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.collection.ByteArrayUtilities; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.events.PlotFlagRemoveEvent; import com.plotsquared.core.events.Result; import com.plotsquared.core.location.Location; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -71,6 +72,7 @@ import javax.annotation.Nullable; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Optional; import java.util.UUID; public class PlotListener { @@ -177,8 +179,9 @@ public class PlotListener { boolean flight = player.getFlight(); GameMode gamemode = player.getGameMode(); if (flight != (gamemode == GameModes.CREATIVE || gamemode == GameModes.SPECTATOR)) { - player.setPersistentMeta("flight", - ByteArrayUtilities.booleanToBytes(player.getFlight())); + try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_FLIGHT)) { + metaDataAccess.set(player.getFlight()); + } } player.setFlight(flyStatus == FlyFlag.FlyStatus.ENABLED); } @@ -346,16 +349,18 @@ public class PlotListener { final FlyFlag.FlyStatus flyStatus = plot.getFlag(FlyFlag.class); if (flyStatus != FlyFlag.FlyStatus.DEFAULT) { - if (player.hasPersistentMeta("flight")) { - player.setFlight( - ByteArrayUtilities.bytesToBoolean(player.getPersistentMeta("flight"))); - player.removePersistentMeta("flight"); - } else { - GameMode gameMode = player.getGameMode(); - if (gameMode == GameModes.SURVIVAL || gameMode == GameModes.ADVENTURE) { - player.setFlight(false); - } else if (!player.getFlight()) { - player.setFlight(true); + try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_FLIGHT)) { + final Optional value = metaDataAccess.get(); + if (value.isPresent()) { + player.setFlight(value.get()); + metaDataAccess.remove(); + } else { + GameMode gameMode = player.getGameMode(); + if (gameMode == GameModes.SURVIVAL || gameMode == GameModes.ADVENTURE) { + player.setFlight(false); + } else if (!player.getFlight()) { + player.setFlight(true); + } } } } diff --git a/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java b/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java new file mode 100644 index 000000000..b4f494edf --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java @@ -0,0 +1,101 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.player; + +import com.plotsquared.core.synchronization.LockRepository; + +import javax.annotation.Nonnull; +import java.util.Optional; + +/** + * Access to player meta data + * + * @param

Player type + * @param Meta data type + */ +public abstract class MetaDataAccess implements AutoCloseable { + + private final PlotPlayer player; + private final MetaDataKey metaDataKey; + private final LockRepository.LockAccess lockAccess; + + MetaDataAccess(@Nonnull final PlotPlayer player, @Nonnull final MetaDataKey metaDataKey, + @Nonnull final LockRepository.LockAccess lockAccess) { + this.player = player; + this.metaDataKey = metaDataKey; + this.lockAccess = lockAccess; + } + + /** + * Check if the player has meta data stored with the given key + * + * @return {@code true} if player has meta data with this key, or + * {@code false} + */ + public abstract boolean has(); + + /** + * Remove the stored value meta data + */ + public abstract void remove(); + + /** + * Set the meta data value + * + * @param value New value + */ + public abstract void set(@Nonnull final T value); + + /** + * Get the stored meta data value + * + * @return Stored value, or {@link Optional#empty()} + */ + @Nonnull public abstract Optional get(); + + @Override public final void close() { + this.lockAccess.close(); + } + + /** + * Get the owner of the meta data + * + * @return Player + */ + @Nonnull public PlotPlayer getPlayer() { + return this.player; + } + + /** + * Get the meta data key + * + * @return Meta data key + */ + @Nonnull public MetaDataKey getMetaDataKey() { + return this.metaDataKey; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/player/MetaDataKey.java b/Core/src/main/java/com/plotsquared/core/player/MetaDataKey.java new file mode 100644 index 000000000..4b51ca12a --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/player/MetaDataKey.java @@ -0,0 +1,107 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.player; + +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; +import com.plotsquared.core.synchronization.LockKey; + +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; + +/** + * Key used to access meta data + * + * @param Meta data type + */ +public final class MetaDataKey { + + private static final Map keyMap = new HashMap<>(); + private static final Object keyMetaData = new Object(); + + private final String key; + private final Class type; + private final LockKey lockKey; + + private MetaDataKey(@Nonnull final String key, @Nonnull final Class type) { + this.key = Preconditions.checkNotNull(key, "Key may not be null"); + this.type = Preconditions.checkNotNull(type, "Type may not be null"); + this.lockKey = LockKey.of(this.key); + } + + /** + * Get a new named lock key + * + * @param key Key name + * @param Type + * @return MetaData key instance + */ + @Nonnull public static MetaDataKey of(@Nonnull final String key, @Nonnull final Class type) { + synchronized (keyMetaData) { + return (MetaDataKey) + keyMap.computeIfAbsent(key, missingKey -> new MetaDataKey<>(missingKey, type)); + } + } + + @Override public String toString() { + return this.key; + } + + @Override public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final MetaDataKey lockKey = (MetaDataKey) o; + return Objects.equal(this.key, lockKey.key); + } + + @Override public int hashCode() { + return Objects.hashCode(this.key); + } + + /** + * Get the {@link LockKey} associated with this key + * + * @return Lock key + */ + @Nonnull public LockKey getLockKey() { + return this.lockKey; + } + + /** + * Get the meta data type + * + * @return Meta data type + */ + @Nonnull public Class getType() { + return this.type; + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java b/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java new file mode 100644 index 000000000..c0380b233 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.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.player; + +import com.plotsquared.core.synchronization.LockRepository; + +import javax.annotation.Nonnull; +import java.util.Optional; + +public final class PersistentMetaDataAccess extends MetaDataAccess { + + PersistentMetaDataAccess(@Nonnull final PlotPlayer player, + @Nonnull final MetaDataKey metaDataKey, + @Nonnull final LockRepository.LockAccess lockAccess) { + super(player, metaDataKey, lockAccess); + } + + @Override public boolean has() { + return this.getPlayer().hasPersistentMeta(getMetaDataKey().toString()); + } + + @Override public void remove() { + this.getPlayer().removePersistentMeta(this.getMetaDataKey().toString()); + } + + @Override public void set(@Nonnull T value) { + this.getPlayer().setPersistentMeta(this.getMetaDataKey(), value); + } + + @Nonnull @Override public Optional get() { + return Optional.ofNullable(this.getPlayer().getPersistentMeta(this.getMetaDataKey())); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/player/PlayerMetaDataKeys.java b/Core/src/main/java/com/plotsquared/core/player/PlayerMetaDataKeys.java new file mode 100644 index 000000000..5140c4b5c --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/player/PlayerMetaDataKeys.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.player; + +public final class PlayerMetaDataKeys { + + public static final MetaDataKey PERSISTENT_FLIGHT = MetaDataKey.of("flight", Boolean.class); + public static final MetaDataKey GRANTED_PLOTS = MetaDataKey.of("grantedPlots", Integer.class); + + private PlayerMetaDataKeys() { + } + +} 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 6d2428d05..61a41a672 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -26,7 +26,9 @@ package com.plotsquared.core.player; import com.google.common.base.Preconditions; +import com.google.common.primitives.Ints; import com.plotsquared.core.PlotSquared; +import com.plotsquared.core.collection.ByteArrayUtilities; import com.plotsquared.core.command.CommandCaller; import com.plotsquared.core.command.RequiredType; import com.plotsquared.core.configuration.CaptionUtility; @@ -45,6 +47,7 @@ import com.plotsquared.core.plot.flag.implementations.DoneFlag; 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.synchronization.LockRepository; import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.Permissions; @@ -54,11 +57,11 @@ import com.plotsquared.core.util.task.TaskManager; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.item.ItemType; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.nio.ByteBuffer; import java.util.Collection; import java.util.Collections; @@ -92,6 +95,8 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer private ConcurrentHashMap meta; private int hash; + private final LockRepository lockRepository = new LockRepository(); + private final PlotAreaManager plotAreaManager; private final EventDispatcher eventDispatcher; private final EconHandler econHandler; @@ -721,18 +726,64 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer } } - public byte[] getPersistentMeta(String key) { + byte[] getPersistentMeta(String key) { return this.metaMap.get(key); } - public void removePersistentMeta(String key) { + void removePersistentMeta(String key) { this.metaMap.remove(key); if (Settings.Enabled_Components.PERSISTENT_META) { DBFunc.removePersistentMeta(getUUID(), key); } } - public void setPersistentMeta(String key, byte[] value) { + /** + * Access keyed persistent meta data for this player. This returns a meta data + * access instance, that MUST be closed. It is meant to be used with try-with-resources, + * like such: + *

{@code
+     * try (final MetaDataAccess access = player.accessPersistentMetaData(PlayerMetaKeys.GRANTS)) {
+     *     int grants = access.get();
+     *     access.set(grants + 1);
+     * }
+     * }
+ * + * @param key Meta data key + * @param Meta data type + * @return Meta data access. MUST be closed after being used + */ + @Nonnull public MetaDataAccess accessPersistentMetaData(@Nonnull final MetaDataKey key) { + return new PersistentMetaDataAccess<>(this, key, this.lockRepository.lock(key.getLockKey())); + } + + void setPersistentMeta(@Nonnull final MetaDataKey key, + @Nonnull final T value) { + if (key.getType().equals(Integer.class)) { + this.setPersistentMeta(key.toString(), Ints.toByteArray((int) value)); + } else if (key.getType().equals(Boolean.class)) { + this.setPersistentMeta(key.toString(), ByteArrayUtilities.booleanToBytes((boolean) value)); + } else { + throw new IllegalArgumentException(String.format("Unknown meta data type '%s'", key.getType().getSimpleName())); + } + } + + @Nullable T getPersistentMeta(@Nonnull final MetaDataKey key) { + final byte[] value = this.getPersistentMeta(key.toString()); + if (value == null) { + return null; + } + final Object returnValue; + if (key.getType().equals(Integer.class)) { + returnValue = Ints.fromByteArray(value); + } else if (key.getType().equals(Boolean.class)) { + returnValue = ByteArrayUtilities.bytesToBoolean(value); + } else { + throw new IllegalArgumentException(String.format("Unknown meta data type '%s'", key.getType().getSimpleName())); + } + return (T) returnValue; + } + + void setPersistentMeta(String key, byte[] value) { boolean delete = hasPersistentMeta(key); this.metaMap.put(key, value); if (Settings.Enabled_Components.PERSISTENT_META) { @@ -740,7 +791,7 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer } } - public boolean hasPersistentMeta(String key) { + boolean hasPersistentMeta(String key) { return this.metaMap.containsKey(key); } From 05ce67fbfebbfca7530905035c53b56b07164158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 23 Jul 2020 19:19:48 +0200 Subject: [PATCH 06/10] Trick the compiler --- .../main/java/com/plotsquared/core/player/PlotPlayer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 61a41a672..434d4477e 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -758,10 +758,11 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer void setPersistentMeta(@Nonnull final MetaDataKey key, @Nonnull final T value) { + final Object rawValue = value; if (key.getType().equals(Integer.class)) { - this.setPersistentMeta(key.toString(), Ints.toByteArray((int) value)); + this.setPersistentMeta(key.toString(), Ints.toByteArray((int) rawValue)); } else if (key.getType().equals(Boolean.class)) { - this.setPersistentMeta(key.toString(), ByteArrayUtilities.booleanToBytes((boolean) value)); + this.setPersistentMeta(key.toString(), ByteArrayUtilities.booleanToBytes((boolean) rawValue)); } else { throw new IllegalArgumentException(String.format("Unknown meta data type '%s'", key.getType().getSimpleName())); } From ad40ab7e1edb1d1dcac7ac50cd4bee6cfcc336a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 23 Jul 2020 19:26:29 +0200 Subject: [PATCH 07/10] Grant plots to the correct player --- Core/src/main/java/com/plotsquared/core/command/Grant.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 429e97168..ad9d09b42 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Grant.java +++ b/Core/src/main/java/com/plotsquared/core/command/Grant.java @@ -83,7 +83,7 @@ public class Grant extends Command { final UUID uuid = uuids.toArray(new UUID[0])[0]; PlotPlayer pp = PlotSquared.platform().getPlayerManager().getPlayerIfExists(uuid); if (pp != null) { - try (final MetaDataAccess access = player.accessPersistentMetaData( + try (final MetaDataAccess access = pp.accessPersistentMetaData( PlayerMetaDataKeys.GRANTED_PLOTS)) { if (args[0].equalsIgnoreCase("check")) { Captions.GRANTED_PLOTS.send(player, access.get().orElse(0)); From 6a63e5bb51285cae5a6b7dc7f136f161ffac1bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 23 Jul 2020 19:30:52 +0200 Subject: [PATCH 08/10] Expose the player's lock repository --- .../java/com/plotsquared/core/player/PlotPlayer.java | 9 +++++++++ 1 file changed, 9 insertions(+) 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 434d4477e..8907a2069 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -836,6 +836,15 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer } } + /** + * Get this player's {@link LockRepository} + * + * @return Lock repository instance + */ + @Nonnull public LockRepository getLockRepository() { + return this.lockRepository; + } + @FunctionalInterface public interface PlotPlayerConverter { PlotPlayer convert(BaseObject object); From d2f40612f41a55acfa74528713ff087d9fc4c12a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Thu, 23 Jul 2020 20:52:32 +0200 Subject: [PATCH 09/10] Switch from Class to TypeLiteral, and implement managed meta access for temporary meta --- .../bukkit/listener/PlayerEvents.java | 157 ++++++++----- .../bukkit/player/BukkitPlayer.java | 14 +- .../com/plotsquared/core/command/Area.java | 24 +- .../com/plotsquared/core/command/Auto.java | 16 +- .../com/plotsquared/core/command/Claim.java | 2 +- .../plotsquared/core/command/CmdConfirm.java | 21 +- .../plotsquared/core/command/DebugExec.java | 40 ---- .../com/plotsquared/core/command/Grant.java | 2 +- .../com/plotsquared/core/command/Inbox.java | 8 +- .../com/plotsquared/core/command/Load.java | 166 +++++++------- .../plotsquared/core/command/MainCommand.java | 46 ++-- .../com/plotsquared/core/command/Save.java | 8 +- .../com/plotsquared/core/command/Setup.java | 66 +++--- .../core/listener/PlotListener.java | 216 ++++++++++-------- .../core/player/ConsolePlayer.java | 13 +- .../core/player/MetaDataAccess.java | 5 +- .../plotsquared/core/player/MetaDataKey.java | 9 +- .../core/player/PersistentMetaDataAccess.java | 11 +- .../core/player/PlayerMetaDataKeys.java | 30 ++- .../plotsquared/core/player/PlotPlayer.java | 57 +++-- .../core/player/TemporaryMetaDataAccess.java | 62 +++++ .../com/plotsquared/core/plot/PlotArea.java | 16 +- .../plotsquared/core/plot/PlotInventory.java | 22 +- .../core/plot/comment/CommentManager.java | 8 +- .../core/plot/expiration/ExpireManager.java | 74 +++--- .../core/setup/CommonSetupSteps.java | 7 +- .../plotsquared/core/util/Permissions.java | 27 ++- .../com/plotsquared/core/util/WEManager.java | 29 ++- .../core/util/task/AutoClaimFinishTask.java | 7 +- 29 files changed, 709 insertions(+), 454 deletions(-) create mode 100644 Core/src/main/java/com/plotsquared/core/player/TemporaryMetaDataAccess.java 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 f334e055b..e07a1ce28 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/listener/PlayerEvents.java @@ -38,6 +38,8 @@ import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.listener.PlayerBlockEventType; import com.plotsquared.core.listener.PlotListener; import com.plotsquared.core.location.Location; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -216,13 +218,14 @@ import org.bukkit.plugin.Plugin; import org.bukkit.projectiles.BlockProjectileSource; import org.bukkit.projectiles.ProjectileSource; import org.bukkit.util.Vector; -import javax.annotation.Nonnull; +import javax.annotation.Nonnull; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.UUID; @@ -731,32 +734,36 @@ import java.util.regex.Pattern; public void onTeleport(PlayerTeleportEvent event) { Player player = event.getPlayer(); BukkitPlayer pp = BukkitUtil.adapt(player); - Plot lastPlot = pp.getMeta(PlotPlayer.META_LAST_PLOT); - org.bukkit.Location to = event.getTo(); - //noinspection ConstantConditions - if (to != null) { - Location location = BukkitUtil.adapt(to); - PlotArea area = location.getPlotArea(); - if (area == null) { - if (lastPlot != null) { - plotExit(pp, lastPlot); - pp.deleteMeta(PlotPlayer.META_LAST_PLOT); + try (final MetaDataAccess lastPlotAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + Plot lastPlot = lastPlotAccess.get().orElse(null); + org.bukkit.Location to = event.getTo(); + //noinspection ConstantConditions + if (to != null) { + Location location = BukkitUtil.adapt(to); + PlotArea area = location.getPlotArea(); + if (area == null) { + if (lastPlot != null) { + plotExit(pp, lastPlot); + lastPlotAccess.remove(); + } + try (final MetaDataAccess lastLocationAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { + lastLocationAccess.remove(); + } + return; } - pp.deleteMeta(PlotPlayer.META_LOCATION); - return; - } - Plot plot = area.getPlot(location); - if (plot != null) { - final boolean result = DenyTeleportFlag.allowsTeleport(pp, plot); - // there is one possibility to still allow teleportation: - // to is identical to the plot's home location, and untrusted-visit is true - // i.e. untrusted-visit can override deny-teleport - // this is acceptable, because otherwise it wouldn't make sense to have both flags set - if (!result && !(plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous() - .equals(BukkitUtil.adaptComplete(to)))) { - MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, - Captions.PERMISSION_ADMIN_ENTRY_DENIED); - event.setCancelled(true); + Plot plot = area.getPlot(location); + if (plot != null) { + final boolean result = DenyTeleportFlag.allowsTeleport(pp, plot); + // there is one possibility to still allow teleportation: + // to is identical to the plot's home location, and untrusted-visit is true + // i.e. untrusted-visit can override deny-teleport + // this is acceptable, because otherwise it wouldn't make sense to have both flags set + if (!result && !(plot.getFlag(UntrustedVisitFlag.class) && plot.getHomeSynchronous().equals(BukkitUtil.adaptComplete(to)))) { + MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, Captions.PERMISSION_ADMIN_ENTRY_DENIED); + event.setCancelled(true); + } } } } @@ -847,28 +854,39 @@ import java.util.regex.Pattern; } // Set last location Location location = BukkitUtil.adapt(to); - pp.setMeta(PlotPlayer.META_LOCATION, location); + try (final MetaDataAccess lastLocationAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { + lastLocationAccess.remove(); + } PlotArea area = location.getPlotArea(); if (area == null) { - pp.deleteMeta(PlotPlayer.META_LAST_PLOT); + try (final MetaDataAccess lastPlotAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + lastPlotAccess.remove(); + } return; } Plot now = area.getPlot(location); - Plot lastPlot = pp.getMeta(PlotPlayer.META_LAST_PLOT); + Plot lastPlot; + try (final MetaDataAccess lastPlotAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + lastPlot = lastPlotAccess.get().orElse(null); + } if (now == null) { - if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !pp - .getMeta("kick", false)) { - MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, - Captions.PERMISSION_ADMIN_EXIT_DENIED); - this.tmpTeleport = false; - if (lastPlot.equals(BukkitUtil.adapt(from).getPlot())) { - player.teleport(from); - } else { - player.teleport(player.getWorld().getSpawnLocation()); + try (final MetaDataAccess kickAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) { + if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse(false)) { + MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, Captions.PERMISSION_ADMIN_EXIT_DENIED); + this.tmpTeleport = false; + if (lastPlot.equals(BukkitUtil.adapt(from).getPlot())) { + player.teleport(from); + } else { + player.teleport(player.getWorld().getSpawnLocation()); + } + this.tmpTeleport = true; + event.setCancelled(true); + return; } - this.tmpTeleport = true; - event.setCancelled(true); - return; } } else if (now.equals(lastPlot)) { ForceFieldListener.handleForcefield(player, pp, now); @@ -909,28 +927,39 @@ import java.util.regex.Pattern; } // Set last location Location location = BukkitUtil.adapt(to); - pp.setMeta(PlotPlayer.META_LOCATION, location); + try (final MetaDataAccess lastLocationAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { + lastLocationAccess.set(location); + } PlotArea area = location.getPlotArea(); if (area == null) { - pp.deleteMeta(PlotPlayer.META_LAST_PLOT); + try (final MetaDataAccess lastPlotAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + lastPlotAccess.remove(); + } return; } Plot now = area.getPlot(location); - Plot lastPlot = pp.getMeta(PlotPlayer.META_LAST_PLOT); + Plot lastPlot; + try (final MetaDataAccess lastPlotAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + lastPlot = lastPlotAccess.get().orElse(null); + } if (now == null) { - if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !pp - .getMeta("kick", false)) { - MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, - Captions.PERMISSION_ADMIN_EXIT_DENIED); - this.tmpTeleport = false; - if (lastPlot.equals(BukkitUtil.adapt(from).getPlot())) { - player.teleport(from); - } else { - player.teleport(player.getWorld().getSpawnLocation()); + try (final MetaDataAccess kickAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) { + if (lastPlot != null && !plotExit(pp, lastPlot) && this.tmpTeleport && !kickAccess.get().orElse(false)) { + MainUtil.sendMessage(pp, Captions.NO_PERMISSION_EVENT, Captions.PERMISSION_ADMIN_EXIT_DENIED); + this.tmpTeleport = false; + if (lastPlot.equals(BukkitUtil.adapt(from).getPlot())) { + player.teleport(from); + } else { + player.teleport(player.getWorld().getSpawnLocation()); + } + this.tmpTeleport = true; + event.setCancelled(true); + return; } - this.tmpTeleport = true; - event.setCancelled(true); - return; } } else if (now.equals(lastPlot)) { ForceFieldListener.handleForcefield(player, pp, now); @@ -1155,8 +1184,15 @@ import java.util.regex.Pattern; Player player = event.getPlayer(); BukkitPlayer pp = BukkitUtil.adapt(player); // Delete last location - Plot plot = (Plot) pp.deleteMeta(PlotPlayer.META_LAST_PLOT); - pp.deleteMeta(PlotPlayer.META_LOCATION); + Plot plot; + try (final MetaDataAccess lastPlotAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + plot = lastPlotAccess.remove(); + } + try (final MetaDataAccess lastLocationAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { + lastLocationAccess.remove(); + } if (plot != null) { plotExit(pp, plot); } @@ -1168,7 +1204,10 @@ import java.util.regex.Pattern; } } if (Settings.Enabled_Components.PERMISSION_CACHE) { - pp.deleteMeta("perm"); + try (final MetaDataAccess> metaDataAccess = + pp.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_PERMISSIONS)) { + metaDataAccess.remove(); + } } Location location = pp.getLocation(); PlotArea area = location.getPlotArea(); 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 15d9bacf8..b3db26369 100644 --- a/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java +++ b/Bukkit/src/main/java/com/plotsquared/bukkit/player/BukkitPlayer.java @@ -69,12 +69,12 @@ import static com.sk89q.worldedit.world.gamemode.GameModes.SURVIVAL; public class BukkitPlayer extends PlotPlayer { private static boolean CHECK_EFFECTIVE = true; - - private final EconHandler econHandler; public final Player player; + private final EconHandler econHandler; private boolean offline; private String name; - + private String lastMessage = ""; + private long lastMessageTime = 0L; /** *

Please do not use this method. Instead use @@ -234,10 +234,10 @@ public class BukkitPlayer extends PlotPlayer { @Override public void sendMessage(String message) { message = message.replace('\u2010', '%').replace('\u2020', '&').replace('\u2030', '&'); - if (!StringMan.isEqual(this.getMeta("lastMessage"), message) || ( - System.currentTimeMillis() - this.getMeta("lastMessageTime") > 5000)) { - setMeta("lastMessage", message); - setMeta("lastMessageTime", System.currentTimeMillis()); + if (!StringMan.isEqual(this.lastMessage, message) || ( + System.currentTimeMillis() - this.lastMessageTime > 5000)) { + this.lastMessage = message; + this.lastMessageTime = System.currentTimeMillis(); this.player.sendMessage(message); } } 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 aad920373..931a86be1 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Area.java +++ b/Core/src/main/java/com/plotsquared/core/command/Area.java @@ -27,8 +27,6 @@ package com.plotsquared.core.command; import com.google.inject.Inject; import com.plotsquared.core.PlotSquared; -import com.plotsquared.core.inject.annotations.WorldConfig; -import com.plotsquared.core.inject.annotations.WorldFile; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.ConfigurationUtil; @@ -36,6 +34,8 @@ import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.AugmentedUtils; import com.plotsquared.core.generator.HybridPlotWorld; +import com.plotsquared.core.inject.annotations.WorldConfig; +import com.plotsquared.core.inject.annotations.WorldFile; import com.plotsquared.core.inject.factory.HybridPlotWorldFactory; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.ConsolePlayer; @@ -72,16 +72,19 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Region; -import javax.annotation.Nonnull; +import javax.annotation.Nonnull; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.UUID; @CommandDeclaration(command = "area", permission = "plots.area", @@ -101,6 +104,8 @@ public class Area extends SubCommand { private final WorldUtil worldUtil; private final RegionManager regionManager; + private final Map> metaData = new HashMap<>(); + @Inject public Area(@Nonnull final PlotAreaManager plotAreaManager, @WorldConfig @Nonnull final YamlConfiguration worldConfiguration, @WorldFile @Nonnull final File worldFile, @@ -264,14 +269,16 @@ public class Area extends SubCommand { case 2: switch (args[1].toLowerCase()) { case "pos1": { // Set position 1 - HybridPlotWorld area = player.getMeta("area_create_area"); + HybridPlotWorld area = (HybridPlotWorld) metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()) + .get("area_create_area"); if (area == null) { Captions.COMMAND_SYNTAX.send(player, "/plot area create [world[:id]] [=]..."); return false; } Location location = player.getLocation(); - player.setMeta("area_pos1", location); + metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()) + .put("area_pos1", location); Captions.SET_ATTRIBUTE.send(player, "area_pos1", location.getX() + "," + location.getZ()); MainUtil.sendMessage(player, @@ -280,14 +287,15 @@ public class Area extends SubCommand { return true; } case "pos2": // Set position 2 and finish creation for type=2 (partial) - final HybridPlotWorld area = player.getMeta("area_create_area"); + final HybridPlotWorld area = (HybridPlotWorld) metaData + .computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()).get("area_create_area"); if (area == null) { Captions.COMMAND_SYNTAX.send(player, "/plot area create [world[:id]] [=]..."); return false; } Location pos1 = player.getLocation(); - Location pos2 = player.getMeta("area_pos1"); + Location pos2 = (Location) metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()).get("area_pos1"); int dx = Math.abs(pos1.getX() - pos2.getX()); int dz = Math.abs(pos1.getZ() - pos2.getZ()); int numX = Math.max(1, @@ -500,7 +508,7 @@ public class Area extends SubCommand { player.teleport(this.worldUtil.getSpawn(pa.getWorldName()), TeleportCause.COMMAND); } - player.setMeta("area_create_area", pa); + metaData.computeIfAbsent(player.getUUID(), missingUUID -> new HashMap<>()).put("area_create_area", pa); MainUtil.sendMessage(player, "$1Go to the first corner and use: $2 " + getCommandString() + " create pos1"); 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 46be2c3e5..2cd105ffa 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Auto.java +++ b/Core/src/main/java/com/plotsquared/core/command/Auto.java @@ -93,7 +93,7 @@ public class Auto extends SubCommand { int diff = allowedPlots - currentPlots; if (diff - sizeX * sizeZ < 0) { try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData( - PlayerMetaDataKeys.GRANTED_PLOTS)) { + PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { if (metaDataAccess.has()) { int grantedPlots = metaDataAccess.get().orElse(0); if (diff < 0 && grantedPlots < sizeX * sizeZ) { @@ -149,7 +149,10 @@ public class Auto extends SubCommand { */ public static void autoClaimSafe(final PlotPlayer player, final PlotArea area, PlotId start, final String schematic) { - player.setMeta(Auto.class.getName(), true); + try (final MetaDataAccess metaDataAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_AUTO)) { + metaDataAccess.set(true); + } autoClaimFromDatabase(player, area, start, new RunnableVal() { @Override public void run(final Plot plot) { try { @@ -253,9 +256,12 @@ public class Auto extends SubCommand { return false; } final int allowed_plots = player.getAllowedPlots(); - if (!force && (player.getMeta(Auto.class.getName(), false) || !checkAllowedPlots(player, - plotarea, allowed_plots, size_x, size_z))) { - return false; + try (final MetaDataAccess metaDataAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_AUTO)) { + if (!force && (metaDataAccess.get().orElse(false) || !checkAllowedPlots(player, + plotarea, allowed_plots, size_x, size_z))) { + return false; + } } if (schematic != null && !schematic.isEmpty()) { 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 c9bfb4c8f..fbbd25013 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Claim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Claim.java @@ -89,7 +89,7 @@ public class Claim extends SubCommand { final PlotArea area = plot.getArea(); - try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.GRANTED_PLOTS)) { + try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { int grants = 0; if (currentPlots >= player.getAllowedPlots() && !force) { if (metaDataAccess.has()) { 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 c8aee497c..412cff610 100644 --- a/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java +++ b/Core/src/main/java/com/plotsquared/core/command/CmdConfirm.java @@ -26,19 +26,29 @@ package com.plotsquared.core.command; import com.plotsquared.core.configuration.Captions; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.task.TaskManager; import com.plotsquared.core.util.task.TaskTime; +import javax.annotation.Nullable; + public class CmdConfirm { - public static CmdInstance getPending(PlotPlayer player) { - return player.getMeta("cmdConfirm"); + @Nullable public static CmdInstance getPending(PlotPlayer player) { + try (final MetaDataAccess metaDataAccess = player.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_CONFIRM)) { + return metaDataAccess.get().orElse(null); + } } public static void removePending(PlotPlayer player) { - player.deleteMeta("cmdConfirm"); + try (final MetaDataAccess metaDataAccess = player.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_CONFIRM)) { + metaDataAccess.remove(); + } } public static void addPending(final PlotPlayer player, String commandStr, @@ -49,7 +59,10 @@ public class CmdConfirm { } TaskManager.runTaskLater(() -> { CmdInstance cmd = new CmdInstance(runnable); - player.setMeta("cmdConfirm", cmd); + try (final MetaDataAccess metaDataAccess = player.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_CONFIRM)) { + metaDataAccess.set(cmd); + } }, TaskTime.ticks(1L)); } } 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 598baf510..bc39a8f3e 100644 --- a/Core/src/main/java/com/plotsquared/core/command/DebugExec.java +++ b/Core/src/main/java/com/plotsquared/core/command/DebugExec.java @@ -409,46 +409,6 @@ public class DebugExec extends SubCommand { } }, "/plot debugexec list-scripts", "List of scripts"); return true; - case "allcmd": - if (args.length < 3) { - Captions.COMMAND_SYNTAX - .send(player, "/plot debugexec allcmd "); - return false; - } - long start = System.currentTimeMillis(); - Command cmd = MainCommand.getInstance().getCommand(args[3]); - String[] params = Arrays.copyOfRange(args, 4, args.length); - if ("true".equals(args[1])) { - Location location = player.getMeta(PlotPlayer.META_LOCATION); - Plot plot = player.getMeta(PlotPlayer.META_LAST_PLOT); - for (Plot current : PlotSquared.get().getBasePlots()) { - player.setMeta(PlotPlayer.META_LOCATION, current.getBottomAbs()); - player.setMeta(PlotPlayer.META_LAST_PLOT, current); - cmd.execute(player, params, null, null); - } - if (location == null) { - player.deleteMeta(PlotPlayer.META_LOCATION); - } else { - player.setMeta(PlotPlayer.META_LOCATION, location); - } - if (plot == null) { - player.deleteMeta(PlotPlayer.META_LAST_PLOT); - } else { - player.setMeta(PlotPlayer.META_LAST_PLOT, plot); - } - player.sendMessage("&c> " + (System.currentTimeMillis() - start)); - return true; - } - init(); - this.scope.put("_2", params); - this.scope.put("_3", cmd); - script = - "_1=PS.getBasePlots().iterator();while(_1.hasNext()){plot=_1.next();if(" - + args[1] - + "){PlotPlayer.setMeta(\"location\",plot.getBottomAbs());PlotPlayer.setMeta(\"lastplot\",plot);_3.onCommand" - + "(PlotPlayer,_2)}}"; - - break; case "all": if (args.length < 3) { Captions.COMMAND_SYNTAX 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 ad9d09b42..a45905522 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Grant.java +++ b/Core/src/main/java/com/plotsquared/core/command/Grant.java @@ -84,7 +84,7 @@ public class Grant extends Command { PlotPlayer pp = PlotSquared.platform().getPlayerManager().getPlayerIfExists(uuid); if (pp != null) { try (final MetaDataAccess access = pp.accessPersistentMetaData( - PlayerMetaDataKeys.GRANTED_PLOTS)) { + PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { if (args[0].equalsIgnoreCase("check")) { Captions.GRANTED_PLOTS.send(player, access.get().orElse(0)); } else { 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 a042e72cb..87ccd16e2 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Inbox.java +++ b/Core/src/main/java/com/plotsquared/core/command/Inbox.java @@ -25,7 +25,9 @@ */ package com.plotsquared.core.command; +import com.google.inject.TypeLiteral; import com.plotsquared.core.configuration.Captions; +import com.plotsquared.core.player.MetaDataAccess; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.comment.CommentInbox; @@ -34,6 +36,7 @@ import com.plotsquared.core.plot.comment.PlotComment; import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.StringMan; import com.plotsquared.core.util.task.RunnableVal; +import com.plotsquared.core.player.MetaDataKey; import java.util.List; @@ -140,7 +143,10 @@ public class Inbox extends SubCommand { StringMan.join(CommentManager.inboxes.keySet(), ", ")); return false; } - player.setMeta("inbox:" + inbox.toString(), System.currentTimeMillis()); + final MetaDataKey metaDataKey = MetaDataKey.of(String.format("inbox:%s", inbox.toString()), new TypeLiteral() {}); + try (final MetaDataAccess metaDataAccess = player.accessTemporaryMetaData(metaDataKey)) { + metaDataAccess.set(System.currentTimeMillis()); + } final int page; if (args.length > 1) { switch (args[1].toLowerCase()) { 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 cc099687b..60d17a771 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Load.java +++ b/Core/src/main/java/com/plotsquared/core/command/Load.java @@ -28,6 +28,8 @@ package com.plotsquared.core.command; import com.google.inject.Inject; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -43,6 +45,7 @@ import javax.annotation.Nonnull; import java.net.MalformedURLException; import java.net.URL; +import java.util.Collections; import java.util.List; @CommandDeclaration(command = "load", @@ -86,44 +89,46 @@ public class Load extends SubCommand { return false; } - if (args.length != 0) { - if (args.length == 1) { - List schematics = player.getMeta("plot_schematics"); - if (schematics == null) { - // No schematics found: - MainUtil.sendMessage(player, Captions.LOAD_NULL); - return false; - } - String schematic; - try { - schematic = schematics.get(Integer.parseInt(args[0]) - 1); - } catch (Exception ignored) { - // use /plot load - MainUtil.sendMessage(player, Captions.NOT_VALID_NUMBER, - "(1, " + schematics.size() + ')'); - return false; - } - final URL url; - try { - url = new URL(Settings.Web.URL + "saves/" + player.getUUID() + '/' + schematic); - } catch (MalformedURLException e) { - e.printStackTrace(); - MainUtil.sendMessage(player, Captions.LOAD_FAILED); - return false; - } - plot.addRunning(); - MainUtil.sendMessage(player, Captions.GENERATING_COMPONENT); - TaskManager.runTaskAsync(() -> { - Schematic taskSchematic = this.schematicHandler.getSchematic(url); - if (taskSchematic == null) { - plot.removeRunning(); - sendMessage(player, Captions.SCHEMATIC_INVALID, - "non-existent or not in gzip format"); - return; + try (final MetaDataAccess> metaDataAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_SCHEMATICS)) { + if (args.length != 0) { + if (args.length == 1) { + List schematics = metaDataAccess.get().orElse(null); + if (schematics == null) { + // No schematics found: + MainUtil.sendMessage(player, Captions.LOAD_NULL); + return false; } - PlotArea area = plot.getArea(); - this.schematicHandler.paste(taskSchematic, plot, 0, area.getMinBuildHeight(), 0, false, - new RunnableVal() { + String schematic; + try { + schematic = schematics.get(Integer.parseInt(args[0]) - 1); + } catch (Exception ignored) { + // use /plot load + MainUtil.sendMessage(player, Captions.NOT_VALID_NUMBER, + "(1, " + schematics.size() + ')'); + return false; + } + final URL url; + try { + url = new URL(Settings.Web.URL + "saves/" + player.getUUID() + '/' + schematic); + } catch (MalformedURLException e) { + e.printStackTrace(); + MainUtil.sendMessage(player, Captions.LOAD_FAILED); + return false; + } + plot.addRunning(); + MainUtil.sendMessage(player, Captions.GENERATING_COMPONENT); + TaskManager.runTaskAsync(() -> { + Schematic taskSchematic = this.schematicHandler.getSchematic(url); + if (taskSchematic == null) { + plot.removeRunning(); + sendMessage(player, Captions.SCHEMATIC_INVALID, + "non-existent or not in gzip format"); + return; + } + PlotArea area = plot.getArea(); + this.schematicHandler + .paste(taskSchematic, plot, 0, area.getMinBuildHeight(), 0, false, new RunnableVal() { @Override public void run(Boolean value) { plot.removeRunning(); if (value) { @@ -133,58 +138,61 @@ public class Load extends SubCommand { } } }); - }); - return true; - } - plot.removeRunning(); - MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, "/plot load "); - return false; - } - - // list schematics - - List schematics = player.getMeta("plot_schematics"); - if (schematics == null) { - plot.addRunning(); - TaskManager.runTaskAsync(() -> { - List schematics1 = this.schematicHandler.getSaves(player.getUUID()); - plot.removeRunning(); - if ((schematics1 == null) || schematics1.isEmpty()) { - MainUtil.sendMessage(player, Captions.LOAD_FAILED); - return; + }); + return true; } - player.setMeta("plot_schematics", schematics1); + plot.removeRunning(); + MainUtil.sendMessage(player, Captions.COMMAND_SYNTAX, "/plot load "); + return false; + } + + // list schematics + + List schematics = metaDataAccess.get().orElse(null); + if (schematics == null) { + plot.addRunning(); + TaskManager.runTaskAsync(() -> { + List schematics1 = this.schematicHandler.getSaves(player.getUUID()); + plot.removeRunning(); + if ((schematics1 == null) || schematics1.isEmpty()) { + MainUtil.sendMessage(player, Captions.LOAD_FAILED); + return; + } + metaDataAccess.set(schematics1); + displaySaves(player); + }); + } else { displaySaves(player); - }); - } else { - displaySaves(player); + } } return true; } public void displaySaves(PlotPlayer player) { - List schematics = player.getMeta("plot_schematics"); - for (int i = 0; i < Math.min(schematics.size(), 32); i++) { - try { - String schematic = schematics.get(i).split("\\.")[0]; - String[] split = schematic.split("_"); - if (split.length < 5) { - continue; + try (final MetaDataAccess> metaDataAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_SCHEMATICS)) { + List schematics = metaDataAccess.get().orElse(Collections.emptyList()); + for (int i = 0; i < Math.min(schematics.size(), 32); i++) { + try { + String schematic = schematics.get(i).split("\\.")[0]; + String[] split = schematic.split("_"); + if (split.length < 5) { + continue; + } + String time = secToTime((System.currentTimeMillis() / 1000) - Long.parseLong(split[0])); + String world = split[1]; + PlotId id = PlotId.fromString(split[2] + ';' + split[3]); + String size = split[4]; + String color = "$4"; + MainUtil.sendMessage(player, + "$3[$2" + (i + 1) + "$3] " + color + time + "$3 | " + color + world + ';' + id + + "$3 | " + color + size + 'x' + size); + } catch (Exception e) { + e.printStackTrace(); } - String time = - secToTime((System.currentTimeMillis() / 1000) - Long.parseLong(split[0])); - String world = split[1]; - PlotId id = PlotId.fromString(split[2] + ';' + split[3]); - String size = split[4]; - String color = "$4"; - MainUtil.sendMessage(player, - "$3[$2" + (i + 1) + "$3] " + color + time + "$3 | " + color + world + ';' + id - + "$3 | " + color + size + 'x' + size); - } catch (Exception e) { - e.printStackTrace(); } + MainUtil.sendMessage(player, Captions.LOAD_LIST); } - MainUtil.sendMessage(player, Captions.LOAD_LIST); } public String secToTime(long time) { 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 d724155cf..cfe608599 100644 --- a/Core/src/main/java/com/plotsquared/core/command/MainCommand.java +++ b/Core/src/main/java/com/plotsquared/core/command/MainCommand.java @@ -31,6 +31,8 @@ import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.ConsolePlayer; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -43,6 +45,7 @@ import com.plotsquared.core.util.task.RunnableVal3; import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; /** @@ -231,7 +234,11 @@ public class MainCommand extends Command { RunnableVal3 confirm, RunnableVal2 whenDone) { // Clear perm caching // - player.deleteMeta("perm"); + try (final MetaDataAccess> permAccess = player.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_PERMISSIONS)) { + permAccess.remove(); + } + // Optional command scope // Location location = null; Plot plot = null; @@ -246,12 +253,17 @@ public class MainCommand extends Command { Location newLoc = newPlot.getCenterSynchronous(); if (player.canTeleport(newLoc)) { // Save meta - location = player.getMeta(PlotPlayer.META_LOCATION); - plot = player.getMeta(PlotPlayer.META_LAST_PLOT); + try (final MetaDataAccess locationMetaDataAccess + = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { + location = locationMetaDataAccess.get().orElse(null); + locationMetaDataAccess.set(newLoc); + } + try (final MetaDataAccess plotMetaDataAccess + = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + plot = plotMetaDataAccess.get().orElse(null); + plotMetaDataAccess.set(newPlot); + } tp = true; - // Set loc - player.setMeta(PlotPlayer.META_LOCATION, newLoc); - player.setMeta(PlotPlayer.META_LAST_PLOT, newPlot); } else { Captions.BORDER.send(player); } @@ -304,15 +316,21 @@ public class MainCommand extends Command { } // Reset command scope // if (tp && !(player instanceof ConsolePlayer)) { - if (location == null) { - player.deleteMeta(PlotPlayer.META_LOCATION); - } else { - player.setMeta(PlotPlayer.META_LOCATION, location); + try (final MetaDataAccess locationMetaDataAccess + = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { + if (location == null) { + locationMetaDataAccess.remove(); + } else { + locationMetaDataAccess.set(location); + } } - if (plot == null) { - player.deleteMeta(PlotPlayer.META_LAST_PLOT); - } else { - player.setMeta(PlotPlayer.META_LAST_PLOT, plot); + try (final MetaDataAccess plotMetaDataAccess + = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + if (plot == null) { + plotMetaDataAccess.remove(); + } else { + plotMetaDataAccess.set(plot); + } } } return CompletableFuture.completedFuture(true); 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 bde167dd9..7ab7f1a41 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Save.java +++ b/Core/src/main/java/com/plotsquared/core/command/Save.java @@ -28,6 +28,8 @@ package com.plotsquared.core.command; import com.google.inject.Inject; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.location.Location; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotId; @@ -104,9 +106,9 @@ public class Save extends SubCommand { return; } MainUtil.sendMessage(player, Captions.SAVE_SUCCESS); - List schematics = player.getMeta("plot_schematics"); - if (schematics != null) { - schematics.add(file + ".schem"); + try (final MetaDataAccess> schematicAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_SCHEMATICS)) { + schematicAccess.get().ifPresent(schematics -> schematics.add(file + ".schem")); } } }); 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 cf412656a..a13b54f92 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,8 @@ import com.google.inject.Inject; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.generator.GeneratorWrapper; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.setup.SetupProcess; import com.plotsquared.core.setup.SetupStep; @@ -72,42 +74,48 @@ 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) { - MainUtil.sendMessage(player, Captions.SETUP_NOT_STARTED); + try (final MetaDataAccess metaDataAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_SETUP)) { + SetupProcess process = metaDataAccess.get().orElse(null); + if (process == null) { + if (args.length > 0) { + MainUtil.sendMessage(player, Captions.SETUP_NOT_STARTED); + return true; + } + process = new SetupProcess(); + metaDataAccess.set(process); + this.setupUtils.updateGenerators(); + SetupStep step = process.getCurrentStep(); + step.announce(player); + displayGenerators(player); return true; } - process = new SetupProcess(); - player.setMeta("setup", process); - this.setupUtils.updateGenerators(); - SetupStep step = process.getCurrentStep(); - step.announce(player); - displayGenerators(player); + if (args.length == 1) { + if ("back".equalsIgnoreCase(args[0])) { + process.back(); + process.getCurrentStep().announce(player); + } else if ("cancel".equalsIgnoreCase(args[0])) { + metaDataAccess.remove(); + MainUtil.sendMessage(player, Captions.SETUP_CANCELLED); + } else { + process.handleInput(player, args[0]); + if (process.getCurrentStep() != null) { + process.getCurrentStep().announce(player); + } + } + } else { + process.getCurrentStep().announce(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"); - MainUtil.sendMessage(player, Captions.SETUP_CANCELLED); - } else { - process.handleInput(player, args[0]); - if (process.getCurrentStep() != null) { - process.getCurrentStep().announce(player); - } - } - } else { - process.getCurrentStep().announce(player); - } - return true; - } @Override public Collection tab(PlotPlayer player, String[] args, boolean space) { - SetupProcess process = (SetupProcess) player.getMeta("setup"); // TODO use generics -> auto cast + SetupProcess process; + try (final MetaDataAccess metaDataAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_SETUP)) { + process = metaDataAccess.get().orElse(null); + } if (process == null) { return Collections.emptyList(); } 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 9fcaad2de..0fb0a8977 100644 --- a/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java +++ b/Core/src/main/java/com/plotsquared/core/listener/PlotListener.java @@ -32,6 +32,7 @@ import com.plotsquared.core.events.PlotFlagRemoveEvent; import com.plotsquared.core.events.Result; import com.plotsquared.core.location.Location; import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.MetaDataKey; import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; @@ -136,14 +137,16 @@ public class PlotListener { .hasPermission(player, "plots.admin.entry.denied")) { return false; } - Plot last = player.getMeta(PlotPlayer.META_LAST_PLOT); - if ((last != null) && !last.getId().equals(plot.getId())) { - plotExit(player, last); + try (final MetaDataAccess lastPlot = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + Plot last = lastPlot.get().orElse(null); + if ((last != null) && !last.getId().equals(plot.getId())) { + plotExit(player, last); + } + if (ExpireManager.IMP != null) { + ExpireManager.IMP.handleEntry(player, plot); + } + lastPlot.set(plot); } - if (ExpireManager.IMP != null) { - ExpireManager.IMP.handleEntry(player, plot); - } - player.setMeta(PlotPlayer.META_LAST_PLOT, plot); this.eventDispatcher.callEntry(player, plot); if (plot.hasOwner()) { // This will inherit values from PlotArea @@ -230,39 +233,47 @@ public class PlotListener { player.setWeather(plot.getFlag(WeatherFlag.class)); ItemType musicFlag = plot.getFlag(MusicFlag.class); - if (musicFlag != null) { - final String rawId = musicFlag.getId(); - if (rawId.contains("disc") || musicFlag == ItemTypes.AIR) { - Location location = player.getLocation(); - Location lastLocation = player.getMeta("music"); - if (lastLocation != null) { - player.playMusic(lastLocation, musicFlag); - if (musicFlag == ItemTypes.AIR) { - player.deleteMeta("music"); + + try (final MetaDataAccess musicMeta = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_MUSIC)) { + if (musicFlag != null) { + final String rawId = musicFlag.getId(); + if (rawId.contains("disc") || musicFlag == ItemTypes.AIR) { + Location location = player.getLocation(); + Location lastLocation = musicMeta.get().orElse(null); + if (lastLocation != null) { + player.playMusic(lastLocation, musicFlag); + if (musicFlag == ItemTypes.AIR) { + musicMeta.remove(); + } + } + if (musicFlag != ItemTypes.AIR) { + try { + musicMeta.set(location); + player.playMusic(location, musicFlag); + } catch (Exception ignored) { + } } } - if (musicFlag != ItemTypes.AIR) { - try { - player.setMeta("music", location); - player.playMusic(location, musicFlag); - } catch (Exception ignored) { - } - } - } - } else { - Location lastLoc = player.getMeta("music"); - if (lastLoc != null) { - player.deleteMeta("music"); - player.playMusic(lastLoc, ItemTypes.AIR); + } else { + musicMeta.get().ifPresent(lastLoc -> { + musicMeta.remove(); + player.playMusic(lastLoc, ItemTypes.AIR); + }); } } + CommentManager.sendTitle(player, plot); if (titles && !player.getAttribute("disabletitles")) { if (!Captions.TITLE_ENTERED_PLOT.getTranslated().isEmpty() || !Captions.TITLE_ENTERED_PLOT_SUB.getTranslated().isEmpty()) { TaskManager.runTaskLaterAsync(() -> { - Plot lastPlot = player.getMeta(PlotPlayer.META_LAST_PLOT); + Plot lastPlot = null; + try (final MetaDataAccess lastPlotAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + lastPlot = lastPlotAccess.get().orElse(null); + } if ((lastPlot != null) && plot.getId().equals(lastPlot.getId())) { Map replacements = new HashMap<>(); replacements.put("%x%", String.valueOf(lastPlot.getId().getX())); @@ -299,89 +310,96 @@ public class PlotListener { } public boolean plotExit(final PlotPlayer player, Plot plot) { - Object previous = player.deleteMeta(PlotPlayer.META_LAST_PLOT); - this.eventDispatcher.callLeave(player, plot); - if (plot.hasOwner()) { - PlotArea pw = plot.getArea(); - if (pw == null) { - return true; - } - if (plot.getFlag(DenyExitFlag.class) && !Permissions - .hasPermission(player, Captions.PERMISSION_ADMIN_EXIT_DENIED) && !player - .getMeta("kick", false)) { - if (previous != null) { - player.setMeta(PlotPlayer.META_LAST_PLOT, previous); + try (final MetaDataAccess lastPlot = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + final Plot previous = lastPlot.remove(); + this.eventDispatcher.callLeave(player, plot); + if (plot.hasOwner()) { + PlotArea pw = plot.getArea(); + if (pw == null) { + return true; } - return false; - } - if (!plot.getFlag(GamemodeFlag.class).equals(GamemodeFlag.DEFAULT) || !plot - .getFlag(GuestGamemodeFlag.class).equals(GamemodeFlag.DEFAULT)) { - if (player.getGameMode() != pw.getGameMode()) { - if (!Permissions.hasPermission(player, "plots.gamemode.bypass")) { - player.setGameMode(pw.getGameMode()); - } else { - MainUtil.sendMessage(player, StringMan - .replaceAll(Captions.GAMEMODE_WAS_BYPASSED.getTranslated(), "{plot}", - plot.toString(), "{gamemode}", - pw.getGameMode().getName().toLowerCase())); + try (final MetaDataAccess kickAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_KICK)) { + if (plot.getFlag(DenyExitFlag.class) && !Permissions + .hasPermission(player, Captions.PERMISSION_ADMIN_EXIT_DENIED) && + !kickAccess.get().orElse(false)) { + if (previous != null) { + lastPlot.set(previous); + } + return false; } } - } - - final String farewell = plot.getFlag(FarewellFlag.class); - if (!farewell.isEmpty()) { - plot.format(Captions.PREFIX_FAREWELL.getTranslated() + farewell, player, false) - .thenAcceptAsync(player::sendMessage); - } - - if (plot.getFlag(NotifyLeaveFlag.class)) { - if (!Permissions.hasPermission(player, "plots.flag.notify-enter.bypass")) { - for (UUID uuid : plot.getOwners()) { - final PlotPlayer owner = PlotSquared.platform().getPlayerManager().getPlayerIfExists(uuid); - if ((owner != null) && !owner.getUUID().equals(player.getUUID())) { - MainUtil.sendMessage(owner, Captions.NOTIFY_LEAVE.getTranslated() - .replace("%player", player.getName()) - .replace("%plot", plot.getId().toString())); + if (!plot.getFlag(GamemodeFlag.class).equals(GamemodeFlag.DEFAULT) || !plot + .getFlag(GuestGamemodeFlag.class).equals(GamemodeFlag.DEFAULT)) { + if (player.getGameMode() != pw.getGameMode()) { + if (!Permissions.hasPermission(player, "plots.gamemode.bypass")) { + player.setGameMode(pw.getGameMode()); + } else { + MainUtil.sendMessage(player, StringMan + .replaceAll(Captions.GAMEMODE_WAS_BYPASSED.getTranslated(), "{plot}", + plot.toString(), "{gamemode}", + pw.getGameMode().getName().toLowerCase())); } } } - } - final FlyFlag.FlyStatus flyStatus = plot.getFlag(FlyFlag.class); - if (flyStatus != FlyFlag.FlyStatus.DEFAULT) { - try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_FLIGHT)) { - final Optional value = metaDataAccess.get(); - if (value.isPresent()) { - player.setFlight(value.get()); - metaDataAccess.remove(); - } else { - GameMode gameMode = player.getGameMode(); - if (gameMode == GameModes.SURVIVAL || gameMode == GameModes.ADVENTURE) { - player.setFlight(false); - } else if (!player.getFlight()) { - player.setFlight(true); + final String farewell = plot.getFlag(FarewellFlag.class); + if (!farewell.isEmpty()) { + plot.format(Captions.PREFIX_FAREWELL.getTranslated() + farewell, player, false) + .thenAcceptAsync(player::sendMessage); + } + + if (plot.getFlag(NotifyLeaveFlag.class)) { + if (!Permissions.hasPermission(player, "plots.flag.notify-enter.bypass")) { + for (UUID uuid : plot.getOwners()) { + final PlotPlayer owner = PlotSquared.platform().getPlayerManager().getPlayerIfExists(uuid); + if ((owner != null) && !owner.getUUID().equals(player.getUUID())) { + MainUtil.sendMessage(owner, Captions.NOTIFY_LEAVE.getTranslated() + .replace("%player", player.getName()) + .replace("%plot", plot.getId().toString())); + } } } } - } - if (plot.getFlag(TimeFlag.class) != TimeFlag.TIME_DISABLED.getValue().longValue()) { - player.setTime(Long.MAX_VALUE); - } + final FlyFlag.FlyStatus flyStatus = plot.getFlag(FlyFlag.class); + if (flyStatus != FlyFlag.FlyStatus.DEFAULT) { + try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_FLIGHT)) { + final Optional value = metaDataAccess.get(); + if (value.isPresent()) { + player.setFlight(value.get()); + metaDataAccess.remove(); + } else { + GameMode gameMode = player.getGameMode(); + if (gameMode == GameModes.SURVIVAL || gameMode == GameModes.ADVENTURE) { + player.setFlight(false); + } else if (!player.getFlight()) { + player.setFlight(true); + } + } + } + } - final PlotWeather plotWeather = plot.getFlag(WeatherFlag.class); - if (plotWeather != PlotWeather.CLEAR) { - player.setWeather(PlotWeather.RESET); - } + if (plot.getFlag(TimeFlag.class) != TimeFlag.TIME_DISABLED.getValue().longValue()) { + player.setTime(Long.MAX_VALUE); + } - Location lastLoc = player.getMeta("music"); - if (lastLoc != null) { - player.deleteMeta("music"); - player.playMusic(lastLoc, ItemTypes.AIR); - } + final PlotWeather plotWeather = plot.getFlag(WeatherFlag.class); + if (plotWeather != PlotWeather.CLEAR) { + player.setWeather(PlotWeather.RESET); + } - feedRunnable.remove(player.getUUID()); - healRunnable.remove(player.getUUID()); + try (final MetaDataAccess musicAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_MUSIC)) { + musicAccess.get().ifPresent(lastLoc -> { + musicAccess.remove(); + player.playMusic(lastLoc, ItemTypes.AIR); + }); + } + + feedRunnable.remove(player.getUUID()); + healRunnable.remove(player.getUUID()); + } } return true; } 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 c6efe33cd..506736de2 100644 --- a/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/ConsolePlayer.java @@ -32,6 +32,7 @@ import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.inject.annotations.ConsoleActor; import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotWeather; import com.plotsquared.core.plot.world.PlotAreaManager; @@ -134,8 +135,16 @@ public class ConsolePlayer extends PlotPlayer { } @Override public void teleport(Location location, TeleportCause cause) { - setMeta(META_LAST_PLOT, location.getPlot()); - setMeta(META_LOCATION, location); + try (final MetaDataAccess lastPlot = accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + if (location.getPlot() == null) { + lastPlot.remove(); + } else { + lastPlot.set(location.getPlot()); + } + } + try (final MetaDataAccess locationMetaDataAccess = accessPersistentMetaData(PlayerMetaDataKeys.TEMPORARY_LOCATION)) { + locationMetaDataAccess.set(location); + } } @Override public boolean isOnline() { diff --git a/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java b/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java index b4f494edf..c38111b73 100644 --- a/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java +++ b/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java @@ -28,6 +28,7 @@ package com.plotsquared.core.player; import com.plotsquared.core.synchronization.LockRepository; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.Optional; /** @@ -59,8 +60,10 @@ public abstract class MetaDataAccess implements AutoCloseable { /** * Remove the stored value meta data + * + * @return Old value, or {@link null} */ - public abstract void remove(); + @Nullable public abstract T remove(); /** * Set the meta data value diff --git a/Core/src/main/java/com/plotsquared/core/player/MetaDataKey.java b/Core/src/main/java/com/plotsquared/core/player/MetaDataKey.java index 4b51ca12a..ab013e9c9 100644 --- a/Core/src/main/java/com/plotsquared/core/player/MetaDataKey.java +++ b/Core/src/main/java/com/plotsquared/core/player/MetaDataKey.java @@ -27,6 +27,7 @@ package com.plotsquared.core.player; import com.google.common.base.Objects; import com.google.common.base.Preconditions; +import com.google.inject.TypeLiteral; import com.plotsquared.core.synchronization.LockKey; import javax.annotation.Nonnull; @@ -44,10 +45,10 @@ public final class MetaDataKey { private static final Object keyMetaData = new Object(); private final String key; - private final Class type; + private final TypeLiteral type; private final LockKey lockKey; - private MetaDataKey(@Nonnull final String key, @Nonnull final Class type) { + private MetaDataKey(@Nonnull final String key, @Nonnull final TypeLiteral type) { this.key = Preconditions.checkNotNull(key, "Key may not be null"); this.type = Preconditions.checkNotNull(type, "Type may not be null"); this.lockKey = LockKey.of(this.key); @@ -60,7 +61,7 @@ public final class MetaDataKey { * @param Type * @return MetaData key instance */ - @Nonnull public static MetaDataKey of(@Nonnull final String key, @Nonnull final Class type) { + @Nonnull public static MetaDataKey of(@Nonnull final String key, @Nonnull final TypeLiteral type) { synchronized (keyMetaData) { return (MetaDataKey) keyMap.computeIfAbsent(key, missingKey -> new MetaDataKey<>(missingKey, type)); @@ -100,7 +101,7 @@ public final class MetaDataKey { * * @return Meta data type */ - @Nonnull public Class getType() { + @Nonnull public TypeLiteral getType() { return this.type; } diff --git a/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java b/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java index c0380b233..e7bb67103 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java +++ b/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java @@ -28,9 +28,10 @@ package com.plotsquared.core.player; import com.plotsquared.core.synchronization.LockRepository; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.Optional; -public final class PersistentMetaDataAccess extends MetaDataAccess { +final class PersistentMetaDataAccess extends MetaDataAccess { PersistentMetaDataAccess(@Nonnull final PlotPlayer player, @Nonnull final MetaDataKey metaDataKey, @@ -42,8 +43,12 @@ public final class PersistentMetaDataAccess extends MetaDataAccess { return this.getPlayer().hasPersistentMeta(getMetaDataKey().toString()); } - @Override public void remove() { - this.getPlayer().removePersistentMeta(this.getMetaDataKey().toString()); + @Override @Nullable public T remove() { + final Object old = this.getPlayer().removePersistentMeta(this.getMetaDataKey().toString()); + if (old == null) { + return null; + } + return (T) old; } @Override public void set(@Nonnull T value) { diff --git a/Core/src/main/java/com/plotsquared/core/player/PlayerMetaDataKeys.java b/Core/src/main/java/com/plotsquared/core/player/PlayerMetaDataKeys.java index 5140c4b5c..d1cf087d9 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlayerMetaDataKeys.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlayerMetaDataKeys.java @@ -25,10 +25,36 @@ */ package com.plotsquared.core.player; +import com.google.inject.TypeLiteral; +import com.plotsquared.core.command.Auto; +import com.plotsquared.core.command.CmdInstance; +import com.plotsquared.core.location.Location; +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotInventory; +import com.plotsquared.core.setup.SetupProcess; + +import java.util.List; +import java.util.Map; + public final class PlayerMetaDataKeys { - public static final MetaDataKey PERSISTENT_FLIGHT = MetaDataKey.of("flight", Boolean.class); - public static final MetaDataKey GRANTED_PLOTS = MetaDataKey.of("grantedPlots", Integer.class); + //@formatter:off + public static final MetaDataKey PERSISTENT_FLIGHT = MetaDataKey.of("flight", new TypeLiteral() {}); + public static final MetaDataKey PERSISTENT_GRANTED_PLOTS = MetaDataKey.of("grantedPlots", new TypeLiteral() {}); + + public static final MetaDataKey TEMPORARY_LAST_PLOT = MetaDataKey.of("lastplot", new TypeLiteral() {}); + public static final MetaDataKey TEMPORARY_MUSIC = MetaDataKey.of("music", new TypeLiteral() {}); + public static final MetaDataKey TEMPORARY_KICK = MetaDataKey.of("kick", new TypeLiteral() {}); + public static final MetaDataKey TEMPORARY_SETUP = MetaDataKey.of("setup", new TypeLiteral() {}); + public static final MetaDataKey TEMPORARY_INVENTORY = MetaDataKey.of("inventory", new TypeLiteral() {}); + public static final MetaDataKey TEMPORARY_IGNORE_EXPIRE_TASK = MetaDataKey.of("ignoreExpireTask", new TypeLiteral() {}); + public static final MetaDataKey TEMPORARY_WORLD_EDIT_REGION_PLOT = MetaDataKey.of("WorldEditRegionPlot", new TypeLiteral() {}); + public static final MetaDataKey TEMPORARY_AUTO = MetaDataKey.of(Auto.class.getName(), new TypeLiteral() {}); + public static final MetaDataKey> TEMPORARY_PERMISSIONS = MetaDataKey.of("permissions", new TypeLiteral>() {}); + public static final MetaDataKey> TEMPORARY_SCHEMATICS = MetaDataKey.of("plot_schematics", new TypeLiteral>() {}); + public static final MetaDataKey TEMPORARY_LOCATION = MetaDataKey.of("location", new TypeLiteral() {}); + public static final MetaDataKey TEMPORARY_CONFIRM = MetaDataKey.of("cmdConfirm", new TypeLiteral() {}); + //@formatter:on private PlayerMetaDataKeys() { } 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 8907a2069..43390b2fe 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java +++ b/Core/src/main/java/com/plotsquared/core/player/PlotPlayer.java @@ -81,9 +81,6 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer private static final Logger logger = LoggerFactory.getLogger("P2/" + PlotPlayer.class.getSimpleName()); - 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<>()); @@ -162,7 +159,7 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer * @param key * @param value */ - public void setMeta(String key, Object value) { + void setMeta(String key, Object value) { if (value == null) { deleteMeta(key); } else { @@ -180,14 +177,14 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer * @param the object type to return * @return the value assigned to the key or null if it does not exist */ - public T getMeta(String key) { + T getMeta(String key) { if (this.meta != null) { return (T) this.meta.get(key); } return null; } - public T getMeta(String key, T defaultValue) { + T getMeta(String key, T defaultValue) { T meta = getMeta(key); if (meta == null) { return defaultValue; @@ -206,7 +203,7 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer * * @param key */ - public Object deleteMeta(String key) { + Object deleteMeta(String key) { return this.meta == null ? null : this.meta.remove(key); } @@ -225,11 +222,13 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer * @return the plot the player is standing on or null if standing on a road or not in a {@link PlotArea} */ public Plot getCurrentPlot() { - Plot value = getMeta(PlotPlayer.META_LAST_PLOT); - if (value == null && !Settings.Enabled_Components.EVENTS) { - return getLocation().getPlot(); + try (final MetaDataAccess lastPlotAccess = + this.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + if (lastPlotAccess.get().orElse(null) == null && !Settings.Enabled_Components.EVENTS) { + return this.getLocation().getPlot(); + } + return lastPlotAccess.get().orElse(null); } - return value; } /** @@ -730,11 +729,12 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer return this.metaMap.get(key); } - void removePersistentMeta(String key) { - this.metaMap.remove(key); + Object removePersistentMeta(String key) { + final Object old = this.metaMap.remove(key); if (Settings.Enabled_Components.PERSISTENT_META) { DBFunc.removePersistentMeta(getUUID(), key); } + return old; } /** @@ -756,15 +756,34 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer return new PersistentMetaDataAccess<>(this, key, this.lockRepository.lock(key.getLockKey())); } + /** + * Access keyed temporary meta data for this player. This returns a meta data + * access instance, that MUST be closed. It is meant to be used with try-with-resources, + * like such: + *

{@code
+     * try (final MetaDataAccess access = player.accessTemporaryMetaData(PlayerMetaKeys.GRANTS)) {
+     *     int grants = access.get();
+     *     access.set(grants + 1);
+     * }
+     * }
+ * + * @param key Meta data key + * @param Meta data type + * @return Meta data access. MUST be closed after being used + */ + @Nonnull public MetaDataAccess accessTemporaryMetaData(@Nonnull final MetaDataKey key) { + return new TemporaryMetaDataAccess<>(this, key, this.lockRepository.lock(key.getLockKey())); + } + void setPersistentMeta(@Nonnull final MetaDataKey key, @Nonnull final T value) { final Object rawValue = value; - if (key.getType().equals(Integer.class)) { + if (key.getType().getRawType().equals(Integer.class)) { this.setPersistentMeta(key.toString(), Ints.toByteArray((int) rawValue)); - } else if (key.getType().equals(Boolean.class)) { + } else if (key.getType().getRawType().equals(Boolean.class)) { this.setPersistentMeta(key.toString(), ByteArrayUtilities.booleanToBytes((boolean) rawValue)); } else { - throw new IllegalArgumentException(String.format("Unknown meta data type '%s'", key.getType().getSimpleName())); + throw new IllegalArgumentException(String.format("Unknown meta data type '%s'", key.getType().toString())); } } @@ -774,12 +793,12 @@ public abstract class PlotPlayer

implements CommandCaller, OfflinePlotPlayer return null; } final Object returnValue; - if (key.getType().equals(Integer.class)) { + if (key.getType().getRawType().equals(Integer.class)) { returnValue = Ints.fromByteArray(value); - } else if (key.getType().equals(Boolean.class)) { + } else if (key.getType().getRawType().equals(Boolean.class)) { returnValue = ByteArrayUtilities.bytesToBoolean(value); } else { - throw new IllegalArgumentException(String.format("Unknown meta data type '%s'", key.getType().getSimpleName())); + throw new IllegalArgumentException(String.format("Unknown meta data type '%s'", key.getType().toString())); } return (T) returnValue; } diff --git a/Core/src/main/java/com/plotsquared/core/player/TemporaryMetaDataAccess.java b/Core/src/main/java/com/plotsquared/core/player/TemporaryMetaDataAccess.java new file mode 100644 index 000000000..b301f5be7 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/player/TemporaryMetaDataAccess.java @@ -0,0 +1,62 @@ +/* + * _____ _ _ _____ _ + * | __ \| | | | / ____| | | + * | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| | + * | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` | + * | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| | + * |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_| + * | | + * |_| + * 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.player; + +import com.plotsquared.core.synchronization.LockRepository; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Optional; + +final class TemporaryMetaDataAccess extends MetaDataAccess { + + TemporaryMetaDataAccess(@Nonnull final PlotPlayer player, + @Nonnull final MetaDataKey metaDataKey, + @Nonnull final LockRepository.LockAccess lockAccess) { + super(player, metaDataKey, lockAccess); + } + + @Override public boolean has() { + return this.getPlayer().getMeta(this.getMetaDataKey().toString()) != null; + } + + @Override @Nullable public T remove() { + final Object old = getPlayer().deleteMeta(this.getMetaDataKey().toString()); + if (old == null) { + return null; + } + return (T) old; + } + + @Override public void set(@Nonnull T value) { + this.getPlayer().setMeta(this.getMetaDataKey().toString(), null); + } + + @Nonnull @Override public Optional get() { + return Optional.ofNullable(this.getPlayer().getMeta(this.getMetaDataKey().toString())); + } + +} 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 815bdeae2..438c4bcde 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotArea.java @@ -42,6 +42,8 @@ import com.plotsquared.core.inject.annotations.WorldConfig; import com.plotsquared.core.location.Direction; import com.plotsquared.core.location.Location; import com.plotsquared.core.location.PlotLoc; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.flag.FlagContainer; import com.plotsquared.core.plot.flag.FlagParseException; @@ -787,8 +789,11 @@ public abstract class PlotArea { } public boolean addPlot(@Nonnull final Plot plot) { - for (PlotPlayer pp : plot.getPlayersInPlot()) { - pp.setMeta(PlotPlayer.META_LAST_PLOT, plot); + for (final PlotPlayer pp : plot.getPlayersInPlot()) { + try (final MetaDataAccess metaDataAccess = pp.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + metaDataAccess.set(plot); + } } return this.plots.put(plot.getId(), plot) == null; } @@ -826,8 +831,11 @@ public abstract class PlotArea { public boolean addPlotIfAbsent(@Nonnull final Plot plot) { if (this.plots.putIfAbsent(plot.getId(), plot) == null) { - for (PlotPlayer pp : plot.getPlayersInPlot()) { - pp.setMeta(PlotPlayer.META_LAST_PLOT, plot); + for (PlotPlayer pp : plot.getPlayersInPlot()) { + try (final MetaDataAccess metaDataAccess = pp.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_LAST_PLOT)) { + metaDataAccess.set(plot); + } } return true; } 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 a810093b0..d843030c3 100644 --- a/Core/src/main/java/com/plotsquared/core/plot/PlotInventory.java +++ b/Core/src/main/java/com/plotsquared/core/plot/PlotInventory.java @@ -25,18 +25,19 @@ */ package com.plotsquared.core.plot; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.util.InventoryUtil; - -import javax.annotation.Nonnull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; + public class PlotInventory { private static final Logger logger = LoggerFactory.getLogger("P2/" + PlotInventory.class.getSimpleName()); - private static final String META_KEY = "inventory"; public final PlotPlayer player; public final int size; private final PlotItemStack[] items; @@ -58,16 +59,25 @@ public class PlotInventory { } public static PlotInventory getOpenPlotInventory(@Nonnull final PlotPlayer plotPlayer) { - return plotPlayer.getMeta(META_KEY, null); + try (final MetaDataAccess inventoryAccess = plotPlayer.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_INVENTORY)) { + return inventoryAccess.get().orElse(null); + } } public static void setPlotInventoryOpen(@Nonnull final PlotPlayer plotPlayer, @Nonnull final PlotInventory plotInventory) { - plotPlayer.setMeta(META_KEY, plotInventory); + try (final MetaDataAccess inventoryAccess = plotPlayer.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_INVENTORY)) { + inventoryAccess.set(plotInventory); + } } public static void removePlotInventoryOpen(@Nonnull final PlotPlayerplotPlayer) { - plotPlayer.deleteMeta(META_KEY); + try (final MetaDataAccess inventoryAccess = plotPlayer.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_INVENTORY)) { + inventoryAccess.remove(); + } } public boolean onClick(int index) { 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 c751fe54a..df899fbd8 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 @@ -26,8 +26,11 @@ package com.plotsquared.core.plot.comment; import com.google.common.annotations.Beta; +import com.google.inject.TypeLiteral; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.MetaDataKey; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.util.task.RunnableVal; @@ -77,7 +80,10 @@ import java.util.concurrent.atomic.AtomicInteger; } public static long getTimestamp(PlotPlayer player, String inbox) { - return player.getMeta("inbox:" + inbox, player.getLastPlayed()); + final MetaDataKey inboxKey = MetaDataKey.of(String.format("inbox:%s", inbox), new TypeLiteral() {}); + try (final MetaDataAccess inboxAccess = player.accessTemporaryMetaData(inboxKey)) { + return inboxAccess.get().orElse(player.getLastPlayed()); + } } public static void addInbox(CommentInbox inbox) { 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 2a3514540..6b14d0866 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 @@ -31,7 +31,9 @@ import com.plotsquared.core.database.DBFunc; import com.plotsquared.core.events.PlotFlagAddEvent; import com.plotsquared.core.events.PlotUnlinkEvent; import com.plotsquared.core.events.Result; +import com.plotsquared.core.player.MetaDataAccess; import com.plotsquared.core.player.OfflinePlotPlayer; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -137,44 +139,42 @@ public class ExpireManager { } } - public void confirmExpiry(final PlotPlayer pp) { - if (pp.getMeta("ignoreExpireTask") != null) { - return; - } - if (plotsToDelete != null && !plotsToDelete.isEmpty() && pp - .hasPermission("plots.admin.command.autoclear")) { - final int num = plotsToDelete.size(); - while (!plotsToDelete.isEmpty()) { - Iterator iter = plotsToDelete.iterator(); - final Plot current = iter.next(); - if (!isExpired(new ArrayDeque<>(tasks), current).isEmpty()) { - TaskManager.runTask(() -> { - pp.setMeta("ignoreExpireTask", true); - current.getCenter(pp::teleport); - pp.deleteMeta("ignoreExpireTask"); - PlotMessage msg = new PlotMessage() - .text(num + " " + (num > 1 ? "plots are" : "plot is") + " expired: ") - .color("$1").text(current.toString()).color("$2") - .command("/plot list expired").tooltip("/plot list expired") - //.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 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"); - msg.send(pp); - }); - return; - } else { - iter.remove(); - } + public void confirmExpiry(final PlotPlayer pp) { + try (final MetaDataAccess metaDataAccess = pp.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_IGNORE_EXPIRE_TASK)) { + if (metaDataAccess.has()) { + return; + } + if (plotsToDelete != null && !plotsToDelete.isEmpty() && pp.hasPermission("plots.admin.command.autoclear")) { + final int num = plotsToDelete.size(); + while (!plotsToDelete.isEmpty()) { + Iterator iter = plotsToDelete.iterator(); + final Plot current = iter.next(); + if (!isExpired(new ArrayDeque<>(tasks), current).isEmpty()) { + TaskManager.runTask(() -> { + metaDataAccess.set(true); + current.getCenter(pp::teleport); + metaDataAccess.remove(); + PlotMessage msg = new PlotMessage().text( + num + " " + (num > 1 ? "plots are" : "plot is") + " expired: ").color("$1").text(current.toString()).color("$2") + .command("/plot list expired").tooltip("/plot list expired") + //.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 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"); + msg.send(pp); + }); + return; + } else { + iter.remove(); + } + } + plotsToDelete.clear(); } - plotsToDelete.clear(); } } 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 2535a0e1f..dad52b55f 100644 --- a/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java +++ b/Core/src/main/java/com/plotsquared/core/setup/CommonSetupSteps.java @@ -30,6 +30,8 @@ import com.plotsquared.core.configuration.Caption; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.events.TeleportCause; import com.plotsquared.core.generator.GeneratorWrapper; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotAreaTerrainType; @@ -221,7 +223,10 @@ public enum CommonSetupSteps implements SetupStep { MainUtil.sendMessage(plotPlayer, Captions.SETUP_WORLD_APPLY_PLOTSQUARED); } builder.worldName(argument); - plotPlayer.deleteMeta("setup"); + try (final MetaDataAccess setupAccess = plotPlayer.accessTemporaryMetaData( + PlayerMetaDataKeys.TEMPORARY_SETUP)) { + setupAccess.remove(); + } String world; if (builder.setupManager() == null) { world = PlotSquared.platform().getInjector().getInstance(SetupUtils.class).setupWorld(builder); 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 34754e7c8..32dc6a747 100644 --- a/Core/src/main/java/com/plotsquared/core/util/Permissions.java +++ b/Core/src/main/java/com/plotsquared/core/util/Permissions.java @@ -28,9 +28,12 @@ package com.plotsquared.core.util; import com.plotsquared.core.command.CommandCaller; import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Settings; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import java.util.HashMap; +import java.util.Map; /** * The Permissions class handles checking user permissions.
@@ -65,19 +68,21 @@ public class Permissions { if (!Settings.Enabled_Components.PERMISSION_CACHE) { return hasPermission((CommandCaller) player, permission); } - HashMap map = player.getMeta("perm"); - if (map != null) { - Boolean result = map.get(permission); - if (result != null) { - return result; + try (final MetaDataAccess> mapAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_PERMISSIONS)) { + Map map = mapAccess.get().orElse(null); + if (map != null) { + final Boolean result = map.get(permission); + if (result != null) { + return result; + } + } else { + mapAccess.set((map = new HashMap<>())); } - } else { - map = new HashMap<>(); - player.setMeta("perm", map); + boolean result = hasPermission((CommandCaller) player, permission); + map.put(permission, result); + return result; } - boolean result = hasPermission((CommandCaller) player, permission); - map.put(permission, result); - return result; } /** diff --git a/Core/src/main/java/com/plotsquared/core/util/WEManager.java b/Core/src/main/java/com/plotsquared/core/util/WEManager.java index ea5d98ab8..ce065063d 100644 --- a/Core/src/main/java/com/plotsquared/core/util/WEManager.java +++ b/Core/src/main/java/com/plotsquared/core/util/WEManager.java @@ -28,6 +28,8 @@ package com.plotsquared.core.util; import com.plotsquared.core.PlotSquared; import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.location.Location; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -100,19 +102,22 @@ public class WEManager { } boolean allowMember = player.hasPermission("plots.worldedit.member"); Plot plot = player.getCurrentPlot(); - if (plot == null) { - plot = player.getMeta("WorldEditRegionPlot"); - } - if (plot != null && (!Settings.Done.RESTRICT_BUILDING || !DoneFlag.isDone(plot)) && ( - (allowMember && plot.isAdded(uuid)) || (!allowMember && (plot.isOwner(uuid)) || plot - .getTrusted().contains(uuid))) && !plot.getFlag(NoWorldeditFlag.class)) { - for (CuboidRegion region : plot.getRegions()) { - BlockVector3 pos1 = region.getMinimumPoint().withY(area.getMinBuildHeight()); - BlockVector3 pos2 = region.getMaximumPoint().withY(area.getMaxBuildHeight()); - CuboidRegion copy = new CuboidRegion(pos1, pos2); - regions.add(copy); + try (final MetaDataAccess metaDataAccess = + player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_WORLD_EDIT_REGION_PLOT)) { + if (plot == null) { + plot = metaDataAccess.get().orElse(null); + } + if (plot != null && (!Settings.Done.RESTRICT_BUILDING || !DoneFlag.isDone(plot)) && ( + (allowMember && plot.isAdded(uuid)) || (!allowMember && (plot.isOwner(uuid)) || plot + .getTrusted().contains(uuid))) && !plot.getFlag(NoWorldeditFlag.class)) { + for (CuboidRegion region : plot.getRegions()) { + BlockVector3 pos1 = region.getMinimumPoint().withY(area.getMinBuildHeight()); + BlockVector3 pos2 = region.getMaximumPoint().withY(area.getMaxBuildHeight()); + CuboidRegion copy = new CuboidRegion(pos1, pos2); + regions.add(copy); + } + metaDataAccess.set(plot); } - player.setMeta("WorldEditRegionPlot", plot); } return regions; } diff --git a/Core/src/main/java/com/plotsquared/core/util/task/AutoClaimFinishTask.java b/Core/src/main/java/com/plotsquared/core/util/task/AutoClaimFinishTask.java index cdcdee0e7..b4dc0a3b3 100644 --- a/Core/src/main/java/com/plotsquared/core/util/task/AutoClaimFinishTask.java +++ b/Core/src/main/java/com/plotsquared/core/util/task/AutoClaimFinishTask.java @@ -30,6 +30,8 @@ import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.events.PlotMergeEvent; import com.plotsquared.core.events.Result; import com.plotsquared.core.location.Direction; +import com.plotsquared.core.player.MetaDataAccess; +import com.plotsquared.core.player.PlayerMetaDataKeys; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; @@ -50,7 +52,10 @@ public final class AutoClaimFinishTask implements Callable { private final EventDispatcher eventDispatcher; @Override public Boolean call() { - player.deleteMeta(Auto.class.getName()); + try (final MetaDataAccess autoAccess + = player.accessTemporaryMetaData(PlayerMetaDataKeys.TEMPORARY_AUTO)) { + autoAccess.remove(); + } if (plot == null) { sendMessage(player, Captions.NO_FREE_PLOTS); return false; From 722361aedb0b363e3830367d8bd0ebccce271183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20S=C3=B6derberg?= Date: Fri, 24 Jul 2020 12:15:07 +0200 Subject: [PATCH 10/10] Implement suggestions from PR comments --- .../com/plotsquared/core/command/Auto.java | 2 +- .../com/plotsquared/core/command/Claim.java | 2 +- .../core/player/MetaDataAccess.java | 31 +++++++++++++++++-- .../core/player/PersistentMetaDataAccess.java | 6 +++- .../core/player/TemporaryMetaDataAccess.java | 6 +++- .../core/plot/expiration/ExpireManager.java | 2 +- 6 files changed, 41 insertions(+), 8 deletions(-) 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 2cd105ffa..aadb763c8 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Auto.java +++ b/Core/src/main/java/com/plotsquared/core/command/Auto.java @@ -94,7 +94,7 @@ public class Auto extends SubCommand { if (diff - sizeX * sizeZ < 0) { try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData( PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { - if (metaDataAccess.has()) { + if (metaDataAccess.isPresent()) { int grantedPlots = metaDataAccess.get().orElse(0); if (diff < 0 && grantedPlots < sizeX * sizeZ) { MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); 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 fbbd25013..d2285e7ba 100644 --- a/Core/src/main/java/com/plotsquared/core/command/Claim.java +++ b/Core/src/main/java/com/plotsquared/core/command/Claim.java @@ -92,7 +92,7 @@ public class Claim extends SubCommand { try (final MetaDataAccess metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { int grants = 0; if (currentPlots >= player.getAllowedPlots() && !force) { - if (metaDataAccess.has()) { + if (metaDataAccess.isPresent()) { grants = metaDataAccess.get().orElse(0); if (grants <= 0) { metaDataAccess.remove(); diff --git a/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java b/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java index c38111b73..800f1c080 100644 --- a/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java +++ b/Core/src/main/java/com/plotsquared/core/player/MetaDataAccess.java @@ -34,7 +34,6 @@ import java.util.Optional; /** * Access to player meta data * - * @param

Player type * @param Meta data type */ public abstract class MetaDataAccess implements AutoCloseable { @@ -42,6 +41,7 @@ public abstract class MetaDataAccess implements AutoCloseable { private final PlotPlayer player; private final MetaDataKey metaDataKey; private final LockRepository.LockAccess lockAccess; + private boolean closed = false; MetaDataAccess(@Nonnull final PlotPlayer player, @Nonnull final MetaDataKey metaDataKey, @Nonnull final LockRepository.LockAccess lockAccess) { @@ -56,12 +56,12 @@ public abstract class MetaDataAccess implements AutoCloseable { * @return {@code true} if player has meta data with this key, or * {@code false} */ - public abstract boolean has(); + public abstract boolean isPresent(); /** * Remove the stored value meta data * - * @return Old value, or {@link null} + * @return Old value, or {@code null} */ @Nullable public abstract T remove(); @@ -81,6 +81,7 @@ public abstract class MetaDataAccess implements AutoCloseable { @Override public final void close() { this.lockAccess.close(); + this.closed = true; } /** @@ -101,4 +102,28 @@ public abstract class MetaDataAccess implements AutoCloseable { return this.metaDataKey; } + /** + * Check whether or not the meta data access has been closed. + * After being closed, all attempts to access the meta data + * through the instance, will lead to {@link IllegalAccessException} + * being thrown + * + * @return {@code true} if the access has been closed + */ + public boolean isClosed() { + return this.closed; + } + + protected void checkClosed() { + if (this.closed) { + sneakyThrow(new IllegalAccessException("The meta data access instance has been closed")); + } + } + + @SuppressWarnings("ALL") + private static void sneakyThrow(final Throwable e) throws E { + throw (E) e; + } + + } diff --git a/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java b/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java index e7bb67103..1e3767c7d 100644 --- a/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java +++ b/Core/src/main/java/com/plotsquared/core/player/PersistentMetaDataAccess.java @@ -39,11 +39,13 @@ final class PersistentMetaDataAccess extends MetaDataAccess { super(player, metaDataKey, lockAccess); } - @Override public boolean has() { + @Override public boolean isPresent() { + this.checkClosed(); return this.getPlayer().hasPersistentMeta(getMetaDataKey().toString()); } @Override @Nullable public T remove() { + this.checkClosed(); final Object old = this.getPlayer().removePersistentMeta(this.getMetaDataKey().toString()); if (old == null) { return null; @@ -52,10 +54,12 @@ final class PersistentMetaDataAccess extends MetaDataAccess { } @Override public void set(@Nonnull T value) { + this.checkClosed(); this.getPlayer().setPersistentMeta(this.getMetaDataKey(), value); } @Nonnull @Override public Optional get() { + this.checkClosed(); return Optional.ofNullable(this.getPlayer().getPersistentMeta(this.getMetaDataKey())); } diff --git a/Core/src/main/java/com/plotsquared/core/player/TemporaryMetaDataAccess.java b/Core/src/main/java/com/plotsquared/core/player/TemporaryMetaDataAccess.java index b301f5be7..22c5dd631 100644 --- a/Core/src/main/java/com/plotsquared/core/player/TemporaryMetaDataAccess.java +++ b/Core/src/main/java/com/plotsquared/core/player/TemporaryMetaDataAccess.java @@ -39,11 +39,13 @@ final class TemporaryMetaDataAccess extends MetaDataAccess { super(player, metaDataKey, lockAccess); } - @Override public boolean has() { + @Override public boolean isPresent() { + this.checkClosed(); return this.getPlayer().getMeta(this.getMetaDataKey().toString()) != null; } @Override @Nullable public T remove() { + this.checkClosed(); final Object old = getPlayer().deleteMeta(this.getMetaDataKey().toString()); if (old == null) { return null; @@ -52,10 +54,12 @@ final class TemporaryMetaDataAccess extends MetaDataAccess { } @Override public void set(@Nonnull T value) { + this.checkClosed(); this.getPlayer().setMeta(this.getMetaDataKey().toString(), null); } @Nonnull @Override public Optional get() { + this.checkClosed(); return Optional.ofNullable(this.getPlayer().getMeta(this.getMetaDataKey().toString())); } 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 6b14d0866..e0fb65d26 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 @@ -142,7 +142,7 @@ public class ExpireManager { public void confirmExpiry(final PlotPlayer pp) { try (final MetaDataAccess metaDataAccess = pp.accessTemporaryMetaData( PlayerMetaDataKeys.TEMPORARY_IGNORE_EXPIRE_TASK)) { - if (metaDataAccess.has()) { + if (metaDataAccess.isPresent()) { return; } if (plotsToDelete != null && !plotsToDelete.isEmpty() && pp.hasPermission("plots.admin.command.autoclear")) {