From f8bc471d4de188f6743d2823409d18e2a3b3b73f Mon Sep 17 00:00:00 2001 From: muhammadeko Date: Sat, 7 May 2022 19:48:20 +0700 Subject: [PATCH 01/28] PluginManager: Use the same class loader and add getPlugin method --- .../emu/grasscutter/plugin/PluginManager.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/main/java/emu/grasscutter/plugin/PluginManager.java b/src/main/java/emu/grasscutter/plugin/PluginManager.java index 7a5e0aa00..4844a698a 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginManager.java +++ b/src/main/java/emu/grasscutter/plugin/PluginManager.java @@ -4,12 +4,12 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.server.event.Event; import emu.grasscutter.server.event.EventHandler; import emu.grasscutter.server.event.HandlerPriority; -import emu.grasscutter.utils.EventConsumer; import emu.grasscutter.utils.Utils; import java.io.File; import java.io.InputStreamReader; import java.lang.reflect.Method; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.*; @@ -47,12 +47,23 @@ public final class PluginManager { List plugins = Arrays.stream(files) .filter(file -> file.getName().endsWith(".jar")) .toList(); - + + URL[] pluginNames = new URL[plugins.size()]; + plugins.forEach(plugin -> { + try { + pluginNames[plugins.indexOf(plugin)] = plugin.toURI().toURL(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + }); + + URLClassLoader classLoader = new URLClassLoader(pluginNames); + plugins.forEach(plugin -> { try { URL url = plugin.toURI().toURL(); try (URLClassLoader loader = new URLClassLoader(new URL[]{url})) { - URL configFile = loader.findResource("plugin.json"); + URL configFile = loader.findResource("plugin.json"); // Find the plugin.json file for each plugin. InputStreamReader fileReader = new InputStreamReader(configFile.openStream()); PluginConfig pluginConfig = Grasscutter.getGsonFactory().fromJson(fileReader, PluginConfig.class); @@ -68,10 +79,10 @@ public final class PluginManager { JarEntry entry = entries.nextElement(); if(entry.isDirectory() || !entry.getName().endsWith(".class") || entry.getName().contains("module-info")) continue; String className = entry.getName().replace(".class", "").replace("/", "."); - loader.loadClass(className); + classLoader.loadClass(className); //For all plugin we use the same class loader. } - Class pluginClass = loader.loadClass(pluginConfig.mainClass); + Class pluginClass = classLoader.loadClass(pluginConfig.mainClass); Plugin pluginInstance = (Plugin) pluginClass.getDeclaredConstructor().newInstance(); this.loadPlugin(pluginInstance, PluginIdentifier.fromPluginConfig(pluginConfig), loader); @@ -156,6 +167,10 @@ public final class PluginManager { .toList().forEach(handler -> this.invokeHandler(event, handler)); } + public Plugin getPlugin(String name) { + return this.plugins.get(name); + } + /** * Performs logic checks then invokes the provided event handler. * @param event The event passed through to the handler. From 14da6214d33341164d89f7f556ec824ba788a256 Mon Sep 17 00:00:00 2001 From: Kimi <34180607+Kimi898246@users.noreply.github.com> Date: Sat, 7 May 2022 21:58:16 +0800 Subject: [PATCH 02/28] Traditional Chinese | Translation Patches yeah i fucked up that one line of translation oops also added two lines of translation too --- src/main/resources/languages/zh-TW.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/languages/zh-TW.json b/src/main/resources/languages/zh-TW.json index 22d1339c8..2e5419290 100644 --- a/src/main/resources/languages/zh-TW.json +++ b/src/main/resources/languages/zh-TW.json @@ -57,7 +57,7 @@ "player_execute_error": "請在遊戲裡使用這條指令。", "command_exist_error": "找不到指令。", "invalid": { - "amount": "無效的 數量.", + "amount": "無效的數量。", "artifactId": "無效的聖遺物ID。", "avatarId": "無效的角色ID。", "avatarLevel": "無效的角色等級。", @@ -119,7 +119,7 @@ }, "coop": { "usage": "用法:coop ", - "success": "Summoned %s to %s's world." + "success": "召喚了 %s 到 %s 的世界。" }, "enter_dungeon": { "usage": "用法:enterdungeon ", @@ -270,7 +270,7 @@ "q_skill_id": "Q技能ID %s。" }, "teleportAll": { - "success": "Summoned all players to your location.", + "success": "召喚了所有玩家到你的位置上。", "error": "此指令僅可在多人遊戲下可用。" }, "teleport": { @@ -295,4 +295,4 @@ "available_commands": "可用指令:" } } -} \ No newline at end of file +} From 7e5696211ce3cb1133fd888dd4a6f70d0e7ecdea Mon Sep 17 00:00:00 2001 From: zhaodice <63996691+zhaodice@users.noreply.github.com> Date: Sat, 7 May 2022 23:19:48 +0800 Subject: [PATCH 03/28] fix issues 629 fix #629 --- src/main/resources/languages/en-US.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index 48ffb5b0b..fb33ba287 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -184,7 +184,7 @@ "account_error": "The account cannot be found." }, "position": { - "success": "Coordinates: %.3f, %.3f, %.3f\nScene id: %d" + "success": "Coordinates: %s, %s, %s\nScene id: %s" }, "reload": { "reload_start": "Reloading config.", @@ -295,4 +295,4 @@ "available_commands": "Available commands: " } } -} \ No newline at end of file +} From e85eb2f48a981be112432fa1a67e510906074346 Mon Sep 17 00:00:00 2001 From: zhaodice <63996691+zhaodice@users.noreply.github.com> Date: Sat, 7 May 2022 23:31:12 +0800 Subject: [PATCH 04/28] fix issue 635 fix #635 --- .../java/emu/grasscutter/command/commands/GiveCharCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java index 87c2d61e2..4b3279202 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java @@ -77,6 +77,6 @@ public final class GiveCharCommand implements CommandHandler { avatar.recalcStats(); targetPlayer.addAvatar(avatar); - CommandHandler.sendMessage(sender, translate("commands.execution.giveChar.given", Integer.toString(avatarId), Integer.toString(level), Integer.toString(targetPlayer.getUid()))); + CommandHandler.sendMessage(sender, translate("commands.giveChar.given", Integer.toString(avatarId), Integer.toString(level), Integer.toString(targetPlayer.getUid()))); } } From 34228dc9cd03b9bb378bd7fbcee97eed13869f19 Mon Sep 17 00:00:00 2001 From: Piotr Blecharski Date: Sat, 7 May 2022 23:20:12 +0200 Subject: [PATCH 05/28] Command list with descriptions in handbook --- .DS_Store | Bin 0 -> 6148 bytes .../emu/grasscutter/command/CommandMap.java | 6 +++++ .../java/emu/grasscutter/tools/Tools.java | 23 ++++++++++++++---- 3 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..eaf6ad184c75dd2ba42a1541ed49d325ff465cce GIT binary patch literal 6148 zcmeHK%}T>S5Z-O8O(;SR3OxqA7ObsU#Y>3w1&ruHr6#6mFlI~Am_sS#tS{t~_&m<+ zZp2arPa<{(X203_$+F*u{b7u8HxG9ivlwFrC}Pco<_p0%>XOv72a(HfkY|OHt zSjr~HUt|E+&V*HiHDiK(TEA=(#3F#`YcPqUY})O<@mjsHw%#$LJ4dIZhxjoO&x%eCf1Z>LjTO9r@x{!ZyfleLatG0> zvZ^2?28aP-U{x5<`=8NTl?l^4i2-8Z#|+^9V1pt$8cT(8>wpHYj~H(tqJWKW2}E0? zqp?&75fH9Q0aYp2PYkZg!Eft4M`Ni_l`}3!hVST+xqhK=IXd`lna;SQkXmAZ7+7SW zuDTYU|0mzS{}+p>M+^`H|B3r}? aDd4x!0CY5#3c&+H7Xe8FHN?QLGVl&qd`++b literal 0 HcmV?d00001 diff --git a/src/main/java/emu/grasscutter/command/CommandMap.java b/src/main/java/emu/grasscutter/command/CommandMap.java index 07deb84fd..a183c6ac3 100644 --- a/src/main/java/emu/grasscutter/command/CommandMap.java +++ b/src/main/java/emu/grasscutter/command/CommandMap.java @@ -79,6 +79,12 @@ public final class CommandMap { return this; } + public List getAnnotationsAsList() { return new LinkedList<>(this.annotations.values()); } + + public HashMap getAnnotations() { + return new LinkedHashMap<>(this.annotations); + } + /** * Returns a list of all registered commands. * diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index 7429c143f..d9923a656 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -13,16 +13,15 @@ import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import com.google.gson.reflect.TypeToken; import emu.grasscutter.GameConstants; import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandMap; import emu.grasscutter.data.GameData; import emu.grasscutter.data.ResourceLoader; import emu.grasscutter.data.def.AvatarData; @@ -111,7 +110,21 @@ final class ToolsWithLanguageOption { writer.println("// Grasscutter " + GameConstants.VERSION + " GM Handbook"); writer.println("// Created " + dtf.format(now) + System.lineSeparator() + System.lineSeparator()); - + + CommandMap cmdMap = new CommandMap(true); + List cmdList = new ArrayList<>(cmdMap.getAnnotationsAsList()); + + writer.println("// Commands"); + for (Command cmd : cmdList) { + String cmdName = cmd.label(); + while (cmdName.length() <= 15) { + cmdName = " " + cmdName; + } + writer.println(cmdName + " : " + cmd.description()); + } + + writer.println(); + list = new ArrayList<>(GameData.getAvatarDataMap().keySet()); Collections.sort(list); From 747d6e91f6505dfe4797afc58dbc8a3efd7971d4 Mon Sep 17 00:00:00 2001 From: Piotr Blecharski Date: Sat, 7 May 2022 23:21:57 +0200 Subject: [PATCH 06/28] Deleted .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index eaf6ad184c75dd2ba42a1541ed49d325ff465cce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%}T>S5Z-O8O(;SR3OxqA7ObsU#Y>3w1&ruHr6#6mFlI~Am_sS#tS{t~_&m<+ zZp2arPa<{(X203_$+F*u{b7u8HxG9ivlwFrC}Pco<_p0%>XOv72a(HfkY|OHt zSjr~HUt|E+&V*HiHDiK(TEA=(#3F#`YcPqUY})O<@mjsHw%#$LJ4dIZhxjoO&x%eCf1Z>LjTO9r@x{!ZyfleLatG0> zvZ^2?28aP-U{x5<`=8NTl?l^4i2-8Z#|+^9V1pt$8cT(8>wpHYj~H(tqJWKW2}E0? zqp?&75fH9Q0aYp2PYkZg!Eft4M`Ni_l`}3!hVST+xqhK=IXd`lna;SQkXmAZ7+7SW zuDTYU|0mzS{}+p>M+^`H|B3r}? aDd4x!0CY5#3c&+H7Xe8FHN?QLGVl&qd`++b From ab5131e9fdbd16fa4a7dee93a0c2cf90e103c778 Mon Sep 17 00:00:00 2001 From: HotaruYS <105128850+HotaruYS@users.noreply.github.com> Date: Sat, 7 May 2022 22:07:55 +0200 Subject: [PATCH 07/28] Respect FrontHTTPS when creating URI for gacha record --- src/main/java/emu/grasscutter/game/gacha/GachaBanner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java index 2317af38e..b48cb0898 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaBanner.java @@ -96,7 +96,7 @@ public class GachaBanner { return toProto(""); } public GachaInfo toProto(String sessionKey) { - String record = "https://" + String record = "http" + (Grasscutter.getConfig().getDispatchOptions().FrontHTTPS ? "s" : "") + "://" + (Grasscutter.getConfig().getDispatchOptions().PublicIp.isEmpty() ? Grasscutter.getConfig().getDispatchOptions().Ip : Grasscutter.getConfig().getDispatchOptions().PublicIp) From 84c1cd7aa75345ad2a3b293ba3a51b5926ceeeb9 Mon Sep 17 00:00:00 2001 From: Magix <27646710+KingRainbow44@users.noreply.github.com> Date: Sat, 7 May 2022 17:58:18 -0400 Subject: [PATCH 08/28] Update PluginManager.java --- src/main/java/emu/grasscutter/plugin/PluginManager.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/emu/grasscutter/plugin/PluginManager.java b/src/main/java/emu/grasscutter/plugin/PluginManager.java index 4844a698a..bc78d12eb 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginManager.java +++ b/src/main/java/emu/grasscutter/plugin/PluginManager.java @@ -52,8 +52,8 @@ public final class PluginManager { plugins.forEach(plugin -> { try { pluginNames[plugins.indexOf(plugin)] = plugin.toURI().toURL(); - } catch (MalformedURLException e) { - e.printStackTrace(); + } catch (MalformedURLException exception) { + Grasscutter.getLogger().warn("Unable to load plugin.", exception); } }); @@ -79,7 +79,7 @@ public final class PluginManager { JarEntry entry = entries.nextElement(); if(entry.isDirectory() || !entry.getName().endsWith(".class") || entry.getName().contains("module-info")) continue; String className = entry.getName().replace(".class", "").replace("/", "."); - classLoader.loadClass(className); //For all plugin we use the same class loader. + classLoader.loadClass(className); // Use the same class loader for ALL plugins. } Class pluginClass = classLoader.loadClass(pluginConfig.mainClass); @@ -182,4 +182,4 @@ public final class PluginManager { (event.isCanceled() && handler.ignoresCanceled()) ) handler.getCallback().consume((T) event); } -} \ No newline at end of file +} From 57cc111350a1beb009a197676eb6d3ecb0f6c8a2 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Sat, 7 May 2022 18:12:53 -0400 Subject: [PATCH 09/28] Simplify the language fallback system --- src/main/java/emu/grasscutter/Config.java | 2 +- .../java/emu/grasscutter/Grasscutter.java | 5 ++- .../java/emu/grasscutter/utils/Language.java | 44 +++++-------------- .../java/emu/grasscutter/utils/Utils.java | 3 +- 4 files changed, 17 insertions(+), 37 deletions(-) diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java index 1111ba920..3982fc46b 100644 --- a/src/main/java/emu/grasscutter/Config.java +++ b/src/main/java/emu/grasscutter/Config.java @@ -23,7 +23,7 @@ public final class Config { public GameServerOptions GameServer = new GameServerOptions(); public DispatchServerOptions DispatchServer = new DispatchServerOptions(); public Locale LocaleLanguage = Locale.getDefault(); - public Locale DefaultLanguage = Locale.US; + public Locale DefaultLanguage = Locale.ENGLISH; public Boolean OpenStamina = true; public GameServerOptions getGameServerOptions() { diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java index 51bc3fcc5..c593f5f13 100644 --- a/src/main/java/emu/grasscutter/Grasscutter.java +++ b/src/main/java/emu/grasscutter/Grasscutter.java @@ -149,9 +149,10 @@ public final class Grasscutter { public static void loadLanguage() { var locale = config.LocaleLanguage; - String languageTag = locale.toLanguageTag(); + var languageTag = locale.toLanguageTag(); + if (languageTag.equals("und")) { - Grasscutter.getLogger().error("Illegal locale language, using en-US instead."); + Grasscutter.getLogger().error("Illegal locale language, using 'en-US' instead."); language = Language.getLanguage("en-US"); } else { language = Language.getLanguage(languageTag); diff --git a/src/main/java/emu/grasscutter/utils/Language.java b/src/main/java/emu/grasscutter/utils/Language.java index 340d35dc2..0af77adc1 100644 --- a/src/main/java/emu/grasscutter/utils/Language.java +++ b/src/main/java/emu/grasscutter/utils/Language.java @@ -19,7 +19,7 @@ public final class Language { * @return A language instance. */ public static Language getLanguage(String langCode) { - return new Language(langCode + ".json"); + return new Language(langCode + ".json", Grasscutter.getConfig().DefaultLanguage.toLanguageTag()); } /** @@ -30,6 +30,7 @@ public final class Language { */ public static String translate(String key, Object... args) { String translated = Grasscutter.getLanguage().get(key); + try { return translated.formatted(args); } catch (Exception exception) { @@ -38,48 +39,25 @@ public final class Language { } } - /** - * creates a language instance. - * @param fileName The name of the language file. - */ - private Language(String fileName) { - @Nullable JsonObject languageData = null; - - languageData = loadLanguage(fileName); - - if (languageData == null) { - Grasscutter.getLogger().info("Now switch to default language"); - languageData = loadDefaultLanguage(); - } - - assert languageData != null : "languageData is null"; - this.languageData = languageData; - } - - /** - * Load default language file and creates a language instance. - * @return language data - */ - private JsonObject loadDefaultLanguage() { - var fileName = Grasscutter.getConfig().DefaultLanguage.toLanguageTag() + ".json"; - return loadLanguage(fileName); - } - /** * Reads a file and creates a language instance. * @param fileName The name of the language file. - * @return language data */ - private JsonObject loadLanguage(String fileName) { + private Language(String fileName, String fallback) { @Nullable JsonObject languageData = null; - + try { InputStream file = Grasscutter.class.getResourceAsStream("/languages/" + fileName); + if(file == null) { + file = Grasscutter.class.getResourceAsStream("/languages/" + fallback); + } + languageData = Grasscutter.getGsonFactory().fromJson(Utils.readFromInputStream(file), JsonObject.class); } catch (Exception exception) { - Grasscutter.getLogger().warn("Failed to load language file: " + fileName); + Grasscutter.getLogger().warn("Failed to load language file: " + fileName, exception); } - return languageData; + + this.languageData = languageData; } /** diff --git a/src/main/java/emu/grasscutter/utils/Utils.java b/src/main/java/emu/grasscutter/utils/Utils.java index 259fc8ad5..6d11822f0 100644 --- a/src/main/java/emu/grasscutter/utils/Utils.java +++ b/src/main/java/emu/grasscutter/utils/Utils.java @@ -1,6 +1,7 @@ package emu.grasscutter.utils; import java.io.*; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.time.*; @@ -254,7 +255,7 @@ public final class Utils { */ public static String readFromInputStream(InputStream stream) { StringBuilder stringBuilder = new StringBuilder(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream,"UTF-8"))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { stringBuilder.append(line); } stream.close(); From 1beddf16c1a8dc5549162e79e761e9c70a24cbe3 Mon Sep 17 00:00:00 2001 From: Magix <27646710+KingRainbow44@users.noreply.github.com> Date: Sat, 7 May 2022 18:17:32 -0400 Subject: [PATCH 10/28] Update build.gradle (in prep for 1.1.0) --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 8c9257777..eefef5b48 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,7 @@ sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 group = 'xyz.grasscutters' -version = '1.0.3-dev' +version = '1.1.0' sourceCompatibility = 17 targetCompatibility = 17 @@ -228,4 +228,4 @@ javadoc { processResources { dependsOn "generateProto" -} \ No newline at end of file +} From 88bc5c4c54c1aadcdc6cc9a24c0f69d4bebce97c Mon Sep 17 00:00:00 2001 From: Kimi <34180607+Kimi898246@users.noreply.github.com> Date: Sun, 8 May 2022 06:25:49 +0800 Subject: [PATCH 11/28] another translation patches because i fucked it up i hate myself --- src/main/resources/languages/zh-TW.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/languages/zh-TW.json b/src/main/resources/languages/zh-TW.json index 2e5419290..7545df6e9 100644 --- a/src/main/resources/languages/zh-TW.json +++ b/src/main/resources/languages/zh-TW.json @@ -127,7 +127,7 @@ "not_found_error": "此副本不存在。", "in_dungeon_error": "你已經在祕境中了。" }, - "giveAll": { + "chAll": { "usage": "用法:giveall [player] [amount]", "started": "正在賦予全部物品...", "success": "已賦予全部物品。", @@ -140,7 +140,7 @@ }, "giveChar": { "usage": "用法:givechar [amount]", - "given": "Given %s with level %s to %s.", + "given": "已將 %s 等級 %s 給予 %s。", "invalid_avatar_id": "無效的角色ID。", "invalid_avatar_level": "無效的角色等級。.", "invalid_avatar_or_player_id": "無效的角色ID/玩家ID。" From 43c27c4679ab104735a0cf743987b6fa5290ad7e Mon Sep 17 00:00:00 2001 From: Kimi <34180607+Kimi898246@users.noreply.github.com> Date: Sun, 8 May 2022 06:47:58 +0800 Subject: [PATCH 12/28] Update zh-TW.json --- src/main/resources/languages/zh-TW.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/languages/zh-TW.json b/src/main/resources/languages/zh-TW.json index 7545df6e9..49e0f256d 100644 --- a/src/main/resources/languages/zh-TW.json +++ b/src/main/resources/languages/zh-TW.json @@ -127,7 +127,7 @@ "not_found_error": "此副本不存在。", "in_dungeon_error": "你已經在祕境中了。" }, - "chAll": { + "giveAll": { "usage": "用法:giveall [player] [amount]", "started": "正在賦予全部物品...", "success": "已賦予全部物品。", From 8e99cb4f35526b3cbc28bfe510869885e186bd56 Mon Sep 17 00:00:00 2001 From: gentlespoon Date: Sat, 7 May 2022 05:00:50 -0700 Subject: [PATCH 13/28] More reliable stamina calculation by separately handling immediate one-time cost and cost over time. --- .../MovementManager/MovementManager.java | 428 ++++++++---------- .../emu/grasscutter/game/player/Player.java | 2 +- .../grasscutter/game/player/TeamManager.java | 2 +- .../recv/HandlerCombatInvocationsNotify.java | 76 +++- .../recv/HandlerEvtDoSkillSuccNotify.java | 6 +- 5 files changed, 268 insertions(+), 246 deletions(-) diff --git a/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java b/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java index 23b45903a..ece02a0fb 100644 --- a/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java +++ b/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java @@ -7,22 +7,31 @@ import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.LifeState; import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.net.proto.EntityMoveInfoOuterClass; +import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; +import emu.grasscutter.net.proto.EvtDoSkillSuccNotifyOuterClass.EvtDoSkillSuccNotify; import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; -import emu.grasscutter.net.proto.VectorOuterClass; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.*; import emu.grasscutter.utils.Position; -import org.jetbrains.annotations.NotNull; import java.lang.Math; import java.util.*; public class MovementManager { - - public HashMap> MotionStatesCategorized = new HashMap<>(); + private final Player player; + private HashMap> MotionStatesCategorized = new HashMap<>(); + private Position currentCoordinates = new Position(0, 0, 0); + private Position previousCoordinates = new Position(0, 0, 0); + private MotionState currentState = MotionState.MOTION_STANDBY; + private MotionState previousState = MotionState.MOTION_STANDBY; + private Timer sustainedStaminaHandlerTimer; + private GameSession cachedSession = null; + private GameEntity cachedEntity = null; + private int staminaRecoverDelay = 0; + private boolean isInSkillMove = false; private enum ConsumptionType { None(0), @@ -31,8 +40,8 @@ public class MovementManager { CLIMB_START(-500), CLIMBING(-150), CLIMB_JUMP(-2500), - DASH(-1800), - SPRINT(-360), + SPRINT(-1800), + DASH(-360), FLY(-60), SWIM_DASH_START(-200), SWIM_DASH(-200), @@ -47,6 +56,7 @@ public class MovementManager { POWERED_FLY(500); public final int amount; + ConsumptionType(int amount) { this.amount = amount; } @@ -55,33 +65,26 @@ public class MovementManager { private class Consumption { public ConsumptionType consumptionType; public int amount; + public Consumption(ConsumptionType ct, int a) { consumptionType = ct; amount = a; } + public Consumption(ConsumptionType ct) { this(ct, ct.amount); } } - private MotionState previousState = MotionState.MOTION_STANDBY; - private MotionState currentState = MotionState.MOTION_STANDBY; - private Position previousCoordinates = new Position(0, 0, 0); - private Position currentCoordinates = new Position(0, 0, 0); + public boolean getIsInSkillMove() { + return isInSkillMove; + } - private final Player player; - - private float landSpeed = 0; - private long landTimeMillisecond = 0; - private Timer movementManagerTickTimer; - private GameSession cachedSession = null; - private GameEntity cachedEntity = null; - private int staminaRecoverDelay = 0; - private int skillCaster = 0; - private int skillCasting = 0; + public void setIsInSkillMove(boolean b) { + isInSkillMove = b; + } public MovementManager(Player player) { - previousCoordinates.add(new Position(0,0,0)); this.player = player; MotionStatesCategorized.put("SWIM", new HashSet<>(Arrays.asList( @@ -129,252 +132,225 @@ public class MovementManager { ))); MotionStatesCategorized.put("FIGHT", new HashSet<>(Arrays.asList( - MotionState.MOTION_FIGHT + MotionState.MOTION_FIGHT ))); - - - } - - public void handle(GameSession session, EntityMoveInfoOuterClass.EntityMoveInfo moveInfo, GameEntity entity) { - if (movementManagerTickTimer == null) { - movementManagerTickTimer = new Timer(); - movementManagerTickTimer.scheduleAtFixedRate(new MotionManagerTick(), 0, 200); - } - // cache info for later use in tick - cachedSession = session; - cachedEntity = entity; - - MotionInfo motionInfo = moveInfo.getMotionInfo(); - moveEntity(entity, moveInfo); - VectorOuterClass.Vector posVector = motionInfo.getPos(); - Position newPos = new Position(posVector.getX(), - posVector.getY(), posVector.getZ());; - if (newPos.getX() != 0 && newPos.getY() != 0 && newPos.getZ() != 0) { - currentCoordinates = newPos; - } - currentState = motionInfo.getState(); - Grasscutter.getLogger().debug("" + currentState + "\t" + (moveInfo.getIsReliable() ? "reliable" : "")); - handleFallOnGround(motionInfo); - } - - public void resetTimer() { - Grasscutter.getLogger().debug("MovementManager ticker stopped"); - movementManagerTickTimer.cancel(); - movementManagerTickTimer = null; - } - - private void moveEntity(GameEntity entity, EntityMoveInfoOuterClass.EntityMoveInfo moveInfo) { - entity.getPosition().set(moveInfo.getMotionInfo().getPos()); - entity.getRotation().set(moveInfo.getMotionInfo().getRot()); - entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime()); - entity.setLastMoveReliableSeq(moveInfo.getReliableSeq()); - entity.setMotionState(moveInfo.getMotionInfo().getState()); } private boolean isPlayerMoving() { float diffX = currentCoordinates.getX() - previousCoordinates.getX(); float diffY = currentCoordinates.getY() - previousCoordinates.getY(); float diffZ = currentCoordinates.getZ() - previousCoordinates.getZ(); - // Grasscutter.getLogger().debug("isPlayerMoving: " + previousCoordinates + ", " + currentCoordinates + ", " + diffX + ", " + diffY + ", " + diffZ); - return Math.abs(diffX) > 0.2 || Math.abs(diffY) > 0.1 || Math.abs(diffZ) > 0.2; + Grasscutter.getLogger().debug("isPlayerMoving: " + previousCoordinates + ", " + currentCoordinates + + ", " + diffX + ", " + diffY + ", " + diffZ); + return Math.abs(diffX) > 0.3 || Math.abs(diffY) > 0.2 || Math.abs(diffZ) > 0.3; } - private int getCurrentStamina() { - return player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); - } - - private int getMaximumStamina() { - return player.getProperty(PlayerProperty.PROP_MAX_STAMINA); - } - - // Returns new stamina - public int updateStamina(GameSession session, int amount) { - int currentStamina = session.getPlayer().getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); - if (amount == 0) { + // Returns new stamina and sends PlayerPropNotify + public int updateStamina(GameSession session, Consumption consumption) { + int currentStamina = player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); + if (consumption.amount == 0) { return currentStamina; } - int playerMaxStamina = session.getPlayer().getProperty(PlayerProperty.PROP_MAX_STAMINA); - int newStamina = currentStamina + amount; + int playerMaxStamina = player.getProperty(PlayerProperty.PROP_MAX_STAMINA); + Grasscutter.getLogger().debug(currentStamina + "/" + playerMaxStamina + "\t" + currentState + "\t" + + (isPlayerMoving() ? "moving" : " ") + "\t(" + consumption.consumptionType + "," + + consumption.amount + ")"); + int newStamina = currentStamina + consumption.amount; if (newStamina < 0) { newStamina = 0; } if (newStamina > playerMaxStamina) { newStamina = playerMaxStamina; } - session.getPlayer().setProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA, newStamina); + player.setProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA, newStamina); session.send(new PacketPlayerPropNotify(player, PlayerProperty.PROP_CUR_PERSIST_STAMINA)); return newStamina; } - private void handleFallOnGround(@NotNull MotionInfo motionInfo) { - MotionState state = motionInfo.getState(); - // land speed and fall on ground event arrive in different packets - // cache land speed - if (state == MotionState.MOTION_LAND_SPEED) { - landSpeed = motionInfo.getSpeed().getY(); - landTimeMillisecond = System.currentTimeMillis(); + // Kills avatar, removes entity and sends notification. + // TODO: Probably move this to Avatar class? since other components may also need to kill avatar. + public void killAvatar(GameSession session, GameEntity entity, PlayerDieType dieType) { + session.send(new PacketAvatarLifeStateChangeNotify(player.getTeamManager().getCurrentAvatarEntity().getAvatar(), + LifeState.LIFE_DEAD, dieType)); + session.send(new PacketLifeStateChangeNotify(entity, LifeState.LIFE_DEAD, dieType)); + entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0); + entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); + entity.getWorld().broadcastPacket(new PacketLifeStateChangeNotify(0, entity, LifeState.LIFE_DEAD)); + player.getScene().removeEntity(entity); + ((EntityAvatar) entity).onDeath(dieType, 0); + } + + public void startSustainedStaminaHandler() { + if (sustainedStaminaHandlerTimer == null) { + sustainedStaminaHandlerTimer = new Timer(); + sustainedStaminaHandlerTimer.scheduleAtFixedRate(new SustainedStaminaHandler(), 0, 200); + Grasscutter.getLogger().debug("[MovementManager] SustainedStaminaHandlerTimer started"); } - if (state == MotionState.MOTION_FALL_ON_GROUND) { - // if not received immediately after MOTION_LAND_SPEED, discard this packet. - // TODO: Test in high latency. - int maxDelay = 200; - if ((System.currentTimeMillis() - landTimeMillisecond) > maxDelay) { - Grasscutter.getLogger().debug("MOTION_FALL_ON_GROUND received after " + maxDelay + "ms, discard."); - return; + } + + public void stopSustainedStaminaHandler() { + Grasscutter.getLogger().debug("[MovementManager] SustainedStaminaHandlerTimer stopped"); + sustainedStaminaHandlerTimer.cancel(); + sustainedStaminaHandlerTimer = null; + } + + // Handlers + + // External trigger handler + + public void handleEvtDoSkillSuccNotify(GameSession session, EvtDoSkillSuccNotify notify) { + handleImmediateStamina(session, notify); + } + + public void handleCombatInvocationsNotify(GameSession session, EntityMoveInfo moveInfo, GameEntity entity) { + // cache info for later use in SustainedStaminaHandler tick + cachedSession = session; + cachedEntity = entity; + MotionInfo motionInfo = moveInfo.getMotionInfo(); + MotionState motionState = motionInfo.getState(); + boolean isReliable = moveInfo.getIsReliable(); + Grasscutter.getLogger().trace("" + motionState + "\t" + (isReliable ? "reliable" : "")); + if (isReliable) { + currentState = motionState; + Vector posVector = motionInfo.getPos(); + Position newPos = new Position(posVector.getX(), posVector.getY(), posVector.getZ()); + if (newPos.getX() != 0 && newPos.getY() != 0 && newPos.getZ() != 0) { + currentCoordinates = newPos; } - float currentHP = cachedEntity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); - float maxHP = cachedEntity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); - float damage = 0; - Grasscutter.getLogger().debug("LandSpeed: " + landSpeed); - if (landSpeed < -23.5) { - damage = (float)(maxHP * 0.33); + } + startSustainedStaminaHandler(); + handleImmediateStamina(session, motionInfo, motionState, entity); + } + + // Internal handler + + private void handleImmediateStamina(GameSession session, MotionInfo motionInfo, MotionState motionState, + GameEntity entity) { + switch (motionState) { + case MOTION_DASH_BEFORE_SHAKE: + if (previousState != MotionState.MOTION_DASH_BEFORE_SHAKE) { + updateStamina(session, new Consumption(ConsumptionType.SPRINT)); + } + break; + case MOTION_CLIMB_JUMP: + if (previousState != MotionState.MOTION_CLIMB_JUMP) { + updateStamina(session, new Consumption(ConsumptionType.CLIMB_JUMP)); + } + break; + case MOTION_SWIM_DASH: + if (previousState != MotionState.MOTION_SWIM_DASH) { + updateStamina(session, new Consumption(ConsumptionType.SWIM_DASH_START)); + } + break; + } + } + + private void handleImmediateStamina(GameSession session, EvtDoSkillSuccNotify notify) { + Consumption consumption = getFightConsumption(notify.getSkillId()); + updateStamina(session, consumption); + } + + private class SustainedStaminaHandler extends TimerTask { + public void run() { + if (Grasscutter.getConfig().OpenStamina) { + boolean moving = isPlayerMoving(); + int currentStamina = player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); + int maxStamina = player.getProperty(PlayerProperty.PROP_MAX_STAMINA); + if (moving || (currentStamina < maxStamina)) { + Grasscutter.getLogger().debug("Player moving: " + moving + ", stamina full: " + + (currentStamina >= maxStamina) + ", recalculate stamina"); + Consumption consumption = new Consumption(ConsumptionType.None); + if (!isInSkillMove) { + if (MotionStatesCategorized.get("CLIMB").contains(currentState)) { + consumption = getClimbSustainedConsumption(); + } else if (MotionStatesCategorized.get("SWIM").contains((currentState))) { + consumption = getSwimSustainedConsumptions(); + } else if (MotionStatesCategorized.get("RUN").contains(currentState)) { + consumption = getRunWalkDashSustainedConsumption(); + } else if (MotionStatesCategorized.get("FLY").contains(currentState)) { + consumption = getFlySustainedConsumption(); + } else if (MotionStatesCategorized.get("STANDBY").contains(currentState)) { + consumption = getStandSustainedConsumption(); + } + } + if (cachedSession != null) { + if (consumption.amount < 0) { + staminaRecoverDelay = 0; + } + if (consumption.amount > 0 && consumption.consumptionType != ConsumptionType.POWERED_FLY) { + // For POWERED_FLY recover immediately - things like Amber's gliding exam may require this. + if (staminaRecoverDelay < 10) { + // For others recover after 2 seconds (10 ticks) - as official server does. + staminaRecoverDelay++; + consumption = new Consumption(ConsumptionType.None); + } + } + updateStamina(cachedSession, consumption); + } + handleDrowning(); + } } - if (landSpeed < -25) { - damage = (float)(maxHP * 0.5); - } - if (landSpeed < -26.5) { - damage = (float)(maxHP * 0.66); - } - if (landSpeed < -28) { - damage = (maxHP * 1); - } - float newHP = currentHP - damage; - if (newHP < 0) { - newHP = 0; - } - Grasscutter.getLogger().debug("Max: " + maxHP + "\tCurr: " + currentHP + "\tDamage: " + damage + "\tnewHP: " + newHP); - cachedEntity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); - cachedEntity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(cachedEntity, FightProperty.FIGHT_PROP_CUR_HP)); - if (newHP == 0) { - killAvatar(cachedSession, cachedEntity, PlayerDieType.PLAYER_DIE_FALL); - } - landSpeed = 0; + previousState = currentState; + previousCoordinates = new Position( + currentCoordinates.getX(), + currentCoordinates.getY(), + currentCoordinates.getZ() + ); } } private void handleDrowning() { - int stamina = getCurrentStamina(); + int stamina = player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); if (stamina < 10) { boolean isSwimming = MotionStatesCategorized.get("SWIM").contains(currentState); - Grasscutter.getLogger().debug(player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA) + "/" + player.getProperty(PlayerProperty.PROP_MAX_STAMINA) + "\t" + currentState + "\t" + isSwimming); + Grasscutter.getLogger().debug(player.getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA) + "/" + + player.getProperty(PlayerProperty.PROP_MAX_STAMINA) + "\t" + currentState + "\t" + isSwimming); if (isSwimming && currentState != MotionState.MOTION_SWIM_IDLE) { killAvatar(cachedSession, cachedEntity, PlayerDieType.PLAYER_DIE_DRAWN); } } } - public void killAvatar(GameSession session, GameEntity entity, PlayerDieType dieType) { - cachedSession.send(new PacketAvatarLifeStateChangeNotify( - cachedSession.getPlayer().getTeamManager().getCurrentAvatarEntity().getAvatar(), - LifeState.LIFE_DEAD, - dieType - )); - cachedSession.send(new PacketLifeStateChangeNotify( - cachedEntity, - LifeState.LIFE_DEAD, - dieType - )); - cachedEntity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, 0); - cachedEntity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(cachedEntity, FightProperty.FIGHT_PROP_CUR_HP)); - entity.getWorld().broadcastPacket(new PacketLifeStateChangeNotify(0, entity, LifeState.LIFE_DEAD)); - session.getPlayer().getScene().removeEntity(entity); - ((EntityAvatar)entity).onDeath(dieType, 0); - } + // Consumption Calculators - private class MotionManagerTick extends TimerTask - { - public void run() { - if (Grasscutter.getConfig().OpenStamina) { - boolean moving = isPlayerMoving(); - if (moving || (getCurrentStamina() < getMaximumStamina())) { - // Grasscutter.getLogger().debug("Player moving: " + moving + ", stamina full: " + (getCurrentStamina() >= getMaximumStamina()) + ", recalculate stamina"); - Consumption consumption = new Consumption(ConsumptionType.None); - - // TODO: refactor these conditions. - if (MotionStatesCategorized.get("CLIMB").contains(currentState)) { - consumption = getClimbConsumption(); - } else if (MotionStatesCategorized.get("SWIM").contains((currentState))) { - consumption = getSwimConsumptions(); - } else if (MotionStatesCategorized.get("RUN").contains(currentState)) { - consumption = getRunWalkDashConsumption(); - } else if (MotionStatesCategorized.get("FLY").contains(currentState)) { - consumption = getFlyConsumption(); - } else if (MotionStatesCategorized.get("STANDBY").contains(currentState)) { - consumption = getStandConsumption(); - } else if (MotionStatesCategorized.get("FIGHT").contains(currentState)) { - consumption = getFightConsumption(); - } - - // delay 2 seconds before start recovering - as official server does. - if (cachedSession != null) { - if (consumption.amount < 0) { - staminaRecoverDelay = 0; - } - if (consumption.amount > 0 && consumption.consumptionType != ConsumptionType.POWERED_FLY) { - if (staminaRecoverDelay < 10) { - staminaRecoverDelay++; - consumption = new Consumption(ConsumptionType.None); - } - } - // Grasscutter.getLogger().debug(getCurrentStamina() + "/" + getMaximumStamina() + "\t" + currentState + "\t" + "isMoving: " + isPlayerMoving() + "\t(" + consumption.consumptionType + "," + consumption.amount + ")"); - updateStamina(cachedSession, consumption.amount); - } - - // tick triggered - handleDrowning(); - } - } - - previousState = currentState; - previousCoordinates = new Position(currentCoordinates.getX(), - currentCoordinates.getY(), currentCoordinates.getZ());; - } - } - - private Consumption getClimbConsumption() { + private Consumption getFightConsumption(int skillCasting) { Consumption consumption = new Consumption(ConsumptionType.None); - if (currentState == MotionState.MOTION_CLIMB) { + HashMap fightingCost = new HashMap<>() {{ + put(10013, -1000); // Kamisato Ayaka + put(10413, -1000); // Mona + }}; + if (fightingCost.containsKey(skillCasting)) { + consumption = new Consumption(ConsumptionType.FIGHT, fightingCost.get(skillCasting)); + } + return consumption; + } + + private Consumption getClimbSustainedConsumption() { + Consumption consumption = new Consumption(ConsumptionType.None); + if (currentState == MotionState.MOTION_CLIMB && isPlayerMoving()) { consumption = new Consumption(ConsumptionType.CLIMBING); if (previousState != MotionState.MOTION_CLIMB && previousState != MotionState.MOTION_CLIMB_JUMP) { consumption = new Consumption(ConsumptionType.CLIMB_START); } - if (!isPlayerMoving()) { - consumption = new Consumption(ConsumptionType.None); - } - } - if (currentState == MotionState.MOTION_CLIMB_JUMP) { - if (previousState != MotionState.MOTION_CLIMB_JUMP) { - consumption = new Consumption(ConsumptionType.CLIMB_JUMP); - } } return consumption; } - private Consumption getSwimConsumptions() { + private Consumption getSwimSustainedConsumptions() { Consumption consumption = new Consumption(ConsumptionType.None); if (currentState == MotionState.MOTION_SWIM_MOVE) { consumption = new Consumption(ConsumptionType.SWIMMING); } if (currentState == MotionState.MOTION_SWIM_DASH) { - consumption = new Consumption(ConsumptionType.SWIM_DASH_START); - if (previousState == MotionState.MOTION_SWIM_DASH) { - consumption = new Consumption(ConsumptionType.SWIM_DASH); - } + consumption = new Consumption(ConsumptionType.SWIM_DASH); } return consumption; } - private Consumption getRunWalkDashConsumption() { + private Consumption getRunWalkDashSustainedConsumption() { Consumption consumption = new Consumption(ConsumptionType.None); - if (currentState == MotionState.MOTION_DASH_BEFORE_SHAKE) { - consumption = new Consumption(ConsumptionType.DASH); - if (previousState == MotionState.MOTION_DASH_BEFORE_SHAKE) { - // only charge once - consumption = new Consumption(ConsumptionType.SPRINT); - } - } if (currentState == MotionState.MOTION_DASH) { - consumption = new Consumption(ConsumptionType.SPRINT); + consumption = new Consumption(ConsumptionType.DASH); } if (currentState == MotionState.MOTION_RUN) { consumption = new Consumption(ConsumptionType.RUN); @@ -385,22 +361,21 @@ public class MovementManager { return consumption; } - private Consumption getFlyConsumption() { + private Consumption getFlySustainedConsumption() { Consumption consumption = new Consumption(ConsumptionType.FLY); HashMap glidingCostReduction = new HashMap<>() {{ put(212301, 0.8f); // Amber put(222301, 0.8f); // Venti }}; float reduction = 1; - for (EntityAvatar entity: cachedSession.getPlayer().getTeamManager().getActiveTeam()) { - for (int skillId: entity.getAvatar().getProudSkillList()) { + for (EntityAvatar entity : cachedSession.getPlayer().getTeamManager().getActiveTeam()) { + for (int skillId : entity.getAvatar().getProudSkillList()) { if (glidingCostReduction.containsKey(skillId)) { reduction = glidingCostReduction.get(skillId); } } } consumption.amount *= reduction; - // POWERED_FLY, e.g. wind tunnel if (currentState == MotionState.MOTION_POWERED_FLY) { consumption = new Consumption(ConsumptionType.POWERED_FLY); @@ -408,7 +383,7 @@ public class MovementManager { return consumption; } - private Consumption getStandConsumption() { + private Consumption getStandSustainedConsumption() { Consumption consumption = new Consumption(ConsumptionType.None); if (currentState == MotionState.MOTION_STANDBY) { consumption = new Consumption(ConsumptionType.STANDBY); @@ -418,25 +393,4 @@ public class MovementManager { } return consumption; } - - private Consumption getFightConsumption() { - Consumption consumption = new Consumption(ConsumptionType.None); - HashMap fightingCost = new HashMap<>() {{ - put(10013, -1000); // Kamisato Ayaka - put(10413, -1000); // Mona - }}; - if (fightingCost.containsKey(skillCasting)) { - consumption = new Consumption(ConsumptionType.FIGHT, fightingCost.get(skillCasting)); - // only handle once, so reset. - skillCasting = 0; - skillCaster = 0; - } - return consumption; - } - - public void notifySkill(int caster, int skillId) { - skillCaster = caster; - skillCasting = skillId; - } } - diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 1eb5e3526..d2ce39d1c 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -1152,7 +1152,7 @@ public class Player { public void onLogout() { // stop stamina calculation - getMovementManager().resetTimer(); + getMovementManager().stopSustainedStaminaHandler(); // force to leave the dungeon if (getScene().getSceneType() == SceneType.SCENE_DUNGEON) { diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java index 16e8942ad..775be2b87 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamManager.java +++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java @@ -557,7 +557,7 @@ public class TeamManager { // return; // } // } - player.getMovementManager().resetTimer(); // prevent drowning immediately after respawn + player.getMovementManager().stopSustainedStaminaHandler(); // prevent drowning immediately after respawn // Revive all team members for (EntityAvatar entity : getActiveTeam()) { diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java index 27e4ca6ff..c7bbccc5e 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java @@ -1,6 +1,8 @@ package emu.grasscutter.server.packet.recv; +import emu.grasscutter.Grasscutter; import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; @@ -8,11 +10,21 @@ import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; +import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; + +import java.util.HashMap; @Opcodes(PacketOpcodes.CombatInvocationsNotify) public class HandlerCombatInvocationsNotify extends PacketHandler { + private float cachedLandingSpeed = 0; + private long cachedLandingTimeMillisecond = 0; + private boolean monitorLandingEvent = false; + @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { CombatInvocationsNotify notif = CombatInvocationsNotify.parseFrom(payload); @@ -28,7 +40,33 @@ public class HandlerCombatInvocationsNotify extends PacketHandler { EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData()); GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId()); if (entity != null) { - session.getPlayer().getMovementManager().handle(session, moveInfo, entity); + // Move player + MotionInfo motionInfo = moveInfo.getMotionInfo(); + entity.getPosition().set(motionInfo.getPos()); + entity.getRotation().set(motionInfo.getRot()); + entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime()); + entity.setLastMoveReliableSeq(moveInfo.getReliableSeq()); + MotionState motionState = motionInfo.getState(); + entity.setMotionState(motionState); + + session.getPlayer().getMovementManager().handleCombatInvocationsNotify(session, moveInfo, entity); + + // TODO: handle MOTION_FIGHT landing + // For plunge attacks, LAND_SPEED is always -30 and is not useful. + // May need the height when starting plunge attack. + + if (monitorLandingEvent) { + if (motionState == MotionState.MOTION_FALL_ON_GROUND) { + monitorLandingEvent = false; + handleFallOnGround(session, entity, motionState); + } + } + if (motionState == MotionState.MOTION_LAND_SPEED) { + // MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packet. Cache land speed for later use. + cachedLandingSpeed = motionInfo.getSpeed().getY(); + cachedLandingTimeMillisecond = System.currentTimeMillis(); + monitorLandingEvent = true; + } } break; default: @@ -47,5 +85,39 @@ public class HandlerCombatInvocationsNotify extends PacketHandler { } } - + private void handleFallOnGround(GameSession session, GameEntity entity, MotionState motionState) { + // If not received immediately after MOTION_LAND_SPEED, discard this packet. + int maxDelay = 200; + long actualDelay = System.currentTimeMillis() - cachedLandingTimeMillisecond; + Grasscutter.getLogger().debug("MOTION_FALL_ON_GROUND received after " + actualDelay + "/" + maxDelay + "ms." + (actualDelay > maxDelay ? " Discard" : "")); + if (actualDelay > maxDelay) { + return; + } + float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); + float damage = 0; + if (cachedLandingSpeed < -23.5) { + damage = (float) (maxHP * 0.33); + } + if (cachedLandingSpeed < -25) { + damage = (float) (maxHP * 0.5); + } + if (cachedLandingSpeed < -26.5) { + damage = (float) (maxHP * 0.66); + } + if (cachedLandingSpeed < -28) { + damage = (maxHP * 1); + } + float newHP = currentHP - damage; + if (newHP < 0) { + newHP = 0; + } + Grasscutter.getLogger().debug(currentHP + "/" + maxHP + "\t" + "\tDamage: " + damage + "\tnewHP: " + newHP); + entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); + entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); + if (newHP == 0) { + session.getPlayer().getMovementManager().killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_FALL); + } + cachedLandingSpeed = 0; + } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java index a57ae9665..6a08693bb 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java @@ -1,6 +1,5 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.Grasscutter; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; @@ -15,10 +14,7 @@ public class HandlerEvtDoSkillSuccNotify extends PacketHandler { EvtDoSkillSuccNotify notify = EvtDoSkillSuccNotify.parseFrom(payload); // TODO: Will be used for deducting stamina for charged skills. - int caster = notify.getCasterId(); - int skillId = notify.getSkillId(); - - session.getPlayer().getMovementManager().notifySkill(caster, skillId); + session.getPlayer().getMovementManager().handleEvtDoSkillSuccNotify(session, notify); } } From 836e0150b541251041a7575613a4bc45fb1d3195 Mon Sep 17 00:00:00 2001 From: gentlespoon Date: Sat, 7 May 2022 16:29:40 -0700 Subject: [PATCH 14/28] Stop stamina consumption on game pause --- .../{SotSManager => }/SotSManager.java | 7 +++-- ...vementManager.java => StaminaManager.java} | 19 ++++++++----- .../emu/grasscutter/game/player/Player.java | 27 +++++++++---------- .../grasscutter/game/player/TeamManager.java | 2 +- .../recv/HandlerCombatInvocationsNotify.java | 6 ++--- .../HandlerEnterTransPointRegionNotify.java | 11 +------- .../recv/HandlerEvtDoSkillSuccNotify.java | 2 +- .../HandlerExitTransPointRegionNotify.java | 2 +- 8 files changed, 33 insertions(+), 43 deletions(-) rename src/main/java/emu/grasscutter/game/managers/{SotSManager => }/SotSManager.java (95%) rename src/main/java/emu/grasscutter/game/managers/{MovementManager/MovementManager.java => StaminaManager.java} (94%) diff --git a/src/main/java/emu/grasscutter/game/managers/SotSManager/SotSManager.java b/src/main/java/emu/grasscutter/game/managers/SotSManager.java similarity index 95% rename from src/main/java/emu/grasscutter/game/managers/SotSManager/SotSManager.java rename to src/main/java/emu/grasscutter/game/managers/SotSManager.java index 0bfdf9454..ed67c6a62 100644 --- a/src/main/java/emu/grasscutter/game/managers/SotSManager/SotSManager.java +++ b/src/main/java/emu/grasscutter/game/managers/SotSManager.java @@ -1,14 +1,11 @@ -package emu.grasscutter.game.managers.SotSManager; +package emu.grasscutter.game.managers; import emu.grasscutter.Grasscutter; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.entity.EntityAvatar; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.managers.MovementManager.MovementManager; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.PlayerProperty; -import emu.grasscutter.game.world.World; import emu.grasscutter.net.proto.ChangeHpReasonOuterClass; import emu.grasscutter.net.proto.PropChangeReasonOuterClass; import emu.grasscutter.server.game.GameSession; @@ -29,6 +26,8 @@ public class SotSManager { private final Player player; private Timer autoRecoverTimer; + public final static int GlobalMaximumSpringVolume = 8500000; + public SotSManager(Player player) { this.player = player; } diff --git a/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager.java similarity index 94% rename from src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java rename to src/main/java/emu/grasscutter/game/managers/StaminaManager.java index ece02a0fb..5fd4f57b4 100644 --- a/src/main/java/emu/grasscutter/game/managers/MovementManager/MovementManager.java +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager.java @@ -1,4 +1,4 @@ -package emu.grasscutter.game.managers.MovementManager; +package emu.grasscutter.game.managers; import emu.grasscutter.Grasscutter; import emu.grasscutter.game.entity.EntityAvatar; @@ -20,9 +20,11 @@ import emu.grasscutter.utils.Position; import java.lang.Math; import java.util.*; -public class MovementManager { +public class StaminaManager { private final Player player; private HashMap> MotionStatesCategorized = new HashMap<>(); + + public final static int GlobalMaximumStamina = 24000; private Position currentCoordinates = new Position(0, 0, 0); private Position previousCoordinates = new Position(0, 0, 0); private MotionState currentState = MotionState.MOTION_STANDBY; @@ -84,7 +86,7 @@ public class MovementManager { isInSkillMove = b; } - public MovementManager(Player player) { + public StaminaManager(Player player) { this.player = player; MotionStatesCategorized.put("SWIM", new HashSet<>(Arrays.asList( @@ -181,11 +183,14 @@ public class MovementManager { } public void startSustainedStaminaHandler() { - if (sustainedStaminaHandlerTimer == null) { - sustainedStaminaHandlerTimer = new Timer(); - sustainedStaminaHandlerTimer.scheduleAtFixedRate(new SustainedStaminaHandler(), 0, 200); - Grasscutter.getLogger().debug("[MovementManager] SustainedStaminaHandlerTimer started"); + if (!player.isPaused()) { + if (sustainedStaminaHandlerTimer == null) { + sustainedStaminaHandlerTimer = new Timer(); + sustainedStaminaHandlerTimer.scheduleAtFixedRate(new SustainedStaminaHandler(), 0, 200); + Grasscutter.getLogger().debug("[MovementManager] SustainedStaminaHandlerTimer started"); + } } + } public void stopSustainedStaminaHandler() { diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index d2ce39d1c..3a2f3cbff 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -22,8 +22,8 @@ import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.mail.MailHandler; -import emu.grasscutter.game.managers.MovementManager.MovementManager; -import emu.grasscutter.game.managers.SotSManager.SotSManager; +import emu.grasscutter.game.managers.StaminaManager; +import emu.grasscutter.game.managers.SotSManager; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.props.PlayerProperty; @@ -62,9 +62,6 @@ import java.util.concurrent.LinkedBlockingQueue; @Entity(value = "players", useDiscriminator = false) public class Player { - @Transient private static int GlobalMaximumSpringVolume = 8500000; - @Transient private static int GlobalMaximumStamina = 24000; - @Id private int id; @Indexed(options = @IndexOptions(unique = true)) private String accountId; @@ -132,7 +129,7 @@ public class Player { @Transient private final InvokeHandler clientAbilityInitFinishHandler; private MapMarksManager mapMarksManager; - @Transient private MovementManager movementManager; + @Transient private StaminaManager staminaManager; private long springLastUsed; @@ -178,7 +175,7 @@ public class Player { this.expeditionInfo = new HashMap<>(); this.messageHandler = null; this.mapMarksManager = new MapMarksManager(); - this.movementManager = new MovementManager(this); + this.staminaManager = new StaminaManager(this); this.sotsManager = new SotSManager(this); } @@ -206,7 +203,7 @@ public class Player { this.getRotation().set(0, 307, 0); this.messageHandler = null; this.mapMarksManager = new MapMarksManager(); - this.movementManager = new MovementManager(this); + this.staminaManager = new StaminaManager(this); this.sotsManager = new SotSManager(this); } @@ -875,11 +872,11 @@ public class Player { } public void onPause() { - + staminaManager.stopSustainedStaminaHandler(); } public void onUnpause() { - + staminaManager.startSustainedStaminaHandler(); } public void sendPacket(BasePacket packet) { @@ -1024,7 +1021,7 @@ public class Player { return mapMarksManager; } - public MovementManager getMovementManager() { return movementManager; } + public StaminaManager getStaminaManager() { return staminaManager; } public SotSManager getSotSManager() { return sotsManager; } @@ -1152,7 +1149,7 @@ public class Player { public void onLogout() { // stop stamina calculation - getMovementManager().stopSustainedStaminaHandler(); + getStaminaManager().stopSustainedStaminaHandler(); // force to leave the dungeon if (getScene().getSceneType() == SceneType.SCENE_DUNGEON) { @@ -1214,7 +1211,7 @@ public class Player { } else if (prop == PlayerProperty.PROP_LAST_CHANGE_AVATAR_TIME) { // 10001 // TODO: implement sanity check } else if (prop == PlayerProperty.PROP_MAX_SPRING_VOLUME) { // 10002 - if (!(value >= 0 && value <= GlobalMaximumSpringVolume)) { return false; } + if (!(value >= 0 && value <= getSotSManager().GlobalMaximumSpringVolume)) { return false; } } else if (prop == PlayerProperty.PROP_CUR_SPRING_VOLUME) { // 10003 int playerMaximumSpringVolume = getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME); if (!(value >= 0 && value <= playerMaximumSpringVolume)) { return false; } @@ -1231,7 +1228,7 @@ public class Player { } else if (prop == PlayerProperty.PROP_IS_TRANSFERABLE) { // 10009 if (!(0 <= value && value <= 1)) { return false; } } else if (prop == PlayerProperty.PROP_MAX_STAMINA) { // 10010 - if (!(value >= 0 && value <= GlobalMaximumStamina)) { return false; } + if (!(value >= 0 && value <= getStaminaManager().GlobalMaximumStamina)) { return false; } } else if (prop == PlayerProperty.PROP_CUR_PERSIST_STAMINA) { // 10011 int playerMaximumStamina = getProperty(PlayerProperty.PROP_MAX_STAMINA); if (!(value >= 0 && value <= playerMaximumStamina)) { return false; } @@ -1242,7 +1239,7 @@ public class Player { } else if (prop == PlayerProperty.PROP_PLAYER_EXP) { // 10014 if (!(0 <= value)) { return false; } } else if (prop == PlayerProperty.PROP_PLAYER_HCOIN) { // 10015 - // see 10015 + // see PlayerProperty.PROP_PLAYER_HCOIN comments } else if (prop == PlayerProperty.PROP_PLAYER_SCOIN) { // 10016 // See 10015 } else if (prop == PlayerProperty.PROP_PLAYER_MP_SETTING_TYPE) { // 10017 diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java index 775be2b87..204af2976 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamManager.java +++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java @@ -557,7 +557,7 @@ public class TeamManager { // return; // } // } - player.getMovementManager().stopSustainedStaminaHandler(); // prevent drowning immediately after respawn + player.getStaminaManager().stopSustainedStaminaHandler(); // prevent drowning immediately after respawn // Revive all team members for (EntityAvatar entity : getActiveTeam()) { diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java index c7bbccc5e..cc9e7b345 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java @@ -16,8 +16,6 @@ import emu.grasscutter.net.proto.PlayerDieTypeOuterClass; import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; -import java.util.HashMap; - @Opcodes(PacketOpcodes.CombatInvocationsNotify) public class HandlerCombatInvocationsNotify extends PacketHandler { @@ -49,7 +47,7 @@ public class HandlerCombatInvocationsNotify extends PacketHandler { MotionState motionState = motionInfo.getState(); entity.setMotionState(motionState); - session.getPlayer().getMovementManager().handleCombatInvocationsNotify(session, moveInfo, entity); + session.getPlayer().getStaminaManager().handleCombatInvocationsNotify(session, moveInfo, entity); // TODO: handle MOTION_FIGHT landing // For plunge attacks, LAND_SPEED is always -30 and is not useful. @@ -116,7 +114,7 @@ public class HandlerCombatInvocationsNotify extends PacketHandler { entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP); entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); if (newHP == 0) { - session.getPlayer().getMovementManager().killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_FALL); + session.getPlayer().getStaminaManager().killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_FALL); } cachedLandingSpeed = 0; } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java index 5591607fe..94c9bfd8b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java @@ -1,20 +1,11 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.game.managers.SotSManager.SotSManager; +import emu.grasscutter.game.managers.SotSManager; import emu.grasscutter.game.player.Player; -import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; -import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; -import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; -import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; - -import java.util.List; @Opcodes(PacketOpcodes.EnterTransPointRegionNotify) public class HandlerEnterTransPointRegionNotify extends PacketHandler { diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java index 6a08693bb..705341fa0 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java @@ -14,7 +14,7 @@ public class HandlerEvtDoSkillSuccNotify extends PacketHandler { EvtDoSkillSuccNotify notify = EvtDoSkillSuccNotify.parseFrom(payload); // TODO: Will be used for deducting stamina for charged skills. - session.getPlayer().getMovementManager().handleEvtDoSkillSuccNotify(session, notify); + session.getPlayer().getStaminaManager().handleEvtDoSkillSuccNotify(session, notify); } } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java index 35ec957cb..0d35c1762 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerExitTransPointRegionNotify.java @@ -1,6 +1,6 @@ package emu.grasscutter.server.packet.recv; -import emu.grasscutter.game.managers.SotSManager.SotSManager; +import emu.grasscutter.game.managers.SotSManager; import emu.grasscutter.game.player.Player; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; From 29f9d6506a2deb1e43a098027ec1c25acd8f7e8f Mon Sep 17 00:00:00 2001 From: gentlespoon Date: Sat, 7 May 2022 18:07:44 -0700 Subject: [PATCH 15/28] Make stamina consumption classes public so others can use. --- .../managers/StaminaManager/Consumption.java | 15 +++++++ .../StaminaManager/ConsumptionType.java | 30 +++++++++++++ .../{ => StaminaManager}/StaminaManager.java | 42 +------------------ .../emu/grasscutter/game/player/Player.java | 2 +- 4 files changed, 47 insertions(+), 42 deletions(-) create mode 100644 src/main/java/emu/grasscutter/game/managers/StaminaManager/Consumption.java create mode 100644 src/main/java/emu/grasscutter/game/managers/StaminaManager/ConsumptionType.java rename src/main/java/emu/grasscutter/game/managers/{ => StaminaManager}/StaminaManager.java (92%) diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/Consumption.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/Consumption.java new file mode 100644 index 000000000..23eb44be9 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/Consumption.java @@ -0,0 +1,15 @@ +package emu.grasscutter.game.managers.StaminaManager; + +public class Consumption { + public ConsumptionType consumptionType; + public int amount; + + public Consumption(ConsumptionType ct, int a) { + consumptionType = ct; + amount = a; + } + + public Consumption(ConsumptionType ct) { + this(ct, ct.amount); + } +} diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/ConsumptionType.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/ConsumptionType.java new file mode 100644 index 000000000..9a2d8ae24 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/ConsumptionType.java @@ -0,0 +1,30 @@ +package emu.grasscutter.game.managers.StaminaManager; + +public enum ConsumptionType { + None(0), + + // consume + CLIMB_START(-500), + CLIMBING(-150), + CLIMB_JUMP(-2500), + SPRINT(-1800), + DASH(-360), + FLY(-60), + SWIM_DASH_START(-200), + SWIM_DASH(-200), + SWIMMING(-80), + FIGHT(0), + + // restore + STANDBY(500), + RUN(500), + WALK(500), + STANDBY_MOVE(500), + POWERED_FLY(500); + + public final int amount; + + ConsumptionType(int amount) { + this.amount = amount; + } +} \ No newline at end of file diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java similarity index 92% rename from src/main/java/emu/grasscutter/game/managers/StaminaManager.java rename to src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java index 5fd4f57b4..3d55e5edf 100644 --- a/src/main/java/emu/grasscutter/game/managers/StaminaManager.java +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java @@ -1,4 +1,4 @@ -package emu.grasscutter.game.managers; +package emu.grasscutter.game.managers.StaminaManager; import emu.grasscutter.Grasscutter; import emu.grasscutter.game.entity.EntityAvatar; @@ -35,48 +35,8 @@ public class StaminaManager { private int staminaRecoverDelay = 0; private boolean isInSkillMove = false; - private enum ConsumptionType { - None(0), - // consume - CLIMB_START(-500), - CLIMBING(-150), - CLIMB_JUMP(-2500), - SPRINT(-1800), - DASH(-360), - FLY(-60), - SWIM_DASH_START(-200), - SWIM_DASH(-200), - SWIMMING(-80), - FIGHT(0), - // restore - STANDBY(500), - RUN(500), - WALK(500), - STANDBY_MOVE(500), - POWERED_FLY(500); - - public final int amount; - - ConsumptionType(int amount) { - this.amount = amount; - } - } - - private class Consumption { - public ConsumptionType consumptionType; - public int amount; - - public Consumption(ConsumptionType ct, int a) { - consumptionType = ct; - amount = a; - } - - public Consumption(ConsumptionType ct) { - this(ct, ct.amount); - } - } public boolean getIsInSkillMove() { return isInSkillMove; diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 3a2f3cbff..b6956153c 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -22,7 +22,7 @@ import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.mail.MailHandler; -import emu.grasscutter.game.managers.StaminaManager; +import emu.grasscutter.game.managers.StaminaManager.StaminaManager; import emu.grasscutter.game.managers.SotSManager; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.EntityType; From eb94adb296a088e65e13c0e2e26dd8d184e55f5d Mon Sep 17 00:00:00 2001 From: Akka <104902222+Akka0@users.noreply.github.com> Date: Sat, 7 May 2022 21:47:13 +0800 Subject: [PATCH 16/28] Monsters tide turn by turn && Ban User Skill && Lua functions --- .../game/entity/EntityMonster.java | 1 + .../grasscutter/game/tower/TowerManager.java | 4 +- .../emu/grasscutter/game/world/Scene.java | 8 +- .../scripts/SceneScriptManager.java | 151 +++++++++++------- .../emu/grasscutter/scripts/ScriptLib.java | 123 +++++++++++--- .../grasscutter/scripts/data/SceneGroup.java | 12 +- .../packet/send/PacketCanUseSkillNotify.java | 19 +++ src/main/resources/logback.xml | 2 + 8 files changed, 232 insertions(+), 88 deletions(-) create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java diff --git a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java index c9d0c0982..0ae6f356b 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityMonster.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityMonster.java @@ -117,6 +117,7 @@ public class EntityMonster extends GameEntity { this.getScene().getDeadSpawnedEntities().add(getSpawnEntry()); } if (getScene().getScriptManager().isInit() && this.getGroupId() > 0) { + getScene().getScriptManager().onMonsterDie(); getScene().getScriptManager().callEvent(EventType.EVENT_ANY_MONSTER_DIE, null); } if (getScene().getChallenge() != null && getScene().getChallenge().getGroup().id == this.getGroupId()) { diff --git a/src/main/java/emu/grasscutter/game/tower/TowerManager.java b/src/main/java/emu/grasscutter/game/tower/TowerManager.java index 51f840663..409549a1f 100644 --- a/src/main/java/emu/grasscutter/game/tower/TowerManager.java +++ b/src/main/java/emu/grasscutter/game/tower/TowerManager.java @@ -7,6 +7,7 @@ import emu.grasscutter.data.def.TowerLevelData; import emu.grasscutter.game.dungeons.DungeonSettleListener; import emu.grasscutter.game.dungeons.TowerDungeonSettleListener; import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify; import emu.grasscutter.server.packet.send.PacketTowerCurLevelRecordChangeNotify; import emu.grasscutter.server.packet.send.PacketTowerEnterLevelRsp; @@ -75,7 +76,8 @@ public class TowerManager { player.getScene().setPrevScenePoint(enterPointId); player.getSession().send(new PacketTowerEnterLevelRsp(currentFloorId, currentLevel)); - + // stop using skill + player.getSession().send(new PacketCanUseSkillNotify(false)); } public void notifyCurLevelRecordChange(){ diff --git a/src/main/java/emu/grasscutter/game/world/Scene.java b/src/main/java/emu/grasscutter/game/world/Scene.java index 97099c9b9..82ce9139f 100644 --- a/src/main/java/emu/grasscutter/game/world/Scene.java +++ b/src/main/java/emu/grasscutter/game/world/Scene.java @@ -105,7 +105,13 @@ public class Scene { public GameEntity getEntityById(int id) { return this.entities.get(id); } - + + public GameEntity getEntityByConfigId(int configId) { + return this.entities.values().stream() + .filter(x -> x.getConfigId() == configId) + .findFirst() + .orElse(null); + } /** * @return the autoCloseTime */ diff --git a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java index 5f6a1b7e6..b8ba800a6 100644 --- a/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java +++ b/src/main/java/emu/grasscutter/scripts/SceneScriptManager.java @@ -1,19 +1,14 @@ package emu.grasscutter.scripts; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import javax.script.Bindings; import javax.script.CompiledScript; import javax.script.ScriptException; -import org.luaj.vm2.LuaTable; import org.luaj.vm2.LuaValue; import org.luaj.vm2.lib.jse.CoerceJavaToLua; @@ -23,12 +18,8 @@ import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.data.def.WorldLevelData; import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityMonster; -import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.game.props.EntityType; import emu.grasscutter.game.world.Scene; import emu.grasscutter.scripts.constants.EventType; -import emu.grasscutter.scripts.constants.ScriptGadgetState; -import emu.grasscutter.scripts.constants.ScriptRegionShape; import emu.grasscutter.scripts.data.SceneBlock; import emu.grasscutter.scripts.data.SceneConfig; import emu.grasscutter.scripts.data.SceneGadget; @@ -56,7 +47,12 @@ public class SceneScriptManager { private final Int2ObjectOpenHashMap> triggers; private final Int2ObjectOpenHashMap regions; - + private SceneGroup currentGroup; + private AtomicInteger monsterAlive; + private AtomicInteger monsterTideCount; + private int monsterSceneLimit; + private ConcurrentLinkedQueue monsterOrders; + public SceneScriptManager(Scene scene) { this.scene = scene; this.scriptLib = new ScriptLib(this); @@ -222,7 +218,8 @@ public class SceneScriptManager { cs.eval(getBindings()); // Set - group.monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, bindings.get("monsters")); + group.monsters = ScriptLoader.getSerializer().toList(SceneMonster.class, bindings.get("monsters")).stream() + .collect(Collectors.toMap(x -> x.config_id, y -> y)); group.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, bindings.get("gadgets")); group.triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, bindings.get("triggers")); group.suites = ScriptLoader.getSerializer().toList(SceneSuite.class, bindings.get("suites")); @@ -235,7 +232,7 @@ public class SceneScriptManager { // Add monsters to suite TODO optimize Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); - group.monsters.forEach(m -> map.put(m.config_id, m)); + group.monsters.entrySet().forEach(m -> map.put(m.getValue().config_id, m)); group.gadgets.forEach(m -> map.put(m.config_id, m)); for (SceneSuite suite : group.suites) { @@ -323,60 +320,92 @@ public class SceneScriptManager { } public void spawnMonstersInGroup(SceneGroup group, int suiteIndex) { - spawnMonstersInGroup(group, group.getSuiteByIndex(suiteIndex)); + this.currentGroup = group; + this.monsterSceneLimit = 0; + var suite = group.getSuiteByIndex(suiteIndex); + if(suite == null){ + return; + } + suite.sceneMonsters.forEach(mob -> spawnMonstersInGroup(group, mob)); } public void spawnMonstersInGroup(SceneGroup group) { - spawnMonstersInGroup(group, null); + this.currentGroup = group; + this.monsterSceneLimit = 0; + group.monsters.values().forEach(mob -> spawnMonstersInGroup(group, mob)); } - - public void spawnMonstersInGroup(SceneGroup group, SceneSuite suite) { - List monsters = group.monsters; - - if (suite != null) { - monsters = suite.sceneMonsters; + public void spawnMonstersInGroup(SceneGroup group,Integer[] ordersConfigId, int tideCount, int sceneLimit) { + this.currentGroup = group; + this.monsterSceneLimit = sceneLimit; + this.monsterTideCount = new AtomicInteger(tideCount); + this.monsterAlive = new AtomicInteger(0); + this.monsterOrders = new ConcurrentLinkedQueue<>(List.of(ordersConfigId)); + + // add the last turn + group.monsters.keySet().stream() + .filter(i -> !this.monsterOrders.contains(i)) + .forEach(this.monsterOrders::add); + for (int i = 0; i < sceneLimit; i++) { + spawnMonstersInGroup(group, group.monsters.get(this.monsterOrders.poll())); + } + } + public void spawnMonstersInGroup(SceneGroup group, SceneMonster monster) { + if(monster == null){ + return; + } + if(this.monsterSceneLimit > 0){ + this.monsterTideCount.decrementAndGet(); + this.monsterAlive.incrementAndGet(); } - List toAdd = new ArrayList<>(); - - for (SceneMonster monster : monsters) { - MonsterData data = GameData.getMonsterDataMap().get(monster.monster_id); - - if (data == null) { - continue; - } - - // Calculate level - int level = monster.level; - - if (getScene().getDungeonData() != null) { - level = getScene().getDungeonData().getShowLevel(); - } else if (getScene().getWorld().getWorldLevel() > 0) { - WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getScene().getWorld().getWorldLevel()); - - if (worldLevelData != null) { - level = worldLevelData.getMonsterLevel(); - } - } - - // Spawn mob - EntityMonster entity = new EntityMonster(getScene(), data, monster.pos, level); - entity.getRotation().set(monster.rot); - entity.setGroupId(group.id); - entity.setConfigId(monster.config_id); - - toAdd.add(entity); + MonsterData data = GameData.getMonsterDataMap().get(monster.monster_id); + + if (data == null) { + return; } - - if (toAdd.size() > 0) { - getScene().addEntities(toAdd); - - for (GameEntity entity : toAdd) { - callEvent(EventType.EVENT_ANY_MONSTER_LIVE, new ScriptArgs(entity.getConfigId())); + + // Calculate level + int level = monster.level; + + if (getScene().getDungeonData() != null) { + level = getScene().getDungeonData().getShowLevel(); + } else if (getScene().getWorld().getWorldLevel() > 0) { + WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getScene().getWorld().getWorldLevel()); + + if (worldLevelData != null) { + level = worldLevelData.getMonsterLevel(); + } + } + + // Spawn mob + EntityMonster entity = new EntityMonster(getScene(), data, monster.pos, level); + entity.getRotation().set(monster.rot); + entity.setGroupId(group.id); + entity.setConfigId(monster.config_id); + + getScene().addEntity(entity); + + callEvent(EventType.EVENT_ANY_MONSTER_LIVE, new ScriptArgs(entity.getConfigId())); + } + + public void onMonsterDie(){ + if(this.monsterSceneLimit <= 0){ + return; + } + if(this.monsterAlive.decrementAndGet() >= this.monsterSceneLimit) { + // maybe not happen + return; + } + if(this.monsterTideCount.get() > 0){ + // add more + spawnMonstersInGroup(this.currentGroup, this.currentGroup.monsters.get(this.monsterOrders.poll())); + }else if(this.monsterAlive.get() == 0){ + // spawn the last turn of monsters + while(!this.monsterOrders.isEmpty()){ + spawnMonstersInGroup(this.currentGroup, this.currentGroup.monsters.get(this.monsterOrders.poll())); } } } - // Events public void callEvent(int eventType, ScriptArgs params) { @@ -405,4 +434,8 @@ public class SceneScriptManager { } } } + +// public LuaValue safetyCall(){ +// +// } } diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index 941b00b60..1b9badc11 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -1,28 +1,24 @@ package emu.grasscutter.scripts; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import org.luaj.vm2.LuaTable; -import org.luaj.vm2.LuaValue; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.data.GameData; -import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.game.dungeons.DungeonChallenge; import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityMonster; import emu.grasscutter.game.entity.GameEntity; -import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.data.SceneGroup; -import emu.grasscutter.scripts.data.SceneMonster; import emu.grasscutter.scripts.data.SceneRegion; -import emu.grasscutter.scripts.data.ScriptArgs; +import emu.grasscutter.server.packet.send.PacketCanUseSkillNotify; import emu.grasscutter.server.packet.send.PacketGadgetStateNotify; import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify; +import org.luaj.vm2.LuaTable; +import org.luaj.vm2.LuaValue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Optional; public class ScriptLib { + public static final Logger logger = LoggerFactory.getLogger(ScriptLib.class); private final SceneScriptManager sceneScriptManager; public ScriptLib(SceneScriptManager sceneScriptManager) { @@ -34,6 +30,8 @@ public class ScriptLib { } public int SetGadgetStateByConfigId(int configId, int gadgetState) { + logger.debug("[LUA] Call SetGadgetStateByConfigId with {},{}", + configId,gadgetState); Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e.getConfigId() == configId).findFirst(); @@ -53,6 +51,8 @@ public class ScriptLib { } public int SetGroupGadgetStateByConfigId(int groupId, int configId, int gadgetState) { + logger.debug("[LUA] Call SetGroupGadgetStateByConfigId with {},{},{}", + groupId,configId,gadgetState); List list = getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e.getGroupId() == groupId).toList(); @@ -71,6 +71,8 @@ public class ScriptLib { } public int SetWorktopOptionsByGroupId(int groupId, int configId, int[] options) { + logger.debug("[LUA] Call SetWorktopOptionsByGroupId with {},{},{}", + groupId,configId,options); Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId).findFirst(); @@ -90,6 +92,8 @@ public class ScriptLib { } public int DelWorktopOptionByGroupId(int groupId, int configId, int option) { + logger.debug("[LUA] Call DelWorktopOptionByGroupId with {},{},{}",groupId,configId,option); + Optional entity = getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e.getConfigId() == configId && e.getGroupId() == groupId).findFirst(); @@ -109,20 +113,24 @@ public class ScriptLib { } // Some fields are guessed - public int AutoMonsterTide(int challengeIndex, int groupId, int[] config_ids, int param4, int param5, int param6) { + public int AutoMonsterTide(int challengeIndex, int groupId, Integer[] ordersConfigId, int tideCount, int sceneLimit, int param6) { + logger.debug("[LUA] Call AutoMonsterTide with {},{},{},{},{},{}", + challengeIndex,groupId,ordersConfigId,tideCount,sceneLimit,param6); + SceneGroup group = getSceneScriptManager().getGroupById(groupId); if (group == null || group.monsters == null) { return 1; } - - // TODO just spawn all from group for now - this.getSceneScriptManager().spawnMonstersInGroup(group); + + this.getSceneScriptManager().spawnMonstersInGroup(group, ordersConfigId, tideCount, sceneLimit); return 0; } public int AddExtraGroupSuite(int groupId, int suite) { + logger.debug("[LUA] Call AddExtraGroupSuite with {},{}", + groupId,suite); SceneGroup group = getSceneScriptManager().getGroupById(groupId); if (group == null || group.monsters == null) { @@ -136,8 +144,17 @@ public class ScriptLib { } // param3 (probably time limit for timed dungeons) - public int ActiveChallenge(int challengeId, int challengeIndex, int param3, int groupId, int objectiveKills, int param5) { + public int ActiveChallenge(int challengeId, int challengeIndex, int timeLimitOrGroupId, int groupId, int objectiveKills, int param5) { + logger.debug("[LUA] Call ActiveChallenge with {},{},{},{},{},{}", + challengeId,challengeIndex,timeLimitOrGroupId,groupId,objectiveKills,param5); + SceneGroup group = getSceneScriptManager().getGroupById(groupId); + var objective = objectiveKills; + + if(group == null){ + group = getSceneScriptManager().getGroupById(timeLimitOrGroupId); + objective = groupId; + } if (group == null || group.monsters == null) { return 1; @@ -146,7 +163,7 @@ public class ScriptLib { DungeonChallenge challenge = new DungeonChallenge(getSceneScriptManager().getScene(), group); challenge.setChallengeId(challengeId); challenge.setChallengeIndex(challengeIndex); - challenge.setObjective(objectiveKills); + challenge.setObjective(objective); getSceneScriptManager().getScene().setChallenge(challenge); @@ -155,26 +172,37 @@ public class ScriptLib { } public int GetGroupMonsterCountByGroupId(int groupId) { + logger.debug("[LUA] Call GetGroupMonsterCountByGroupId with {}", + groupId); return (int) getSceneScriptManager().getScene().getEntities().values().stream() .filter(e -> e instanceof EntityMonster && e.getGroupId() == groupId) .count(); } public int GetGroupVariableValue(String var) { + logger.debug("[LUA] Call GetGroupVariableValue with {}", + var); return getSceneScriptManager().getVariables().getOrDefault(var, 0); } public int SetGroupVariableValue(String var, int value) { + logger.debug("[LUA] Call SetGroupVariableValue with {},{}", + var, value); getSceneScriptManager().getVariables().put(var, value); return 0; } public LuaValue ChangeGroupVariableValue(String var, int value) { + logger.debug("[LUA] Call ChangeGroupVariableValue with {},{}", + var, value); + getSceneScriptManager().getVariables().put(var, getSceneScriptManager().getVariables().get(var) + value); return LuaValue.ZERO; } public int RefreshGroup(LuaTable table) { + logger.debug("[LUA] Call RefreshGroup with {}", + table); // Kill and Respawn? int groupId = table.get("group_id").toint(); int suite = table.get("suite").toint(); @@ -192,6 +220,8 @@ public class ScriptLib { } public int GetRegionEntityCount(LuaTable table) { + logger.debug("[LUA] Call GetRegionEntityCount with {}", + table); int regionId = table.get("region_eid").toint(); int entityType = table.get("entity_type").toint(); @@ -205,21 +235,68 @@ public class ScriptLib { } public void PrintContextLog(String msg) { - Grasscutter.getLogger().info("[LUA] " + msg); + logger.info("[LUA] " + msg); } - public int TowerCountTimeStatus(int var1, int var2){ + public int TowerCountTimeStatus(int isDone, int var2){ + logger.debug("[LUA] Call TowerCountTimeStatus with {},{}", + isDone,var2); + // TODO record time return 0; } public int GetGroupMonsterCount(int var1){ - // Maybe... - return GetGroupMonsterCountByGroupId(var1); + logger.debug("[LUA] Call GetGroupMonsterCount with {}", + var1); + + return (int) getSceneScriptManager().getScene().getEntities().values().stream() + .filter(e -> e instanceof EntityMonster) + .count(); } public int SetMonsterBattleByGroup(int var1, int var2, int var3){ + logger.debug("[LUA] Call SetMonsterBattleByGroup with {},{},{}", + var1,var2,var3); + return 0; } public int CauseDungeonFail(int var1){ + logger.debug("[LUA] Call CauseDungeonFail with {}", + var1); + return 0; } + // 8-1 + public int GetGroupVariableValueByGroup(int var1, String var2, int var3){ + logger.debug("[LUA] Call GetGroupVariableValueByGroup with {},{},{}", + var1,var2,var3); + + //TODO + + return getSceneScriptManager().getVariables().getOrDefault(var2, 0); + } + + public int SetIsAllowUseSkill(int canUse, int var2){ + logger.debug("[LUA] Call SetIsAllowUseSkill with {},{}", + canUse,var2); + + getSceneScriptManager().getScene().broadcastPacket(new PacketCanUseSkillNotify(canUse == 1)); + return 0; + } + + public int KillEntityByConfigId(LuaTable table){ + logger.debug("[LUA] Call KillEntityByConfigId with {}", + table); + var configId = table.get("config_id"); + if(configId == LuaValue.NIL){ + return 1; + } + + var entity = getSceneScriptManager().getScene().getEntityByConfigId(configId.toint()); + if(entity == null){ + return 1; + } + getSceneScriptManager().getScene().killEntity(entity, 0); + return 0; + } + } diff --git a/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java b/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java index a13db7b68..690cd3d0d 100644 --- a/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java +++ b/src/main/java/emu/grasscutter/scripts/data/SceneGroup.java @@ -1,17 +1,21 @@ package emu.grasscutter.scripts.data; -import java.util.List; - import emu.grasscutter.utils.Position; +import java.util.List; +import java.util.Map; + public class SceneGroup { public transient int block_id; // Not an actual variable in the scripts but we will keep it here for reference public int id; public int refresh_id; public Position pos; - - public List monsters; + + /** + * ConfigId - Monster + */ + public Map monsters; public List gadgets; public List triggers; public List regions; diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java new file mode 100644 index 000000000..f8fe1314a --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCanUseSkillNotify.java @@ -0,0 +1,19 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CanUseSkillNotifyOuterClass; + +public class PacketCanUseSkillNotify extends BasePacket { + + public PacketCanUseSkillNotify(boolean canUseSkill) { + super(PacketOpcodes.CanUseSkillNotify); + + CanUseSkillNotifyOuterClass.CanUseSkillNotify proto = CanUseSkillNotifyOuterClass.CanUseSkillNotify.newBuilder() + .setIsCanUseSkill(canUseSkill) + .build(); + + this.setData(proto); + } + +} diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 91d3f133c..1fc6831cb 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -19,4 +19,6 @@ + + \ No newline at end of file From 50307ea3a93e05ac1ae1e08ef01b3dd432a191b9 Mon Sep 17 00:00:00 2001 From: Zakhil Date: Sun, 8 May 2022 03:19:24 +0200 Subject: [PATCH 17/28] Added polish locale (#655) --- src/main/resources/languages/pl-PL.json | 298 ++++++++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 src/main/resources/languages/pl-PL.json diff --git a/src/main/resources/languages/pl-PL.json b/src/main/resources/languages/pl-PL.json new file mode 100644 index 000000000..e9ff74e25 --- /dev/null +++ b/src/main/resources/languages/pl-PL.json @@ -0,0 +1,298 @@ +{ + "messages": { + "game": { + "port_bind": "Serwer gry uruchomiony na porcie: %s", + "connect": "Klient połączył się z %s", + "disconnect": "Klient rozłączył się z %s", + "game_update_error": "Wystąpił błąd podczas aktualizacji gry.", + "command_error": "Błąd komendy:" + }, + "dispatch": { + "port_bind": "[Dispatch] Serwer dispatch wystartował na porcie %s", + "request": "[Dispatch] Klient %s %s zapytanie: %s", + "keystore": { + "general_error": "[Dispatch] Błąd łądowania keystore!", + "password_error": "[Dispatch] Nie można załadować keystore. Próba z domyślnym hasłem keystore...", + "no_keystore_error": "[Dispatch] Brak certyfikatu SSL! Przejście na serwer HTTP.", + "default_password": "[Dispatch] Domyślne hasło keystore zadziałało. Rozważ ustawienie go na 123456 w pliku config.json." + }, + "no_commands_error": "Komendy nie są wspierane w trybie DISPATCH_ONLY.", + "unhandled_request_error": "[Dispatch] Potencjalnie niepodtrzymane %s zapytanie: %s", + "account": { + "login_attempt": "[Dispatch] Klient %s próbuje się zalogować", + "login_success": "[Dispatch] Klient %s zalogował się jako %s", + "login_token_attempt": "[Dispatch] Klient %s próbuje się zalogować poprzez token", + "login_token_error": "[Dispatch] Klient %s nie mógł się zalogować poprzez token", + "login_token_success": "[Dispatch] Klient %s zalogował się poprzez token jako %s", + "combo_token_success": "[Dispatch] Klient %s pomyślnie wymienił combo token", + "combo_token_error": "[Dispatch] Klient %s nie wymienił combo token'u", + "account_login_create_success": "[Dispatch] Klient %s nie mógł się zalogować: Konto %s stworzone", + "account_login_create_error": "[Dispatch] Klient %s nie mógł się zalogować: Tworzenie konta nie powiodło się", + "account_login_exist_error": "[Dispatch] Klient %s nie mógł się zalogować: Nie znaleziono konta", + "account_cache_error": "Błąd pamięci cache konta gry", + "session_key_error": "Błędny klucz sesji.", + "username_error": "Nazwa użytkownika nie znaleziona.", + "username_create_error": "Nazwa użytkownika nie znaleziona, tworzenie nie powiodło się." + } + }, + "status": { + "free_software": "Grasscutter to DARMOWE oprogramowanie. Jeżeli ktoś Ci je sprzedał, to zostałeś oscamowany. Strona domowa: https://github.com/Grasscutters/Grasscutter", + "starting": "Uruchamianie Grasscutter...", + "shutdown": "Wyłączanie...", + "done": "Gotowe! Wpisz \"help\" aby uzyskać pomoc", + "error": "Wystąpił błąd.", + "welcome": "Witamy w Grasscutter", + "run_mode_error": "Błędny tryb pracy serwera: %s.", + "run_mode_help": "Tryb pracy serwera musi być ustawiony na 'HYBRID', 'DISPATCH_ONLY', lub 'GAME_ONLY'. Nie można wystartować Grasscutter...", + "create_resources": "Tworzenie folderu resources...", + "resources_error": "Umieść kopię 'BinOutput' i 'ExcelBinOutput' w folderze resources." + } + }, + "commands": { + "generic": { + "not_specified": "Nie podano komendy.", + "unknown_command": "Nieznana komenda: %s", + "permission_error": "Nie masz uprawnień do tej komendy.", + "console_execute_error": "Tą komende można wywołać tylko z konsoli.", + "player_execute_error": "Wywołaj tą komendę w grze.", + "command_exist_error": "Nie znaleziono komendy.", + "invalid": { + "amount": "Błędna ilość.", + "artifactId": "Błędne ID artefaktu.", + "avatarId": "Błędne id postaci.", + "avatarLevel": "Błędny poziom postaci.", + "entityId": "Błędne id obiektu.", + "id przedmiotu": "Błędne id przedmiotu.", + "itemLevel": "Błędny poziom przedmiotu.", + "itemRefinement": "Błędne ulepszenie.", + "playerId": "Błędne playerId.", + "uid": "Błędne UID." + } + }, + "execution": { + "uid_error": "Błędne UID.", + "player_exist_error": "Gracz nie znaleziony.", + "player_offline_error": "Gracz nie jest online.", + "item_id_error": "Błędne ID przedmiotu.", + "item_player_exist_error": "Błędny przedmiot lub UID.", + "entity_id_error": "Błędne ID obiektu.", + "player_exist_offline_error": "Gracz nie znaleziony lub jest offline.", + "argument_error": "Błędne argumenty.", + "clear_target": "Cel wyczyszczony.", + "set_target": "Następne komendy będą celować w @%s.", + "need_target": "Ta komenda wymaga docelowego UID. Dodaj argument <@UID> lub ustaw stały cel poleceniem /target @UID." + }, + "status": { + "enabled": "Włączone", + "disabled": "Wyłączone", + "help": "Pomoc", + "success": "Sukces" + }, + "account": { + "modify": "Modyfikuj konta użytkowników", + "invalid": "Błędne UID.", + "exists": "Konto już istnieje.", + "create": "Stworzono konto z UID %s.", + "delete": "Konto usunięte.", + "no_account": "Nie znaleziono konta.", + "command_usage": "Użycie: account [uid]" + }, + "broadcast": { + "command_usage": "Użycie: broadcast ", + "message_sent": "Wiadomość wysłana." + }, + "changescene": { + "usage": "Użycie: changescene ", + "already_in_scene": "Już jesteś na tej scenie.", + "success": "Zmieniono scene na %s.", + "exists_error": "Ta scena nie istenieje." + }, + "clear": { + "command_usage": "Użycie: clear ", + "weapons": "Wyczyszczono bronie dla %s.", + "artifacts": "Wyczyszczono artefakty dla %s.", + "materials": "Wyczyszczono materiały dla %s.", + "furniture": "Wyczyszczono meble dla %s.", + "displays": "Wyczyszczono displays dla %s.", + "virtuals": "Wyczyszczono virtuals dla %s.", + "everything": "Wyczyszczono wszystko dla %s." + }, + "coop": { + "usage": "Użycie: coop ", + "success": "Przyzwano %s do świata %s." + }, + "enter_dungeon": { + "usage": "Użycie: enterdungeon ", + "changed": "Zmieniono loch na %s", + "not_found_error": "Ten loch nie istnieje", + "in_dungeon_error": "Już jesteś w tym lochu" + }, + "giveAll": { + "usage": "Użycie: giveall [gracz] [ilość]", + "started": "Dodawanie wszystkich przedmiotów...", + "success": "Pomyślnie dodano wszystkie przedmioty dla %s.", + "invalid_amount_or_playerId": "Błędna ilość lub ID gracza." + }, + "giveArtifact": { + "usage": "Użycie: giveart|gart [gracz] [[,]]... [poziom]", + "id_error": "Błędne ID artefaktu.", + "success": "Dano %s dla %s." + }, + "giveChar": { + "usage": "Użycie: givechar [ilość]", + "given": "Dano %s z poziomem %s dla %s.", + "invalid_avatar_id": "Błędne ID postaci.", + "invalid_avatar_level": "Błędny poziom postaci.", + "invalid_avatar_or_player_id": "Błędne ID postaci lub gracza." + }, + "give": { + "usage": "Użycie: give [ilość] [poziom]", + "refinement_only_applicable_weapons": "Ulepszenie można zastosować tylko dla broni.", + "refinement_must_between_1_and_5": "Ulepszenie musi być pomiędzy 1, a 5.", + "given": "Dano %s %s dla %s.", + "given_with_level_and_refinement": "Dano %s z poziomem %s, ulepszeniem %s %s razy dla %s", + "given_level": "Dano %s z poziomem %s %s razy dla %s" + }, + "godmode": { + "success": "Godmode jest teraz %s dla %s." + }, + "heal": { + "success": "Wszystkie postacie zostały wyleczone." + }, + "kick": { + "player_kick_player": "Gracz [%s:%s] wyrzucił gracza [%s:%s]", + "server_kick_player": "Wyrzucono gracza [%s:%s]" + }, + "kill": { + "usage": "Użycie: killall [UID gracza] [ID sceny]", + "scene_not_found_in_player_world": "Scena nie znaleziona w świecie gracza", + "kill_monsters_in_scene": "Zabito %s potworów w scenie %s" + }, + "killCharacter": { + "usage": "Użycie: /killcharacter [ID gracza]", + "success": "Zabito aktualną postać gracza %s." + }, + "list": { + "success": "Teraz jest %s gracz(y) online:" + }, + "permission": { + "usage": "Użycie: permission ", + "add": "Dodano uprawnienie", + "has_error": "To konto już ma to uprawnienie!", + "remove": "Usunięto uprawnienie.", + "not_have_error": "To konto nie ma tych uprawnień!", + "account_error": "Konto nie może zostać znalezione." + }, + "position": { + "success": "Koordynaty: %.3f, %.3f, %.3f\nID sceny: %d" + }, + "reload": { + "reload_start": "Ponowne ładowanie konfiguracji.", + "reload_done": "Ponowne ładowanie zakończone." + }, + "resetConst": { + "reset_all": "Resetuj konstelacje wszystkich postaci.", + "success": "Konstelacje dla %s zostały zresetowane. Proszę zalogować się ponownie aby zobaczyć zmiany." + }, + "resetShopLimit": { + "usage": "Użycie: /resetshop " + }, + "sendMail": { + "usage": "Użycie: `/sendmail [id szablonu]`", + "user_not_exist": "Gracz o ID '%s' nie istnieje", + "start_composition": "Komponowanie wiadomości.\nProszę użyj `/sendmail ` aby kontynuować.\nMożesz użyć `/sendmail stop` w dowolnym momencie", + "templates": "Szablony zostaną zaimplementowane niedługo...", + "invalid_arguments": "Błędne argumenty.\nUżycie `/sendmail [id szablonu]`", + "send_cancel": "Anulowano wysyłanie wiadomości", + "send_done": "Wysłano wiadomość do gracza %s!", + "send_all_done": "Wysłano wiadomośc do wszystkich graczy!", + "not_composition_end": "Komponowanie nie jest na ostatnim etapie.\nProszę użyj `/sendmail %s` lub `/sendmail stop` aby anulować", + "please_use": "Proszę użyj `/sendmail %s`", + "set_title": "Tytuł wiadomości to teraz: '%s'.\nUżyj '/sendmail ' aby kontynuować.", + "set_contents": "Treść wiadomości to teraz '%s'.\nUżyj '/sendmail ' aby kontynuować.", + "set_message_sender": "Nadawca wiadomości to teraz '%s'.\nUżyj '/sendmail [ilość] [poziom]' aby kontynuować.", + "send": "Załączono %s %s (poziom %s) do wiadomości.\nDodaj więcej przedmiotów lub użyj `/sendmail finish` aby wysłać wiadomość.", + "invalid_arguments_please_use": "Błędne argumenty \nProszę użyj `/sendmail %s`", + "title": "", + "message": "", + "sender": "", + "arguments": " [ilość] [poziom]", + "error": "BŁĄD: niepoprawny etap konstrukcji: %s. Sprawdź konsolę aby dowiedzieć się więcej." + }, + "sendMessage": { + "usage": "Użycie: /sendmessage ", + "success": "Wiadomość wysłana." + }, + "setFetterLevel": { + "usage": "Użycie: setfetterlevel ", + "range_error": "Poziom przyjaźni musi być pomiędzy 0,a 10.", + "success": "Poziom przyjaźni ustawiono na: %s", + "level_error": "Błędny poziom przyjaźni." + }, + "setStats": { + "usage_console": "Użycie: setstats|stats @ ", + "usage_ingame": "Użycie: setstats|stats [@UID] ", + "help_message": "\n\tWartości dla Statystyka: hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Bonus DMG żywiołu: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) RES na żywioł: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys\n", + "value_error": "Błędna wartość statystyki.", + "uid_error": "Błędne UID.", + "player_error": "Gracza nie znaleziono lub jest offline.", + "set_self": "%s ustawiono na %s.", + "set_for_uid": "%s dla %s ustawiono na %s.", + "set_max_hp": "Maksymalne HP ustawione na %s." + }, + "setWorldLevel": { + "usage": "Użycie: setworldlevel ", + "value_error": "Poziom świata musi być pomiędzy 0, a 8", + "success": "Ustawiono poziom świata na: %s.", + "invalid_world_level": "Invalid world level." + }, + "spawn": { + "usage": "Użycie: /spawn [ilość] [poziom(tylko potwory)]", + "success": "Stworzono %s %s." + }, + "stop": { + "success": "Serwer wyłącza się..." + }, + "talent": { + "usage_1": "Aby ustawić poziom talentu: /talent set ", + "usage_2": "Inny sposób na ustawienie poziomu talentu: /talent ", + "usage_3": "Aby uzyskać ID talentu: /talent getid", + "lower_16": "Błędny poziom talentu. Poziom powinien być mniejszy niż 16", + "set_id": "Ustawiono talent na %s.", + "set_atk": "Ustawiono talent Atak Podstawowy na poziom %s.", + "set_e": "Ustawiono poziom talentu E na %s.", + "set_q": "Ustawiono poziom talentu Q na %s.", + "invalid_skill_id": "Błędne ID umiejętności.", + "set_this": "Ustawiono ten talent na poziom %s.", + "invalid_level": "Błędny poziom talentu.", + "normal_attack_id": "ID podstawowego ataku: %s.", + "e_skill_id": "ID umiejętności E: %s.", + "q_skill_id": "ID umiejętności Q: %s." + }, + "teleportAll": { + "success": "Przyzwano wszystkich graczy do Ciebie.", + "error": "Możesz użyć tej komendy wyłącznie w trybie MP." + }, + "teleport": { + "usage_server": "Użycie: /tp @ [ID sceny]", + "usage": "Użycie: /tp [@] [ID sceny]", + "specify_player_id": "Musisz określić ID gracza.", + "invalid_position": "Błędna pozycja.", + "success": "Przeteleportowano %s do %s, %s, %s w scenie %s" + }, + "weather": { + "usage": "Użycie: weather [ID klimatu]", + "success": "Zmieniono pogodę na %s z klimatem %s", + "invalid_id": "Błędne ID." + }, + "drop": { + "command_usage": "Użycie: drop [ilość]", + "success": "Wyrzucono %s of %s." + }, + "help": { + "usage": "Użycie: ", + "aliases": "Aliasy: ", + "available_commands": "Dostępne komendy: " + } + } +} \ No newline at end of file From 549471b76e9e84663317103b2e5e7aecdfd462a1 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Sat, 7 May 2022 23:44:35 -0400 Subject: [PATCH 18/28] Fix language fallback'ing --- src/main/java/emu/grasscutter/utils/Language.java | 6 ++++-- src/main/java/emu/grasscutter/utils/Utils.java | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/emu/grasscutter/utils/Language.java b/src/main/java/emu/grasscutter/utils/Language.java index 0af77adc1..cda46e512 100644 --- a/src/main/java/emu/grasscutter/utils/Language.java +++ b/src/main/java/emu/grasscutter/utils/Language.java @@ -48,11 +48,13 @@ public final class Language { try { InputStream file = Grasscutter.class.getResourceAsStream("/languages/" + fileName); - if(file == null) { + String translationContents = Utils.readFromInputStream(file); + if(translationContents.equals("empty")) { file = Grasscutter.class.getResourceAsStream("/languages/" + fallback); + translationContents = Utils.readFromInputStream(file); } - languageData = Grasscutter.getGsonFactory().fromJson(Utils.readFromInputStream(file), JsonObject.class); + languageData = Grasscutter.getGsonFactory().fromJson(translationContents, JsonObject.class); } catch (Exception exception) { Grasscutter.getLogger().warn("Failed to load language file: " + fileName, exception); } diff --git a/src/main/java/emu/grasscutter/utils/Utils.java b/src/main/java/emu/grasscutter/utils/Utils.java index 6d11822f0..1d79c496e 100644 --- a/src/main/java/emu/grasscutter/utils/Utils.java +++ b/src/main/java/emu/grasscutter/utils/Utils.java @@ -18,6 +18,8 @@ import io.netty.buffer.Unpooled; import org.slf4j.Logger; +import javax.annotation.Nullable; + import static emu.grasscutter.utils.Language.translate; @SuppressWarnings({"UnusedReturnValue", "BooleanMethodIsAlwaysInverted"}) @@ -253,7 +255,9 @@ public final class Utils { * @param stream The input stream. * @return The string. */ - public static String readFromInputStream(InputStream stream) { + public static String readFromInputStream(@Nullable InputStream stream) { + if(stream == null) return "empty"; + StringBuilder stringBuilder = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { @@ -261,6 +265,8 @@ public final class Utils { } stream.close(); } catch (IOException e) { Grasscutter.getLogger().warn("Failed to read from input stream."); + } catch (NullPointerException ignored) { + return "empty"; } return stringBuilder.toString(); } From c9e8d6cad7f2a6fe8deeb77b25facb6b776d5626 Mon Sep 17 00:00:00 2001 From: KingRainbow44 Date: Sat, 7 May 2022 19:39:31 -0400 Subject: [PATCH 19/28] Add a plugin schema --- plugin-schema.json | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 plugin-schema.json diff --git a/plugin-schema.json b/plugin-schema.json new file mode 100644 index 000000000..4fc772416 --- /dev/null +++ b/plugin-schema.json @@ -0,0 +1,49 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "JSON schema for a Grasscutter Plugin", + "type": "object", + "additionalProperties": true, + "definitions": { + "plugin-name": { + "type": "string", + "pattern": "^[A-Za-z\\d_.-]+$" + } + }, + "required": [ "name", "description", "mainClass" ], + "properties": { + "name": { + "description": "The unique name of plugin.", + "$ref": "#/definitions/plugin-name" + }, + "mainClass": { + "description": "The plugin's initial class file.", + "type": "string", + "pattern": "^(?!org\\.bukkit\\.)([a-zA-Z_$][a-zA-Z\\d_$]*\\.)*[a-zA-Z_$][a-zA-Z\\d_$]*$" + }, + "version": { + "description": "A plugin revision identifier.", + "type": [ "string", "number" ] + }, + "description": { + "description": "Human readable plugin summary.", + "type": "string" + }, + "author": { + "description": "The plugin author.", + "type": "string" + }, + "authors": { + "description": "The plugin contributors.", + "type": "array", + "items": { + "type": "string" + } + }, + "website": { + "title": "Website", + "description": "The URL to the plugin's site", + "type": "string", + "format": "uri" + } + } +} \ No newline at end of file From 94a6a79b4a907fbf028ec03887aba4b4caceebbb Mon Sep 17 00:00:00 2001 From: gentlespoon Date: Sat, 7 May 2022 21:07:06 -0700 Subject: [PATCH 20/28] Fix null reference on stamina timer when paused player disconnects. --- .../StaminaManager/StaminaManager.java | 30 ++++++++----------- .../emu/grasscutter/game/player/Player.java | 4 +-- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java b/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java index 3d55e5edf..5065b12b3 100644 --- a/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java +++ b/src/main/java/emu/grasscutter/game/managers/StaminaManager/StaminaManager.java @@ -29,19 +29,16 @@ public class StaminaManager { private Position previousCoordinates = new Position(0, 0, 0); private MotionState currentState = MotionState.MOTION_STANDBY; private MotionState previousState = MotionState.MOTION_STANDBY; - private Timer sustainedStaminaHandlerTimer; + private final Timer sustainedStaminaHandlerTimer = new Timer(); + private final SustainedStaminaHandler handleSustainedStamina = new SustainedStaminaHandler(); + private boolean timerRunning = false; private GameSession cachedSession = null; private GameEntity cachedEntity = null; private int staminaRecoverDelay = 0; private boolean isInSkillMove = false; - - - - public boolean getIsInSkillMove() { return isInSkillMove; } - public void setIsInSkillMove(boolean b) { isInSkillMove = b; } @@ -139,24 +136,23 @@ public class StaminaManager { entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP)); entity.getWorld().broadcastPacket(new PacketLifeStateChangeNotify(0, entity, LifeState.LIFE_DEAD)); player.getScene().removeEntity(entity); - ((EntityAvatar) entity).onDeath(dieType, 0); + ((EntityAvatar)entity).onDeath(dieType, 0); } public void startSustainedStaminaHandler() { - if (!player.isPaused()) { - if (sustainedStaminaHandlerTimer == null) { - sustainedStaminaHandlerTimer = new Timer(); - sustainedStaminaHandlerTimer.scheduleAtFixedRate(new SustainedStaminaHandler(), 0, 200); - Grasscutter.getLogger().debug("[MovementManager] SustainedStaminaHandlerTimer started"); - } + if (!player.isPaused() && !timerRunning) { + timerRunning = true; + sustainedStaminaHandlerTimer.scheduleAtFixedRate(handleSustainedStamina, 0, 200); + // Grasscutter.getLogger().debug("[MovementManager] SustainedStaminaHandlerTimer started"); } - } public void stopSustainedStaminaHandler() { - Grasscutter.getLogger().debug("[MovementManager] SustainedStaminaHandlerTimer stopped"); - sustainedStaminaHandlerTimer.cancel(); - sustainedStaminaHandlerTimer = null; + if (timerRunning) { + timerRunning = false; + sustainedStaminaHandlerTimer.cancel(); + // Grasscutter.getLogger().debug("[MovementManager] SustainedStaminaHandlerTimer stopped"); + } } // Handlers diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index b6956153c..71ae9d8c6 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -872,11 +872,11 @@ public class Player { } public void onPause() { - staminaManager.stopSustainedStaminaHandler(); + getStaminaManager().stopSustainedStaminaHandler(); } public void onUnpause() { - staminaManager.startSustainedStaminaHandler(); + getStaminaManager().startSustainedStaminaHandler(); } public void sendPacket(BasePacket packet) { From 06564da009c6a8cc40700209f41362e176aa22d2 Mon Sep 17 00:00:00 2001 From: Mateoust <46558043+Mateoust@users.noreply.github.com> Date: Sun, 8 May 2022 13:03:14 +0800 Subject: [PATCH 21/28] fix issues 646 --- src/main/resources/languages/zh-CN.json | 2 +- src/main/resources/languages/zh-TW.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index b9bc5b22a..4ce6196bc 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -173,7 +173,7 @@ "success": "已杀死 %s 目前使用的角色。" }, "list": { - "message": "目前在线人数:%s" + "success": "目前在线人数:%s" }, "permission": { "usage": "用法:permission ", diff --git a/src/main/resources/languages/zh-TW.json b/src/main/resources/languages/zh-TW.json index 49e0f256d..7a7f5c100 100644 --- a/src/main/resources/languages/zh-TW.json +++ b/src/main/resources/languages/zh-TW.json @@ -173,7 +173,7 @@ "success": "已殺死 %s 目前的場上角色。" }, "list": { - "message": "目前總線上人數:%s" + "success": "目前總線上人數:%s" }, "permission": { "usage": "用法:permission ", From 21cd002fbda1a62f4bb3daff8b500eb5420a52f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=8A=E6=9E=AB?= Date: Sun, 8 May 2022 10:45:16 +0800 Subject: [PATCH 22/28] Fix typo && update zh-CN.json --- src/main/resources/languages/zh-CN.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index 4ce6196bc..e78b76776 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -36,10 +36,10 @@ } }, "status": { - "free_software": "Grasscutter 是免费开源软件。如果你是付费购买的,那已经被骗了。Github:https://github.com/Grasscutters/Grasscutter", + "free_software": "Grasscutter 是免费开源软件,遵循Apache-2.0 license。如果您是付费购买的,那您已经被骗了。项目地址:Github:https://github.com/Grasscutters/Grasscutter", "starting": "正在启动 Grasscutter...", "shutdown": "正在关闭...", - "done": "加載完成!输入 \"help\" 查看命令列表", + "done": "加载完成!输入 \"help\" 查看命令列表", "error": "发生了一个错误。", "welcome": "欢迎使用 Grasscutter", "run_mode_error": "无效的服务器运行模式: %s。", @@ -119,7 +119,7 @@ }, "coop": { "usage": "用法:coop ", - "success": "已召唤 %s 到 %s的世界" + "success": "已强制召唤 %s 到 %s的世界" }, "enter_dungeon": { "usage": "用法:enterdungeon ", @@ -188,7 +188,7 @@ }, "reload": { "reload_start": "正在重载配置文件和数据。", - "reload_done": "重装完毕。" + "reload_done": "重载完毕。" }, "resetConst": { "reset_all": "重置所有角色的命座。", @@ -260,14 +260,14 @@ "lower_16": "无效的天赋等级,天赋等级应低于16。", "set_id": "将天赋等级设为 %s。", "set_atk": "将普通攻击等级设为 %s。", - "set_e": "设定天赋E等级为 %s。", - "set_q": "设定天赋Q等级为 %s。", + "set_e": "设定元素战技等级为 %s。", + "set_q": "设定元素爆发等级为 %s。", "invalid_skill_id": "无效的技能ID。", "set_this": "将天赋等级设为 %s。", "invalid_level": "无效的天赋等级。", "normal_attack_id": "普通攻击的 ID 为 %s。", - "e_skill_id": "E技能ID %s。", - "q_skill_id": "Q技能ID %s。" + "e_skill_id": "元素战技ID %s。", + "q_skill_id": "元素爆发ID %s。" }, "teleportAll": { "success": "已将全部玩家传送到你的位置", @@ -287,7 +287,7 @@ }, "drop": { "command_usage": "用法:drop [amount]", - "success": "已將 %s x %s 丟在附近。" + "success": "已将 %s x %s 丟在附近。" }, "help": { "usage": "用法:", From d7a82e1c9ff8af7512afe6c61abbf3eac88e0310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=8A=E6=9E=AB?= Date: Sun, 8 May 2022 11:38:56 +0800 Subject: [PATCH 23/28] Update zh-CN.json --- src/main/resources/languages/zh-CN.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index e78b76776..18ff2165c 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -140,7 +140,7 @@ }, "giveChar": { "usage": "用法:givechar [amount]", - "given": "Given %s with level %s to %s.", + "given": "给予角色 %s 等级 %s 向UID %s.", "invalid_avatar_id": "无效的角色ID。", "invalid_avatar_level": "无效的角色等級。.", "invalid_avatar_or_player_id": "无效的角色ID/玩家ID。" @@ -151,7 +151,7 @@ "refinement_must_between_1_and_5": "精炼等级必须在 1 到 5 之间。", "given": "已将 %s 个 %s 给予 %s。", "given_with_level_and_refinement": "已将 %s [等級%s, 精炼%s] %s个给予 %s", - "given_level": "已将 %s 等级 %s %s 个给予 %s" + "given_level": "已将 %s 等级 %s %s 个给予UID %s" }, "godmode": { "success": "上帝模式被设置为 %s 。 [用户:%s]" From 4c911d6f55eb35e787b09de5e279cbb5371d4f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=8A=E6=9E=AB?= Date: Sun, 8 May 2022 11:51:07 +0800 Subject: [PATCH 24/28] Update zh-CN.json --- src/main/resources/languages/zh-CN.json | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index 18ff2165c..8faa0e4ae 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -41,7 +41,7 @@ "shutdown": "正在关闭...", "done": "加载完成!输入 \"help\" 查看命令列表", "error": "发生了一个错误。", - "welcome": "欢迎使用 Grasscutter", + "welcome": "欢迎使用 Grasscutter!珍惜这段美妙的旅途吧!", "run_mode_error": "无效的服务器运行模式: %s。", "run_mode_help": "服务器运行模式必须为 HYBRID、DISPATCH_ONLY 或 GAME_ONLY。Grasscutter 启动失败...", "create_resources": "正在创建 resources 目录...", @@ -52,12 +52,12 @@ "generic": { "not_specified": "没有指定命令。", "unknown_command": "未知的命令:%s", - "permission_error": "您没有执行此命令的权限。", - "console_execute_error": "此命令只能在服务器控制台执行。", - "player_execute_error": "此命令只能在游戏内执行。", - "command_exist_error": "找不到命令。", + "permission_error": "哼哼哼!您没有执行此命令的权限!请联系服务器管理员解决!", + "console_execute_error": "此命令只能在服务器控制台执行呐~", + "player_execute_error": "此命令只能在游戏内执行哦~", + "command_exist_error": "这条命令……好像找不到呢?。", "invalid": { - "amount": "无效的 数量.", + "amount": "无效的数量.", "artifactId": "无效的圣遗物ID。", "avatarId": "无效的角色ID。", "avatarLevel": "无效的角色等級。", @@ -147,14 +147,14 @@ }, "give": { "usage": "用法:give [amount] [level] [refinement]", - "refinement_only_applicable_weapons": "精炼等级参数仅在武器上可用", - "refinement_must_between_1_and_5": "精炼等级必须在 1 到 5 之间。", + "refinement_only_applicable_weapons": "精炼等阶参数仅在给予武器时可用", + "refinement_must_between_1_and_5": "精炼等阶必须在 1 到 5 之间。", "given": "已将 %s 个 %s 给予 %s。", "given_with_level_and_refinement": "已将 %s [等級%s, 精炼%s] %s个给予 %s", "given_level": "已将 %s 等级 %s %s 个给予UID %s" }, "godmode": { - "success": "上帝模式被设置为 %s 。 [用户:%s]" + "success": "上帝模式已被设置为 %s 。 [用户:%s]" }, "heal": { "success": "所有角色已被治疗。" @@ -204,7 +204,7 @@ "templates": "邮件模板尚未实装...", "invalid_arguments": "无效的参数。\n指令使用方法 `/sendmail [templateId]`", "send_cancel": "取消发送邮件", - "send_done": "已将邮件给 %s!", + "send_done": "已将邮件发送给 %s!", "send_all_done": "邮件已发送给所有人!", "not_composition_end": "现在邮件发送未到最后阶段。\n请使用 `/sendmail %s` 继续发送邮件,或使用 `/sendmail stop` 来停止发送邮件。", "please_use": "请使用 `/sendmail %s`", @@ -257,7 +257,7 @@ "usage_1": "设置天赋等级:/talent set ", "usage_2": "另一种设置天赋等级的命令使用方法:/talent ", "usage_3": "获取天赋ID指令用法:/talent getid", - "lower_16": "无效的天赋等级,天赋等级应低于16。", + "lower_16": "无效的天赋等级,天赋等级应小于等于15。", "set_id": "将天赋等级设为 %s。", "set_atk": "将普通攻击等级设为 %s。", "set_e": "设定元素战技等级为 %s。", @@ -271,7 +271,7 @@ }, "teleportAll": { "success": "已将全部玩家传送到你的位置", - "error": "命令仅限多人游戏使用。" + "error": "命令仅限处于多人游戏状态下使用。" }, "teleport": { "usage_server": "用法:/tp @ [scene id]", @@ -282,8 +282,8 @@ }, "weather": { "usage": "用法:weather [climateId]", - "success": "已将当前天气设定为 %s,气候则为 %s。", - "invalid_id": "无效的ID。" + "success": "已将当前天气设定为 %s,气候为 %s。", + "invalid_id": "无效的天气ID。" }, "drop": { "command_usage": "用法:drop [amount]", From 257a92f3ef354ef81d9550e53fd01aab4dc8cf0e Mon Sep 17 00:00:00 2001 From: Magix <27646710+KingRainbow44@users.noreply.github.com> Date: Sat, 7 May 2022 21:24:18 -0400 Subject: [PATCH 25/28] Update build.yml --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 49a9d8b53..d14ebf3e0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,4 +31,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: Grasscutter - path: grasscutter-*-dev.jar + path: grasscutter-*.jar From a46d58e5f6417eb642f003b66566a5ee53c22642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=E5=9D=97=E5=90=9B?= Date: Sun, 8 May 2022 10:33:53 +0800 Subject: [PATCH 26/28] Add command description multilingual --- .../java/emu/grasscutter/command/Command.java | 2 - .../grasscutter/command/CommandHandler.java | 3 + .../emu/grasscutter/command/CommandMap.java | 8 ++ .../command/commands/AccountCommand.java | 7 +- .../command/commands/BroadcastCommand.java | 8 +- .../command/commands/ChangeSceneCommand.java | 8 +- .../command/commands/ClearCommand.java | 6 +- .../command/commands/CoopCommand.java | 8 +- .../command/commands/DropCommand.java | 8 +- .../command/commands/EnterDungeonCommand.java | 8 +- .../command/commands/GiveAllCommand.java | 8 +- .../command/commands/GiveArtifactCommand.java | 7 +- .../command/commands/GiveCharCommand.java | 8 +- .../command/commands/GiveCommand.java | 10 +- .../command/commands/GodModeCommand.java | 9 +- .../command/commands/HealCommand.java | 8 +- .../command/commands/HelpCommand.java | 24 ++-- .../command/commands/KickCommand.java | 8 +- .../command/commands/KillAllCommand.java | 8 +- .../commands/KillCharacterCommand.java | 8 +- .../command/commands/ListCommand.java | 8 +- .../command/commands/PermissionCommand.java | 8 +- .../command/commands/PositionCommand.java | 8 +- .../command/commands/ReloadCommand.java | 8 +- .../command/commands/ResetConstCommand.java | 6 +- .../commands/ResetShopLimitCommand.java | 8 +- .../command/commands/RestartCommand.java | 9 +- .../command/commands/SendMailCommand.java | 10 +- .../command/commands/SendMessageCommand.java | 7 +- .../commands/SetFetterLevelCommand.java | 6 +- .../command/commands/SetStatsCommand.java | 8 +- .../commands/SetWorldLevelCommand.java | 6 +- .../command/commands/SpawnCommand.java | 8 +- .../command/commands/StopCommand.java | 8 +- .../command/commands/TalentCommand.java | 8 +- .../command/commands/TeleportAllCommand.java | 8 +- .../command/commands/TeleportCommand.java | 8 +- .../command/commands/WeatherCommand.java | 8 +- .../java/emu/grasscutter/tools/Tools.java | 12 +- src/main/resources/languages/en-US.json | 105 ++++++++++++------ 40 files changed, 306 insertions(+), 115 deletions(-) diff --git a/src/main/java/emu/grasscutter/command/Command.java b/src/main/java/emu/grasscutter/command/Command.java index 734f454ea..c94804678 100644 --- a/src/main/java/emu/grasscutter/command/Command.java +++ b/src/main/java/emu/grasscutter/command/Command.java @@ -9,8 +9,6 @@ public @interface Command { String usage() default "No usage specified"; - String description() default "No description specified"; - String[] aliases() default {}; String permission() default ""; diff --git a/src/main/java/emu/grasscutter/command/CommandHandler.java b/src/main/java/emu/grasscutter/command/CommandHandler.java index ffe21c9be..dadb87bb3 100644 --- a/src/main/java/emu/grasscutter/command/CommandHandler.java +++ b/src/main/java/emu/grasscutter/command/CommandHandler.java @@ -6,6 +6,9 @@ import emu.grasscutter.game.player.Player; import java.util.List; public interface CommandHandler { + + String description(); + /** * Send a message to the target. * diff --git a/src/main/java/emu/grasscutter/command/CommandMap.java b/src/main/java/emu/grasscutter/command/CommandMap.java index a183c6ac3..6b6a852af 100644 --- a/src/main/java/emu/grasscutter/command/CommandMap.java +++ b/src/main/java/emu/grasscutter/command/CommandMap.java @@ -85,6 +85,14 @@ public final class CommandMap { return new LinkedHashMap<>(this.annotations); } + public HashMap getHandlersAndAnnotations() { + HashMap hashMap = new HashMap<>(); + this.commands.forEach((key, handler) -> { + hashMap.put(handler, this.annotations.get(key)); + }); + return hashMap; + } + /** * Returns a list of all registered commands. * diff --git a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java index 627f4680f..1c5c8228e 100644 --- a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java @@ -9,9 +9,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "account", usage = "account [uid]", description = "Modify user accounts") +@Command(label = "account", usage = "account [uid]") public final class AccountCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.account.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (sender != null) { diff --git a/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java b/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java index 1aa234919..fcabb131c 100644 --- a/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java @@ -9,10 +9,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "broadcast", usage = "broadcast ", - description = "Sends a message to all the players", aliases = {"b"}, permission = "server.broadcast") +@Command(label = "broadcast", usage = "broadcast ", aliases = {"b"}, permission = "server.broadcast") public final class BroadcastCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.broadcast.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (args.size() < 1) { diff --git a/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java b/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java index 1a4e97927..ea7bfe0f6 100644 --- a/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java @@ -8,9 +8,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "changescene", usage = "changescene ", - description = "Changes your scene", aliases = {"scene"}, permission = "player.changescene") +@Command(label = "changescene", usage = "changescene ", aliases = {"scene"}, permission = "player.changescene") public final class ChangeSceneCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.changescene.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/ClearCommand.java b/src/main/java/emu/grasscutter/command/commands/ClearCommand.java index 47d9f2c0d..d416bec52 100644 --- a/src/main/java/emu/grasscutter/command/commands/ClearCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ClearCommand.java @@ -13,11 +13,15 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "clear", usage = "clear ", //Merged /clearartifacts and /clearweapons to /clear [uid] - description = "Deletes unequipped unlocked items, including yellow rarity ones from your inventory", aliases = {"clear"}, permission = "player.clearinv") public final class ClearCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.clear.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/CoopCommand.java b/src/main/java/emu/grasscutter/command/commands/CoopCommand.java index 96411019b..120665b76 100644 --- a/src/main/java/emu/grasscutter/command/commands/CoopCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/CoopCommand.java @@ -9,9 +9,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "coop", usage = "coop [host UID]", - description = "Forces someone to join the world of others", permission = "server.coop") +@Command(label = "coop", usage = "coop [host UID]", permission = "server.coop") public final class CoopCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.coop.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/DropCommand.java b/src/main/java/emu/grasscutter/command/commands/DropCommand.java index a33a32603..a187cfda8 100644 --- a/src/main/java/emu/grasscutter/command/commands/DropCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/DropCommand.java @@ -13,10 +13,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "drop", usage = "drop [amount]", - description = "Drops an item near you", aliases = {"d", "dropitem"}, permission = "server.drop") +@Command(label = "drop", usage = "drop [amount]", aliases = {"d", "dropitem"}, permission = "server.drop") public final class DropCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.drop.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java b/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java index 434e80c8f..d92d537e9 100644 --- a/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java @@ -8,9 +8,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "enterdungeon", usage = "enterdungeon ", - description = "Enter a dungeon", aliases = {"dungeon"}, permission = "player.enterdungeon") +@Command(label = "enterdungeon", usage = "enterdungeon ", aliases = {"dungeon"}, permission = "player.enterdungeon") public final class EnterDungeonCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.enter_dungeon.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java index bb11de3c2..5009a4462 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java @@ -15,10 +15,14 @@ import java.util.*; import static emu.grasscutter.utils.Language.translate; -@Command(label = "giveall", usage = "giveall [amount]", - description = "Gives all items", aliases = {"givea"}, permission = "player.giveall", threading = true) +@Command(label = "giveall", usage = "giveall [amount]", aliases = {"givea"}, permission = "player.giveall", threading = true) public final class GiveAllCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.giveAll.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java index 541cc440e..d41e83671 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java @@ -16,8 +16,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "giveart", usage = "giveart [[,]]... [level]", description = "Gives the player a specified artifact", aliases = {"gart"}, permission = "player.giveart") +@Command(label = "giveart", usage = "giveart [[,]]... [level]", aliases = {"gart"}, permission = "player.giveart") public final class GiveArtifactCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.giveArtifact.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java index 4b3279202..0e784639d 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java @@ -12,10 +12,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "givechar", usage = "givechar [level]", - description = "Gives the player a specified character", aliases = {"givec"}, permission = "player.givechar") +@Command(label = "givechar", usage = "givechar [level]", aliases = {"givec"}, permission = "player.givechar") public final class GiveCharCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.giveChar.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java index 2f020f7b3..3daa2dff3 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java @@ -1,6 +1,5 @@ package emu.grasscutter.command.commands; -import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.data.GameData; @@ -12,12 +11,12 @@ import emu.grasscutter.game.props.ActionReason; import java.util.LinkedList; import java.util.List; -import java.util.regex.Pattern; import java.util.regex.Matcher; +import java.util.regex.Pattern; import static emu.grasscutter.utils.Language.translate; -@Command(label = "give", usage = "give [amount] [level]", description = "Gives an item to you or the specified player", aliases = { +@Command(label = "give", usage = "give [amount] [level]", aliases = { "g", "item", "giveitem"}, permission = "player.give") public final class GiveCommand implements CommandHandler { Pattern lvlRegex = Pattern.compile("l(?:vl?)?(\\d+)"); // Java is a joke of a proglang that doesn't have raw string literals @@ -32,6 +31,11 @@ public final class GiveCommand implements CommandHandler { return -1; } + @Override + public String description() { + return translate("commands.give.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java b/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java index 9abebb8db..4fd2999a6 100644 --- a/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java @@ -1,6 +1,5 @@ package emu.grasscutter.command.commands; -import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; import emu.grasscutter.command.CommandHandler; import emu.grasscutter.game.player.Player; @@ -9,10 +8,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "godmode", usage = "godmode [on|off|toggle]", - description = "Prevents you from taking damage. Defaults to toggle.", permission = "player.godmode") +@Command(label = "godmode", usage = "godmode [on|off|toggle]", permission = "player.godmode") public final class GodModeCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.godmode.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/HealCommand.java b/src/main/java/emu/grasscutter/command/commands/HealCommand.java index bb0b861b0..b459ecb8c 100644 --- a/src/main/java/emu/grasscutter/command/commands/HealCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/HealCommand.java @@ -11,9 +11,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "heal", usage = "heal|h", aliases = {"h"}, - description = "Heal all characters in your current team.", permission = "player.heal") +@Command(label = "heal", usage = "heal|h", aliases = {"h"}, permission = "player.heal") public final class HealCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.heal.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/HelpCommand.java b/src/main/java/emu/grasscutter/command/commands/HelpCommand.java index 93ac831b3..dbb85bf9d 100644 --- a/src/main/java/emu/grasscutter/command/commands/HelpCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/HelpCommand.java @@ -10,22 +10,26 @@ import java.util.*; import static emu.grasscutter.utils.Language.translate; -@Command(label = "help", usage = "help [command]", - description = "Sends the help message or shows information about a specified command") +@Command(label = "help", usage = "help [command]") public final class HelpCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.help.description"); + } + @Override public void execute(Player player, Player targetPlayer, List args) { if (args.size() < 1) { HashMap handlers = CommandMap.getInstance().getHandlers(); - List annotations = new ArrayList<>(); + HashMap annotations = new HashMap<>(); for (String key : handlers.keySet()) { Command annotation = handlers.get(key).getClass().getAnnotation(Command.class); if (!Arrays.asList(annotation.aliases()).contains(key)) { if (player != null && !Objects.equals(annotation.permission(), "") && !player.getAccount().hasPermission(annotation.permission())) continue; - annotations.add(annotation); + annotations.put(annotation, handlers.get(key)); } } @@ -39,7 +43,7 @@ public final class HelpCommand implements CommandHandler { } else { Command annotation = handler.getClass().getAnnotation(Command.class); - builder.append(" ").append(annotation.description()).append("\n"); + builder.append(" ").append(handler.description()).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); @@ -56,12 +60,12 @@ public final class HelpCommand implements CommandHandler { } } - void SendAllHelpMessage(Player player, List annotations) { + void SendAllHelpMessage(Player player, HashMap annotations) { if (player == null) { StringBuilder builder = new StringBuilder("\n" + translate("commands.help.available_commands") + "\n"); - annotations.forEach(annotation -> { + annotations.forEach((annotation, handler) -> { builder.append(annotation.label()).append("\n"); - builder.append(" ").append(annotation.description()).append("\n"); + builder.append(" ").append(handler.description()).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); @@ -76,9 +80,9 @@ public final class HelpCommand implements CommandHandler { CommandHandler.sendMessage(null, builder.toString()); } else { CommandHandler.sendMessage(player, translate("commands.help.available_commands")); - annotations.forEach(annotation -> { + annotations.forEach((annotation, handler) -> { StringBuilder builder = new StringBuilder(annotation.label()).append("\n"); - builder.append(" ").append(annotation.description()).append("\n"); + builder.append(" ").append(handler.description()).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); diff --git a/src/main/java/emu/grasscutter/command/commands/KickCommand.java b/src/main/java/emu/grasscutter/command/commands/KickCommand.java index 270e28150..71b487cc4 100644 --- a/src/main/java/emu/grasscutter/command/commands/KickCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KickCommand.java @@ -8,10 +8,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "kick", usage = "kick", - description = "Kicks the specified player from the server (WIP)", permission = "server.kick") +@Command(label = "kick", usage = "kick", permission = "server.kick") public final class KickCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.kick.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java b/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java index 423c60bbd..1fa51eec4 100644 --- a/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java @@ -12,10 +12,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "killall", usage = "killall [sceneId]", - description = "Kill all entities", permission = "server.killall") +@Command(label = "killall", usage = "killall [sceneId]", permission = "server.killall") public final class KillAllCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.kill.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java b/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java index f1e0f0f8c..f3fdb4998 100644 --- a/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java @@ -13,10 +13,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "killcharacter", usage = "killcharacter", aliases = {"suicide", "kill"}, - description = "Kills the players current character", permission = "player.killcharacter") +@Command(label = "killcharacter", usage = "killcharacter", aliases = {"suicide", "kill"}, permission = "player.killcharacter") public final class KillCharacterCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.killCharacter.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/ListCommand.java b/src/main/java/emu/grasscutter/command/commands/ListCommand.java index bc35e65e1..7834d2467 100644 --- a/src/main/java/emu/grasscutter/command/commands/ListCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ListCommand.java @@ -10,10 +10,14 @@ import java.util.Map; import static emu.grasscutter.utils.Language.translate; -@Command(label = "list", usage = "list [uid]", - description = "List online players", aliases = {"players"}) +@Command(label = "list", usage = "list [uid]", aliases = {"players"}) public final class ListCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.list.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { Map playersMap = Grasscutter.getGameServer().getPlayers(); diff --git a/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java b/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java index 69c8ce899..309451945 100644 --- a/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java @@ -10,10 +10,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "permission", usage = "permission ", - description = "Grants or removes a permission for a user", permission = "*") +@Command(label = "permission", usage = "permission ", permission = "*") public final class PermissionCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.permission.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/PositionCommand.java b/src/main/java/emu/grasscutter/command/commands/PositionCommand.java index 7f6548c5b..3a3b40a3f 100644 --- a/src/main/java/emu/grasscutter/command/commands/PositionCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/PositionCommand.java @@ -9,10 +9,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "position", usage = "position", aliases = {"pos"}, - description = "Get coordinates.") +@Command(label = "position", usage = "position", aliases = {"pos"}) public final class PositionCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.position.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java index 6c85d2024..8e3e5e5aa 100644 --- a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java @@ -9,10 +9,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "reload", usage = "reload", - description = "Reload server config", permission = "server.reload") +@Command(label = "reload", usage = "reload", permission = "server.reload") public final class ReloadCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.reload.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { CommandHandler.sendMessage(sender, translate("commands.reload.reload_start")); diff --git a/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java b/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java index 706fb95e0..9eba8e4c4 100644 --- a/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java @@ -11,10 +11,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "resetconst", usage = "resetconst [all]", - description = "Resets the constellation level on your current active character, will need to relog after using the command to see any changes.", aliases = {"resetconstellation"}, permission = "player.resetconstellation") public final class ResetConstCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.resetConst.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java b/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java index aeae0abbf..bba8da32c 100644 --- a/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java @@ -9,9 +9,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "resetshop", usage = "resetshop", - description = "Reset target player's shop refresh time.", permission = "server.resetshop") +@Command(label = "resetshop", usage = "resetshop", permission = "server.resetshop") public final class ResetShopLimitCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.status.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/RestartCommand.java b/src/main/java/emu/grasscutter/command/commands/RestartCommand.java index e3b8b2747..2c56ae443 100644 --- a/src/main/java/emu/grasscutter/command/commands/RestartCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/RestartCommand.java @@ -6,9 +6,16 @@ import emu.grasscutter.game.player.Player; import java.util.List; -@Command(label = "restart", usage = "restart - Restarts the current session") +import static emu.grasscutter.utils.Language.translate; + +@Command(label = "restart", usage = "restart") public final class RestartCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.restart.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (sender == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java b/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java index 838bea567..a56d68165 100644 --- a/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java @@ -13,8 +13,7 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @SuppressWarnings("ConstantConditions") -@Command(label = "sendmail", usage = "sendmail [templateId]", - description = "Sends mail to the specified user. The usage of this command changes based on it's composition state.", permission = "server.sendmail") +@Command(label = "sendmail", usage = "sendmail [templateId]", permission = "server.sendmail") public final class SendMailCommand implements CommandHandler { // TODO: You should be able to do /sendmail and then just send subsequent messages until you finish @@ -24,6 +23,11 @@ public final class SendMailCommand implements CommandHandler { // Key = User that is constructing the mail. private static final HashMap mailBeingConstructed = new HashMap(); + @Override + public String description() { + return translate("commands.sendMail.description"); + } + // Yes this is awful and I hate it. @Override public void execute(Player sender, Player targetPlayer, List args) { @@ -40,7 +44,7 @@ public final class SendMailCommand implements CommandHandler { MailBuilder mailBuilder; switch (args.get(0).toLowerCase()) { case "help" -> { - CommandHandler.sendMessage(sender, this.getClass().getAnnotation(Command.class).description() + "\nUsage: " + this.getClass().getAnnotation(Command.class).usage()); + CommandHandler.sendMessage(sender, this.description() + "\nUsage: " + this.getClass().getAnnotation(Command.class).usage()); return; } case "all" -> mailBuilder = new MailBuilder(true, new Mail()); diff --git a/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java b/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java index acf63dea0..36e53de10 100644 --- a/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java @@ -8,10 +8,15 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "say", usage = "say ", description = "Sends a message to a player as the server", +@Command(label = "say", usage = "say ", aliases = {"sendservmsg", "sendservermessage", "sendmessage"}, permission = "server.sendmessage") public final class SendMessageCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.sendMessage.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java b/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java index 7184c679c..e098d99a5 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java @@ -12,10 +12,14 @@ import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify; import static emu.grasscutter.utils.Language.translate; @Command(label = "setfetterlevel", usage = "setfetterlevel ", - description = "Sets your fetter level for your current active character", aliases = {"setfetterlvl", "setfriendship"}, permission = "player.setfetterlevel") public final class SetFetterLevelCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.setFetterLevel.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java index 233eb4d73..11cb8ab80 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java @@ -15,8 +15,7 @@ import emu.grasscutter.utils.Language; import static emu.grasscutter.utils.Language.translate; -@Command(label = "setstats", usage = "setstats|stats ", - description = "Set fight property for your current active character", aliases = {"stats"}, permission = "player.setstats") +@Command(label = "setstats", usage = "setstats|stats ", aliases = {"stats"}, permission = "player.setstats") public final class SetStatsCommand implements CommandHandler { static class Stat { String name; @@ -174,6 +173,11 @@ public final class SetStatsCommand implements CommandHandler { stats.put("_nonextra_physical_add_hurt", new Stat("NONEXTRA_PHYSICAL_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT, true)); } + @Override + public String description() { + return translate("commands.setStats.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { String syntax = sender == null ? translate("commands.setStats.usage_console") : translate("commands.setStats.ingame"); diff --git a/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java b/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java index 914d8cecc..16b10bc6c 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java @@ -10,10 +10,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "setworldlevel", usage = "setworldlevel ", - description = "Sets your world level (Relog to see proper effects)", aliases = {"setworldlvl"}, permission = "player.setworldlevel") public final class SetWorldLevelCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.setWorldLevel.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java b/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java index c66a45b50..8a995402b 100644 --- a/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java @@ -22,10 +22,14 @@ import java.util.Random; import static emu.grasscutter.utils.Language.translate; -@Command(label = "spawn", usage = "spawn [amount] [level(monster only)]", - description = "Spawns an entity near you", permission = "server.spawn") +@Command(label = "spawn", usage = "spawn [amount] [level(monster only)]", permission = "server.spawn") public final class SpawnCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.spawn.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/StopCommand.java b/src/main/java/emu/grasscutter/command/commands/StopCommand.java index ad4903107..64326a748 100644 --- a/src/main/java/emu/grasscutter/command/commands/StopCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/StopCommand.java @@ -9,10 +9,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "stop", usage = "stop", - description = "Stops the server", permission = "server.stop") +@Command(label = "stop", usage = "stop", permission = "server.stop") public final class StopCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.stop.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { CommandHandler.sendMessage(null, translate("commands.stop.success")); diff --git a/src/main/java/emu/grasscutter/command/commands/TalentCommand.java b/src/main/java/emu/grasscutter/command/commands/TalentCommand.java index c9b2e8931..ca1bff76d 100644 --- a/src/main/java/emu/grasscutter/command/commands/TalentCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TalentCommand.java @@ -14,8 +14,7 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "talent", usage = "talent ", - description = "Set talent level for your current active character", permission = "player.settalent") +@Command(label = "talent", usage = "talent ", permission = "player.settalent") public final class TalentCommand implements CommandHandler { private void setTalentLevel(Player sender, Player player, Avatar avatar, int talentId, int talentLevel) { int oldLevel = avatar.getSkillLevelMap().get(talentId); @@ -44,6 +43,11 @@ public final class TalentCommand implements CommandHandler { CommandHandler.sendMessage(sender, translate(successMessage, talentLevel)); } + @Override + public String description() { + return translate("commands.talent.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java b/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java index 54c6101f7..d25e73f96 100644 --- a/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java @@ -10,9 +10,13 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "tpall", usage = "tpall", - description = "Teleports all players in your world to your position", permission = "player.tpall") +@Command(label = "tpall", usage = "tpall", permission = "player.tpall") public final class TeleportAllCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.teleportAll.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java b/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java index 06b669a17..364e4188f 100644 --- a/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java @@ -10,8 +10,7 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "teleport", usage = "teleport [scene id]", aliases = {"tp"}, - description = "Change the player's position.", permission = "player.teleport") +@Command(label = "teleport", usage = "teleport [scene id]", aliases = {"tp"}, permission = "player.teleport") public final class TeleportCommand implements CommandHandler { private float parseRelative(String input, Float current) { // TODO: Maybe this will be useful elsewhere later @@ -25,6 +24,11 @@ public final class TeleportCommand implements CommandHandler { return current; } + @Override + public String description() { + return translate("commands.teleport.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java b/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java index df8a6a01f..d2a6c5f64 100644 --- a/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java @@ -11,10 +11,14 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "weather", usage = "weather [climateId]", - description = "Changes the weather.", aliases = {"w"}, permission = "player.weather") +@Command(label = "weather", usage = "weather [climateId]", aliases = {"w"}, permission = "player.weather") public final class WeatherCommand implements CommandHandler { + @Override + public String description() { + return translate("commands.weather.description"); + } + @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index d9923a656..b5558833f 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -21,6 +21,7 @@ import com.google.gson.reflect.TypeToken; import emu.grasscutter.GameConstants; import emu.grasscutter.Grasscutter; import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; import emu.grasscutter.command.CommandMap; import emu.grasscutter.data.GameData; import emu.grasscutter.data.ResourceLoader; @@ -112,17 +113,16 @@ final class ToolsWithLanguageOption { writer.println("// Created " + dtf.format(now) + System.lineSeparator() + System.lineSeparator()); CommandMap cmdMap = new CommandMap(true); - List cmdList = new ArrayList<>(cmdMap.getAnnotationsAsList()); + HashMap cmdList = cmdMap.getHandlersAndAnnotations(); writer.println("// Commands"); - for (Command cmd : cmdList) { - String cmdName = cmd.label(); + cmdList.forEach((handler, command) -> { + String cmdName = command.label(); while (cmdName.length() <= 15) { cmdName = " " + cmdName; } - writer.println(cmdName + " : " + cmd.description()); - } - + writer.println(cmdName + " : " + handler.description()); + }); writer.println(); list = new ArrayList<>(GameData.getAvatarDataMap().keySet()); diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index fb33ba287..438674e9c 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -95,17 +95,20 @@ "create": "Account created with UID %s.", "delete": "Account deleted.", "no_account": "Account not found.", - "command_usage": "Usage: account [uid]" + "command_usage": "Usage: account [uid]", + "description": "Modify user accounts" }, "broadcast": { "command_usage": "Usage: broadcast ", - "message_sent": "Message sent." + "message_sent": "Message sent.", + "description": "Sends a message to all the players" }, "changescene": { "usage": "Usage: changescene ", "already_in_scene": "You are already in that scene.", "success": "Changed to scene %s.", - "exists_error": "The specified scene does not exist." + "exists_error": "The specified scene does not exist.", + "description": "Changes your scene" }, "clear": { "command_usage": "Usage: clear ", @@ -115,35 +118,41 @@ "furniture": "Cleared furniture for %s.", "displays": "Cleared displays for %s.", "virtuals": "Cleared virtuals for %s.", - "everything": "Cleared everything for %s." + "everything": "Cleared everything for %s.", + "description": "Deletes unequipped unlocked items, including yellow rarity ones from your inventory" }, "coop": { "usage": "Usage: coop ", - "success": "Summoned %s to %s's world." + "success": "Summoned %s to %s's world.", + "description": "Forces someone to join the world of others" }, "enter_dungeon": { "usage": "Usage: enterdungeon ", "changed": "Changed to dungeon %s", "not_found_error": "Dungeon does not exist", - "in_dungeon_error": "You are already in that dungeon" + "in_dungeon_error": "You are already in that dungeon", + "description": "Enter a dungeon" }, "giveAll": { "usage": "Usage: giveall [player] [amount]", "started": "Receiving all items...", "success": "Successfully gave all items to %s.", - "invalid_amount_or_playerId": "Invalid amount or player ID." + "invalid_amount_or_playerId": "Invalid amount or player ID.", + "description": "Gives all items" }, "giveArtifact": { "usage": "Usage: giveart|gart [player] [[,]]... [level]", "id_error": "Invalid artifact ID.", - "success": "Given %s to %s." + "success": "Given %s to %s.", + "description": "Gives the player a specified artifact" }, "giveChar": { "usage": "Usage: givechar [amount]", "given": "Given %s with level %s to %s.", "invalid_avatar_id": "Invalid avatar id.", "invalid_avatar_level": "Invalid avatar level.", - "invalid_avatar_or_player_id": "Invalid avatar or player ID." + "invalid_avatar_or_player_id": "Invalid avatar or player ID.", + "description": "Gives the player a specified character" }, "give": { "usage": "Usage: give [amount] [level]", @@ -151,29 +160,36 @@ "refinement_must_between_1_and_5": "Refinement must be between 1 and 5.", "given": "Given %s of %s to %s.", "given_with_level_and_refinement": "Given %s with level %s, refinement %s %s times to %s", - "given_level": "Given %s with level %s %s times to %s" + "given_level": "Given %s with level %s %s times to %s", + "description": "Gives an item to you or the specified player" }, "godmode": { - "success": "Godmode is now %s for %s." + "success": "Godmode is now %s for %s.", + "description": "Prevents you from taking damage. Defaults to toggle." }, "heal": { - "success": "All characters have been healed." + "success": "All characters have been healed.", + "description": "Heal all characters in your current team." }, "kick": { "player_kick_player": "Player [%s:%s] has kicked player [%s:%s]", - "server_kick_player": "Kicking player [%s:%s]" + "server_kick_player": "Kicking player [%s:%s]", + "description": "Kicks the specified player from the server (WIP)" }, "kill": { "usage": "Usage: killall [playerUid] [sceneId]", "scene_not_found_in_player_world": "Scene not found in player world", - "kill_monsters_in_scene": "Killing %s monsters in scene %s" + "kill_monsters_in_scene": "Killing %s monsters in scene %s", + "description": "Kill all entities" }, "killCharacter": { "usage": "Usage: /killcharacter [playerId]", - "success": "Killed %s's current character." + "success": "Killed %s's current character.", + "description": "Kills the players current character" }, "list": { - "success": "There are %s player(s) online:" + "success": "There are %s player(s) online:", + "description": "List online players" }, "permission": { "usage": "Usage: permission ", @@ -181,21 +197,26 @@ "has_error": "They already have this permission!", "remove": "Permission removed.", "not_have_error": "They don't have this permission!", - "account_error": "The account cannot be found." + "account_error": "The account cannot be found.", + "description": "Grants or removes a permission for a user" }, "position": { - "success": "Coordinates: %s, %s, %s\nScene id: %s" + "success": "Coordinates: %s, %s, %s\nScene id: %s", + "description": "Get coordinates." }, "reload": { "reload_start": "Reloading config.", - "reload_done": "Reload complete." + "reload_done": "Reload complete.", + "description": "Reload server config" }, "resetConst": { "reset_all": "Reset all avatars' constellations.", - "success": "Constellations for %s have been reset. Please relog to see changes." + "success": "Constellations for %s have been reset. Please relog to see changes.", + "description": "Resets the constellation level on your current active character, will need to relog after using the command to see any changes." }, "resetShopLimit": { - "usage": "Usage: /resetshop " + "usage": "Usage: /resetshop ", + "description": "Reset target player's shop refresh time." }, "sendMail": { "usage": "Usage: give [player] [amount]", @@ -217,17 +238,20 @@ "message": "", "sender": "", "arguments": " [amount] [level]", - "error": "ERROR: invalid construction stage %s. Check console for stacktrace." + "error": "ERROR: invalid construction stage %s. Check console for stacktrace.", + "description": "Sends mail to the specified user. The usage of this command changes based on it's composition state." }, "sendMessage": { "usage": "Usage: sendmessage ", - "success": "Message sent." + "success": "Message sent.", + "description": "Sends a message to a player as the server" }, "setFetterLevel": { "usage": "Usage: setfetterlevel ", "range_error": "Fetter level must be between 0 and 10.", "success": "Fetter level set to %s", - "level_error": "Invalid fetter level." + "level_error": "Invalid fetter level.", + "description": "Sets your fetter level for your current active character" }, "setStats": { "usage_console": "Usage: setstats|stats @ ", @@ -238,20 +262,24 @@ "player_error": "Player not found or offline.", "set_self": "%s set to %s.", "set_for_uid": "%s for %s set to %s.", - "set_max_hp": "MAX HP set to %s." + "set_max_hp": "MAX HP set to %s.", + "description": "Set fight property for your current active character" }, "setWorldLevel": { "usage": "Usage: setworldlevel ", "value_error": "World level must be between 0-8", "success": "World level set to %s.", - "invalid_world_level": "Invalid world level." + "invalid_world_level": "Invalid world level.", + "description": "Sets your world level (Relog to see proper effects)" }, "spawn": { "usage": "Usage: spawn [amount] [level(monster only)]", - "success": "Spawned %s of %s." + "success": "Spawned %s of %s.", + "description": "Spawns an entity near you" }, "stop": { - "success": "Server shutting down..." + "success": "Server shutting down...", + "description": "Stops the server" }, "talent": { "usage_1": "To set talent level: /talent set ", @@ -267,32 +295,41 @@ "invalid_level": "Invalid talent level.", "normal_attack_id": "Normal Attack ID %s.", "e_skill_id": "E skill ID %s.", - "q_skill_id": "Q skill ID %s." + "q_skill_id": "Q skill ID %s.", + "description": "Set talent level for your current active character" }, "teleportAll": { "success": "Summoned all players to your location.", - "error": "You only can use this command in MP mode." + "error": "You only can use this command in MP mode.", + "description": "Teleports all players in your world to your position" }, "teleport": { "usage_server": "Usage: /tp @ [scene id]", "usage": "Usage: /tp [@] [scene id]", "specify_player_id": "You must specify a player id.", "invalid_position": "Invalid position.", - "success": "Teleported %s to %s, %s, %s in scene %s" + "success": "Teleported %s to %s, %s, %s in scene %s", + "description": "Change the player's position." }, "weather": { "usage": "Usage: weather [climateId]", "success": "Changed weather to %s with climate %s", - "invalid_id": "Invalid ID." + "invalid_id": "Invalid ID.", + "description": "Changes the weather." }, "drop": { "command_usage": "Usage: drop [amount]", - "success": "Dropped %s of %s." + "success": "Dropped %s of %s.", + "description": "Drops an item near you" }, "help": { "usage": "Usage: ", "aliases": "Aliases: ", - "available_commands": "Available commands: " + "available_commands": "Available commands: ", + "description": "Sends the help message or shows information about a specified command" + }, + "restart": { + "description": "Restarts the current session" } } } From ef3579da82990111f3f0c826bfd4983655319c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=E5=9D=97=E5=90=9B?= Date: Sun, 8 May 2022 11:51:32 +0800 Subject: [PATCH 27/28] add Command description --- src/main/java/emu/grasscutter/command/Command.java | 2 ++ src/main/java/emu/grasscutter/command/CommandHandler.java | 2 +- .../java/emu/grasscutter/command/commands/HelpCommand.java | 6 +++--- src/main/java/emu/grasscutter/tools/Tools.java | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/emu/grasscutter/command/Command.java b/src/main/java/emu/grasscutter/command/Command.java index c94804678..734f454ea 100644 --- a/src/main/java/emu/grasscutter/command/Command.java +++ b/src/main/java/emu/grasscutter/command/Command.java @@ -9,6 +9,8 @@ public @interface Command { String usage() default "No usage specified"; + String description() default "No description specified"; + String[] aliases() default {}; String permission() default ""; diff --git a/src/main/java/emu/grasscutter/command/CommandHandler.java b/src/main/java/emu/grasscutter/command/CommandHandler.java index dadb87bb3..76d5d7b04 100644 --- a/src/main/java/emu/grasscutter/command/CommandHandler.java +++ b/src/main/java/emu/grasscutter/command/CommandHandler.java @@ -7,7 +7,7 @@ import java.util.List; public interface CommandHandler { - String description(); + default String description() { return null; }; /** * Send a message to the target. diff --git a/src/main/java/emu/grasscutter/command/commands/HelpCommand.java b/src/main/java/emu/grasscutter/command/commands/HelpCommand.java index dbb85bf9d..323c2878b 100644 --- a/src/main/java/emu/grasscutter/command/commands/HelpCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/HelpCommand.java @@ -43,7 +43,7 @@ public final class HelpCommand implements CommandHandler { } else { Command annotation = handler.getClass().getAnnotation(Command.class); - builder.append(" ").append(handler.description()).append("\n"); + builder.append(" ").append(handler.description() == null ? annotation.description(): handler.description()).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); @@ -65,7 +65,7 @@ public final class HelpCommand implements CommandHandler { StringBuilder builder = new StringBuilder("\n" + translate("commands.help.available_commands") + "\n"); annotations.forEach((annotation, handler) -> { builder.append(annotation.label()).append("\n"); - builder.append(" ").append(handler.description()).append("\n"); + builder.append(" ").append(handler.description() == null ? annotation.description() : handler.description()).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); @@ -82,7 +82,7 @@ public final class HelpCommand implements CommandHandler { CommandHandler.sendMessage(player, translate("commands.help.available_commands")); annotations.forEach((annotation, handler) -> { StringBuilder builder = new StringBuilder(annotation.label()).append("\n"); - builder.append(" ").append(handler.description()).append("\n"); + builder.append(" ").append(handler.description() == null ? annotation.description() : handler.description()).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index b5558833f..a1bcb1b9a 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -121,7 +121,7 @@ final class ToolsWithLanguageOption { while (cmdName.length() <= 15) { cmdName = " " + cmdName; } - writer.println(cmdName + " : " + handler.description()); + writer.println(cmdName + " : " + (handler.description() == null ? command.description() : handler.description())); }); writer.println(); From 3a5503de725a991b8bc520444c3ab1f1349ffcb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=E5=9D=97=E5=90=9B?= Date: Sun, 8 May 2022 14:44:14 +0800 Subject: [PATCH 28/28] Using annotation key translation --- .../java/emu/grasscutter/command/Command.java | 2 +- .../grasscutter/command/CommandHandler.java | 2 -- .../emu/grasscutter/command/CommandMap.java | 8 ------- .../command/commands/AccountCommand.java | 7 +----- .../command/commands/BroadcastCommand.java | 7 +----- .../command/commands/ChangeSceneCommand.java | 6 +---- .../command/commands/ClearCommand.java | 6 +---- .../command/commands/CoopCommand.java | 6 +---- .../command/commands/DropCommand.java | 7 +----- .../command/commands/EnterDungeonCommand.java | 6 +---- .../command/commands/GiveAllCommand.java | 7 +----- .../command/commands/GiveArtifactCommand.java | 6 +---- .../command/commands/GiveCharCommand.java | 7 +----- .../command/commands/GiveCommand.java | 7 +----- .../command/commands/GodModeCommand.java | 7 +----- .../command/commands/HealCommand.java | 6 +---- .../command/commands/HelpCommand.java | 23 ++++++++----------- .../command/commands/KickCommand.java | 7 +----- .../command/commands/KillAllCommand.java | 7 +----- .../commands/KillCharacterCommand.java | 7 +----- .../command/commands/ListCommand.java | 7 +----- .../command/commands/PermissionCommand.java | 7 +----- .../command/commands/PositionCommand.java | 7 +----- .../command/commands/ReloadCommand.java | 7 +----- .../command/commands/ResetConstCommand.java | 7 +----- .../commands/ResetShopLimitCommand.java | 6 +---- .../command/commands/RestartCommand.java | 7 +----- .../command/commands/SendMailCommand.java | 9 ++------ .../command/commands/SendMessageCommand.java | 7 +----- .../commands/SetFetterLevelCommand.java | 7 +----- .../command/commands/SetStatsCommand.java | 7 +----- .../commands/SetWorldLevelCommand.java | 7 +----- .../command/commands/SpawnCommand.java | 7 +----- .../command/commands/StopCommand.java | 7 +----- .../command/commands/TalentCommand.java | 7 +----- .../command/commands/TeleportAllCommand.java | 6 +---- .../command/commands/TeleportCommand.java | 7 +----- .../command/commands/WeatherCommand.java | 7 +----- .../java/emu/grasscutter/tools/Tools.java | 12 ++++++---- src/main/resources/languages/en-US.json | 1 + 40 files changed, 53 insertions(+), 227 deletions(-) diff --git a/src/main/java/emu/grasscutter/command/Command.java b/src/main/java/emu/grasscutter/command/Command.java index 734f454ea..045f6a51c 100644 --- a/src/main/java/emu/grasscutter/command/Command.java +++ b/src/main/java/emu/grasscutter/command/Command.java @@ -9,7 +9,7 @@ public @interface Command { String usage() default "No usage specified"; - String description() default "No description specified"; + String description() default "commands.generic.no_description_specified"; String[] aliases() default {}; diff --git a/src/main/java/emu/grasscutter/command/CommandHandler.java b/src/main/java/emu/grasscutter/command/CommandHandler.java index 76d5d7b04..f4fe12b3f 100644 --- a/src/main/java/emu/grasscutter/command/CommandHandler.java +++ b/src/main/java/emu/grasscutter/command/CommandHandler.java @@ -7,8 +7,6 @@ import java.util.List; public interface CommandHandler { - default String description() { return null; }; - /** * Send a message to the target. * diff --git a/src/main/java/emu/grasscutter/command/CommandMap.java b/src/main/java/emu/grasscutter/command/CommandMap.java index 6b6a852af..a183c6ac3 100644 --- a/src/main/java/emu/grasscutter/command/CommandMap.java +++ b/src/main/java/emu/grasscutter/command/CommandMap.java @@ -85,14 +85,6 @@ public final class CommandMap { return new LinkedHashMap<>(this.annotations); } - public HashMap getHandlersAndAnnotations() { - HashMap hashMap = new HashMap<>(); - this.commands.forEach((key, handler) -> { - hashMap.put(handler, this.annotations.get(key)); - }); - return hashMap; - } - /** * Returns a list of all registered commands. * diff --git a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java index 1c5c8228e..4b287afa7 100644 --- a/src/main/java/emu/grasscutter/command/commands/AccountCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/AccountCommand.java @@ -9,14 +9,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "account", usage = "account [uid]") +@Command(label = "account", usage = "account [uid]", description = "commands.account.description") public final class AccountCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.account.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (sender != null) { diff --git a/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java b/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java index fcabb131c..95f0c7c05 100644 --- a/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/BroadcastCommand.java @@ -9,14 +9,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "broadcast", usage = "broadcast ", aliases = {"b"}, permission = "server.broadcast") +@Command(label = "broadcast", usage = "broadcast ", aliases = {"b"}, permission = "server.broadcast", description = "commands.broadcast.description") public final class BroadcastCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.broadcast.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (args.size() < 1) { diff --git a/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java b/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java index ea7bfe0f6..594eb27c6 100644 --- a/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ChangeSceneCommand.java @@ -8,12 +8,8 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "changescene", usage = "changescene ", aliases = {"scene"}, permission = "player.changescene") +@Command(label = "changescene", usage = "changescene ", aliases = {"scene"}, permission = "player.changescene", description = "commands.changescene.description") public final class ChangeSceneCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.changescene.description"); - } @Override public void execute(Player sender, Player targetPlayer, List args) { diff --git a/src/main/java/emu/grasscutter/command/commands/ClearCommand.java b/src/main/java/emu/grasscutter/command/commands/ClearCommand.java index d416bec52..38f78e638 100644 --- a/src/main/java/emu/grasscutter/command/commands/ClearCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ClearCommand.java @@ -13,15 +13,11 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "clear", usage = "clear ", //Merged /clearartifacts and /clearweapons to /clear [uid] + description = "commands.clear.description", aliases = {"clear"}, permission = "player.clearinv") public final class ClearCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.clear.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/CoopCommand.java b/src/main/java/emu/grasscutter/command/commands/CoopCommand.java index 120665b76..cf7d4fc82 100644 --- a/src/main/java/emu/grasscutter/command/commands/CoopCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/CoopCommand.java @@ -9,12 +9,8 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "coop", usage = "coop [host UID]", permission = "server.coop") +@Command(label = "coop", usage = "coop [host UID]", permission = "server.coop", description = "commands.coop.description") public final class CoopCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.coop.description"); - } @Override public void execute(Player sender, Player targetPlayer, List args) { diff --git a/src/main/java/emu/grasscutter/command/commands/DropCommand.java b/src/main/java/emu/grasscutter/command/commands/DropCommand.java index a187cfda8..10c306cad 100644 --- a/src/main/java/emu/grasscutter/command/commands/DropCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/DropCommand.java @@ -13,14 +13,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "drop", usage = "drop [amount]", aliases = {"d", "dropitem"}, permission = "server.drop") +@Command(label = "drop", usage = "drop [amount]", aliases = {"d", "dropitem"}, permission = "server.drop", description = "commands.drop.description") public final class DropCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.drop.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java b/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java index d92d537e9..8534c034f 100644 --- a/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/EnterDungeonCommand.java @@ -8,12 +8,8 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "enterdungeon", usage = "enterdungeon ", aliases = {"dungeon"}, permission = "player.enterdungeon") +@Command(label = "enterdungeon", usage = "enterdungeon ", aliases = {"dungeon"}, permission = "player.enterdungeon", description = "commands.enter_dungeon.description") public final class EnterDungeonCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.enter_dungeon.description"); - } @Override public void execute(Player sender, Player targetPlayer, List args) { diff --git a/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java index 5009a4462..c94d67129 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveAllCommand.java @@ -15,14 +15,9 @@ import java.util.*; import static emu.grasscutter.utils.Language.translate; -@Command(label = "giveall", usage = "giveall [amount]", aliases = {"givea"}, permission = "player.giveall", threading = true) +@Command(label = "giveall", usage = "giveall [amount]", aliases = {"givea"}, permission = "player.giveall", threading = true, description = "commands.giveAll.description") public final class GiveAllCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.giveAll.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java index d41e83671..b87642bb2 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveArtifactCommand.java @@ -16,12 +16,8 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "giveart", usage = "giveart [[,]]... [level]", aliases = {"gart"}, permission = "player.giveart") +@Command(label = "giveart", usage = "giveart [[,]]... [level]", aliases = {"gart"}, permission = "player.giveart", description = "commands.giveArtifact.description") public final class GiveArtifactCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.giveArtifact.description"); - } @Override public void execute(Player sender, Player targetPlayer, List args) { diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java index 0e784639d..5c6bad0d2 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveCharCommand.java @@ -12,14 +12,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "givechar", usage = "givechar [level]", aliases = {"givec"}, permission = "player.givechar") +@Command(label = "givechar", usage = "givechar [level]", aliases = {"givec"}, permission = "player.givechar", description = "commands.giveChar.description") public final class GiveCharCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.giveChar.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java index 3daa2dff3..19a9a8d26 100644 --- a/src/main/java/emu/grasscutter/command/commands/GiveCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GiveCommand.java @@ -17,7 +17,7 @@ import java.util.regex.Pattern; import static emu.grasscutter.utils.Language.translate; @Command(label = "give", usage = "give [amount] [level]", aliases = { - "g", "item", "giveitem"}, permission = "player.give") + "g", "item", "giveitem"}, permission = "player.give", description = "commands.give.description") public final class GiveCommand implements CommandHandler { Pattern lvlRegex = Pattern.compile("l(?:vl?)?(\\d+)"); // Java is a joke of a proglang that doesn't have raw string literals Pattern refineRegex = Pattern.compile("r(\\d+)"); @@ -31,11 +31,6 @@ public final class GiveCommand implements CommandHandler { return -1; } - @Override - public String description() { - return translate("commands.give.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java b/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java index 4fd2999a6..bf2a00c9f 100644 --- a/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/GodModeCommand.java @@ -8,14 +8,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "godmode", usage = "godmode [on|off|toggle]", permission = "player.godmode") +@Command(label = "godmode", usage = "godmode [on|off|toggle]", permission = "player.godmode", description = "commands.godmode.description") public final class GodModeCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.godmode.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/HealCommand.java b/src/main/java/emu/grasscutter/command/commands/HealCommand.java index b459ecb8c..440db0a49 100644 --- a/src/main/java/emu/grasscutter/command/commands/HealCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/HealCommand.java @@ -11,12 +11,8 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "heal", usage = "heal|h", aliases = {"h"}, permission = "player.heal") +@Command(label = "heal", usage = "heal|h", aliases = {"h"}, permission = "player.heal", description = "commands.heal.description") public final class HealCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.heal.description"); - } @Override public void execute(Player sender, Player targetPlayer, List args) { diff --git a/src/main/java/emu/grasscutter/command/commands/HelpCommand.java b/src/main/java/emu/grasscutter/command/commands/HelpCommand.java index 323c2878b..8a222f7a6 100644 --- a/src/main/java/emu/grasscutter/command/commands/HelpCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/HelpCommand.java @@ -10,26 +10,21 @@ import java.util.*; import static emu.grasscutter.utils.Language.translate; -@Command(label = "help", usage = "help [command]") +@Command(label = "help", usage = "help [command]", description = "commands.help.description") public final class HelpCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.help.description"); - } - @Override public void execute(Player player, Player targetPlayer, List args) { if (args.size() < 1) { HashMap handlers = CommandMap.getInstance().getHandlers(); - HashMap annotations = new HashMap<>(); + List annotations = new ArrayList<>(); for (String key : handlers.keySet()) { Command annotation = handlers.get(key).getClass().getAnnotation(Command.class); if (!Arrays.asList(annotation.aliases()).contains(key)) { if (player != null && !Objects.equals(annotation.permission(), "") && !player.getAccount().hasPermission(annotation.permission())) continue; - annotations.put(annotation, handlers.get(key)); + annotations.add(annotation); } } @@ -43,7 +38,7 @@ public final class HelpCommand implements CommandHandler { } else { Command annotation = handler.getClass().getAnnotation(Command.class); - builder.append(" ").append(handler.description() == null ? annotation.description(): handler.description()).append("\n"); + builder.append(" ").append(translate(annotation.description())).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); @@ -60,12 +55,12 @@ public final class HelpCommand implements CommandHandler { } } - void SendAllHelpMessage(Player player, HashMap annotations) { + void SendAllHelpMessage(Player player, List annotations) { if (player == null) { StringBuilder builder = new StringBuilder("\n" + translate("commands.help.available_commands") + "\n"); - annotations.forEach((annotation, handler) -> { + annotations.forEach(annotation -> { builder.append(annotation.label()).append("\n"); - builder.append(" ").append(handler.description() == null ? annotation.description() : handler.description()).append("\n"); + builder.append(" ").append(translate(annotation.description())).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); @@ -80,9 +75,9 @@ public final class HelpCommand implements CommandHandler { CommandHandler.sendMessage(null, builder.toString()); } else { CommandHandler.sendMessage(player, translate("commands.help.available_commands")); - annotations.forEach((annotation, handler) -> { + annotations.forEach(annotation -> { StringBuilder builder = new StringBuilder(annotation.label()).append("\n"); - builder.append(" ").append(handler.description() == null ? annotation.description() : handler.description()).append("\n"); + builder.append(" ").append(translate(annotation.description())).append("\n"); builder.append(translate("commands.help.usage")).append(annotation.usage()); if (annotation.aliases().length >= 1) { builder.append("\n").append(translate("commands.help.aliases")); diff --git a/src/main/java/emu/grasscutter/command/commands/KickCommand.java b/src/main/java/emu/grasscutter/command/commands/KickCommand.java index 71b487cc4..9741226e7 100644 --- a/src/main/java/emu/grasscutter/command/commands/KickCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KickCommand.java @@ -8,14 +8,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "kick", usage = "kick", permission = "server.kick") +@Command(label = "kick", usage = "kick", permission = "server.kick", description = "commands.kick.description") public final class KickCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.kick.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java b/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java index 1fa51eec4..da9ac7b5e 100644 --- a/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KillAllCommand.java @@ -12,14 +12,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "killall", usage = "killall [sceneId]", permission = "server.killall") +@Command(label = "killall", usage = "killall [sceneId]", permission = "server.killall", description = "commands.kill.description") public final class KillAllCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.kill.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java b/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java index f3fdb4998..3eda6f7e7 100644 --- a/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/KillCharacterCommand.java @@ -13,14 +13,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "killcharacter", usage = "killcharacter", aliases = {"suicide", "kill"}, permission = "player.killcharacter") +@Command(label = "killcharacter", usage = "killcharacter", aliases = {"suicide", "kill"}, permission = "player.killcharacter", description = "commands.list.description") public final class KillCharacterCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.killCharacter.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/ListCommand.java b/src/main/java/emu/grasscutter/command/commands/ListCommand.java index 7834d2467..53a274e52 100644 --- a/src/main/java/emu/grasscutter/command/commands/ListCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ListCommand.java @@ -10,14 +10,9 @@ import java.util.Map; import static emu.grasscutter.utils.Language.translate; -@Command(label = "list", usage = "list [uid]", aliases = {"players"}) +@Command(label = "list", usage = "list [uid]", aliases = {"players"}, description = "commands.list.description") public final class ListCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.list.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { Map playersMap = Grasscutter.getGameServer().getPlayers(); diff --git a/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java b/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java index 309451945..4b945b3d1 100644 --- a/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/PermissionCommand.java @@ -10,14 +10,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "permission", usage = "permission ", permission = "*") +@Command(label = "permission", usage = "permission ", permission = "*", description = "commands.permission.description") public final class PermissionCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.permission.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/PositionCommand.java b/src/main/java/emu/grasscutter/command/commands/PositionCommand.java index 3a3b40a3f..b5a250af6 100644 --- a/src/main/java/emu/grasscutter/command/commands/PositionCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/PositionCommand.java @@ -9,14 +9,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "position", usage = "position", aliases = {"pos"}) +@Command(label = "position", usage = "position", aliases = {"pos"}, description = "commands.position.description") public final class PositionCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.position.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java index 8e3e5e5aa..29eb93d0d 100644 --- a/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ReloadCommand.java @@ -9,14 +9,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "reload", usage = "reload", permission = "server.reload") +@Command(label = "reload", usage = "reload", permission = "server.reload", description = "commands.reload.description") public final class ReloadCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.reload.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { CommandHandler.sendMessage(sender, translate("commands.reload.reload_start")); diff --git a/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java b/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java index 9eba8e4c4..3a77cee4d 100644 --- a/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ResetConstCommand.java @@ -11,14 +11,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "resetconst", usage = "resetconst [all]", - aliases = {"resetconstellation"}, permission = "player.resetconstellation") + aliases = {"resetconstellation"}, permission = "player.resetconstellation", description = "commands.resetConst.description") public final class ResetConstCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.resetConst.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java b/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java index bba8da32c..7aa84ff6a 100644 --- a/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/ResetShopLimitCommand.java @@ -9,12 +9,8 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "resetshop", usage = "resetshop", permission = "server.resetshop") +@Command(label = "resetshop", usage = "resetshop", permission = "server.resetshop", description = "commands.status.description") public final class ResetShopLimitCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.status.description"); - } @Override public void execute(Player sender, Player targetPlayer, List args) { diff --git a/src/main/java/emu/grasscutter/command/commands/RestartCommand.java b/src/main/java/emu/grasscutter/command/commands/RestartCommand.java index 2c56ae443..045a49d9e 100644 --- a/src/main/java/emu/grasscutter/command/commands/RestartCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/RestartCommand.java @@ -8,14 +8,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "restart", usage = "restart") +@Command(label = "restart", usage = "restart", description = "commands.restart.description") public final class RestartCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.restart.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (sender == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java b/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java index a56d68165..69aafa20b 100644 --- a/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SendMailCommand.java @@ -13,7 +13,7 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @SuppressWarnings("ConstantConditions") -@Command(label = "sendmail", usage = "sendmail [templateId]", permission = "server.sendmail") +@Command(label = "sendmail", usage = "sendmail [templateId]", permission = "server.sendmail", description = "commands.sendMail.description") public final class SendMailCommand implements CommandHandler { // TODO: You should be able to do /sendmail and then just send subsequent messages until you finish @@ -23,11 +23,6 @@ public final class SendMailCommand implements CommandHandler { // Key = User that is constructing the mail. private static final HashMap mailBeingConstructed = new HashMap(); - @Override - public String description() { - return translate("commands.sendMail.description"); - } - // Yes this is awful and I hate it. @Override public void execute(Player sender, Player targetPlayer, List args) { @@ -44,7 +39,7 @@ public final class SendMailCommand implements CommandHandler { MailBuilder mailBuilder; switch (args.get(0).toLowerCase()) { case "help" -> { - CommandHandler.sendMessage(sender, this.description() + "\nUsage: " + this.getClass().getAnnotation(Command.class).usage()); + CommandHandler.sendMessage(sender, translate(this.getClass().getAnnotation(Command.class).description()) + "\nUsage: " + this.getClass().getAnnotation(Command.class).usage()); return; } case "all" -> mailBuilder = new MailBuilder(true, new Mail()); diff --git a/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java b/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java index 36e53de10..18d6264db 100644 --- a/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SendMessageCommand.java @@ -9,14 +9,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "say", usage = "say ", - aliases = {"sendservmsg", "sendservermessage", "sendmessage"}, permission = "server.sendmessage") + aliases = {"sendservmsg", "sendservermessage", "sendmessage"}, permission = "server.sendmessage", description = "commands.sendMessage.description") public final class SendMessageCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.sendMessage.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java b/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java index e098d99a5..ca5a3cb43 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetFetterLevelCommand.java @@ -12,14 +12,9 @@ import emu.grasscutter.server.packet.send.PacketAvatarFetterDataNotify; import static emu.grasscutter.utils.Language.translate; @Command(label = "setfetterlevel", usage = "setfetterlevel ", - aliases = {"setfetterlvl", "setfriendship"}, permission = "player.setfetterlevel") + aliases = {"setfetterlvl", "setfriendship"}, permission = "player.setfetterlevel", description = "commands.setFetterLevel.description") public final class SetFetterLevelCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.setFetterLevel.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java index 11cb8ab80..c7ed78a58 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetStatsCommand.java @@ -15,7 +15,7 @@ import emu.grasscutter.utils.Language; import static emu.grasscutter.utils.Language.translate; -@Command(label = "setstats", usage = "setstats|stats ", aliases = {"stats"}, permission = "player.setstats") +@Command(label = "setstats", usage = "setstats|stats ", aliases = {"stats"}, permission = "player.setstats", description = "commands.setStats.description") public final class SetStatsCommand implements CommandHandler { static class Stat { String name; @@ -173,11 +173,6 @@ public final class SetStatsCommand implements CommandHandler { stats.put("_nonextra_physical_add_hurt", new Stat("NONEXTRA_PHYSICAL_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT, true)); } - @Override - public String description() { - return translate("commands.setStats.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { String syntax = sender == null ? translate("commands.setStats.usage_console") : translate("commands.setStats.ingame"); diff --git a/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java b/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java index 16b10bc6c..41b959336 100644 --- a/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SetWorldLevelCommand.java @@ -10,14 +10,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; @Command(label = "setworldlevel", usage = "setworldlevel ", - aliases = {"setworldlvl"}, permission = "player.setworldlevel") + aliases = {"setworldlvl"}, permission = "player.setworldlevel", description = "commands.setWorldLevel.description") public final class SetWorldLevelCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.setWorldLevel.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java b/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java index 8a995402b..7f0c704c6 100644 --- a/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/SpawnCommand.java @@ -22,14 +22,9 @@ import java.util.Random; import static emu.grasscutter.utils.Language.translate; -@Command(label = "spawn", usage = "spawn [amount] [level(monster only)]", permission = "server.spawn") +@Command(label = "spawn", usage = "spawn [amount] [level(monster only)]", permission = "server.spawn", description = "commands.spawn.description") public final class SpawnCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.spawn.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/StopCommand.java b/src/main/java/emu/grasscutter/command/commands/StopCommand.java index 64326a748..129b27b24 100644 --- a/src/main/java/emu/grasscutter/command/commands/StopCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/StopCommand.java @@ -9,14 +9,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "stop", usage = "stop", permission = "server.stop") +@Command(label = "stop", usage = "stop", permission = "server.stop", description = "commands.stop.description") public final class StopCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.stop.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { CommandHandler.sendMessage(null, translate("commands.stop.success")); diff --git a/src/main/java/emu/grasscutter/command/commands/TalentCommand.java b/src/main/java/emu/grasscutter/command/commands/TalentCommand.java index ca1bff76d..1540a81f8 100644 --- a/src/main/java/emu/grasscutter/command/commands/TalentCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TalentCommand.java @@ -14,7 +14,7 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "talent", usage = "talent ", permission = "player.settalent") +@Command(label = "talent", usage = "talent ", permission = "player.settalent", description = "commands.talent.description") public final class TalentCommand implements CommandHandler { private void setTalentLevel(Player sender, Player player, Avatar avatar, int talentId, int talentLevel) { int oldLevel = avatar.getSkillLevelMap().get(talentId); @@ -43,11 +43,6 @@ public final class TalentCommand implements CommandHandler { CommandHandler.sendMessage(sender, translate(successMessage, talentLevel)); } - @Override - public String description() { - return translate("commands.talent.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java b/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java index d25e73f96..175f69b81 100644 --- a/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TeleportAllCommand.java @@ -10,12 +10,8 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "tpall", usage = "tpall", permission = "player.tpall") +@Command(label = "tpall", usage = "tpall", permission = "player.tpall", description = "commands.teleportAll.description") public final class TeleportAllCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.teleportAll.description"); - } @Override public void execute(Player sender, Player targetPlayer, List args) { diff --git a/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java b/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java index 364e4188f..0d15b55af 100644 --- a/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/TeleportCommand.java @@ -10,7 +10,7 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "teleport", usage = "teleport [scene id]", aliases = {"tp"}, permission = "player.teleport") +@Command(label = "teleport", usage = "teleport [scene id]", aliases = {"tp"}, permission = "player.teleport", description = "commands.teleport.description") public final class TeleportCommand implements CommandHandler { private float parseRelative(String input, Float current) { // TODO: Maybe this will be useful elsewhere later @@ -24,11 +24,6 @@ public final class TeleportCommand implements CommandHandler { return current; } - @Override - public String description() { - return translate("commands.teleport.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java b/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java index d2a6c5f64..dd0002790 100644 --- a/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java +++ b/src/main/java/emu/grasscutter/command/commands/WeatherCommand.java @@ -11,14 +11,9 @@ import java.util.List; import static emu.grasscutter.utils.Language.translate; -@Command(label = "weather", usage = "weather [climateId]", aliases = {"w"}, permission = "player.weather") +@Command(label = "weather", usage = "weather [climateId]", aliases = {"w"}, permission = "player.weather", description = "commands.weather.description") public final class WeatherCommand implements CommandHandler { - @Override - public String description() { - return translate("commands.weather.description"); - } - @Override public void execute(Player sender, Player targetPlayer, List args) { if (targetPlayer == null) { diff --git a/src/main/java/emu/grasscutter/tools/Tools.java b/src/main/java/emu/grasscutter/tools/Tools.java index a1bcb1b9a..f69aafc80 100644 --- a/src/main/java/emu/grasscutter/tools/Tools.java +++ b/src/main/java/emu/grasscutter/tools/Tools.java @@ -31,6 +31,8 @@ import emu.grasscutter.data.def.MonsterData; import emu.grasscutter.data.def.SceneData; import emu.grasscutter.utils.Utils; +import static emu.grasscutter.utils.Language.translate; + public final class Tools { public static void createGmHandbook() throws Exception { ToolsWithLanguageOption.createGmHandbook(getLanguageOption()); @@ -113,16 +115,16 @@ final class ToolsWithLanguageOption { writer.println("// Created " + dtf.format(now) + System.lineSeparator() + System.lineSeparator()); CommandMap cmdMap = new CommandMap(true); - HashMap cmdList = cmdMap.getHandlersAndAnnotations(); + List cmdList = new ArrayList<>(cmdMap.getAnnotationsAsList()); writer.println("// Commands"); - cmdList.forEach((handler, command) -> { - String cmdName = command.label(); + for (Command cmd : cmdList) { + String cmdName = cmd.label(); while (cmdName.length() <= 15) { cmdName = " " + cmdName; } - writer.println(cmdName + " : " + (handler.description() == null ? command.description() : handler.description())); - }); + writer.println(cmdName + " : " + translate(cmd.description())); + } writer.println(); list = new ArrayList<>(GameData.getAvatarDataMap().keySet()); diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index 438674e9c..9a7485608 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -56,6 +56,7 @@ "console_execute_error": "This command can only be run from the console.", "player_execute_error": "Run this command in-game.", "command_exist_error": "No command found.", + "no_description_specified": "No description specified", "invalid": { "amount": "Invalid amount.", "artifactId": "Invalid artifactId.",