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.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<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();
if (container.isEmpty()) {
return new PersistentDataContainerData(new HashMap<>());
}
final HashMap<String, PersistentDataTag<?>> 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 -> {

@ -34,9 +34,9 @@ public class PersistentDataContainerData {
return Optional.empty();
}
public Optional<BukkitPersistentDataTagType> getTagType(@NotNull final String tagType) {
public Optional<PersistentDataTagType> 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();
}

@ -19,16 +19,17 @@ public class PersistentDataTag<T> {
*/
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<BukkitPersistentDataTagType> getType() {
return BukkitPersistentDataTagType.getDataType(type);
public Optional<PersistentDataTagType> getType() {
return PersistentDataTagType.getDataType(type);
}
}

@ -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<BukkitPersistentDataTagType> getDataType(@NotNull String typeName) {
for (BukkitPersistentDataTagType type : values()) {
public static Optional<PersistentDataTagType> getDataType(@NotNull String typeName) {
for (PersistentDataTagType type : values()) {
if (type.name().equalsIgnoreCase(typeName)) {
return Optional.of(type);
}

@ -62,13 +62,13 @@ public class DataAdaptionTests {
private String getTestSerializedPersistentDataContainer() {
final HashMap<String, PersistentDataTag<?>> 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();

Loading…
Cancel
Save