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] 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); }