diff --git a/common/src/main/java/net/william278/husksync/data/DataSnapshot.java b/common/src/main/java/net/william278/husksync/data/DataSnapshot.java
index 9f6cf135..b2bb5cfa 100644
--- a/common/src/main/java/net/william278/husksync/data/DataSnapshot.java
+++ b/common/src/main/java/net/william278/husksync/data/DataSnapshot.java
@@ -23,10 +23,16 @@ import com.google.common.collect.Maps;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import de.themoep.minedown.adventure.MineDown;
+import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
import net.william278.desertwell.util.Version;
import net.william278.husksync.HuskSync;
import net.william278.husksync.adapter.Adaptable;
import net.william278.husksync.adapter.DataAdapter;
+import org.apache.commons.text.WordUtils;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,6 +47,7 @@ import java.util.stream.Collectors;
*
* @since 3.0
*/
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class DataSnapshot {
/*
@@ -59,7 +66,7 @@ public class DataSnapshot {
protected OffsetDateTime timestamp;
@SerializedName("save_cause")
- protected SaveCause saveCause;
+ protected String saveCause;
@SerializedName("server_name")
protected String serverName;
@@ -77,7 +84,7 @@ public class DataSnapshot {
protected Map data;
private DataSnapshot(@NotNull UUID id, boolean pinned, @NotNull OffsetDateTime timestamp,
- @NotNull SaveCause saveCause, @NotNull String serverName, @NotNull Map data,
+ @NotNull String saveCause, @NotNull String serverName, @NotNull Map data,
@NotNull Version minecraftVersion, @NotNull String platformType, int formatVersion) {
this.id = id;
this.pinned = pinned;
@@ -90,10 +97,6 @@ public class DataSnapshot {
this.formatVersion = formatVersion;
}
- @SuppressWarnings("unused")
- private DataSnapshot() {
- }
-
@NotNull
@ApiStatus.Internal
public static DataSnapshot.Builder builder(@NotNull HuskSync plugin) {
@@ -196,7 +199,7 @@ public class DataSnapshot {
*/
@NotNull
public SaveCause getSaveCause() {
- return saveCause;
+ return SaveCause.of(saveCause);
}
/**
@@ -219,7 +222,7 @@ public class DataSnapshot {
* @since 3.0
*/
public void setSaveCause(@NotNull SaveCause saveCause) {
- this.saveCause = saveCause;
+ this.saveCause = saveCause.name();
}
/**
@@ -270,24 +273,21 @@ public class DataSnapshot {
*
* @since 3.0
*/
+ @NoArgsConstructor(access = AccessLevel.PRIVATE)
public static class Packed extends DataSnapshot implements Adaptable {
protected Packed(@NotNull UUID id, boolean pinned, @NotNull OffsetDateTime timestamp,
- @NotNull SaveCause saveCause, @NotNull String serverName, @NotNull Map data,
+ @NotNull String saveCause, @NotNull String serverName, @NotNull Map data,
@NotNull Version minecraftVersion, @NotNull String platformType, int formatVersion) {
super(id, pinned, timestamp, saveCause, serverName, data, minecraftVersion, platformType, formatVersion);
}
- @SuppressWarnings("unused")
- private Packed() {
- }
-
@ApiStatus.Internal
public void edit(@NotNull HuskSync plugin, @NotNull Consumer editor) {
final Unpacked data = unpack(plugin);
editor.accept(data);
this.pinned = data.isPinned();
- this.saveCause = data.getSaveCause();
+ this.saveCause = data.getSaveCause().name();
this.data = data.serializeData(plugin);
}
@@ -341,7 +341,7 @@ public class DataSnapshot {
private final Map deserialized;
private Unpacked(@NotNull UUID id, boolean pinned, @NotNull OffsetDateTime timestamp,
- @NotNull SaveCause saveCause, @NotNull String serverName, @NotNull Map data,
+ @NotNull String saveCause, @NotNull String serverName, @NotNull Map data,
@NotNull Version minecraftVersion, @NotNull String platformType, int formatVersion,
@NotNull HuskSync plugin) {
super(id, pinned, timestamp, saveCause, serverName, data, minecraftVersion, platformType, formatVersion);
@@ -349,7 +349,7 @@ public class DataSnapshot {
}
private Unpacked(@NotNull UUID id, boolean pinned, @NotNull OffsetDateTime timestamp,
- @NotNull SaveCause saveCause, @NotNull String serverName, @NotNull Map data,
+ @NotNull String saveCause, @NotNull String serverName, @NotNull Map data,
@NotNull Version minecraftVersion, @NotNull String platformType, int formatVersion) {
super(id, pinned, timestamp, saveCause, serverName, Map.of(), minecraftVersion, platformType, formatVersion);
this.deserialized = data;
@@ -719,7 +719,7 @@ public class DataSnapshot {
id,
pinned || plugin.getSettings().getSynchronization().doAutoPin(saveCause),
timestamp,
- saveCause,
+ saveCause.name(),
serverName,
data,
plugin.getMinecraftVersion(),
@@ -742,138 +742,253 @@ public class DataSnapshot {
}
+ public interface Cause {
+
+ @NotNull
+ String name();
+
+ /**
+ * Returns the capitalized display name of the cause.
+ *
+ * @return the cause display name
+ */
+ @NotNull
+ default String getDisplayName() {
+ return WordUtils.capitalizeFully(name().replaceAll("_", " "));
+ }
+
+ }
+
/**
- * Identifies the cause of a player data save.
- *
- * @implNote This enum is saved in the database.
+ * A string wrapper, for identifying the cause of a player data save.
*
* Cause names have a max length of 32 characters.
*/
- public enum SaveCause {
+ @Accessors(fluent = true)
+ @Getter
+ @AllArgsConstructor(access = AccessLevel.PRIVATE)
+ public static class SaveCause implements Cause {
/**
* Indicates data saved when a player disconnected from the server (either to change servers, or to log off)
*
* @since 2.0
*/
- DISCONNECT,
+ public static final SaveCause DISCONNECT = of("DISCONNECT");
+
/**
* Indicates data saved when the world saved
*
* @since 2.0
*/
- WORLD_SAVE,
+ public static final SaveCause WORLD_SAVE = of("WORLD_SAVE");
+
/**
* Indicates data saved when the user died
*
* @since 2.1
*/
- DEATH,
+ public static final SaveCause DEATH = of("DEATH");
+
/**
* Indicates data saved when the server shut down
*
* @since 2.0
*/
- SERVER_SHUTDOWN,
+ public static final SaveCause SERVER_SHUTDOWN = of("SERVER_SHUTDOWN");
+
/**
* Indicates data was saved by editing inventory contents via the {@code /inventory} command
*
* @since 2.0
*/
- INVENTORY_COMMAND,
+ public static final SaveCause INVENTORY_COMMAND = of("INVENTORY_COMMAND");
+
/**
* Indicates data was saved by editing Ender Chest contents via the {@code /enderchest} command
*
* @since 2.0
*/
- ENDERCHEST_COMMAND,
+ public static final SaveCause ENDERCHEST_COMMAND = of("ENDERCHEST_COMMAND");
+
/**
* Indicates data was saved by restoring it from a previous version
*
* @since 2.0
*/
- BACKUP_RESTORE,
+ public static final SaveCause BACKUP_RESTORE = of("BACKUP_RESTORE");
+
/**
* Indicates data was saved by an API call
*
* @since 2.0
*/
- API,
+ public static final SaveCause API = of("API");
+
/**
* Indicates data was saved from being imported from MySQLPlayerDataBridge
*
* @since 2.0
*/
- MPDB_MIGRATION,
+ public static final SaveCause MPDB_MIGRATION = of("MPDB_MIGRATION");
+
/**
* Indicates data was saved from being imported from a legacy version (v1.x -> v2.x)
*
* @since 2.0
*/
- LEGACY_MIGRATION,
+ public static final SaveCause LEGACY_MIGRATION = of("LEGACY_MIGRATION");
+
/**
* Indicates data was saved from being imported from a legacy version (v2.x -> v3.x)
*
* @since 3.0
*/
- CONVERTED_FROM_V2;
+ public static final SaveCause CONVERTED_FROM_V2 = of("CONVERTED_FROM_V2");
@NotNull
- public String getDisplayName() {
- return name().toLowerCase(Locale.ENGLISH);
+ private final String name;
+
+ /**
+ * Get or create a {@link SaveCause} from a name
+ *
+ * @param name the name to be displayed
+ * @return the cause
+ */
+ @NotNull
+ public static SaveCause of(@NotNull String name) {
+ return new SaveCause(name.length() > 32 ? name.substring(0, 31) : name);
}
@NotNull
public String getLocale(@NotNull HuskSync plugin) {
- return plugin.getLocales().getRawLocale("save_cause_" + name().toLowerCase())
+ return plugin.getLocales()
+ .getRawLocale("save_cause_" + name().toLowerCase(Locale.ENGLISH))
.orElse(getDisplayName());
}
+
+ @NotNull
+ public static SaveCause[] values() {
+ return new SaveCause[]{
+ DISCONNECT, WORLD_SAVE, DEATH, SERVER_SHUTDOWN, INVENTORY_COMMAND, ENDERCHEST_COMMAND,
+ BACKUP_RESTORE, API, MPDB_MIGRATION, LEGACY_MIGRATION, CONVERTED_FROM_V2
+ };
+ }
}
/**
- * Represents the cause of a player having their data updated.
+ * A string wrapper, for identifying the cause of a player data update.
+ *
+ * Cause names have a max length of 32 characters.
*/
- public enum UpdateCause {
+ @Accessors(fluent = true)
+ @Getter
+ @AllArgsConstructor(access = AccessLevel.PRIVATE)
+ public static class UpdateCause implements Cause {
+
/**
* Indicates the data was updated by a synchronization process
*
* @since 3.0
*/
- SYNCHRONIZED("synchronization_complete", "synchronization_failed"),
+ public static final UpdateCause SYNCHRONIZED = of("SYNCHRONIZED",
+ "synchronization_complete", "synchronization_failed"
+ );
+
/**
* Indicates the data was updated by a user joining the server
*
* @since 3.0
*/
- NEW_USER("user_registration_complete", null),
+ public static final UpdateCause NEW_USER = of("NEW_USER",
+ "user_registration_complete", null
+ );
+
/**
* Indicates the data was updated by a data update process (management command, API, etc.)
*
* @since 3.0
*/
- UPDATED("data_update_complete", "data_update_failed");
+ public static final UpdateCause UPDATED = of("UPDATED",
+ "data_update_complete", "data_update_failed"
+ );
+
+ /**
+ * Indicates data was saved by an API call
+ *
+ * @since 3.3.3
+ */
+ public static final UpdateCause API = of("API");
- private final String completedLocale;
- private final String failureLocale;
+ @NotNull
+ private final String name;
+ @Nullable
+ private String completedLocale;
+ @Nullable
+ private String failureLocale;
+
+ /**
+ * Get or create a {@link UpdateCause} from a name and completed/failure locales
+ *
+ * @param name the name to be displayed
+ * @param completedLocale the locale to be displayed on successful update,
+ * or {@code null} if none is to be shown
+ * @param failureLocale the locale to be displayed on a failed update,
+ * or {@code null} if none is to be shown
+ * @return the cause
+ */
+ public static UpdateCause of(@NotNull String name, @Nullable String completedLocale,
+ @Nullable String failureLocale) {
+ return new UpdateCause(
+ name.length() > 32 ? name.substring(0, 31) : name,
+ completedLocale, failureLocale
+ );
+ }
- UpdateCause(@Nullable String completedLocale, @Nullable String failureLocale) {
- this.completedLocale = completedLocale;
- this.failureLocale = failureLocale;
+ /**
+ * Get or create a {@link UpdateCause} from a name
+ *
+ * @param name the name to be displayed
+ * @return the cause
+ */
+ @NotNull
+ public static UpdateCause of(@NotNull String name) {
+ return of(name, null, null);
}
+ /**
+ * Get the message to be displayed when a user's data is successfully updated.
+ *
+ * @param plugin plugin instance
+ * @return the message
+ */
public Optional getCompletedLocale(@NotNull HuskSync plugin) {
- if (completedLocale != null) {
- return plugin.getLocales().getLocale(completedLocale);
+ if (completedLocale() != null) {
+ return Optional.of(plugin.getLocales().getLocale(completedLocale())
+ .orElse(plugin.getLocales().format(getDisplayName())));
}
return Optional.empty();
}
+ /**
+ * Get the message to be displayed when a user's data fails to update.
+ *
+ * @param plugin plugin instance
+ * @return the message
+ */
public Optional getFailedLocale(@NotNull HuskSync plugin) {
- if (failureLocale != null) {
- return plugin.getLocales().getLocale(failureLocale);
+ if (failureLocale() != null) {
+ return Optional.of(plugin.getLocales().getLocale(failureLocale())
+ .orElse(plugin.getLocales().format(failureLocale())));
}
return Optional.empty();
}
+ @NotNull
+ public static UpdateCause[] values() {
+ return new UpdateCause[]{
+ SYNCHRONIZED, NEW_USER, UPDATED
+ };
+ }
}
}
diff --git a/gradle.properties b/gradle.properties
index 849c1fcd..3d8afa95 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,7 +3,7 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.daemon=true
javaVersion=17
-plugin_version=3.3.2
+plugin_version=3.3.3
plugin_archive=husksync
plugin_description=A modern, cross-server player data synchronization system