mirror of
https://github.com/WiIIiam278/HuskSync.git
synced 2025-12-19 14:59:21 +00:00
Fix PersistentDataContainer synchronisation, bump to v2.0.2
This commit is contained in:
@@ -0,0 +1,60 @@
|
|||||||
|
package net.william278.husksync.data;
|
||||||
|
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the type of persistent data tag, implemented by a Bukkit PersistentDataType.
|
||||||
|
*/
|
||||||
|
public enum BukkitPersistentDataTagType {
|
||||||
|
|
||||||
|
BYTE(PersistentDataType.BYTE),
|
||||||
|
SHORT(PersistentDataType.SHORT),
|
||||||
|
INTEGER(PersistentDataType.INTEGER),
|
||||||
|
LONG(PersistentDataType.LONG),
|
||||||
|
FLOAT(PersistentDataType.FLOAT),
|
||||||
|
DOUBLE(PersistentDataType.DOUBLE),
|
||||||
|
STRING(PersistentDataType.STRING),
|
||||||
|
BYTE_ARRAY(PersistentDataType.BYTE_ARRAY),
|
||||||
|
INTEGER_ARRAY(PersistentDataType.INTEGER_ARRAY),
|
||||||
|
LONG_ARRAY(PersistentDataType.LONG_ARRAY),
|
||||||
|
TAG_CONTAINER_ARRAY(PersistentDataType.TAG_CONTAINER_ARRAY),
|
||||||
|
TAG_CONTAINER(PersistentDataType.TAG_CONTAINER);
|
||||||
|
|
||||||
|
public final PersistentDataType<?, ?> dataType;
|
||||||
|
|
||||||
|
BukkitPersistentDataTagType(PersistentDataType<?, ?> persistentDataType) {
|
||||||
|
this.dataType = persistentDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Optional<BukkitPersistentDataTagType> getDataType(@NotNull String typeName) {
|
||||||
|
for (BukkitPersistentDataTagType type : values()) {
|
||||||
|
if (type.name().equalsIgnoreCase(typeName)) {
|
||||||
|
return Optional.of(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the {@link BukkitPersistentDataTagType} of a tag in a {@link PersistentDataContainer}.
|
||||||
|
*
|
||||||
|
* @param container The {@link PersistentDataContainer} to check.
|
||||||
|
* @param key The {@link NamespacedKey} of the tag to check.
|
||||||
|
* @return The {@link BukkitPersistentDataTagType} of the key, or {@link Optional#empty()} if the key does not exist.
|
||||||
|
*/
|
||||||
|
public static Optional<BukkitPersistentDataTagType> getKeyDataType(@NotNull PersistentDataContainer container,
|
||||||
|
@NotNull NamespacedKey key) {
|
||||||
|
for (BukkitPersistentDataTagType dataType : values()) {
|
||||||
|
if (container.has(key, dataType.dataType)) {
|
||||||
|
return Optional.of(dataType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@ import net.william278.husksync.BukkitHuskSync;
|
|||||||
import net.william278.husksync.data.*;
|
import net.william278.husksync.data.*;
|
||||||
import net.william278.husksync.editor.ItemEditorMenu;
|
import net.william278.husksync.editor.ItemEditorMenu;
|
||||||
import net.william278.husksync.util.Version;
|
import net.william278.husksync.util.Version;
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.advancement.Advancement;
|
import org.bukkit.advancement.Advancement;
|
||||||
import org.bukkit.advancement.AdvancementProgress;
|
import org.bukkit.advancement.AdvancementProgress;
|
||||||
@@ -402,17 +401,20 @@ public class BukkitPlayer extends OnlineUser {
|
|||||||
if (container.isEmpty()) {
|
if (container.isEmpty()) {
|
||||||
return new PersistentDataContainerData(new HashMap<>());
|
return new PersistentDataContainerData(new HashMap<>());
|
||||||
}
|
}
|
||||||
final HashMap<String, Byte[]> persistentDataMap = new HashMap<>();
|
final HashMap<String, PersistentDataTag> persistentDataMap = new HashMap<>();
|
||||||
// Set persistent data keys; ignore keys that we cannot synchronise as byte arrays
|
// Set persistent data keys; ignore keys that we cannot synchronise as byte arrays
|
||||||
for (final NamespacedKey key : container.getKeys()) {
|
for (final NamespacedKey key : container.getKeys()) {
|
||||||
try {
|
BukkitPersistentDataTagType.getKeyDataType(container, key).ifPresent(dataType -> {
|
||||||
persistentDataMap.put(key.toString(), ArrayUtils.toObject(container.get(key, PersistentDataType.BYTE_ARRAY)));
|
final Object value = container.get(key, dataType.dataType);
|
||||||
} catch (IllegalArgumentException | NullPointerException ignored) {
|
if (value != null) {
|
||||||
}
|
persistentDataMap.put(key.toString(), new PersistentDataTag(dataType.name(), value));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return new PersistentDataContainerData(persistentDataMap);
|
return new PersistentDataContainerData(persistentDataMap);
|
||||||
}).exceptionally(throwable -> {
|
}).exceptionally(throwable -> {
|
||||||
BukkitHuskSync.getInstance().getLoggingAdapter().log(Level.WARNING, "Could not read " + player.getName() + "'s persistent data map, skipping!");
|
BukkitHuskSync.getInstance().getLoggingAdapter().log(Level.WARNING,
|
||||||
|
"Could not read " + player.getName() + "'s persistent data map, skipping!");
|
||||||
throwable.printStackTrace();
|
throwable.printStackTrace();
|
||||||
return new PersistentDataContainerData(new HashMap<>());
|
return new PersistentDataContainerData(new HashMap<>());
|
||||||
});
|
});
|
||||||
@@ -423,14 +425,48 @@ public class BukkitPlayer extends OnlineUser {
|
|||||||
return CompletableFuture.runAsync(() -> {
|
return CompletableFuture.runAsync(() -> {
|
||||||
player.getPersistentDataContainer().getKeys().forEach(namespacedKey ->
|
player.getPersistentDataContainer().getKeys().forEach(namespacedKey ->
|
||||||
player.getPersistentDataContainer().remove(namespacedKey));
|
player.getPersistentDataContainer().remove(namespacedKey));
|
||||||
persistentDataContainerData.persistentDataMap.keySet().forEach(keyString -> {
|
final Map<String, PersistentDataTag> dataMap = persistentDataContainerData.persistentDataMap;
|
||||||
|
dataMap.keySet().forEach(keyString -> {
|
||||||
final NamespacedKey key = NamespacedKey.fromString(keyString);
|
final NamespacedKey key = NamespacedKey.fromString(keyString);
|
||||||
if (key != null) {
|
if (key != null) {
|
||||||
final byte[] data = ArrayUtils.toPrimitive(persistentDataContainerData
|
// Set a tag with the given key and value. This is crying out for a refactor.
|
||||||
.persistentDataMap.get(keyString));
|
BukkitPersistentDataTagType.getDataType(dataMap.get(keyString).type).ifPresentOrElse(dataType -> {
|
||||||
player.getPersistentDataContainer().set(key, PersistentDataType.BYTE_ARRAY, data);
|
switch (dataType) {
|
||||||
|
case BYTE -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.BYTE, (byte) dataMap.get(keyString).value);
|
||||||
|
case SHORT -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.SHORT, (short) dataMap.get(keyString).value);
|
||||||
|
case INTEGER -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.INTEGER, (int) dataMap.get(keyString).value);
|
||||||
|
case LONG -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.LONG, (long) dataMap.get(keyString).value);
|
||||||
|
case FLOAT -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.FLOAT, (float) dataMap.get(keyString).value);
|
||||||
|
case DOUBLE -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.DOUBLE, (double) dataMap.get(keyString).value);
|
||||||
|
case STRING -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.STRING, (String) dataMap.get(keyString).value);
|
||||||
|
case BYTE_ARRAY -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.BYTE_ARRAY, (byte[]) dataMap.get(keyString).value);
|
||||||
|
case INTEGER_ARRAY -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.INTEGER_ARRAY, (int[]) dataMap.get(keyString).value);
|
||||||
|
case LONG_ARRAY -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.LONG_ARRAY, (long[]) dataMap.get(keyString).value);
|
||||||
|
case TAG_CONTAINER -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.TAG_CONTAINER, (PersistentDataContainer) dataMap.get(keyString).value);
|
||||||
|
case TAG_CONTAINER_ARRAY -> player.getPersistentDataContainer().set(key,
|
||||||
|
PersistentDataType.TAG_CONTAINER_ARRAY, (PersistentDataContainer[]) dataMap.get(keyString).value);
|
||||||
|
}
|
||||||
|
}, () -> BukkitHuskSync.getInstance().getLoggingAdapter().log(Level.WARNING,
|
||||||
|
"Could not set " + player.getName() + "'s persistent data key " + keyString +
|
||||||
|
" with the invalid type, " + dataMap.get(keyString).type + ". Skipping!"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
BukkitHuskSync.getInstance().getLoggingAdapter().log(Level.WARNING,
|
||||||
|
"Could not write " + player.getName() + "'s persistent data map, skipping!");
|
||||||
|
throwable.printStackTrace();
|
||||||
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ public class PersistentDataContainerData {
|
|||||||
* Map of namespaced key strings to a byte array representing the persistent data
|
* Map of namespaced key strings to a byte array representing the persistent data
|
||||||
*/
|
*/
|
||||||
@SerializedName("persistent_data_map")
|
@SerializedName("persistent_data_map")
|
||||||
public Map<String, Byte[]> persistentDataMap;
|
public Map<String, PersistentDataTag> persistentDataMap;
|
||||||
|
|
||||||
public PersistentDataContainerData(@NotNull final Map<String, Byte[]> persistentDataMap) {
|
public PersistentDataContainerData(@NotNull final Map<String, PersistentDataTag> persistentDataMap) {
|
||||||
this.persistentDataMap = persistentDataMap;
|
this.persistentDataMap = persistentDataMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package net.william278.husksync.data;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a persistent data tag set by a plugin.
|
||||||
|
*/
|
||||||
|
public class PersistentDataTag {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The enumerated primitive data type name value of the tag
|
||||||
|
*/
|
||||||
|
public String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the tag
|
||||||
|
*/
|
||||||
|
public Object value;
|
||||||
|
|
||||||
|
public PersistentDataTag(@NotNull String type, @NotNull Object value) {
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PersistentDataTag() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ public class UserData {
|
|||||||
* </p>
|
* </p>
|
||||||
* This value is to be incremented whenever the format changes.
|
* This value is to be incremented whenever the format changes.
|
||||||
*/
|
*/
|
||||||
public static final int CURRENT_FORMAT_VERSION = 1;
|
public static final int CURRENT_FORMAT_VERSION = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the user's status data, including health, food, etc.
|
* Stores the user's status data, including health, food, etc.
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8'
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
javaVersion=16
|
javaVersion=16
|
||||||
|
|
||||||
plugin_version=2.0.1
|
plugin_version=2.0.2
|
||||||
plugin_archive=husksync
|
plugin_archive=husksync
|
||||||
Reference in New Issue
Block a user