diff --git a/modules/Gem/pom.xml b/modules/Gem/pom.xml
index 6476837..013d68c 100644
--- a/modules/Gem/pom.xml
+++ b/modules/Gem/pom.xml
@@ -66,6 +66,10 @@
placeholderapi
https://repo.extendedclip.com/content/repositories/placeholderapi/
+
+ helpch
+ https://repo.helpch.at/releases/
+
@@ -78,8 +82,32 @@
me.clip
placeholderapi
- 2.11.1
+ 2.11.5
provided
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ org.mockito
+ mockito-core
+ 5.11.0
+ test
+
+
+ org.mockito
+ mockito-inline
+ 5.2.0
+ test
+
+
+ net.bytebuddy
+ byte-buddy
+ 1.14.17
+ test
+
diff --git a/modules/Gem/src/main/java/com/mcatk/gem/command/CommandGem.java b/modules/Gem/src/main/java/com/mcatk/gem/command/CommandGem.java
index ee7c43e..b549756 100644
--- a/modules/Gem/src/main/java/com/mcatk/gem/command/CommandGem.java
+++ b/modules/Gem/src/main/java/com/mcatk/gem/command/CommandGem.java
@@ -41,7 +41,7 @@ public void run() {
}
switch (args[0].toLowerCase()) {
case "set":
- set();
+ set(sender, args);
break;
case "check":
check();
@@ -60,13 +60,20 @@ public void run() {
return true;
}
- private void set() {
+ private void set(CommandSender sender, String[] args) {
if (args.length != 3) {
sendParameterError();
} else {
try {
- Gem.getPlugin().getGemExecutor().setGems(args[1], Integer.parseInt(args[2]));
- sender.sendMessage(Message.INFO + args[1] + " 的宝石设置为: " + args[2]);
+ final String playerName = args[1];
+ final int gems = Integer.parseInt(args[2]);
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ Gem.getPlugin().getGemExecutor().setGems(playerName, gems);
+ sender.sendMessage(Message.INFO + playerName + " 的宝石设置为: " + gems);
+ }
+ }.runTaskAsynchronously(Gem.getPlugin());
} catch (NumberFormatException e) {
sender.sendMessage(Message.ERROR + "宝石必须是整数");
}
diff --git a/modules/Gem/src/test/java/com/mcatk/gem/command/CommandGemBenchmarkTest.java b/modules/Gem/src/test/java/com/mcatk/gem/command/CommandGemBenchmarkTest.java
new file mode 100644
index 0000000..417de7b
--- /dev/null
+++ b/modules/Gem/src/test/java/com/mcatk/gem/command/CommandGemBenchmarkTest.java
@@ -0,0 +1,94 @@
+package com.mcatk.gem.command;
+
+import com.mcatk.gem.Gem;
+import com.mcatk.gem.GemExecutor;
+import org.bukkit.Bukkit;
+import org.bukkit.Server;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.scheduler.BukkitScheduler;
+import org.bukkit.scheduler.BukkitTask;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.lang.reflect.Field;
+import java.util.logging.Logger;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CommandGemBenchmarkTest {
+
+ private Gem gemMock;
+ private GemExecutor gemExecutorMock;
+ private CommandSender senderMock;
+ private Command commandMock;
+ private Server serverMock;
+ private BukkitScheduler schedulerMock;
+
+ @Before
+ public void setUp() throws Exception {
+ // Mock Gem.plugin (static field)
+ gemMock = mock(Gem.class);
+ Field pluginField = Gem.class.getDeclaredField("plugin");
+ pluginField.setAccessible(true);
+ pluginField.set(null, gemMock);
+
+ // Mock GemExecutor
+ gemExecutorMock = mock(GemExecutor.class);
+ lenient().when(gemMock.getGemExecutor()).thenReturn(gemExecutorMock);
+ lenient().when(gemMock.getLogger()).thenReturn(Logger.getLogger("GemTest"));
+
+ // Mock Bukkit.server (static)
+ serverMock = mock(Server.class);
+ Field serverField = Bukkit.class.getDeclaredField("server");
+ serverField.setAccessible(true);
+ serverField.set(null, serverMock);
+
+ // Mock Scheduler
+ schedulerMock = mock(BukkitScheduler.class);
+ lenient().when(serverMock.getScheduler()).thenReturn(schedulerMock);
+
+ // Mock generic runTaskAsynchronously
+ lenient().when(schedulerMock.runTaskAsynchronously(any(Plugin.class), any(Runnable.class)))
+ .thenReturn(mock(BukkitTask.class));
+
+ // Mock CommandSender
+ senderMock = mock(CommandSender.class);
+ when(senderMock.isOp()).thenReturn(true);
+
+ // Mock Command
+ commandMock = mock(Command.class);
+ }
+
+ @Test
+ public void testSetGemsAsync() {
+ CommandGem commandGem = new CommandGem();
+ String[] args = new String[]{"set", "player", "100"};
+
+ long startTime = System.currentTimeMillis();
+ commandGem.onCommand(senderMock, commandMock, "gem", args);
+ long endTime = System.currentTimeMillis();
+
+ long duration = endTime - startTime;
+ System.out.println("Execution time: " + duration + "ms");
+
+ // Assert that it returns immediately (non-blocking)
+ assertTrue("Execution should be async and take < 50ms, but took " + duration + "ms", duration < 50);
+
+ // Capture and run the task
+ ArgumentCaptor runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ verify(schedulerMock).runTaskAsynchronously(any(Plugin.class), runnableCaptor.capture());
+
+ runnableCaptor.getValue().run();
+
+ // Verify logic executed
+ verify(gemExecutorMock).setGems("player", 100);
+ verify(senderMock).sendMessage(contains("100"));
+ }
+}