diff --git a/bukkit/src/main/java/net/william278/husksync/data/BukkitPersistentTypeMapping.java b/bukkit/src/main/java/net/william278/husksync/data/BukkitPersistentTypeMapping.java new file mode 100644 index 00000000..ad746265 --- /dev/null +++ b/bukkit/src/main/java/net/william278/husksync/data/BukkitPersistentTypeMapping.java @@ -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(PersistentDataTagType type, PersistentDataType 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 bukkitType) { + this.type = type; + this.bukkitType = bukkitType; + } + + @NotNull + public PersistentDataTag 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> getMapping(@NotNull PersistentDataTagType type) { + for (BukkitPersistentTypeMapping mapping : PRIMITIVE_TYPE_MAPPINGS) { + if (mapping.type().equals(type)) { + return Optional.of(mapping); + } + } + return Optional.empty(); + } + + +} diff --git a/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java b/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java index 4b58c4c7..f25abe54 100644 --- a/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java +++ b/bukkit/src/main/java/net/william278/husksync/player/BukkitPlayer.java @@ -21,7 +21,6 @@ import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; @@ -37,19 +36,6 @@ import java.util.logging.Level; */ 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 Audience audience; @@ -450,64 +436,27 @@ public class BukkitPlayer extends OnlineUser { @Override public CompletableFuture getPersistentDataContainer() { - return CompletableFuture.supplyAsync(() -> { + final CompletableFuture future = new CompletableFuture<>(); + final Map> persistentDataMap = new HashMap<>(); + + Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> { final PersistentDataContainer container = player.getPersistentDataContainer(); - if (container.isEmpty()) { - return new PersistentDataContainerData(new HashMap<>()); - } - final HashMap> persistentDataMap = new HashMap<>(); - for (final NamespacedKey key : container.getKeys()) { - PersistentDataType type = null; - for (PersistentDataType dataType : PRIMITIVE_PERSISTENT_DATA_TYPES) { - if (container.has(key, dataType)) { + container.getKeys().forEach(key -> { + BukkitPersistentTypeMapping type = null; + for (BukkitPersistentTypeMapping dataType : BukkitPersistentTypeMapping.PRIMITIVE_TYPE_MAPPINGS) { + if (container.has(key, dataType.bukkitType())) { type = dataType; break; } } if (type != null) { - // This is absolutely disgusting code and needs to be swiftly put out of its misery with a refactor - 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)))); - } + persistentDataMap.put(key.toString(), type.getContainerValue(container, key)); } - } - return new PersistentDataContainerData(persistentDataMap); - }).exceptionally(throwable -> { + }); + future.complete(new PersistentDataContainerData(persistentDataMap)); + }); + + return future.exceptionally(throwable -> { BukkitHuskSync.getInstance().log(Level.WARNING, "Could not read " + player.getName() + "'s persistent data map, skipping!"); throwable.printStackTrace(); @@ -523,51 +472,12 @@ public class BukkitPlayer extends OnlineUser { container.getTags().forEach(keyString -> { final NamespacedKey key = NamespacedKey.fromString(keyString); if (key != null) { - // Set a tag with the given key and value. This is crying out for a refactor. - container.getTagType(keyString).ifPresentOrElse(dataType -> { - switch (dataType) { - case BYTE -> container.getTagValue(keyString, byte.class).ifPresent( - value -> player.getPersistentDataContainer().set(key, - PersistentDataType.BYTE, value)); - 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!")); + container.getTagType(keyString) + .flatMap(BukkitPersistentTypeMapping::getMapping) + .ifPresentOrElse(mapping -> mapping.setContainerValue(container, player, key), + () -> BukkitHuskSync.getInstance().log(Level.WARNING, + "Could not set " + player.getName() + "'s persistent data key " + keyString + + " as it has an invalid type. Skipping!")); } }); }).exceptionally(throwable -> { diff --git a/common/src/main/java/net/william278/husksync/data/PersistentDataContainerData.java b/common/src/main/java/net/william278/husksync/data/PersistentDataContainerData.java index 1458ee0d..b886fe19 100644 --- a/common/src/main/java/net/william278/husksync/data/PersistentDataContainerData.java +++ b/common/src/main/java/net/william278/husksync/data/PersistentDataContainerData.java @@ -34,9 +34,9 @@ public class PersistentDataContainerData { return Optional.empty(); } - public Optional getTagType(@NotNull final String tagType) { + public Optional getTagType(@NotNull final String tagType) { if (persistentDataMap.containsKey(tagType)) { - return BukkitPersistentDataTagType.getDataType(persistentDataMap.get(tagType).type); + return PersistentDataTagType.getDataType(persistentDataMap.get(tagType).type); } return Optional.empty(); } diff --git a/common/src/main/java/net/william278/husksync/data/PersistentDataTag.java b/common/src/main/java/net/william278/husksync/data/PersistentDataTag.java index a4222637..e27f3650 100644 --- a/common/src/main/java/net/william278/husksync/data/PersistentDataTag.java +++ b/common/src/main/java/net/william278/husksync/data/PersistentDataTag.java @@ -19,16 +19,17 @@ public class PersistentDataTag { */ public T value; - public PersistentDataTag(@NotNull BukkitPersistentDataTagType type, @NotNull T value) { + public PersistentDataTag(@NotNull PersistentDataTagType type, @NotNull T value) { this.type = type.name(); this.value = value; } + @SuppressWarnings("unused") private PersistentDataTag() { } - public Optional getType() { - return BukkitPersistentDataTagType.getDataType(type); + public Optional getType() { + return PersistentDataTagType.getDataType(type); } } diff --git a/common/src/main/java/net/william278/husksync/data/BukkitPersistentDataTagType.java b/common/src/main/java/net/william278/husksync/data/PersistentDataTagType.java similarity index 72% rename from common/src/main/java/net/william278/husksync/data/BukkitPersistentDataTagType.java rename to common/src/main/java/net/william278/husksync/data/PersistentDataTagType.java index b6c30848..6182ffb0 100644 --- a/common/src/main/java/net/william278/husksync/data/BukkitPersistentDataTagType.java +++ b/common/src/main/java/net/william278/husksync/data/PersistentDataTagType.java @@ -7,7 +7,7 @@ import java.util.Optional; /** * Represents the type of a {@link PersistentDataTag} */ -public enum BukkitPersistentDataTagType { +public enum PersistentDataTagType { BYTE, SHORT, @@ -23,8 +23,8 @@ public enum BukkitPersistentDataTagType { TAG_CONTAINER; - public static Optional getDataType(@NotNull String typeName) { - for (BukkitPersistentDataTagType type : values()) { + public static Optional getDataType(@NotNull String typeName) { + for (PersistentDataTagType type : values()) { if (type.name().equalsIgnoreCase(typeName)) { return Optional.of(type); } diff --git a/common/src/test/java/net/william278/husksync/data/DataAdaptionTests.java b/common/src/test/java/net/william278/husksync/data/DataAdaptionTests.java index f40d4725..a45b5d78 100644 --- a/common/src/test/java/net/william278/husksync/data/DataAdaptionTests.java +++ b/common/src/test/java/net/william278/husksync/data/DataAdaptionTests.java @@ -62,13 +62,13 @@ public class DataAdaptionTests { private String getTestSerializedPersistentDataContainer() { final HashMap> persistentDataTest = new HashMap<>(); - persistentDataTest.put("husksync:byte_test", new PersistentDataTag<>(BukkitPersistentDataTagType.BYTE, 0x01)); - persistentDataTest.put("husksync:double_test", new PersistentDataTag<>(BukkitPersistentDataTagType.DOUBLE, 2d)); - persistentDataTest.put("husksync:string_test", new PersistentDataTag<>(BukkitPersistentDataTagType.STRING, "test")); - persistentDataTest.put("husksync:int_test", new PersistentDataTag<>(BukkitPersistentDataTagType.INTEGER, 3)); - persistentDataTest.put("husksync:long_test", new PersistentDataTag<>(BukkitPersistentDataTagType.LONG, 4L)); - persistentDataTest.put("husksync:float_test", new PersistentDataTag<>(BukkitPersistentDataTagType.FLOAT, 5f)); - persistentDataTest.put("husksync:short_test", new PersistentDataTag<>(BukkitPersistentDataTagType.SHORT, 6)); + persistentDataTest.put("husksync:byte_test", new PersistentDataTag<>(PersistentDataTagType.BYTE, 0x01)); + persistentDataTest.put("husksync:double_test", new PersistentDataTag<>(PersistentDataTagType.DOUBLE, 2d)); + persistentDataTest.put("husksync:string_test", new PersistentDataTag<>(PersistentDataTagType.STRING, "test")); + persistentDataTest.put("husksync:int_test", new PersistentDataTag<>(PersistentDataTagType.INTEGER, 3)); + persistentDataTest.put("husksync:long_test", new PersistentDataTag<>(PersistentDataTagType.LONG, 4L)); + persistentDataTest.put("husksync:float_test", new PersistentDataTag<>(PersistentDataTagType.FLOAT, 5f)); + persistentDataTest.put("husksync:short_test", new PersistentDataTag<>(PersistentDataTagType.SHORT, 6)); final PersistentDataContainerData persistentDataContainerData = new PersistentDataContainerData(persistentDataTest); final DataAdapter dataAdapter = new JsonDataAdapter();