From a5d3015c6e967d63afc5197b3cd18e233b6a17fd Mon Sep 17 00:00:00 2001 From: William278 Date: Tue, 13 Feb 2024 16:23:33 +0000 Subject: [PATCH] feat: allow customizable save / update causes --- .../husksync/data/DataSnapshot.java | 213 ++++++++++++++---- gradle.properties | 2 +- 2 files changed, 165 insertions(+), 50 deletions(-) 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