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