refactor: Use mappings class for PDC tag type handling

feat/data-edit-commands
William 2 years ago
parent 3425c97245
commit 1d7f6a8d8b
No known key found for this signature in database

@ -0,0 +1,54 @@
package net.william278.husksync.data;
import org.bukkit.NamespacedKey;
import org.bukkit.entity.Player;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import java.util.Optional;
public record BukkitPersistentTypeMapping<T, Z>(PersistentDataTagType type, PersistentDataType<T, Z> bukkitType) {
public static final BukkitPersistentTypeMapping<?, ?>[] PRIMITIVE_TYPE_MAPPINGS = new BukkitPersistentTypeMapping<?, ?>[]{
new BukkitPersistentTypeMapping<>(PersistentDataTagType.BYTE, PersistentDataType.BYTE),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.SHORT, PersistentDataType.SHORT),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.INTEGER, PersistentDataType.INTEGER),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.LONG, PersistentDataType.LONG),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.FLOAT, PersistentDataType.FLOAT),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.DOUBLE, PersistentDataType.DOUBLE),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.STRING, PersistentDataType.STRING),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.BYTE_ARRAY, PersistentDataType.BYTE_ARRAY),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.INTEGER_ARRAY, PersistentDataType.INTEGER_ARRAY),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.LONG_ARRAY, PersistentDataType.LONG_ARRAY),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.TAG_CONTAINER_ARRAY, PersistentDataType.TAG_CONTAINER_ARRAY),
new BukkitPersistentTypeMapping<>(PersistentDataTagType.TAG_CONTAINER, PersistentDataType.TAG_CONTAINER)
};
public BukkitPersistentTypeMapping(@NotNull PersistentDataTagType type, @NotNull PersistentDataType<T, Z> bukkitType) {
this.type = type;
this.bukkitType = bukkitType;
}
@NotNull
public PersistentDataTag<Z> getContainerValue(@NotNull PersistentDataContainer container, @NotNull NamespacedKey key) throws NullPointerException {
return new PersistentDataTag<>(type, Objects.requireNonNull(container.get(key, bukkitType)));
}
public void setContainerValue(@NotNull PersistentDataContainerData container, @NotNull Player player, @NotNull NamespacedKey key) throws NullPointerException {
container.getTagValue(key.toString(), bukkitType.getPrimitiveType())
.ifPresent(value -> player.getPersistentDataContainer().set(key, bukkitType, (Z) value));
}
public static Optional<BukkitPersistentTypeMapping<?, ?>> getMapping(@NotNull PersistentDataTagType type) {
for (BukkitPersistentTypeMapping<?, ?> mapping : PRIMITIVE_TYPE_MAPPINGS) {
if (mapping.type().equals(type)) {
return Optional.of(mapping);
}
}
return Optional.empty();
}
}

@ -21,7 +21,6 @@ import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -37,19 +36,6 @@ import java.util.logging.Level;
*/ */
public class BukkitPlayer extends OnlineUser { public class BukkitPlayer extends OnlineUser {
private static final PersistentDataType<?, ?>[] PRIMITIVE_PERSISTENT_DATA_TYPES = new PersistentDataType<?, ?>[]{
PersistentDataType.BYTE,
PersistentDataType.SHORT,
PersistentDataType.INTEGER,
PersistentDataType.LONG,
PersistentDataType.FLOAT,
PersistentDataType.DOUBLE,
PersistentDataType.STRING,
PersistentDataType.BYTE_ARRAY,
PersistentDataType.INTEGER_ARRAY,
PersistentDataType.LONG_ARRAY,
PersistentDataType.TAG_CONTAINER_ARRAY,
PersistentDataType.TAG_CONTAINER};
private final Player player; private final Player player;
private final Audience audience; private final Audience audience;
@ -450,64 +436,27 @@ public class BukkitPlayer extends OnlineUser {
@Override @Override
public CompletableFuture<PersistentDataContainerData> getPersistentDataContainer() { public CompletableFuture<PersistentDataContainerData> getPersistentDataContainer() {
return CompletableFuture.supplyAsync(() -> { final CompletableFuture<PersistentDataContainerData> future = new CompletableFuture<>();
final Map<String, PersistentDataTag<?>> persistentDataMap = new HashMap<>();
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
final PersistentDataContainer container = player.getPersistentDataContainer(); final PersistentDataContainer container = player.getPersistentDataContainer();
if (container.isEmpty()) { container.getKeys().forEach(key -> {
return new PersistentDataContainerData(new HashMap<>()); BukkitPersistentTypeMapping<?, ?> type = null;
} for (BukkitPersistentTypeMapping<?, ?> dataType : BukkitPersistentTypeMapping.PRIMITIVE_TYPE_MAPPINGS) {
final HashMap<String, PersistentDataTag<?>> persistentDataMap = new HashMap<>(); if (container.has(key, dataType.bukkitType())) {
for (final NamespacedKey key : container.getKeys()) {
PersistentDataType<?, ?> type = null;
for (PersistentDataType<?, ?> dataType : PRIMITIVE_PERSISTENT_DATA_TYPES) {
if (container.has(key, dataType)) {
type = dataType; type = dataType;
break; break;
} }
} }
if (type != null) { if (type != null) {
// This is absolutely disgusting code and needs to be swiftly put out of its misery with a refactor persistentDataMap.put(key.toString(), type.getContainerValue(container, key));
final Class<?> primitiveType = type.getPrimitiveType();
if (String.class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.STRING,
Objects.requireNonNull(container.get(key, PersistentDataType.STRING))));
} else if (int.class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.INTEGER,
Objects.requireNonNull(container.get(key, PersistentDataType.INTEGER))));
} else if (double.class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.DOUBLE,
Objects.requireNonNull(container.get(key, PersistentDataType.DOUBLE))));
} else if (float.class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.FLOAT,
Objects.requireNonNull(container.get(key, PersistentDataType.FLOAT))));
} else if (long.class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.LONG,
Objects.requireNonNull(container.get(key, PersistentDataType.LONG))));
} else if (short.class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.SHORT,
Objects.requireNonNull(container.get(key, PersistentDataType.SHORT))));
} else if (byte.class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.BYTE,
Objects.requireNonNull(container.get(key, PersistentDataType.BYTE))));
} else if (byte[].class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.BYTE_ARRAY,
Objects.requireNonNull(container.get(key, PersistentDataType.BYTE_ARRAY))));
} else if (int[].class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.INTEGER_ARRAY,
Objects.requireNonNull(container.get(key, PersistentDataType.INTEGER_ARRAY))));
} else if (long[].class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.LONG_ARRAY,
Objects.requireNonNull(container.get(key, PersistentDataType.LONG_ARRAY))));
} else if (PersistentDataContainer.class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.TAG_CONTAINER,
Objects.requireNonNull(container.get(key, PersistentDataType.TAG_CONTAINER))));
} else if (PersistentDataContainer[].class.equals(primitiveType)) {
persistentDataMap.put(key.toString(), new PersistentDataTag<>(BukkitPersistentDataTagType.TAG_CONTAINER_ARRAY,
Objects.requireNonNull(container.get(key, PersistentDataType.TAG_CONTAINER_ARRAY))));
}
} }
} });
return new PersistentDataContainerData(persistentDataMap); future.complete(new PersistentDataContainerData(persistentDataMap));
}).exceptionally(throwable -> { });
return future.exceptionally(throwable -> {
BukkitHuskSync.getInstance().log(Level.WARNING, BukkitHuskSync.getInstance().log(Level.WARNING,
"Could not read " + player.getName() + "'s persistent data map, skipping!"); "Could not read " + player.getName() + "'s persistent data map, skipping!");
throwable.printStackTrace(); throwable.printStackTrace();
@ -523,51 +472,12 @@ public class BukkitPlayer extends OnlineUser {
container.getTags().forEach(keyString -> { container.getTags().forEach(keyString -> {
final NamespacedKey key = NamespacedKey.fromString(keyString); final NamespacedKey key = NamespacedKey.fromString(keyString);
if (key != null) { if (key != null) {
// Set a tag with the given key and value. This is crying out for a refactor. container.getTagType(keyString)
container.getTagType(keyString).ifPresentOrElse(dataType -> { .flatMap(BukkitPersistentTypeMapping::getMapping)
switch (dataType) { .ifPresentOrElse(mapping -> mapping.setContainerValue(container, player, key),
case BYTE -> container.getTagValue(keyString, byte.class).ifPresent( () -> BukkitHuskSync.getInstance().log(Level.WARNING,
value -> player.getPersistentDataContainer().set(key, "Could not set " + player.getName() + "'s persistent data key " + keyString +
PersistentDataType.BYTE, value)); " as it has an invalid type. Skipping!"));
case SHORT -> container.getTagValue(keyString, short.class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.SHORT, value));
case INTEGER -> container.getTagValue(keyString, int.class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.INTEGER, value));
case LONG -> container.getTagValue(keyString, long.class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.LONG, value));
case FLOAT -> container.getTagValue(keyString, float.class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.FLOAT, value));
case DOUBLE -> container.getTagValue(keyString, double.class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.DOUBLE, value));
case STRING -> container.getTagValue(keyString, String.class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.STRING, value));
case BYTE_ARRAY -> container.getTagValue(keyString, byte[].class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.BYTE_ARRAY, value));
case INTEGER_ARRAY -> container.getTagValue(keyString, int[].class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.INTEGER_ARRAY, value));
case LONG_ARRAY -> container.getTagValue(keyString, long[].class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.LONG_ARRAY, value));
case TAG_CONTAINER ->
container.getTagValue(keyString, PersistentDataContainer.class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.TAG_CONTAINER, value));
case TAG_CONTAINER_ARRAY ->
container.getTagValue(keyString, PersistentDataContainer[].class).ifPresent(
value -> player.getPersistentDataContainer().set(key,
PersistentDataType.TAG_CONTAINER_ARRAY, value));
}
}, () -> BukkitHuskSync.getInstance().log(Level.WARNING,
"Could not set " + player.getName() + "'s persistent data key " + keyString +
" as it has an invalid type. Skipping!"));
} }
}); });
}).exceptionally(throwable -> { }).exceptionally(throwable -> {

@ -34,9 +34,9 @@ public class PersistentDataContainerData {
return Optional.empty(); return Optional.empty();
} }
public Optional<BukkitPersistentDataTagType> getTagType(@NotNull final String tagType) { public Optional<PersistentDataTagType> getTagType(@NotNull final String tagType) {
if (persistentDataMap.containsKey(tagType)) { if (persistentDataMap.containsKey(tagType)) {
return BukkitPersistentDataTagType.getDataType(persistentDataMap.get(tagType).type); return PersistentDataTagType.getDataType(persistentDataMap.get(tagType).type);
} }
return Optional.empty(); return Optional.empty();
} }

@ -19,16 +19,17 @@ public class PersistentDataTag<T> {
*/ */
public T value; public T value;
public PersistentDataTag(@NotNull BukkitPersistentDataTagType type, @NotNull T value) { public PersistentDataTag(@NotNull PersistentDataTagType type, @NotNull T value) {
this.type = type.name(); this.type = type.name();
this.value = value; this.value = value;
} }
@SuppressWarnings("unused")
private PersistentDataTag() { private PersistentDataTag() {
} }
public Optional<BukkitPersistentDataTagType> getType() { public Optional<PersistentDataTagType> getType() {
return BukkitPersistentDataTagType.getDataType(type); return PersistentDataTagType.getDataType(type);
} }
} }

@ -7,7 +7,7 @@ import java.util.Optional;
/** /**
* Represents the type of a {@link PersistentDataTag} * Represents the type of a {@link PersistentDataTag}
*/ */
public enum BukkitPersistentDataTagType { public enum PersistentDataTagType {
BYTE, BYTE,
SHORT, SHORT,
@ -23,8 +23,8 @@ public enum BukkitPersistentDataTagType {
TAG_CONTAINER; TAG_CONTAINER;
public static Optional<BukkitPersistentDataTagType> getDataType(@NotNull String typeName) { public static Optional<PersistentDataTagType> getDataType(@NotNull String typeName) {
for (BukkitPersistentDataTagType type : values()) { for (PersistentDataTagType type : values()) {
if (type.name().equalsIgnoreCase(typeName)) { if (type.name().equalsIgnoreCase(typeName)) {
return Optional.of(type); return Optional.of(type);
} }

@ -62,13 +62,13 @@ public class DataAdaptionTests {
private String getTestSerializedPersistentDataContainer() { private String getTestSerializedPersistentDataContainer() {
final HashMap<String, PersistentDataTag<?>> persistentDataTest = new HashMap<>(); final HashMap<String, PersistentDataTag<?>> persistentDataTest = new HashMap<>();
persistentDataTest.put("husksync:byte_test", new PersistentDataTag<>(BukkitPersistentDataTagType.BYTE, 0x01)); persistentDataTest.put("husksync:byte_test", new PersistentDataTag<>(PersistentDataTagType.BYTE, 0x01));
persistentDataTest.put("husksync:double_test", new PersistentDataTag<>(BukkitPersistentDataTagType.DOUBLE, 2d)); persistentDataTest.put("husksync:double_test", new PersistentDataTag<>(PersistentDataTagType.DOUBLE, 2d));
persistentDataTest.put("husksync:string_test", new PersistentDataTag<>(BukkitPersistentDataTagType.STRING, "test")); persistentDataTest.put("husksync:string_test", new PersistentDataTag<>(PersistentDataTagType.STRING, "test"));
persistentDataTest.put("husksync:int_test", new PersistentDataTag<>(BukkitPersistentDataTagType.INTEGER, 3)); persistentDataTest.put("husksync:int_test", new PersistentDataTag<>(PersistentDataTagType.INTEGER, 3));
persistentDataTest.put("husksync:long_test", new PersistentDataTag<>(BukkitPersistentDataTagType.LONG, 4L)); persistentDataTest.put("husksync:long_test", new PersistentDataTag<>(PersistentDataTagType.LONG, 4L));
persistentDataTest.put("husksync:float_test", new PersistentDataTag<>(BukkitPersistentDataTagType.FLOAT, 5f)); persistentDataTest.put("husksync:float_test", new PersistentDataTag<>(PersistentDataTagType.FLOAT, 5f));
persistentDataTest.put("husksync:short_test", new PersistentDataTag<>(BukkitPersistentDataTagType.SHORT, 6)); persistentDataTest.put("husksync:short_test", new PersistentDataTag<>(PersistentDataTagType.SHORT, 6));
final PersistentDataContainerData persistentDataContainerData = new PersistentDataContainerData(persistentDataTest); final PersistentDataContainerData persistentDataContainerData = new PersistentDataContainerData(persistentDataTest);
final DataAdapter dataAdapter = new JsonDataAdapter(); final DataAdapter dataAdapter = new JsonDataAdapter();

Loading…
Cancel
Save