diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/api/entity/player/PlayerData.java b/extension/src/main/java/de/jeremystartm/pickshadow/api/entity/player/PlayerData.java index 86beb16..849bcfa 100644 --- a/extension/src/main/java/de/jeremystartm/pickshadow/api/entity/player/PlayerData.java +++ b/extension/src/main/java/de/jeremystartm/pickshadow/api/entity/player/PlayerData.java @@ -20,16 +20,27 @@ package de.jeremystartm.pickshadow.api.entity.player; +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.reflect.TypeToken; import de.jeremystartm.pickshadow.misc.TabListHandler; import de.staropensource.sosengine.base.logging.LoggerInstance; import fr.mrmicky.fastboard.adventure.FastBoard; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Map; +import java.util.UUID; + +import static java.util.Map.entry; + @Setter @Getter @SuppressWarnings({ "JavadocDeclaration" }) @@ -72,16 +83,97 @@ public final class PlayerData { @ApiStatus.Experimental private @NotNull FastBoard playerListScoreboard; + /** + * Contains when the player has + * first been seen on the server. + * + * @since v1-release0 + * -- GETTER -- + * Returns when the player has + * first been seen on the server. + * + * @return first played date and time + * @since v1-release0 + */ + private ZonedDateTime firstSeen; + /** * Creates and initializes an instance of this class. + *

+ * This constructor creates a completely + * new instance without any data. * * @param player {@link Player} to use * @since v1-release0 */ - PlayerData(Player player) { + PlayerData(@NotNull Player player) { this.player = player; this.logger = new LoggerInstance.Builder().setClazz(getClass()).setOrigin("PSSE").setMetadata(player.getName()).build(); //TabListHandler.getInstance().initializeTabList(this); + firstSeen = ZonedDateTime.now(); + } + + /** + * Creates and initializes an instance of this class. + *

+ * This constructor creates a new instance + * from already existing player data. + * + * @param player {@link Player} to use + * @param firstSeen when the player was first seen + * @since v1-release0 + */ + private PlayerData(@NotNull Player player, @NotNull ZonedDateTime firstSeen) { + this.player = player; + this.logger = new LoggerInstance.Builder().setClazz(getClass()).setOrigin("PSSE").setMetadata(player.getName()).build(); + + TabListHandler.getInstance().initializeTabList(this); + this.firstSeen = firstSeen; + } + + /** + * Deserializes a JSON object and creates + * a new {@link PlayerData} instance. + * + * @param jsonString JSON string + * @throws JsonSyntaxException on invalid JSON + * @throws RuntimeException on invalid PlayerData serialization + * @since v1-release0 + */ + public static @NotNull PlayerData fromJSON(@NotNull String jsonString) throws JsonSyntaxException, NullPointerException { + try { + Map<@NotNull String, @NotNull String> data = new Gson().fromJson(jsonString, new TypeToken>() { + }.getType()); + Player player = Bukkit.getPlayer(UUID.fromString(data.get("playerUUID"))); + + if (player == null) + throw new NullPointerException("Player is null"); + + return new PlayerData( + player, + ZonedDateTime.parse(data.get("firstPlayed")) + ); + } catch (Exception exception) { + if (exception instanceof JsonSyntaxException) + throw exception; + else + throw new RuntimeException("A conversion method failed", exception); + } + } + + /** + * Serializes this instance into a JSON object. + * + * @return serialized {@link PlayerData} instance in JSON + * @since v1-release0 + */ + public @NotNull String toJSON() { + return new Gson().toJson( + Map.ofEntries( + entry("playerUUID", player.getUniqueId().toString()), + entry("firstPlayed", firstSeen.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)) + ), + new TypeToken>(){}.getType()); } }