diff --git a/base/color/pom.xml b/base/color/pom.xml index 6c7ecfe..fde67dd 100644 --- a/base/color/pom.xml +++ b/base/color/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyplugin-parent - 1.5.12 + 1.5.13 ../../pom.xml diff --git a/base/command-alias/pom.xml b/base/command-alias/pom.xml index d0675fd..757239a 100644 --- a/base/command-alias/pom.xml +++ b/base/command-alias/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyplugin-parent - 1.5.12 + 1.5.13 ../../pom.xml diff --git a/base/command/pom.xml b/base/command/pom.xml index a6187a1..7910f07 100644 --- a/base/command/pom.xml +++ b/base/command/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/base/gui/pom.xml b/base/gui/pom.xml index 183eec0..74df82a 100644 --- a/base/gui/pom.xml +++ b/base/gui/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/base/gui/src/test/java/PageTest.java b/base/gui/src/test/java/PageTest.java new file mode 100644 index 0000000..d20a8a8 --- /dev/null +++ b/base/gui/src/test/java/PageTest.java @@ -0,0 +1,21 @@ +import org.junit.Test; + +public class PageTest { + + + @Test + public void test() { + System.out.println(maxPage(0, 10)); + System.out.println(maxPage(10, 10)); + System.out.println(maxPage(5, 10)); + System.out.println(maxPage(15, 10)); + System.out.println(maxPage(19, 10)); + System.out.println(maxPage(20, 10)); + + } + + int maxPage(int contents, int size) { + if (contents == 0 || size == 0) return 1; + return (contents / size) + ((contents % size) == 0 ? 0 : 1); + } +} diff --git a/base/main/pom.xml b/base/main/pom.xml index be7b5a1..f75994e 100644 --- a/base/main/pom.xml +++ b/base/main/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/base/messages/pom.xml b/base/messages/pom.xml index bba3b8d..388984e 100644 --- a/base/messages/pom.xml +++ b/base/messages/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyplugin-parent - 1.5.12 + 1.5.13 ../../pom.xml diff --git a/base/storage/pom.xml b/base/storage/pom.xml index 5cf812b..1eb1fe2 100644 --- a/base/storage/pom.xml +++ b/base/storage/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/base/user/pom.xml b/base/user/pom.xml index 4911834..a7d36c2 100644 --- a/base/user/pom.xml +++ b/base/user/pom.xml @@ -6,7 +6,7 @@ cc.carm.lib easyplugin-parent - 1.5.12 + 1.5.13 ../../pom.xml diff --git a/base/user/src/main/java/cc/carm/lib/easyplugin/user/AbstractUserData.java b/base/user/src/main/java/cc/carm/lib/easyplugin/user/AbstractUserData.java new file mode 100644 index 0000000..ad00b6c --- /dev/null +++ b/base/user/src/main/java/cc/carm/lib/easyplugin/user/AbstractUserData.java @@ -0,0 +1,47 @@ +package cc.carm.lib.easyplugin.user; + +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public abstract class AbstractUserData implements UserData { + + protected final @NotNull K key; + + /** + * Used to mark the data as dropping (save and unload) status. + */ + protected boolean dropping = false; + + protected AbstractUserData(@NotNull K key) { + this.key = key; + } + + /** + * @param dropping true if the data is dropping, false otherwise + */ + public void setDropping(boolean dropping) { + this.dropping = dropping; + } + + /** + * @return true if the data is dropping, false otherwise + */ + public boolean isDropping() { + return dropping; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AbstractUserData abstractUserData = (AbstractUserData) o; + return key.equals(abstractUserData.key); + } + + @Override + public int hashCode() { + return Objects.hash(key); + } + +} diff --git a/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserData.java b/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserData.java index 0589902..a704fc2 100644 --- a/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserData.java +++ b/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserData.java @@ -2,31 +2,22 @@ package cc.carm.lib.easyplugin.user; import org.jetbrains.annotations.NotNull; -import java.util.Objects; +public interface UserData { -public abstract class UserData { + @NotNull K key(); - protected final @NotNull K key; - - protected UserData(@NotNull K key) { - this.key = key; + @Deprecated + default @NotNull K getKey() { + return key(); } - public @NotNull K getKey() { - return key; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - UserData userData = (UserData) o; - return key.equals(userData.key); - } - - @Override - public int hashCode() { - return Objects.hash(key); - } + /** + * @param dropping true if the data is dropping, false otherwise + */ + void setDropping(boolean dropping); + /** + * @return true if the data is dropping, false otherwise + */ + boolean isDropping(); } diff --git a/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserDataManager.java b/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserDataManager.java index 3ee304f..8ff94d4 100644 --- a/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserDataManager.java +++ b/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserDataManager.java @@ -1,15 +1,12 @@ package cc.carm.lib.easyplugin.user; import cc.carm.lib.easyplugin.EasyPlugin; -import com.google.common.collect.ImmutableSet; -import org.bukkit.Bukkit; -import org.bukkit.OfflinePlayer; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; @@ -21,7 +18,7 @@ import java.util.function.Supplier; import java.util.logging.Logger; import java.util.stream.Collectors; -public abstract class UserDataManager> { +public abstract class UserDataManager> implements UserDataRegistry { protected final @NotNull EasyPlugin plugin; @@ -47,6 +44,7 @@ public abstract class UserDataManager> { this.dataCache = cacheMap; } + @Override public void shutdown() { this.executor.shutdown(); } @@ -55,14 +53,11 @@ public abstract class UserDataManager> { return plugin; } - protected @NotNull Logger getLogger() { + @Override + public @NotNull Logger getLogger() { return getPlugin().getLogger(); } - public String serializeKey(@NotNull K key) { - return key.toString(); - } - public abstract @NotNull U emptyUser(@NotNull K key); public @NotNull U errorUser(@NotNull K key) { @@ -73,36 +68,16 @@ public abstract class UserDataManager> { protected abstract void saveData(@NotNull U data) throws Exception; - public @NotNull CompletableFuture load(@NotNull K key) { - return load(key, false); - } - - public @NotNull CompletableFuture load(@NotNull K key, boolean cache) { - return load(key, () -> cache); - } - public @NotNull Map getDataCache() { return dataCache; } - @Unmodifiable - public @NotNull Set list() { - return ImmutableSet.copyOf(getDataCache().values()); - } - - public @NotNull U get(@NotNull K key) { - return Optional.ofNullable(getNullable(key)).orElseThrow(() -> new NullPointerException("User " + key + " not found.")); - } - - public @Nullable U getNullable(@NotNull K key) { - return getDataCache().get(key); - } - - public @NotNull Optional<@Nullable U> getOptional(@NotNull K key) { - return Optional.ofNullable(getNullable(key)); - } - + @Override public @NotNull CompletableFuture load(@NotNull K key, @NotNull Supplier cacheCondition) { + U cached = getNullable(key); + if (cached != null) { + return CompletableFuture.supplyAsync(() -> cached); // Return cached data async. + } return CompletableFuture.supplyAsync(() -> { String identifier = serializeKey(key); @@ -124,11 +99,12 @@ public abstract class UserDataManager> { } }, executor).thenApply((data) -> { - if (cacheCondition.get()) dataCache.put(key, data); + if (cacheCondition.get() && !data.isDropping()) dataCache.put(key, data); return data; }); } + @Override public @NotNull CompletableFuture save(@NotNull U user) { return CompletableFuture.supplyAsync(() -> { String identifier = serializeKey(user.getKey()); @@ -148,17 +124,18 @@ public abstract class UserDataManager> { }, executor); } - public @NotNull CompletableFuture unload(@NotNull K key) { - return unload(key, true); - } - + @Override public @NotNull CompletableFuture unload(@NotNull K key, boolean save) { U data = getNullable(key); if (data == null) return CompletableFuture.completedFuture(false); - + data.setDropping(true); // Mark the data as unloading. if (save) { return save(data).thenApply(result -> { - this.dataCache.remove(key); + // Check if the data is still unloading, + // which cloud be interrupted by the next load. + if (data.isDropping()) { + this.dataCache.remove(key); + } return result; }); } else { @@ -168,6 +145,7 @@ public abstract class UserDataManager> { } + @Override public @NotNull CompletableFuture modify(@NotNull K key, @NotNull Consumer consumer) { U cached = getNullable(key); if (cached != null) { @@ -176,13 +154,14 @@ public abstract class UserDataManager> { return true; }, executor); } else { - return load(key, false).thenApply((data) -> { + return load(key, true).thenApply((data) -> { consumer.accept(data); return data; - }).thenCompose(this::save); + }).thenCompose(data -> unload(key, true)); } } + @Override public @NotNull CompletableFuture peek(@NotNull K key, @NotNull Function function) { U cached = getNullable(key); if (cached != null) { @@ -192,10 +171,6 @@ public abstract class UserDataManager> { } } - public @NotNull CompletableFuture> loadOnline(@NotNull Function function) { - return loadGroup(Bukkit.getOnlinePlayers(), function, OfflinePlayer::isOnline); - } - public @NotNull CompletableFuture> loadGroup(@NotNull Collection users, @NotNull Function function, @NotNull Predicate cacheCondition) { @@ -218,15 +193,7 @@ public abstract class UserDataManager> { return task.thenApply(Collections::unmodifiableMap); } - public @NotNull CompletableFuture> loadGroup(@NotNull Collection allKeys, - @NotNull Predicate cacheCondition) { - return loadGroup(allKeys, Function.identity(), cacheCondition); - } - - public @NotNull CompletableFuture> loadGroup(@NotNull Collection allKeys) { - return loadGroup(allKeys, (v) -> false); - } - + @Override public void saveAll() { if (getDataCache().isEmpty()) return; for (U u : getDataCache().values()) { @@ -239,6 +206,7 @@ public abstract class UserDataManager> { } } + @Override public int unloadAll(boolean save) { if (save) saveAll(); int size = getDataCache().size(); diff --git a/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserDataRegistry.java b/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserDataRegistry.java new file mode 100644 index 0000000..9d5734d --- /dev/null +++ b/base/user/src/main/java/cc/carm/lib/easyplugin/user/UserDataRegistry.java @@ -0,0 +1,95 @@ +package cc.carm.lib.easyplugin.user; + +import com.google.common.collect.ImmutableSet; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.logging.Logger; + +public interface UserDataRegistry> { + + void shutdown(); + + @NotNull Logger getLogger(); + + + @NotNull Map cache(); + + default String serializeKey(@NotNull K key) { + return key.toString(); + } + + default @NotNull CompletableFuture load(@NotNull K key) { + return load(key, false); + } + + default @NotNull CompletableFuture load(@NotNull K key, boolean cache) { + return load(key, () -> cache); + } + + + @Unmodifiable + default @NotNull Set list() { + return ImmutableSet.copyOf(cache().values()); + } + + default @NotNull U get(@NotNull K key) { + return Optional.ofNullable(getNullable(key)).orElseThrow(() -> new NullPointerException("User " + key + " not found.")); + } + + default @Nullable U getNullable(@NotNull K key) { + return cache().get(key); + } + + default @NotNull Optional<@Nullable U> getOptional(@NotNull K key) { + return Optional.ofNullable(getNullable(key)); + } + + @NotNull CompletableFuture load(@NotNull K key, @NotNull Supplier cacheCondition); + + @NotNull CompletableFuture save(@NotNull U user); + + default @NotNull CompletableFuture unload(@NotNull K key) { + return unload(key, true); + } + + @NotNull CompletableFuture unload(@NotNull K key, boolean save); + + @NotNull CompletableFuture modify(@NotNull K key, @NotNull Consumer consumer); + + @NotNull CompletableFuture peek(@NotNull K key, @NotNull Function function); + + default @NotNull CompletableFuture> loadOnline(@NotNull Function function) { + return loadGroup(Bukkit.getOnlinePlayers(), function, OfflinePlayer::isOnline); + } + + @NotNull CompletableFuture> loadGroup(@NotNull Collection users, + @NotNull Function function, + @NotNull Predicate cacheCondition); + + default @NotNull CompletableFuture> loadGroup(@NotNull Collection allKeys, + @NotNull Predicate cacheCondition) { + return loadGroup(allKeys, Function.identity(), cacheCondition); + } + + default @NotNull CompletableFuture> loadGroup(@NotNull Collection allKeys) { + return loadGroup(allKeys, (v) -> false); + } + + void saveAll(); + + int unloadAll(boolean save); +} diff --git a/base/utils/pom.xml b/base/utils/pom.xml index 9f620d3..53eec5d 100644 --- a/base/utils/pom.xml +++ b/base/utils/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/collection/all/pom.xml b/collection/all/pom.xml index 51ae26f..82b4f25 100644 --- a/collection/all/pom.xml +++ b/collection/all/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/collection/bom/pom.xml b/collection/bom/pom.xml index f86a5e0..0995f40 100644 --- a/collection/bom/pom.xml +++ b/collection/bom/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/collection/common/pom.xml b/collection/common/pom.xml index 2b7f711..d18a475 100644 --- a/collection/common/pom.xml +++ b/collection/common/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/extension/gh-checker/pom.xml b/extension/gh-checker/pom.xml index d89893d..9157aab 100644 --- a/extension/gh-checker/pom.xml +++ b/extension/gh-checker/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/extension/papi/pom.xml b/extension/papi/pom.xml index 86c7376..0ddc754 100644 --- a/extension/papi/pom.xml +++ b/extension/papi/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/extension/vault/pom.xml b/extension/vault/pom.xml index 3fd1cde..c814e21 100644 --- a/extension/vault/pom.xml +++ b/extension/vault/pom.xml @@ -5,7 +5,7 @@ easyplugin-parent cc.carm.lib - 1.5.12 + 1.5.13 ../../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index 495f195..6271dc3 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ cc.carm.lib easyplugin-parent pom - 1.5.12 + 1.5.13 base/color base/utils