Add managed persistent meta data access

This commit is contained in:
Alexander Söderberg 2020-07-23 19:18:21 +02:00 committed by Alexander Söderberg
parent 2575787bd0
commit 555860cf83
9 changed files with 474 additions and 110 deletions

View File

@ -26,7 +26,6 @@
package com.plotsquared.core.command; package com.plotsquared.core.command;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.CaptionUtility; 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.PlotAutoMergeEvent;
import com.plotsquared.core.events.Result; import com.plotsquared.core.events.Result;
import com.plotsquared.core.events.TeleportCause; 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.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
@ -91,27 +92,29 @@ public class Auto extends SubCommand {
} }
int diff = allowedPlots - currentPlots; int diff = allowedPlots - currentPlots;
if (diff - sizeX * sizeZ < 0) { if (diff - sizeX * sizeZ < 0) {
if (player.hasPersistentMeta("grantedPlots")) { try (final MetaDataAccess<Integer> metaDataAccess = player.accessPersistentMetaData(
int grantedPlots = Ints.fromByteArray(player.getPersistentMeta("grantedPlots")); PlayerMetaDataKeys.GRANTED_PLOTS)) {
if (diff < 0 && grantedPlots < sizeX * sizeZ) { if (metaDataAccess.has()) {
MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); int grantedPlots = metaDataAccess.get().orElse(0);
return false; if (diff < 0 && grantedPlots < sizeX * sizeZ) {
} else if (diff >= 0 && grantedPlots + diff < sizeX * sizeZ) { MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS);
MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS); return false;
return false; } else if (diff >= 0 && grantedPlots + diff < sizeX * sizeZ) {
} else { MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS);
int left = grantedPlots + diff < 0 ? 0 : diff - sizeX * sizeZ; return false;
if (left == 0) {
player.removePersistentMeta("grantedPlots");
} else { } 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, } else {
"" + (grantedPlots - left), "" + left); MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS);
return false;
} }
} else {
MainUtil.sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS);
return false;
} }
} }
return true; return true;

View File

@ -25,7 +25,6 @@
*/ */
package com.plotsquared.core.command; package com.plotsquared.core.command;
import com.google.common.primitives.Ints;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.CaptionUtility;
import com.plotsquared.core.configuration.Captions; 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.events.Result;
import com.plotsquared.core.location.Direction; import com.plotsquared.core.location.Direction;
import com.plotsquared.core.location.Location; 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.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
@ -85,54 +86,57 @@ public class Claim extends SubCommand {
int currentPlots = Settings.Limit.GLOBAL ? int currentPlots = Settings.Limit.GLOBAL ?
player.getPlotCount() : player.getPlotCount() :
player.getPlotCount(location.getWorldName()); player.getPlotCount(location.getWorldName());
int grants = 0;
if (currentPlots >= player.getAllowedPlots() && !force) { final PlotArea area = plot.getArea();
if (player.hasPersistentMeta("grantedPlots")) {
grants = Ints.fromByteArray(player.getPersistentMeta("grantedPlots")); try (final MetaDataAccess<Integer> metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.GRANTED_PLOTS)) {
if (grants <= 0) { int grants = 0;
player.removePersistentMeta("grantedPlots"); 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); return sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS);
} }
} else {
return sendMessage(player, Captions.CANT_CLAIM_MORE_PLOTS);
} }
}
if (!plot.canClaim(player)) { if (!plot.canClaim(player)) {
return sendMessage(player, Captions.PLOT_IS_CLAIMED); return sendMessage(player, Captions.PLOT_IS_CLAIMED);
} }
final PlotArea area = plot.getArea(); if (schematic != null && !schematic.isEmpty()) {
if (schematic != null && !schematic.isEmpty()) { if (area.isSchematicClaimSpecify()) {
if (area.isSchematicClaimSpecify()) { if (!area.hasSchematic(schematic)) {
if (!area.hasSchematic(schematic)) { return sendMessage(player, Captions.SCHEMATIC_INVALID, "non-existent: " + 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)
if (!Permissions.hasPermission(player, CaptionUtility && !force) {
.format(player, Captions.PERMISSION_CLAIM_SCHEMATIC.getTranslated(), schematic)) return sendMessage(player, Captions.NO_SCHEMATIC_PERMISSION, 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) {
if ((this.econHandler != null) && area.useEconomy() && !force) { Expression<Double> costExr = area.getPrices().get("claim");
Expression<Double> costExr = area.getPrices().get("claim"); double cost = costExr.evaluate((double) currentPlots);
double cost = costExr.evaluate((double) currentPlots); if (cost > 0d) {
if (cost > 0d) { if (this.econHandler.getMoney(player) < cost) {
if (this.econHandler.getMoney(player) < cost) { return sendMessage(player, Captions.CANNOT_AFFORD_PLOT, "" + 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 > 0) { if (grants == 1) {
if (grants == 1) { metaDataAccess.remove();
player.removePersistentMeta("grantedPlots"); } else {
} else { metaDataAccess.set(grants - 1);
player.setPersistentMeta("grantedPlots", Ints.toByteArray(grants - 1)); }
sendMessage(player, Captions.REMOVED_GRANTED_PLOT, "1", (grants - 1));
} }
sendMessage(player, Captions.REMOVED_GRANTED_PLOT, "1", (grants - 1));
} }
int border = area.getBorder(); int border = area.getBorder();
if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !force) { if (border != Integer.MAX_VALUE && plot.getDistanceFromOrigin() > border && !force) {

View File

@ -30,6 +30,8 @@ import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.CaptionUtility; import com.plotsquared.core.configuration.CaptionUtility;
import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Captions;
import com.plotsquared.core.database.DBFunc; 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.player.PlotPlayer;
import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.MainUtil;
import com.plotsquared.core.util.Permissions; import com.plotsquared.core.util.Permissions;
@ -42,7 +44,6 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
@CommandDeclaration(command = "grant", @CommandDeclaration(command = "grant",
category = CommandCategory.CLAIMING, category = CommandCategory.CLAIMING,
@ -80,41 +81,40 @@ public class Grant extends Command {
MainUtil.sendMessage(player, Captions.INVALID_PLAYER); MainUtil.sendMessage(player, Captions.INVALID_PLAYER);
} else { } else {
final UUID uuid = uuids.toArray(new UUID[0])[0]; final UUID uuid = uuids.toArray(new UUID[0])[0];
final Consumer<byte[]> 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); PlotPlayer<?> pp = PlotSquared.platform().getPlayerManager().getPlayerIfExists(uuid);
if (pp != null) { if (pp != null) {
result.accept(player.getPersistentMeta("grantedPlots")); try (final MetaDataAccess<Integer> 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 { } else {
DBFunc.getPersistentMeta(uuid, new RunnableVal<Map<String, byte[]>>() { DBFunc.getPersistentMeta(uuid, new RunnableVal<Map<String, byte[]>>() {
@Override public void run(Map<String, byte[]> value) { @Override public void run(Map<String, byte[]> 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);
}
} }
}); });
} }

View File

@ -26,12 +26,13 @@
package com.plotsquared.core.listener; package com.plotsquared.core.listener;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.collection.ByteArrayUtilities;
import com.plotsquared.core.configuration.Captions; import com.plotsquared.core.configuration.Captions;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.events.PlotFlagRemoveEvent; import com.plotsquared.core.events.PlotFlagRemoveEvent;
import com.plotsquared.core.events.Result; import com.plotsquared.core.events.Result;
import com.plotsquared.core.location.Location; 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.player.PlotPlayer;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea; import com.plotsquared.core.plot.PlotArea;
@ -71,6 +72,7 @@ import javax.annotation.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
public class PlotListener { public class PlotListener {
@ -177,8 +179,9 @@ public class PlotListener {
boolean flight = player.getFlight(); boolean flight = player.getFlight();
GameMode gamemode = player.getGameMode(); GameMode gamemode = player.getGameMode();
if (flight != (gamemode == GameModes.CREATIVE || gamemode == GameModes.SPECTATOR)) { if (flight != (gamemode == GameModes.CREATIVE || gamemode == GameModes.SPECTATOR)) {
player.setPersistentMeta("flight", try (final MetaDataAccess<Boolean> metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_FLIGHT)) {
ByteArrayUtilities.booleanToBytes(player.getFlight())); metaDataAccess.set(player.getFlight());
}
} }
player.setFlight(flyStatus == FlyFlag.FlyStatus.ENABLED); player.setFlight(flyStatus == FlyFlag.FlyStatus.ENABLED);
} }
@ -346,16 +349,18 @@ public class PlotListener {
final FlyFlag.FlyStatus flyStatus = plot.getFlag(FlyFlag.class); final FlyFlag.FlyStatus flyStatus = plot.getFlag(FlyFlag.class);
if (flyStatus != FlyFlag.FlyStatus.DEFAULT) { if (flyStatus != FlyFlag.FlyStatus.DEFAULT) {
if (player.hasPersistentMeta("flight")) { try (final MetaDataAccess<Boolean> metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_FLIGHT)) {
player.setFlight( final Optional<Boolean> value = metaDataAccess.get();
ByteArrayUtilities.bytesToBoolean(player.getPersistentMeta("flight"))); if (value.isPresent()) {
player.removePersistentMeta("flight"); player.setFlight(value.get());
} else { metaDataAccess.remove();
GameMode gameMode = player.getGameMode(); } else {
if (gameMode == GameModes.SURVIVAL || gameMode == GameModes.ADVENTURE) { GameMode gameMode = player.getGameMode();
player.setFlight(false); if (gameMode == GameModes.SURVIVAL || gameMode == GameModes.ADVENTURE) {
} else if (!player.getFlight()) { player.setFlight(false);
player.setFlight(true); } else if (!player.getFlight()) {
player.setFlight(true);
}
} }
} }
} }

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <P> Player type
* @param <T> Meta data type
*/
public abstract class MetaDataAccess<T> implements AutoCloseable {
private final PlotPlayer<?> player;
private final MetaDataKey<T> metaDataKey;
private final LockRepository.LockAccess lockAccess;
MetaDataAccess(@Nonnull final PlotPlayer<?> player, @Nonnull final MetaDataKey<T> 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<T> 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<T> getMetaDataKey() {
return this.metaDataKey;
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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 <T> Meta data type
*/
public final class MetaDataKey<T> {
private static final Map<String, MetaDataKey> keyMap = new HashMap<>();
private static final Object keyMetaData = new Object();
private final String key;
private final Class<T> type;
private final LockKey lockKey;
private MetaDataKey(@Nonnull final String key, @Nonnull final Class<T> 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 <T> Type
* @return MetaData key instance
*/
@Nonnull public static <T> MetaDataKey<T> of(@Nonnull final String key, @Nonnull final Class<T> type) {
synchronized (keyMetaData) {
return (MetaDataKey<T>)
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<T> getType() {
return this.type;
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.player;
import com.plotsquared.core.synchronization.LockRepository;
import javax.annotation.Nonnull;
import java.util.Optional;
public final class PersistentMetaDataAccess<T> extends MetaDataAccess<T> {
PersistentMetaDataAccess(@Nonnull final PlotPlayer<?> player,
@Nonnull final MetaDataKey<T> 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<T> get() {
return Optional.ofNullable(this.getPlayer().getPersistentMeta(this.getMetaDataKey()));
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.player;
public final class PlayerMetaDataKeys {
public static final MetaDataKey<Boolean> PERSISTENT_FLIGHT = MetaDataKey.of("flight", Boolean.class);
public static final MetaDataKey<Integer> GRANTED_PLOTS = MetaDataKey.of("grantedPlots", Integer.class);
private PlayerMetaDataKeys() {
}
}

View File

@ -26,7 +26,9 @@
package com.plotsquared.core.player; package com.plotsquared.core.player;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.primitives.Ints;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.collection.ByteArrayUtilities;
import com.plotsquared.core.command.CommandCaller; import com.plotsquared.core.command.CommandCaller;
import com.plotsquared.core.command.RequiredType; import com.plotsquared.core.command.RequiredType;
import com.plotsquared.core.configuration.CaptionUtility; 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.PlotAreaManager;
import com.plotsquared.core.plot.world.SinglePlotArea; import com.plotsquared.core.plot.world.SinglePlotArea;
import com.plotsquared.core.plot.world.SinglePlotAreaManager; import com.plotsquared.core.plot.world.SinglePlotAreaManager;
import com.plotsquared.core.synchronization.LockRepository;
import com.plotsquared.core.util.EconHandler; import com.plotsquared.core.util.EconHandler;
import com.plotsquared.core.util.EventDispatcher; import com.plotsquared.core.util.EventDispatcher;
import com.plotsquared.core.util.Permissions; 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.extension.platform.Actor;
import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameMode;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -92,6 +95,8 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer
private ConcurrentHashMap<String, Object> meta; private ConcurrentHashMap<String, Object> meta;
private int hash; private int hash;
private final LockRepository lockRepository = new LockRepository();
private final PlotAreaManager plotAreaManager; private final PlotAreaManager plotAreaManager;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final EconHandler econHandler; private final EconHandler econHandler;
@ -721,18 +726,64 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer
} }
} }
public byte[] getPersistentMeta(String key) { byte[] getPersistentMeta(String key) {
return this.metaMap.get(key); return this.metaMap.get(key);
} }
public void removePersistentMeta(String key) { void removePersistentMeta(String key) {
this.metaMap.remove(key); this.metaMap.remove(key);
if (Settings.Enabled_Components.PERSISTENT_META) { if (Settings.Enabled_Components.PERSISTENT_META) {
DBFunc.removePersistentMeta(getUUID(), key); 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:
* <pre>{@code
* try (final MetaDataAccess<Integer> access = player.accessPersistentMetaData(PlayerMetaKeys.GRANTS)) {
* int grants = access.get();
* access.set(grants + 1);
* }
* }</pre>
*
* @param key Meta data key
* @param <T> Meta data type
* @return Meta data access. MUST be closed after being used
*/
@Nonnull public <T> MetaDataAccess<T> accessPersistentMetaData(@Nonnull final MetaDataKey<T> key) {
return new PersistentMetaDataAccess<>(this, key, this.lockRepository.lock(key.getLockKey()));
}
<T> void setPersistentMeta(@Nonnull final MetaDataKey<T> 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> T getPersistentMeta(@Nonnull final MetaDataKey<T> 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); boolean delete = hasPersistentMeta(key);
this.metaMap.put(key, value); this.metaMap.put(key, value);
if (Settings.Enabled_Components.PERSISTENT_META) { if (Settings.Enabled_Components.PERSISTENT_META) {
@ -740,7 +791,7 @@ public abstract class PlotPlayer<P> implements CommandCaller, OfflinePlotPlayer
} }
} }
public boolean hasPersistentMeta(String key) { boolean hasPersistentMeta(String key) {
return this.metaMap.containsKey(key); return this.metaMap.containsKey(key);
} }