diff --git a/gradle.properties b/gradle.properties index da10c9912..6cb218115 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ version = 1.20.4-R0.1-SNAPSHOT mcVersion = 1.20.4 -paperCommit = 7ac24a18940da12beb39a030113f6e459f348e2f +paperCommit = ba31f4128208e954d6648001724887352f71ece9 org.gradle.caching = true org.gradle.parallel = true diff --git a/patches/0004-Add-more-Player-API.patch b/patches/0004-Add-more-Player-API.patch index 3c576ded2..cc571bc61 100644 --- a/patches/0004-Add-more-Player-API.patch +++ b/patches/0004-Add-more-Player-API.patch @@ -77,8 +77,90 @@ index 7411f58f9f36beaadcc47c2264a4af313956ee03..201fe24d393beb8d0be4c4212aff5643 @NotNull @Override public HandlerList getHandlers() { +diff --git a/src/main/java/moe/caramel/daydream/event/player/AsyncPlayerDataPreLoadEvent.java b/src/main/java/moe/caramel/daydream/event/player/AsyncPlayerDataPreLoadEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..96b35864b50695c27f22005aa5581e5c2bc38735 +--- /dev/null ++++ b/src/main/java/moe/caramel/daydream/event/player/AsyncPlayerDataPreLoadEvent.java +@@ -0,0 +1,76 @@ ++package moe.caramel.daydream.event.player; ++ ++import com.destroystokyo.paper.profile.PlayerProfile; ++import com.mojang.authlib.GameProfile; ++import org.bukkit.event.Event; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.ApiStatus; ++import org.jetbrains.annotations.NotNull; ++import java.net.InetAddress; ++import java.util.UUID; ++ ++/** ++ * 비동기 플레이어 데이터 사전 로드 이벤트 ++ *

++ * {@link org.bukkit.event.player.AsyncPlayerPreLoginEvent} 호출 이후에 ++ * 플레이어의 {@link GameProfile}이 완성되면 호출됩니다. ++ *

++ */ ++public abstract class AsyncPlayerDataPreLoadEvent extends Event { ++ ++ private static final HandlerList HANDLER_LIST = new HandlerList(); ++ public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } ++ public static @NotNull HandlerList getHandlerList() { return HANDLER_LIST; } ++ ++ @ApiStatus.Internal ++ public AsyncPlayerDataPreLoadEvent() { ++ super(true); ++ } ++ ++ /** ++ * 플레이어의 프로필을 가져옵니다. ++ * ++ * @return 플레이어의 프로필 ++ */ ++ @NotNull ++ public abstract GameProfile getGameProfile(); ++ ++ /** ++ * 플레이어의 프로필을 가져옵니다. ++ * ++ * @deprecated 메서드를 호출할 때마다 새로운 프로필 미러가 생성됩니다. ++ * {@link #getGameProfile()}를 사용하세요. ++ * @return 플레이어의 프로필 ++ */ ++ @NotNull ++ @Deprecated ++ public abstract PlayerProfile getProfile(); ++ ++ /** ++ * 플레이어의 이름을 가져옵니다. ++ * ++ * @return 플레이어의 이름 ++ */ ++ @NotNull ++ public final String getName() { ++ return getGameProfile().getName(); ++ } ++ ++ /** ++ * 플레이어의 UUID를 가져옵니다. ++ * ++ * @return 플레이어의 UUID ++ */ ++ @NotNull ++ public final UUID getUniqueId() { ++ return getGameProfile().getId(); ++ } ++ ++ /** ++ * 플레이어의 IP 주소를 가져옵니다. ++ * ++ * @return 플레이어의 IP 주소 ++ */ ++ @NotNull ++ public abstract InetAddress getAddress(); ++} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index c6cb4f17469a8f2e60dd3e28d41402851ce5fb21..e95cb88e22b607e193bade4eadf635b4704d14e0 100644 +index d048ae07cc33fd77d128cc1ebf88b0804969fa3c..ecdef5d7376668f15cd5ef778cc86ba860748f6a 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1939,6 +1939,22 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM diff --git a/patches/0012-Add-more-Advancement-API.patch b/patches/0012-Add-more-Advancement-API.patch index 64b7ee95b..ee33743ae 100644 --- a/patches/0012-Add-more-Advancement-API.patch +++ b/patches/0012-Add-more-Advancement-API.patch @@ -373,6 +373,79 @@ index 0000000000000000000000000000000000000000..98cb796221c7bef250861a2f89e9ccf9 + @NotNull + AdvancementBuilder enableCount(final int count, final @NotNull JsonElement criterion); +} +diff --git a/src/main/java/moe/caramel/daydream/advancement/AdvancementFormat.java b/src/main/java/moe/caramel/daydream/advancement/AdvancementFormat.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d89f3ad6fcc5365a3234b26b6765352993e437f3 +--- /dev/null ++++ b/src/main/java/moe/caramel/daydream/advancement/AdvancementFormat.java +@@ -0,0 +1,67 @@ ++package moe.caramel.daydream.advancement; ++ ++import com.google.gson.JsonElement; ++import org.jetbrains.annotations.NotNull; ++import java.util.Objects; ++ ++/** ++ * 발전 과제 데이터 저장 포맷 ++ * ++ * @param 타입 ++ */ ++public final class AdvancementFormat { ++ ++ /** ++ * Json (기본) ++ */ ++ public static final AdvancementFormat JSON = new AdvancementFormat<>("json", false); ++ /** ++ * 압축된 Json ++ */ ++ public static final AdvancementFormat COMPRESSED_JSON = new AdvancementFormat<>("compressed_json", true); ++ /** ++ * NBT ++ */ ++ public static final AdvancementFormat NBT = new AdvancementFormat<>("nbt", false); ++ /** ++ * 압축된 NBT ++ */ ++ public static final AdvancementFormat COMPRESSED_NBT = new AdvancementFormat<>("compressed_nbt", true); ++ /** ++ * 진행도 맵 ++ */ ++ public static final AdvancementFormat PROGRESS_MAP = new AdvancementFormat<>("progress_map", false); ++ ++ private final String name; ++ private final boolean compressed; ++ ++ private AdvancementFormat(final @NotNull String name, final boolean compressed) { ++ this.name = name; ++ this.compressed = compressed; ++ } ++ ++ /** ++ * 요구하는 데이터 형식이 압축된 데이터 형식인지 확인합니다. ++ * ++ * @return 만약 {@code true}인 경우 압축된 데이터를 요구합니다 ++ */ ++ public boolean isCompressed() { ++ return compressed; ++ } ++ ++ @Override ++ public boolean equals(final Object o) { ++ if (this == o) { ++ return true; ++ } else if (o instanceof AdvancementFormat that) { ++ return (compressed == that.compressed) && Objects.equals(name, that.name); ++ } else { ++ return false; ++ } ++ } ++ ++ @Override ++ public int hashCode() { ++ return Objects.hash(name, compressed); ++ } ++} diff --git a/src/main/java/moe/caramel/daydream/advancement/AdvancementReward.java b/src/main/java/moe/caramel/daydream/advancement/AdvancementReward.java new file mode 100644 index 0000000000000000000000000000000000000000..74347bc8c9a45be1cb9af9fb41641e903f86b95f @@ -440,168 +513,366 @@ index 0000000000000000000000000000000000000000..74347bc8c9a45be1cb9af9fb41641e90 + @Nullable + NamespacedKey function(); +} -diff --git a/src/main/java/moe/caramel/daydream/advancement/AdvancementSaveFormat.java b/src/main/java/moe/caramel/daydream/advancement/AdvancementSaveFormat.java +diff --git a/src/main/java/moe/caramel/daydream/advancement/PlayerAdvancementData.java b/src/main/java/moe/caramel/daydream/advancement/PlayerAdvancementData.java new file mode 100644 -index 0000000000000000000000000000000000000000..f7924313d2e08cef47561f4470194193292a1be0 +index 0000000000000000000000000000000000000000..a1f319cbebde6a5476e9ac2b282ffc1ef9f4862d --- /dev/null -+++ b/src/main/java/moe/caramel/daydream/advancement/AdvancementSaveFormat.java -@@ -0,0 +1,60 @@ ++++ b/src/main/java/moe/caramel/daydream/advancement/PlayerAdvancementData.java +@@ -0,0 +1,56 @@ +package moe.caramel.daydream.advancement; + -+import com.google.gson.JsonElement; ++import moe.caramel.daydream.advancement.progress.CriterionProgress; ++import org.bukkit.NamespacedKey; +import org.jetbrains.annotations.NotNull; -+import java.util.Objects; ++import org.jetbrains.annotations.Nullable; ++import java.time.Instant; ++import java.util.Map; + +/** -+ * 발전 과제 저장 포맷 -+ * -+ * @param 타입 ++ * 플레이어 발전 과제 데이터 + */ -+public final class AdvancementSaveFormat { ++public interface PlayerAdvancementData { + + /** -+ * Json (기본) ++ * 새로운 진행도 맵을 생성합니다. ++ * ++ * @see #loadFromData(AdvancementFormat, Object) ++ * @return 진행도 맵 + */ -+ public static final AdvancementSaveFormat JSON = new AdvancementSaveFormat<>("json", false); ++ @NotNull ++ ProgressMap createProgressMap(); ++ + /** -+ * 압축된 Json ++ * 새로운 기준 진행도를 생성합니다. ++ * ++ * @see ProgressMap#newProgress(NamespacedKey, Map) ++ * @param obtainedTime 기준 달성 시간 ({@code null}인 경우 달성하지 않음) ++ * @return 기준 진행도 + */ -+ public static final AdvancementSaveFormat COMPRESSED_JSON = new AdvancementSaveFormat<>("compressed_json", true); ++ @NotNull ++ CriterionProgress createCriterionProgress(final @Nullable Instant obtainedTime); ++ + /** -+ * NBT ++ * 데이터에서 발전 과제 진행도를 로드합니다. ++ * ++ * @param format 발전 과제 데이터 저장 포맷 ++ * @param data 진행도 데이터 ++ * @param 데이터의 타입 ++ * @throws Exception 일부 데이터는 읽는 도중 예외가 던져질 수 있습니다. + */ -+ public static final AdvancementSaveFormat NBT = new AdvancementSaveFormat<>("nbt", false); ++ void loadFromData(final @NotNull AdvancementFormat format, final @NotNull T data) throws Exception; ++ + /** -+ * 압축된 NBT ++ * 발전 과제 진행도를 직렬화된 데이터로 변환합니다. ++ * ++ * @see moe.caramel.daydream.event.player.PlayerAdvancementSaveEvent#getData() ++ * @param format 발전 과제 데이터 저장 포맷 ++ * @param progress 진행도 데이터 ++ * @return 진행도 데이터 ++ * @param 데이터의 타입 ++ * @throws Exception 일부 데이터는 저장 도중 예외가 던져질 수 있습니다. + */ -+ public static final AdvancementSaveFormat COMPRESSED_NBT = new AdvancementSaveFormat<>("compressed_nbt", true); ++ @NotNull ++ T saveToData(final @NotNull AdvancementFormat format, final @NotNull ProgressMap progress) throws Exception; ++} +diff --git a/src/main/java/moe/caramel/daydream/advancement/ProgressMap.java b/src/main/java/moe/caramel/daydream/advancement/ProgressMap.java +new file mode 100644 +index 0000000000000000000000000000000000000000..ba50b933cfd0fc98cddb326317cdbc505083f233 +--- /dev/null ++++ b/src/main/java/moe/caramel/daydream/advancement/ProgressMap.java +@@ -0,0 +1,53 @@ ++package moe.caramel.daydream.advancement; + -+ private final String name; -+ private final boolean compressed; ++import moe.caramel.daydream.advancement.progress.CountableProgress; ++import moe.caramel.daydream.advancement.progress.CriterionProgress; ++import moe.caramel.daydream.advancement.progress.CriteriaProgress; ++import org.bukkit.NamespacedKey; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Nullable; ++import java.time.Instant; ++import java.util.Map; ++import java.util.function.BiConsumer; + -+ private AdvancementSaveFormat(final @NotNull String name, final boolean compressed) { -+ this.name = name; -+ this.compressed = compressed; -+ } ++/** ++ * 플레이어 발전 과제 진행도 맵 ++ */ ++public interface ProgressMap { + + /** -+ * 요구하는 데이터 형식이 압축된 데이터 형식인지 확인합니다. ++ * 진행도 맵의 데이터를 가져옵니다. + * -+ * @return 만약 {@code true}인 경우 압축된 데이터를 요구합니다 ++ * @return 수정할 수 없는 데이터 맵 + */ -+ public boolean isCompressed() { -+ return compressed; -+ } ++ @NotNull ++ Map getData(); + -+ @Override -+ public boolean equals(final Object o) { -+ if (this == o) return true; -+ if (o == null || getClass() != o.getClass()) return false; -+ final AdvancementSaveFormat that = (AdvancementSaveFormat) o; -+ return (compressed == that.compressed) && Objects.equals(name, that.name); -+ } ++ /** ++ * 진행도 맵에 대하여 반복을 실행합니다. ++ * ++ * @param action 수행할 작업 ++ */ ++ void iterator(final @NotNull BiConsumer action); + -+ @Override -+ public int hashCode() { -+ return Objects.hash(name, compressed); -+ } ++ /** ++ * 주어진 발전 과제에 대하여 새로운 진행도를 생성하고 추가합니다. ++ * ++ * @param key 대상 발전 과제의 키 ++ * @param criteria 기준 달성 목록 ++ * @return 생성된 진행도 ++ */ ++ @NotNull ++ CriteriaProgress newProgress(final @NotNull NamespacedKey key, final @NotNull Map criteria); ++ ++ /** ++ * 주어진 발전 과제에 대하여 새로운 카운트 형식의 진행도를 생성하고 추가합니다. ++ * ++ * @param key 대상 발전 과제의 키 ++ * @param currentCount 현재 카운트 ++ * @param obtainedTime 기준 달성 시간 ({@code null}인 경우 달성하지 않음) ++ * @return 생성된 카운트 형식의 진행도 ++ */ ++ @NotNull ++ CountableProgress newCountProgress(final @NotNull NamespacedKey key, final int currentCount, final @Nullable Instant obtainedTime); ++} +diff --git a/src/main/java/moe/caramel/daydream/advancement/progress/CountableProgress.java b/src/main/java/moe/caramel/daydream/advancement/progress/CountableProgress.java +new file mode 100644 +index 0000000000000000000000000000000000000000..2a26693dc8161dec6e94f8c26e9baec2b8ee0e18 +--- /dev/null ++++ b/src/main/java/moe/caramel/daydream/advancement/progress/CountableProgress.java +@@ -0,0 +1,14 @@ ++package moe.caramel.daydream.advancement.progress; ++ ++/** ++ * 카운트 형식의 발전 과제 진행도 ++ */ ++public interface CountableProgress extends CriteriaProgress { ++ ++ /** ++ * 현재 카운트를 가져옵니다. ++ * ++ * @return 현재 카운트 ++ */ ++ int getCurrentCount(); ++} +diff --git a/src/main/java/moe/caramel/daydream/advancement/progress/CriteriaProgress.java b/src/main/java/moe/caramel/daydream/advancement/progress/CriteriaProgress.java +new file mode 100644 +index 0000000000000000000000000000000000000000..da5f54828cd0ad73e74c78550415811016bc6b90 +--- /dev/null ++++ b/src/main/java/moe/caramel/daydream/advancement/progress/CriteriaProgress.java +@@ -0,0 +1,18 @@ ++package moe.caramel.daydream.advancement.progress; ++ ++/** ++ * 발전 과제 진행도 ({@link CriterionProgress}의 집합) ++ *

++ * {@link org.bukkit.advancement.AdvancementProgress}와 동일하지만 ++ * NMS를 직접 래핑하므로 제한된 작업만 가능합니다. ++ *

++ */ ++public interface CriteriaProgress { ++ ++ /** ++ * 발전 과제를 달성했는지 여부를 가져옵니다. ++ * ++ * @return 발전 과제 달성 여부 ++ */ ++ boolean isProgressDone(); +} +diff --git a/src/main/java/moe/caramel/daydream/advancement/progress/CriterionProgress.java b/src/main/java/moe/caramel/daydream/advancement/progress/CriterionProgress.java +new file mode 100644 +index 0000000000000000000000000000000000000000..56100df41aa947444cdb16b015ab5a91024b257d +--- /dev/null ++++ b/src/main/java/moe/caramel/daydream/advancement/progress/CriterionProgress.java +@@ -0,0 +1,37 @@ ++package moe.caramel.daydream.advancement.progress; ++ ++import org.jetbrains.annotations.Nullable; ++import java.time.Instant; ++ ++/** ++ * 기준 진행도 ++ * ++ * @see CriteriaProgress ++ */ ++public interface CriterionProgress { ++ ++ /** ++ * 기준을 달성했는지 여부를 가져옵니다. ++ * ++ * @return 기준 달성 여부 ++ */ ++ boolean isProgressDone(); ++ ++ /** ++ * 기준을 달성한 것으로 변경합니다. ++ */ ++ void setGrant(); ++ ++ /** ++ * 기준을 달성하지 않은 것으로 변경합니다. ++ */ ++ void setRevoke(); ++ ++ /** ++ * 기준의 달성 시간을 가져옵니다. ++ * ++ * @return 기준 달성 시간 ++ */ ++ @Nullable ++ Instant getObtainedTime(); ++} +diff --git a/src/main/java/moe/caramel/daydream/event/player/AsyncPlayerDataPreLoadEvent.java b/src/main/java/moe/caramel/daydream/event/player/AsyncPlayerDataPreLoadEvent.java +index 96b35864b50695c27f22005aa5581e5c2bc38735..c3a9f5dff5ddf53d5070b429eb9dfad45fd0c193 100644 +--- a/src/main/java/moe/caramel/daydream/event/player/AsyncPlayerDataPreLoadEvent.java ++++ b/src/main/java/moe/caramel/daydream/event/player/AsyncPlayerDataPreLoadEvent.java +@@ -73,4 +73,18 @@ public abstract class AsyncPlayerDataPreLoadEvent extends Event { + */ + @NotNull + public abstract InetAddress getAddress(); ++ ++ // Daydream start - Add more Advancement API ++ /** ++ * 플레이어 발전 과제 데이터를 생성하고 가져옵니다. ++ *

++ * 플레이어의 로그인이 완료되기 전에 생성되기에 중복 로그인으로 ++ * 인한 데이터 증발 등 데이터 관리에 주의해주세요. ++ *

++ * ++ * @return 플레이어 발전 과제 데이터 (이미 생성된 경우 기존의 인스턴스를 가져옴) ++ */ ++ @NotNull ++ public abstract moe.caramel.daydream.advancement.PlayerAdvancementData createAndGetAdvancements(); ++ // Daydream end - Add more Advancement API + } diff --git a/src/main/java/moe/caramel/daydream/event/player/PlayerAdvancementPreLoadEvent.java b/src/main/java/moe/caramel/daydream/event/player/PlayerAdvancementPreLoadEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..21bbda2d1fae053aa5734652c5670a74b6e1d06c +index 0000000000000000000000000000000000000000..c4be6c058e86cde01fbd2d84d6cc3d8c548abd65 --- /dev/null +++ b/src/main/java/moe/caramel/daydream/event/player/PlayerAdvancementPreLoadEvent.java -@@ -0,0 +1,81 @@ +@@ -0,0 +1,114 @@ +package moe.caramel.daydream.event.player; + -+import com.google.gson.JsonElement; ++import moe.caramel.daydream.advancement.AdvancementFormat; ++import moe.caramel.daydream.advancement.PlayerAdvancementData; ++import moe.caramel.daydream.advancement.ProgressMap; ++import moe.caramel.daydream.advancement.progress.CriterionProgress; +import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; -+import java.util.ArrayList; -+import java.util.List; ++import org.jetbrains.annotations.Nullable; ++import java.time.Instant; + +/** + * 플레이어의 발전 과제 데이터를 로드하기 직전에 호출됩니다. -+ *

일반적으로 {@link org.bukkit.event.player.PlayerJoinEvent} 이전에 호출됩니다.

-+ * -+ * @param 타입 ++ *

++ * 일반적으로 {@link org.bukkit.event.player.PlayerJoinEvent} 이전에 호출됩니다. ++ *

+ */ -+public sealed class PlayerAdvancementPreLoadEvent extends PlayerEvent { ++public final class PlayerAdvancementPreLoadEvent extends PlayerEvent implements Cancellable, PlayerAdvancementData { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } + public static @NotNull HandlerList getHandlerList() { return HANDLER_LIST; } + -+ private final boolean compressed; -+ private List data; ++ private final PlayerAdvancementData provider; ++ private final Reason reason; ++ private boolean cancelled; + + @ApiStatus.Internal -+ public PlayerAdvancementPreLoadEvent(final @NotNull Player who, final boolean compressed) { ++ public PlayerAdvancementPreLoadEvent(final @NotNull Player who, final @NotNull PlayerAdvancementData provider, final @NotNull Reason reason) { + super(who); -+ this.compressed = compressed; -+ this.data = new ArrayList<>(); ++ this.provider = provider; ++ this.reason = reason; + } + + /** -+ * 요구하는 데이터 형식이 압축된 데이터 형식인지 확인합니다. ++ * 플레이어 발전 과제 데이터를 가져옵니다. + * -+ * @return 만약 {@code true}인 경우 압축된 데이터를 요구합니다 ++ * @return 플레이어 발전 과제 데이터 + */ -+ public boolean isCompressed() { -+ return compressed; ++ @NotNull ++ public PlayerAdvancementData getData() { ++ return provider; + } + + /** -+ * 로드할 발전 과제 데이터를 가져옵니다. ++ * 이벤트 호출 사유를 가져옵니다. + * -+ * @return 발전 과제 데이터 ++ * @return 이벤트 호출 사유 + */ + @NotNull -+ public List getReplaceData() { -+ return data; ++ public Reason getReason() { ++ return reason; + } + + /** -+ * 로드할 발전 과제 데이터를 설정합니다. ++ * 발전 과제 데이터를 파일에서 읽어오는 바닐라 동작을 취소할지 여부를 가져옵니다. + * -+ * @param data 발전 과제 데이터 ++ * @return 바닐라 동작 취소 여부 + */ -+ public void addReplaceData(final @NotNull T data) { -+ this.data.add(data); ++ @Override ++ public boolean isCancelled() { ++ return cancelled; + } + + /** -+ * 서버가 Json 형식으로 데이터를 저장하는 경우 ++ * 발전 과제 데이터를 파일에서 읽어오는 바닐라 동작을 취소할지 여부를 결정합니다. ++ * ++ * @param cancel 바닐라 동작 취소 여부 + */ -+ public static final class Json extends PlayerAdvancementPreLoadEvent { -+ -+ public Json(final @NotNull Player who, final boolean compressed) { -+ super(who, compressed); -+ } ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; + } + + /** -+ * 서버가 Json 형식으로 데이터를 저장하는 경우 ++ * 이벤트 호출 사유 + */ -+ public static final class Nbt extends PlayerAdvancementPreLoadEvent { ++ public enum Reason { ++ /** ++ * 플레이어 접속 ++ */ ++ PLAYER_JOIN, ++ /** ++ * 서버 리소스 리로드 ++ */ ++ SERVER_RESOURCE_RELOAD ++ } + -+ public Nbt(final @NotNull Player who, final boolean compressed) { -+ super(who, compressed); -+ } ++ // =========================== (Provider wrapper) ++ ++ @Override ++ public @NotNull ProgressMap createProgressMap() { ++ return provider.createProgressMap(); ++ } ++ ++ @Override ++ public @NotNull CriterionProgress createCriterionProgress(final @Nullable Instant obtainedTime) { ++ return provider.createCriterionProgress(obtainedTime); ++ } ++ ++ @Override ++ public void loadFromData(final @NotNull AdvancementFormat format, final @NotNull T data) throws Exception { ++ this.provider.loadFromData(format, data); ++ } ++ ++ @Override ++ public @NotNull T saveToData(final @NotNull AdvancementFormat format, final @NotNull ProgressMap progress) throws Exception { ++ return provider.saveToData(format, progress); + } +} diff --git a/src/main/java/moe/caramel/daydream/event/player/PlayerAdvancementSaveEvent.java b/src/main/java/moe/caramel/daydream/event/player/PlayerAdvancementSaveEvent.java new file mode 100644 -index 0000000000000000000000000000000000000000..81cf8963c7a1ec67fb0368c2f457a3a77561b589 +index 0000000000000000000000000000000000000000..f8eb1cb00a070733a9ee2d7b3dc2ea73ebd63880 --- /dev/null +++ b/src/main/java/moe/caramel/daydream/event/player/PlayerAdvancementSaveEvent.java -@@ -0,0 +1,95 @@ +@@ -0,0 +1,72 @@ +package moe.caramel.daydream.event.player; + -+import com.google.gson.JsonElement; ++import moe.caramel.daydream.advancement.ProgressMap; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; @@ -612,26 +883,22 @@ index 0000000000000000000000000000000000000000..81cf8963c7a1ec67fb0368c2f457a3a7 + +/** + * 플레이어 발전 과제 데이터가 저장될 때 호출됩니다. -+ * -+ * @param 타입 + */ -+public sealed class PlayerAdvancementSaveEvent extends PlayerEvent implements Cancellable { ++public final class PlayerAdvancementSaveEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } + public static @NotNull HandlerList getHandlerList() { return HANDLER_LIST; } + + private final NamespacedKey section; -+ private final T data; -+ private final boolean compressed; ++ private final ProgressMap progress; + private boolean cancelled; + + @ApiStatus.Internal -+ public PlayerAdvancementSaveEvent(final @NotNull Player who, final @NotNull NamespacedKey section, final @NotNull T data, final boolean compressed) { ++ public PlayerAdvancementSaveEvent(final @NotNull Player who, final @NotNull NamespacedKey section, final @NotNull ProgressMap progress) { + super(who); + this.section = section; -+ this.data = data; -+ this.compressed = compressed; ++ this.progress = progress; + } + + /** @@ -646,52 +913,33 @@ index 0000000000000000000000000000000000000000..81cf8963c7a1ec67fb0368c2f457a3a7 + } + + /** -+ * 요구하는 데이터 형식이 압축된 데이터 형식인지 확인합니다. -+ * -+ * @return 만약 {@code true}인 경우 압축된 데이터를 요구합니다 -+ */ -+ public boolean isCompressed() { -+ return compressed; -+ } -+ -+ @Override -+ public boolean isCancelled() { -+ return this.cancelled; -+ } -+ -+ @Override -+ public void setCancelled(final boolean cancel) { -+ this.cancelled = cancel; -+ } -+ -+ /** + * 저장될 발전 과제 데이터를 가져옵니다. + * + * @return 발전 과제 데이터 + */ + @NotNull -+ public T getData() { -+ return data; ++ public ProgressMap getData() { ++ return progress; + } + + /** -+ * 서버가 Json 형식으로 데이터를 저장하는 경우 ++ * 발전 과제 데이터를 파일에 저장하는 바닐라 동작을 취소할지 여부를 가져옵니다. ++ * ++ * @return 바닐라 동작 취소 여부 + */ -+ public static final class Json extends PlayerAdvancementSaveEvent { -+ -+ public Json(final @NotNull Player who, final @NotNull NamespacedKey section, final @NotNull JsonElement json, final boolean compressed) { -+ super(who, section, json, compressed); -+ } ++ @Override ++ public boolean isCancelled() { ++ return this.cancelled; + } + + /** -+ * 서버가 Json 형식으로 데이터를 저장하는 경우 ++ * 발전 과제 데이터를 파일에 저장하는 바닐라 동작을 취소할지 여부를 결정합니다. ++ * ++ * @param cancel 바닐라 동작 취소 여부 + */ -+ public static final class Nbt extends PlayerAdvancementSaveEvent { -+ -+ public Nbt(final @NotNull Player who, final @NotNull NamespacedKey section, final @NotNull byte[] nbt, final boolean compressed) { -+ super(who, section, nbt, compressed); -+ } ++ @Override ++ public void setCancelled(final boolean cancel) { ++ this.cancelled = cancel; + } +} diff --git a/src/main/java/moe/caramel/daydream/event/player/PlayerAdvancementScreenEvent.java b/src/main/java/moe/caramel/daydream/event/player/PlayerAdvancementScreenEvent.java @@ -1101,7 +1349,7 @@ index f9bc179da071e7bd57cefc50d6763317fb643b74..3b1b55977d94de338f536896babedc7e + // Daydream end - Add more Advancement API } diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index e8d57cd3373c84853d5adcacdf97eec8aa245a71..573a858d16ba64467f7734752a6ba3461e07bee2 100644 +index acee4f659f0657ccb09514c64b08e86c7abe23fb..e4d8a2bb70efe374d9fe59aaae816e5d687a0e84 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -3195,6 +3195,38 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM @@ -1117,7 +1365,7 @@ index e8d57cd3373c84853d5adcacdf97eec8aa245a71..573a858d16ba64467f7734752a6ba346 + * @param 데이터 타입 + */ + @NotNull -+ public T serializeAdvancementProgress(@NotNull moe.caramel.daydream.advancement.AdvancementSaveFormat format); ++ public T serializeAdvancementProgress(@NotNull moe.caramel.daydream.advancement.AdvancementFormat format); + + /** + * 플레이어의 직렬화된 발전 과제 데이터를 가져옵니다. @@ -1128,7 +1376,7 @@ index e8d57cd3373c84853d5adcacdf97eec8aa245a71..573a858d16ba64467f7734752a6ba346 + * @param 데이터 타입 + */ + @NotNull -+ public T serializeAdvancementProgress(@NotNull moe.caramel.daydream.advancement.AdvancementSaveFormat format, @NotNull org.bukkit.NamespacedKey saveSection); ++ public T serializeAdvancementProgress(@NotNull moe.caramel.daydream.advancement.AdvancementFormat format, @NotNull org.bukkit.NamespacedKey saveSection); + + /** + * 플레이어에게 발전 과제 알림을 전송합니다.