diff --git a/src/main/java/emu/grasscutter/Configuration.java b/src/main/java/emu/grasscutter/Configuration.java index 4cbd0130c..486ca8739 100644 --- a/src/main/java/emu/grasscutter/Configuration.java +++ b/src/main/java/emu/grasscutter/Configuration.java @@ -4,9 +4,11 @@ import emu.grasscutter.utils.ConfigContainer; import emu.grasscutter.utils.ConfigContainer.*; import java.util.Locale; +import java.nio.file.Paths; import static emu.grasscutter.Grasscutter.config; + /** * A data container for the server's configuration. * @@ -24,12 +26,12 @@ public final class Configuration extends ConfigContainer { public static final Locale LANGUAGE = config.language.language; public static final Locale FALLBACK_LANGUAGE = config.language.fallback; - public static final String DATA_FOLDER = config.folderStructure.data; - public static final String RESOURCES_FOLDER = config.folderStructure.resources; - public static final String KEYS_FOLDER = config.folderStructure.keys; - public static final String PLUGINS_FOLDER = config.folderStructure.plugins; - public static final String SCRIPTS_FOLDER = config.folderStructure.scripts; - public static final String PACKETS_FOLDER = config.folderStructure.packets; + private static final String DATA_FOLDER = config.folderStructure.data; + private static final String RESOURCES_FOLDER = config.folderStructure.resources; + private static final String KEYS_FOLDER = config.folderStructure.keys; + private static final String PLUGINS_FOLDER = config.folderStructure.plugins; + private static final String SCRIPTS_FOLDER = config.folderStructure.scripts; + private static final String PACKETS_FOLDER = config.folderStructure.packets; public static final Server SERVER = config.server; public static final Database DATABASE = config.databaseInfo; @@ -49,17 +51,36 @@ public final class Configuration extends ConfigContainer { /* * Utilities */ - + public static String DATA() { + return DATA_FOLDER; + } + public static String DATA(String path) { - return DATA_FOLDER + "/" + path; + return Paths.get(DATA_FOLDER, path).toString(); } public static String RESOURCE(String path) { - return RESOURCES_FOLDER + "/" + path; + return Paths.get(RESOURCES_FOLDER, path).toString(); + } + + public static String KEY(String path) { + return Paths.get(KEYS_FOLDER, path).toString(); } + public static String PLUGIN() { + return PLUGINS_FOLDER; + } + + public static String PLUGIN(String path) { + return Paths.get(PLUGINS_FOLDER, path).toString(); + } + public static String SCRIPT(String path) { - return SCRIPTS_FOLDER + "/" + path; + return Paths.get(SCRIPTS_FOLDER, path).toString(); + } + + public static String PACKET(String path) { + return Paths.get(PACKETS_FOLDER, path).toString(); } /** @@ -91,4 +112,4 @@ public final class Configuration extends ConfigContainer { public static int lr(int left, int right) { return left == 0 ? right : left; } -} \ No newline at end of file +} diff --git a/src/main/java/emu/grasscutter/Grasscutter.java b/src/main/java/emu/grasscutter/Grasscutter.java index bc5144d97..316c2030e 100644 --- a/src/main/java/emu/grasscutter/Grasscutter.java +++ b/src/main/java/emu/grasscutter/Grasscutter.java @@ -304,7 +304,7 @@ public final class Grasscutter { getLogger().info(translate("messages.status.done")); String input = null; boolean isLastInterrupted = false; - while (true) { + while (config.server.game.enableConsole) { try { input = consoleLineReader.readLine("> "); } catch (UserInterruptException e) { diff --git a/src/main/java/emu/grasscutter/command/commands/JoinCommand.java b/src/main/java/emu/grasscutter/command/commands/JoinCommand.java deleted file mode 100644 index 84258a2f2..000000000 --- a/src/main/java/emu/grasscutter/command/commands/JoinCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -package emu.grasscutter.command.commands; - -import emu.grasscutter.Grasscutter; -import emu.grasscutter.command.Command; -import emu.grasscutter.command.CommandHandler; -import emu.grasscutter.game.avatar.Avatar; -import emu.grasscutter.game.player.Player; -import emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp; - -import java.util.ArrayList; -import java.util.List; - -import static emu.grasscutter.utils.Language.translate; - -@Command(label = "join", usage = "join [AvatarIDs] such as\"join 10000038 10000039\"", - description = "commands.join.description", permission = "player.join") -public class JoinCommand implements CommandHandler { - - @Override - public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate(sender, "commands.execution.need_target")); - return; - } - - List avatarIds = new ArrayList<>(); - for (String arg : args) { - try { - int avatarId = Integer.parseInt(arg); - avatarIds.add(avatarId); - } catch (Exception ignored) { - ignored.printStackTrace(); - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.avatarId")); - return; - } - } - - - for (int i = 0; i < args.size(); i++) { - Avatar avatar = targetPlayer.getAvatars().getAvatarById(avatarIds.get(i)); - if (avatar == null) { - CommandHandler.sendMessage(sender, translate("commands.generic.invalid.avatarId")); - return; - } - if (targetPlayer.getTeamManager().getCurrentTeamInfo().contains(avatar)){ - continue; - } - targetPlayer.getTeamManager().getCurrentTeamInfo().addAvatar(avatar); - } - - // Packet - targetPlayer.getTeamManager().updateTeamEntities(new PacketChangeMpTeamAvatarRsp(targetPlayer, targetPlayer.getTeamManager().getCurrentTeamInfo())); - } -} diff --git a/src/main/java/emu/grasscutter/command/commands/RemoveCommand.java b/src/main/java/emu/grasscutter/command/commands/RemoveCommand.java deleted file mode 100644 index f39b6da24..000000000 --- a/src/main/java/emu/grasscutter/command/commands/RemoveCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -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; -import emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static emu.grasscutter.utils.Language.translate; - -@Command(label = "remove", usage = "remove [indexOfYourTeams] index start from 1", - description = "commands.remove.description", permission = "player.remove") -public class RemoveCommand implements CommandHandler { - - @Override - public void execute(Player sender, Player targetPlayer, List args) { - if (targetPlayer == null) { - CommandHandler.sendMessage(sender, translate(sender, "commands.execution.need_target")); - return; - } - - List avatarIndexList = new ArrayList<>(); - for (String arg : args) { - try { - int avatarIndex = Integer.parseInt(arg); - if (!avatarIndexList.contains(avatarIndex)) { - avatarIndexList.add(avatarIndex); - } - } catch (Exception ignored) { - ignored.printStackTrace(); - CommandHandler.sendMessage(sender, translate("commands.remove.invalid_index")); - return; - } - } - - Collections.sort(avatarIndexList, Collections.reverseOrder()); - - for (int i = 0; i < avatarIndexList.size(); i++) { - if (avatarIndexList.get(i) > targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars().size() || avatarIndexList.get(i) <= 0) { - CommandHandler.sendMessage(targetPlayer, translate("commands.remove.invalid_index")); - return; - } - targetPlayer.getTeamManager().getCurrentTeamInfo().removeAvatar(avatarIndexList.get(i) - 1); - } - - // Packet - targetPlayer.getTeamManager().updateTeamEntities(new PacketChangeMpTeamAvatarRsp(targetPlayer, targetPlayer.getTeamManager().getCurrentTeamInfo())); - } -} diff --git a/src/main/java/emu/grasscutter/command/commands/TeamCommand.java b/src/main/java/emu/grasscutter/command/commands/TeamCommand.java new file mode 100644 index 000000000..6dc8448d1 --- /dev/null +++ b/src/main/java/emu/grasscutter/command/commands/TeamCommand.java @@ -0,0 +1,268 @@ +package emu.grasscutter.command.commands; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.command.Command; +import emu.grasscutter.command.CommandHandler; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.server.packet.send.PacketChangeMpTeamAvatarRsp; + +import java.util.List; +import java.util.ArrayList; +import java.util.HashSet; + +import static emu.grasscutter.utils.Language.translate; +import static emu.grasscutter.Configuration.*; + +@Command(label = "team", usage = "team [avatarId,...] [index|first|last|index-index,...]", +permission = "player.team", permissionTargeted = "player.team.others", description = "commands.team.description") +public final class TeamCommand implements CommandHandler { + private static final int BASE_AVATARID = 10000000; + + @Override + public void execute(Player sender, Player targetPlayer, List args) { + if (targetPlayer == null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.execution.need_target")); + return; + } + + if (args.isEmpty()) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.usage")); + return; + } + + switch (args.get(0)) { + case "add": + if (!addCommand(sender, targetPlayer, args)) return; + break; + + case "remove": + if (!removeCommand(sender, targetPlayer, args)) return; + break; + + case "set": + if (!setCommand(sender, targetPlayer, args)) return; + break; + + default: + CommandHandler.sendMessage(sender, translate(sender, "commands.team.invalid_usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.team.usage")); + return; + } + + targetPlayer.getTeamManager().updateTeamEntities( + new PacketChangeMpTeamAvatarRsp(targetPlayer, targetPlayer.getTeamManager().getCurrentTeamInfo())); + } + + private boolean addCommand(Player sender, Player targetPlayer, List args) { + if (args.size() < 2) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.invalid_usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.team.add_usage")); + return false; + } + + int index = -1; + if (args.size() > 2) { + try { + index = Integer.parseInt(args.get(2)) - 1; + if (index < 0) index = 0; + } catch (Exception e) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.invalid_index")); + return false; + } + } + + var avatarIds = args.get(1).split(","); + var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars(); + + if (currentTeamAvatars.size() + avatarIds.length > GAME_OPTIONS.avatarLimits.singlePlayerTeam) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.add_too_much", GAME_OPTIONS.avatarLimits.singlePlayerTeam)); + return false; + } + + for (var avatarId: avatarIds) { + try { + int id = Integer.parseInt(avatarId); + var ret = addAvatar(sender, targetPlayer, id, index); + if (index > 0) ++index; + if (!ret) continue; + } catch (Exception e) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.failed_to_add_avatar", avatarId)); + continue; + } + } + return true; + } + + private boolean removeCommand(Player sender, Player targetPlayer, List args) { + if (args.size() < 2) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.invalid_usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.team.remove_usage")); + return false; + } + + var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars(); + var avatarCount = currentTeamAvatars.size(); + + var metaIndexList = args.get(1).split(","); + var indexes = new HashSet(); + var ignoreList = new ArrayList(); + for (var metaIndex: metaIndexList) { + // step 1: parse metaIndex to indexes + var subIndexes = transformToIndexes(metaIndex, avatarCount); + if (subIndexes == null) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.failed_to_parse_index", metaIndex)); + continue; + } + + // step 2: get all of the avatar id through indexes + for (var avatarIndex: subIndexes) { + try { + indexes.add(currentTeamAvatars.get(avatarIndex - 1)); + } catch (Exception e) { + ignoreList.add(avatarIndex); + continue; + } + } + } + + // step 3: check if user remove all of the avatar + if (indexes.size() >= avatarCount) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.remove_too_much")); + return false; + } + + // step 4: hint user for ignore index + if (!ignoreList.isEmpty()) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.ignore_index", ignoreList)); + } + + // step 5: remove + currentTeamAvatars.removeAll(indexes); + return true; + } + + private boolean setCommand(Player sender, Player targetPlayer, List args) { + if (args.size() < 3) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.invalid_usage")); + CommandHandler.sendMessage(sender, translate(sender, "commands.team.set_usage")); + return false; + } + + var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars(); + + int index; + try { + index = Integer.parseInt(args.get(1)) - 1; + if (index < 0) index = 0; + } catch(Exception e) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.failed_to_parse_index", args.get(1))); + return false; + } + + if (index + 1 > currentTeamAvatars.size()) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.index_out_of_range")); + return false; + } + + int avatarId; + try { + avatarId = Integer.parseInt(args.get(2)); + } catch(Exception e) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.failed_parse_avatar_id", args.get(2))); + return false; + } + if (avatarId < BASE_AVATARID) { + avatarId += BASE_AVATARID; + } + + if (currentTeamAvatars.contains(avatarId)) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.avatar_already_in_team", avatarId)); + return false; + } + + if (!targetPlayer.getAvatars().hasAvatar(avatarId)) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.avatar_not_found", avatarId)); + return false; + } + + currentTeamAvatars.set(index, avatarId); + return true; + } + + private boolean addAvatar(Player sender, Player targetPlayer, int avatarId, int index) { + if (avatarId < BASE_AVATARID) { + avatarId += BASE_AVATARID; + } + var currentTeamAvatars = targetPlayer.getTeamManager().getCurrentTeamInfo().getAvatars(); + if (currentTeamAvatars.contains(avatarId)) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.avatar_already_in_team", avatarId)); + return false; + } + if (!sender.getAvatars().hasAvatar(avatarId)) { + CommandHandler.sendMessage(sender, translate(sender, "commands.team.avatar_not_found", avatarId)); + return false; + } + if (index < 0) { + currentTeamAvatars.add(avatarId); + } else { + currentTeamAvatars.add(index, avatarId); + } + return true; + } + + private List transformToIndexes(String metaIndexes, int listLength) { + // step 1: check if metaIndexes is a special constants + if (metaIndexes.equals("first")) { + return List.of(1); + } else if (metaIndexes.equals("last")) { + return List.of(listLength); + } + + // step 2: check if metaIndexes is a range + if (metaIndexes.contains("-")) { + var range = metaIndexes.split("-"); + if (range.length < 2) { + return null; + } + + int min, max; + try { + min = switch (range[0]) { + case "first" -> 1; + case "last" -> listLength; + default -> Integer.parseInt(range[0]); + }; + + max = switch (range[1]) { + case "first" -> 1; + case "last" -> listLength; + default -> Integer.parseInt(range[1]); + }; + } catch (Exception e) { + return null; + } + + if (min > max) { + min ^= max; + max ^= min; + min ^= max; + } + + var indexes = new ArrayList(); + for (int i = min; i <= max; ++i) { + indexes.add(i); + } + return indexes; + } + + // step 3: index is a value, simply return + try { + int index = Integer.parseInt(metaIndexes); + return List.of(index); + } catch (Exception e) { + return null; + } + } + +} diff --git a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java index 4cbfde094..e4fafd814 100644 --- a/src/main/java/emu/grasscutter/game/gacha/GachaManager.java +++ b/src/main/java/emu/grasscutter/game/gacha/GachaManager.java @@ -358,7 +358,7 @@ public class GachaManager { if(this.watchService == null) { try { this.watchService = FileSystems.getDefault().newWatchService(); - Path path = new File(DATA_FOLDER).toPath(); + Path path = new File(DATA()).toPath(); path.register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY}, SensitivityWatchEventModifier.HIGH); } catch (Exception e) { Grasscutter.getLogger().error("Unable to load the Gacha Manager Watch Service. If ServerOptions.watchGacha is true it will not auto-reload"); diff --git a/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java b/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java index 8e77504d6..685f054f6 100644 --- a/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java +++ b/src/main/java/emu/grasscutter/net/packet/PacketOpcodes.java @@ -14,28 +14,26 @@ public class PacketOpcodes { public static final int AbilityInvocationsNotify = 1133; public static final int AcceptCityReputationRequestReq = 2845; public static final int AcceptCityReputationRequestRsp = 2875; - public static final int AchievementAllDataNotify = 1155; - public static final int AchievementUpdateNotify = 1146; - public static final int ActivityCoinInfoNotify = 2056; - public static final int ActivityCondStateChangeNotify = 2162; + public static final int AchievementAllDataNotify = 2685; + public static final int AchievementUpdateNotify = 2675; + public static final int ActivityCoinInfoNotify = 2080; + public static final int ActivityCondStateChangeNotify = 2102; public static final int ActivityDisableTransferPointInteractionNotify = 8295; - public static final int ActivityInfoNotify = 2023; - public static final int ActivityPlayOpenAnimNotify = 2164; - public static final int ActivitySaleChangeNotify = 2043; + public static final int ActivityInfoNotify = 2074; + public static final int ActivityPlayOpenAnimNotify = 2187; + public static final int ActivitySaleChangeNotify = 2166; public static final int ActivityScheduleInfoNotify = 2180; - public static final int ActivityScheduleInfoNotify_1 = 2187; - public static final int ActivitySelectAvatarCardReq = 2153; - public static final int ActivitySelectAvatarCardRsp = 2069; + public static final int ActivitySelectAvatarCardReq = 2056; + public static final int ActivitySelectAvatarCardRsp = 2174; public static final int ActivityTakeAllScoreRewardReq = 8708; public static final int ActivityTakeAllScoreRewardRsp = 8836; public static final int ActivityTakeScoreRewardReq = 8767; public static final int ActivityTakeScoreRewardRsp = 8445; - public static final int ActivityTakeWatcherRewardBatchReq = 2027; - public static final int ActivityTakeWatcherRewardBatchRsp = 2036; - public static final int ActivityTakeWatcherRewardReq = 2074; - public static final int ActivityTakeWatcherRewardRsp = 2180; - public static final int ActivityTakeWatcherRewardRsp_1 = 2187; - public static final int ActivityUpdateWatcherNotify = 2101; + public static final int ActivityTakeWatcherRewardBatchReq = 2042; + public static final int ActivityTakeWatcherRewardBatchRsp = 2013; + public static final int ActivityTakeWatcherRewardReq = 2101; + public static final int ActivityTakeWatcherRewardRsp = 2153; + public static final int ActivityUpdateWatcherNotify = 2069; public static final int AddBlacklistReq = 4067; public static final int AddBlacklistRsp = 4020; public static final int AddFriendNotify = 4026; @@ -55,16 +53,16 @@ public class PacketOpcodes { public static final int AnchorPointOpRsp = 4263; public static final int AnimatorForceSetAirMoveNotify = 308; public static final int AntiAddictNotify = 177; - public static final int ArenaChallengeFinishNotify = 2083; + public static final int ArenaChallengeFinishNotify = 2027; public static final int AskAddFriendNotify = 4062; public static final int AskAddFriendReq = 4037; public static final int AskAddFriendRsp = 4093; - public static final int AsterLargeInfoNotify = 2133; - public static final int AsterLittleInfoNotify = 2058; - public static final int AsterMidCampInfoNotify = 2115; - public static final int AsterMidInfoNotify = 2151; - public static final int AsterMiscInfoNotify = 2098; - public static final int AsterProgressInfoNotify = 2065; + public static final int AsterLargeInfoNotify = 2073; + public static final int AsterLittleInfoNotify = 2098; + public static final int AsterMidCampInfoNotify = 2001; + public static final int AsterMidInfoNotify = 2051; + public static final int AsterMiscInfoNotify = 2041; + public static final int AsterProgressInfoNotify = 2151; public static final int AvatarAddNotify = 1759; public static final int AvatarBuffAddNotify = 367; public static final int AvatarBuffDelNotify = 320; @@ -136,21 +134,21 @@ public class PacketOpcodes { public static final int BeginCameraSceneLookNotify = 261; public static final int BigTalentPointConvertReq = 1037; public static final int BigTalentPointConvertRsp = 1093; - public static final int BlessingAcceptAllGivePicReq = 2176; - public static final int BlessingAcceptAllGivePicRsp = 2050; - public static final int BlessingAcceptGivePicReq = 2134; - public static final int BlessingAcceptGivePicRsp = 2117; - public static final int BlessingGetAllRecvPicRecordListReq = 2090; - public static final int BlessingGetAllRecvPicRecordListRsp = 2140; - public static final int BlessingGetFriendPicListReq = 2077; - public static final int BlessingGetFriendPicListRsp = 2182; - public static final int BlessingGiveFriendPicReq = 2161; - public static final int BlessingGiveFriendPicRsp = 2076; - public static final int BlessingRecvFriendPicNotify = 2184; - public static final int BlessingRedeemRewardReq = 2172; - public static final int BlessingRedeemRewardRsp = 2039; - public static final int BlessingScanReq = 2186; - public static final int BlessingScanRsp = 2007; + public static final int BlessingAcceptAllGivePicReq = 2032; + public static final int BlessingAcceptAllGivePicRsp = 2148; + public static final int BlessingAcceptGivePicReq = 2090; + public static final int BlessingAcceptGivePicRsp = 2140; + public static final int BlessingGetAllRecvPicRecordListReq = 2184; + public static final int BlessingGetAllRecvPicRecordListRsp = 2176; + public static final int BlessingGetFriendPicListReq = 2161; + public static final int BlessingGetFriendPicListRsp = 2076; + public static final int BlessingGiveFriendPicReq = 2134; + public static final int BlessingGiveFriendPicRsp = 2117; + public static final int BlessingRecvFriendPicNotify = 2050; + public static final int BlessingRedeemRewardReq = 2077; + public static final int BlessingRedeemRewardRsp = 2182; + public static final int BlessingScanReq = 2172; + public static final int BlessingScanRsp = 2039; public static final int BlitzRushParkourRestartReq = 8212; public static final int BlitzRushParkourRestartRsp = 8962; public static final int BlossomBriefInfoNotify = 2710; @@ -292,6 +290,7 @@ public class PacketOpcodes { public static final int DataResVersionNotify = 136; public static final int DealAddFriendReq = 4044; public static final int DealAddFriendRsp = 4045; + public static final int DebugNotify = 101; public static final int DeleteFriendNotify = 4083; public static final int DeleteFriendReq = 4079; public static final int DeleteFriendRsp = 4091; @@ -323,10 +322,10 @@ public class PacketOpcodes { public static final int DraftOwnerStartInviteRsp = 5415; public static final int DraftOwnerTwiceConfirmNotify = 5434; public static final int DraftTwiceConfirmResultNotify = 5497; - public static final int DragonSpineChapterFinishNotify = 2196; - public static final int DragonSpineChapterOpenNotify = 2070; - public static final int DragonSpineChapterProgressChangeNotify = 2001; - public static final int DragonSpineCoinChangeNotify = 2189; + public static final int DragonSpineChapterFinishNotify = 2043; + public static final int DragonSpineChapterOpenNotify = 2196; + public static final int DragonSpineChapterProgressChangeNotify = 2189; + public static final int DragonSpineCoinChangeNotify = 2123; public static final int DropHintNotify = 673; public static final int DropItemReq = 634; public static final int DropItemRsp = 679; @@ -388,8 +387,8 @@ public class PacketOpcodes { public static final int EchoShellTakeRewardReq = 8801; public static final int EchoShellTakeRewardRsp = 8888; public static final int EchoShellUpdateNotify = 8730; - public static final int EffigyChallengeInfoNotify = 2159; - public static final int EffigyChallengeResultNotify = 2024; + public static final int EffigyChallengeInfoNotify = 2071; + public static final int EffigyChallengeResultNotify = 2034; public static final int EndCameraSceneLookNotify = 238; public static final int EnterChessDungeonReq = 8336; public static final int EnterChessDungeonRsp = 8581; @@ -405,8 +404,8 @@ public class PacketOpcodes { public static final int EnterSceneReadyRsp = 296; public static final int EnterSceneWeatherAreaNotify = 258; public static final int EnterTransPointRegionNotify = 255; - public static final int EnterTrialAvatarActivityDungeonReq = 2031; - public static final int EnterTrialAvatarActivityDungeonRsp = 2175; + public static final int EnterTrialAvatarActivityDungeonReq = 2020; + public static final int EnterTrialAvatarActivityDungeonRsp = 2087; public static final int EnterWorldAreaReq = 273; public static final int EnterWorldAreaRsp = 263; public static final int EntityAiKillSelfNotify = 370; @@ -460,17 +459,17 @@ public class PacketOpcodes { public static final int ExitFishingRsp = 5839; public static final int ExitSceneWeatherAreaNotify = 223; public static final int ExitTransPointRegionNotify = 246; - public static final int ExpeditionChallengeEnterRegionNotify = 2095; - public static final int ExpeditionChallengeFinishedNotify = 2197; - public static final int ExpeditionRecallReq = 2114; - public static final int ExpeditionRecallRsp = 2108; - public static final int ExpeditionStartReq = 2032; - public static final int ExpeditionStartRsp = 2148; - public static final int ExpeditionTakeRewardReq = 2053; - public static final int ExpeditionTakeRewardRsp = 2181; + public static final int ExpeditionChallengeEnterRegionNotify = 2192; + public static final int ExpeditionChallengeFinishedNotify = 2015; + public static final int ExpeditionRecallReq = 2053; + public static final int ExpeditionRecallRsp = 2181; + public static final int ExpeditionStartReq = 2114; + public static final int ExpeditionStartRsp = 2108; + public static final int ExpeditionTakeRewardReq = 2124; + public static final int ExpeditionTakeRewardRsp = 2168; public static final int FindHilichurlAcceptQuestNotify = 8292; public static final int FindHilichurlFinishSecondQuestNotify = 8799; - public static final int FinishDeliveryNotify = 2126; + public static final int FinishDeliveryNotify = 2003; public static final int FinishedParentQuestNotify = 415; public static final int FinishedParentQuestUpdateNotify = 437; public static final int FinishMainCoopReq = 1963; @@ -489,20 +488,20 @@ public class PacketOpcodes { public static final int FishEscapeNotify = 5836; public static final int FishingGallerySettleNotify = 8870; public static final int FishPoolDataNotify = 5850; - public static final int FleurFairBalloonSettleNotify = 2192; + public static final int FleurFairBalloonSettleNotify = 2064; public static final int FleurFairBuffEnergyNotify = 5392; - public static final int FleurFairFallSettleNotify = 2015; + public static final int FleurFairFallSettleNotify = 2040; public static final int FleurFairFinishGalleryStageNotify = 5323; - public static final int FleurFairMusicGameSettleReq = 2064; - public static final int FleurFairMusicGameSettleRsp = 2040; - public static final int FleurFairMusicGameStartReq = 2105; - public static final int FleurFairMusicGameStartRsp = 2179; - public static final int FleurFairReplayMiniGameReq = 2146; - public static final int FleurFairReplayMiniGameRsp = 2089; + public static final int FleurFairMusicGameSettleReq = 2105; + public static final int FleurFairMusicGameSettleRsp = 2179; + public static final int FleurFairMusicGameStartReq = 2146; + public static final int FleurFairMusicGameStartRsp = 2089; + public static final int FleurFairReplayMiniGameReq = 2022; + public static final int FleurFairReplayMiniGameRsp = 2033; public static final int FleurFairStageSettleNotify = 5358; - public static final int FlightActivityRestartReq = 2073; - public static final int FlightActivityRestartRsp = 2045; - public static final int FlightActivitySettleNotify = 2195; + public static final int FlightActivityRestartReq = 2115; + public static final int FlightActivityRestartRsp = 2070; + public static final int FlightActivitySettleNotify = 2045; public static final int FocusAvatarReq = 1710; public static final int FocusAvatarRsp = 1772; public static final int ForceAddPlayerFriendReq = 4084; @@ -563,10 +562,10 @@ public class PacketOpcodes { public static final int GalleryStartNotify = 5560; public static final int GalleryStopNotify = 5515; public static final int GallerySumoKillMonsterNotify = 5546; - public static final int GetActivityInfoReq = 2011; - public static final int GetActivityInfoRsp = 2170; - public static final int GetActivityScheduleReq = 2663; - public static final int GetActivityScheduleRsp = 2651; + public static final int GetActivityInfoReq = 2164; + public static final int GetActivityInfoRsp = 2023; + public static final int GetActivityScheduleReq = 2011; + public static final int GetActivityScheduleRsp = 2170; public static final int GetActivityShopSheetInfoReq = 744; public static final int GetActivityShopSheetInfoRsp = 745; public static final int GetAllActivatedBargainDataReq = 480; @@ -583,8 +582,8 @@ public class PacketOpcodes { public static final int GetAreaExplorePointRsp = 202; public static final int GetAuthkeyReq = 1445; public static final int GetAuthkeyRsp = 1475; - public static final int GetAuthSalesmanInfoReq = 2082; - public static final int GetAuthSalesmanInfoRsp = 2173; + public static final int GetAuthSalesmanInfoReq = 2031; + public static final int GetAuthSalesmanInfoRsp = 2175; public static final int GetBargainDataReq = 467; public static final int GetBargainDataRsp = 420; public static final int GetBattlePassProductReq = 2643; @@ -595,8 +594,8 @@ public class PacketOpcodes { public static final int GetBonusActivityRewardRsp = 2555; public static final int GetChatEmojiCollectionReq = 4057; public static final int GetChatEmojiCollectionRsp = 4043; - public static final int GetCityHuntingOfferReq = 4456; - public static final int GetCityHuntingOfferRsp = 4747; + public static final int GetCityHuntingOfferReq = 4345; + public static final int GetCityHuntingOfferRsp = 4348; public static final int GetCityReputationInfoReq = 2860; public static final int GetCityReputationInfoRsp = 2833; public static final int GetCityReputationMapInfoReq = 2891; @@ -607,8 +606,8 @@ public class PacketOpcodes { public static final int GetDailyDungeonEntryInfoRsp = 936; public static final int GetDungeonEntryExploreConditionReq = 3208; public static final int GetDungeonEntryExploreConditionRsp = 3391; - public static final int GetExpeditionAssistInfoListReq = 2124; - public static final int GetExpeditionAssistInfoListRsp = 2168; + public static final int GetExpeditionAssistInfoListReq = 2017; + public static final int GetExpeditionAssistInfoListRsp = 2099; public static final int GetFriendShowAvatarInfoReq = 4061; public static final int GetFriendShowAvatarInfoRsp = 4038; public static final int GetFriendShowNameCardInfoReq = 4032; @@ -618,8 +617,8 @@ public class PacketOpcodes { public static final int GetGachaInfoRsp = 1533; public static final int GetHomeLevelUpRewardReq = 4508; public static final int GetHomeLevelUpRewardRsp = 4864; - public static final int GetHuntingOfferRewardReq = 4769; - public static final int GetHuntingOfferRewardRsp = 4860; + public static final int GetHuntingOfferRewardReq = 4313; + public static final int GetHuntingOfferRewardRsp = 4301; public static final int GetInvestigationMonsterReq = 1928; public static final int GetInvestigationMonsterRsp = 1921; public static final int GetMailItemReq = 1415; @@ -786,14 +785,14 @@ public class PacketOpcodes { public static final int HomeUpdateFishFarmingInfoReq = 4810; public static final int HomeUpdateFishFarmingInfoRsp = 4500; public static final int HostPlayerNotify = 310; - public static final int HuntingFailNotify = 4345; - public static final int HuntingGiveUpReq = 4313; - public static final int HuntingGiveUpRsp = 4301; - public static final int HuntingOngoingNotify = 4348; - public static final int HuntingRevealClueNotify = 4564; - public static final int HuntingRevealFinalNotify = 4335; - public static final int HuntingStartNotify = 4694; - public static final int HuntingSuccessNotify = 4325; + public static final int HuntingFailNotify = 4315; + public static final int HuntingGiveUpReq = 4337; + public static final int HuntingGiveUpRsp = 4306; + public static final int HuntingOngoingNotify = 4327; + public static final int HuntingRevealClueNotify = 4336; + public static final int HuntingRevealFinalNotify = 4343; + public static final int HuntingStartNotify = 4317; + public static final int HuntingSuccessNotify = 4326; public static final int InBattleMechanicusBuildingPointsNotify = 5344; public static final int InBattleMechanicusCardResultNotify = 5388; public static final int InBattleMechanicusConfirmCardNotify = 5397; @@ -827,7 +826,7 @@ public class PacketOpcodes { public static final int LifeStateChangeNotify = 1233; public static final int LiveEndNotify = 801; public static final int LiveStartNotify = 820; - public static final int LoadActivityTerrainNotify = 2152; + public static final int LoadActivityTerrainNotify = 2129; public static final int LuaEnvironmentEffectNotify = 3175; public static final int LuaSetOptionNotify = 353; public static final int LunaRiteAreaFinishNotify = 8822; @@ -1093,8 +1092,8 @@ public class PacketOpcodes { public static final int ReadMailNotify = 1410; public static final int ReadPrivateChatReq = 4984; public static final int ReadPrivateChatRsp = 5029; - public static final int ReceivedTrialAvatarActivityRewardReq = 2020; - public static final int ReceivedTrialAvatarActivityRewardRsp = 2087; + public static final int ReceivedTrialAvatarActivityRewardReq = 2093; + public static final int ReceivedTrialAvatarActivityRewardRsp = 2138; public static final int RechargeReq = 4135; public static final int RechargeRsp = 4125; public static final int RedeemLegendaryKeyReq = 481; @@ -1120,8 +1119,8 @@ public class PacketOpcodes { public static final int RequestLiveInfoRsp = 867; public static final int ResinCardDataUpdateNotify = 4126; public static final int ResinChangeNotify = 623; - public static final int RestartEffigyChallengeReq = 2061; - public static final int RestartEffigyChallengeRsp = 2112; + public static final int RestartEffigyChallengeReq = 2120; + public static final int RestartEffigyChallengeRsp = 2127; public static final int ReunionActivateNotify = 5081; public static final int ReunionBriefInfoReq = 5085; public static final int ReunionBriefInfoRsp = 5075; @@ -1151,12 +1150,12 @@ public class PacketOpcodes { public static final int RogueResumeDungeonRsp = 8759; public static final int RogueSwitchAvatarReq = 8856; public static final int RogueSwitchAvatarRsp = 8141; - public static final int SalesmanDeliverItemReq = 2103; - public static final int SalesmanDeliverItemRsp = 2198; - public static final int SalesmanTakeRewardReq = 2091; - public static final int SalesmanTakeRewardRsp = 2171; - public static final int SalesmanTakeSpecialRewardReq = 2156; - public static final int SalesmanTakeSpecialRewardRsp = 2102; + public static final int SalesmanDeliverItemReq = 2091; + public static final int SalesmanDeliverItemRsp = 2171; + public static final int SalesmanTakeRewardReq = 2162; + public static final int SalesmanTakeRewardRsp = 2156; + public static final int SalesmanTakeSpecialRewardReq = 2082; + public static final int SalesmanTakeSpecialRewardRsp = 2173; public static final int SaveCoopDialogReq = 1972; public static final int SaveCoopDialogRsp = 1952; public static final int SaveMainCoopReq = 1995; @@ -1215,35 +1214,34 @@ public class PacketOpcodes { public static final int SceneTimeNotify = 229; public static final int SceneTransToPointReq = 256; public static final int SceneTransToPointRsp = 283; - public static final int SceneUnlockInfoNotify = 3386; public static final int SceneWeatherForcastReq = 3167; public static final int SceneWeatherForcastRsp = 3023; - public static final int SeaLampCoinNotify = 2028; - public static final int SeaLampContributeItemReq = 2122; - public static final int SeaLampContributeItemRsp = 2084; - public static final int SeaLampFlyLampNotify = 2075; - public static final int SeaLampFlyLampReq = 2174; - public static final int SeaLampFlyLampRsp = 2080; - public static final int SeaLampPopularityNotify = 2062; - public static final int SeaLampTakeContributionRewardReq = 2052; - public static final int SeaLampTakeContributionRewardRsp = 2057; - public static final int SeaLampTakePhaseRewardReq = 2109; - public static final int SeaLampTakePhaseRewardRsp = 2132; + public static final int SeaLampCoinNotify = 2152; + public static final int SeaLampContributeItemReq = 2075; + public static final int SeaLampContributeItemRsp = 2028; + public static final int SeaLampFlyLampNotify = 2062; + public static final int SeaLampFlyLampReq = 2052; + public static final int SeaLampFlyLampRsp = 2057; + public static final int SeaLampPopularityNotify = 2199; + public static final int SeaLampTakeContributionRewardReq = 2109; + public static final int SeaLampTakeContributionRewardRsp = 2132; + public static final int SeaLampTakePhaseRewardReq = 2122; + public static final int SeaLampTakePhaseRewardRsp = 2084; public static final int SealBattleBeginNotify = 225; public static final int SealBattleEndNotify = 249; public static final int SealBattleProgressNotify = 285; public static final int SeeMonsterReq = 299; public static final int SeeMonsterRsp = 300; - public static final int SelectAsterMidDifficultyReq = 2019; - public static final int SelectAsterMidDifficultyRsp = 2003; - public static final int SelectEffigyChallengeConditionReq = 2143; - public static final int SelectEffigyChallengeConditionRsp = 2072; + public static final int SelectAsterMidDifficultyReq = 2065; + public static final int SelectAsterMidDifficultyRsp = 2058; + public static final int SelectEffigyChallengeConditionReq = 2061; + public static final int SelectEffigyChallengeConditionRsp = 2112; public static final int SelectRoguelikeDungeonCardReq = 8964; public static final int SelectRoguelikeDungeonCardRsp = 8572; public static final int SelectWorktopOptionReq = 837; public static final int SelectWorktopOptionRsp = 893; - public static final int ServerAnnounceNotify = 2199; - public static final int ServerAnnounceRevokeNotify = 2129; + public static final int ServerAnnounceNotify = 2103; + public static final int ServerAnnounceRevokeNotify = 2198; public static final int ServerBuffChangeNotify = 332; public static final int ServerCondMeetQuestListUpdateNotify = 401; public static final int ServerDisconnectClientNotify = 186; @@ -1258,8 +1256,8 @@ public class PacketOpcodes { public static final int SetChatEmojiCollectionRsp = 4077; public static final int SetCoopChapterViewedReq = 1980; public static final int SetCoopChapterViewedRsp = 1988; - public static final int SetCurExpeditionChallengeIdReq = 2017; - public static final int SetCurExpeditionChallengeIdRsp = 2099; + public static final int SetCurExpeditionChallengeIdReq = 2095; + public static final int SetCurExpeditionChallengeIdRsp = 2197; public static final int SetEntityClientDataNotify = 3303; public static final int SetEquipLockStateReq = 635; public static final int SetEquipLockStateRsp = 657; @@ -1306,14 +1304,14 @@ public class PacketOpcodes { public static final int SocialDataNotify = 4063; public static final int SpringUseReq = 1720; public static final int SpringUseRsp = 1727; - public static final int StartArenaChallengeLevelReq = 2022; - public static final int StartArenaChallengeLevelRsp = 2033; + public static final int StartArenaChallengeLevelReq = 2083; + public static final int StartArenaChallengeLevelRsp = 2097; public static final int StartBuoyantCombatGalleryReq = 8313; public static final int StartBuoyantCombatGalleryRsp = 8754; public static final int StartCoopPointReq = 1956; public static final int StartCoopPointRsp = 1962; - public static final int StartEffigyChallengeReq = 2123; - public static final int StartEffigyChallengeRsp = 2166; + public static final int StartEffigyChallengeReq = 2159; + public static final int StartEffigyChallengeRsp = 2024; public static final int StartFishingReq = 5845; public static final int StartFishingRsp = 5848; public static final int StartRogueEliteCellChallengeReq = 8620; @@ -1342,12 +1340,12 @@ public class PacketOpcodes { public static final int SumoSwitchTeamRsp = 8356; public static final int SyncScenePlayTeamEntityNotify = 3296; public static final int SyncTeamEntityNotify = 338; - public static final int TakeAchievementGoalRewardReq = 2695; - public static final int TakeAchievementGoalRewardRsp = 2698; - public static final int TakeAchievementRewardReq = 2685; - public static final int TakeAchievementRewardRsp = 2675; - public static final int TakeAsterSpecialRewardReq = 2051; - public static final int TakeAsterSpecialRewardRsp = 2041; + public static final int TakeAchievementGoalRewardReq = 2663; + public static final int TakeAchievementGoalRewardRsp = 2651; + public static final int TakeAchievementRewardReq = 2695; + public static final int TakeAchievementRewardRsp = 2698; + public static final int TakeAsterSpecialRewardReq = 2133; + public static final int TakeAsterSpecialRewardRsp = 2195; public static final int TakeBattlePassMissionPointReq = 2617; public static final int TakeBattlePassMissionPointRsp = 2636; public static final int TakeBattlePassRewardReq = 2613; @@ -1362,18 +1360,18 @@ public class PacketOpcodes { public static final int TakeCompoundOutputRsp = 117; public static final int TakeCoopRewardReq = 1996; public static final int TakeCoopRewardRsp = 1981; - public static final int TakeDeliveryDailyRewardReq = 2055; - public static final int TakeDeliveryDailyRewardRsp = 2104; - public static final int TakeEffigyFirstPassRewardReq = 2071; - public static final int TakeEffigyFirstPassRewardRsp = 2034; - public static final int TakeEffigyRewardReq = 2113; - public static final int TakeEffigyRewardRsp = 2008; + public static final int TakeDeliveryDailyRewardReq = 2126; + public static final int TakeDeliveryDailyRewardRsp = 2019; + public static final int TakeEffigyFirstPassRewardReq = 2113; + public static final int TakeEffigyFirstPassRewardRsp = 2008; + public static final int TakeEffigyRewardReq = 2143; + public static final int TakeEffigyRewardRsp = 2072; public static final int TakeFirstShareRewardReq = 4008; public static final int TakeFirstShareRewardRsp = 4017; public static final int TakeFurnitureMakeReq = 4751; public static final int TakeFurnitureMakeRsp = 4457; - public static final int TakeHuntingOfferReq = 4750; - public static final int TakeHuntingOfferRsp = 4782; + public static final int TakeHuntingOfferReq = 4335; + public static final int TakeHuntingOfferRsp = 4325; public static final int TakeInvestigationRewardReq = 1926; public static final int TakeInvestigationRewardRsp = 1925; public static final int TakeInvestigationTargetRewardReq = 1915; @@ -1421,17 +1419,17 @@ public class PacketOpcodes { public static final int TowerSurrenderRsp = 2462; public static final int TowerTeamSelectReq = 2493; public static final int TowerTeamSelectRsp = 2444; - public static final int TreasureMapBonusChallengeNotify = 2121; - public static final int TreasureMapCurrencyNotify = 2127; - public static final int TreasureMapDetectorDataNotify = 4272; - public static final int TreasureMapGuideTaskDoneNotify = 2200; + public static final int TreasureMapBonusChallengeNotify = 2188; + public static final int TreasureMapCurrencyNotify = 2177; + public static final int TreasureMapDetectorDataNotify = 4271; + public static final int TreasureMapGuideTaskDoneNotify = 2186; public static final int TreasureMapHostInfoNotify = 8960; - public static final int TreasureMapMpChallengeNotify = 2177; - public static final int TreasureMapPreTaskDoneNotify = 2188; - public static final int TreasureMapRegionActiveNotify = 2141; - public static final int TreasureMapRegionInfoNotify = 2120; - public static final int TrialAvatarFirstPassDungeonNotify = 2093; - public static final int TrialAvatarInDungeonIndexNotify = 2138; + public static final int TreasureMapMpChallengeNotify = 2200; + public static final int TreasureMapPreTaskDoneNotify = 2007; + public static final int TreasureMapRegionActiveNotify = 2121; + public static final int TreasureMapRegionInfoNotify = 2141; + public static final int TrialAvatarFirstPassDungeonNotify = 2055; + public static final int TrialAvatarInDungeonIndexNotify = 2104; public static final int TriggerCreateGadgetToEquipPartNotify = 373; public static final int TriggerRoguelikeCurseNotify = 8878; public static final int TriggerRoguelikeRuneReq = 8607; @@ -1476,8 +1474,6 @@ public class PacketOpcodes { public static final int UseWidgetRetractGadgetRsp = 4297; public static final int VehicleInteractReq = 862; public static final int VehicleInteractRsp = 889; - public static final int VehicleSpawnReq = 809; - public static final int VehicleSpawnRsp = 865; public static final int VehicleStaminaNotify = 866; public static final int ViewCodexReq = 4210; public static final int ViewCodexRsp = 4209; @@ -1485,7 +1481,7 @@ public class PacketOpcodes { public static final int WatcherChangeNotify = 2233; public static final int WatcherEventNotify = 2210; public static final int WatcherEventTypeNotify = 2215; - public static final int WaterSpritePhaseFinishNotify = 2097; + public static final int WaterSpritePhaseFinishNotify = 2036; public static final int WeaponAwakenReq = 664; public static final int WeaponAwakenRsp = 601; public static final int WeaponPromoteReq = 626; @@ -1523,19 +1519,9 @@ public class PacketOpcodes { public static final int WorldRoutineTypeRefreshNotify = 3545; // Unknown - public static final int UNKNOWN = 2013; - public static final int UNKNOWN_1 = 2042; public static final int UNKNOWN_2 = 343; public static final int UNKNOWN_3 = 4259; public static final int UNKNOWN_4 = 4261; - public static final int UNKNOWN_5 = 4306; - public static final int UNKNOWN_6 = 4315; - public static final int UNKNOWN_7 = 4317; - public static final int UNKNOWN_8 = 4326; - public static final int UNKNOWN_9 = 4327; - public static final int UNKNOWN_10 = 4336; - public static final int UNKNOWN_11 = 4337; - public static final int UNKNOWN_12 = 4343; public static final int UNKNOWN_13 = 5932; public static final int UNKNOWN_14 = 5959; public static final int UNKNOWN_15 = 67; diff --git a/src/main/java/emu/grasscutter/plugin/Plugin.java b/src/main/java/emu/grasscutter/plugin/Plugin.java index b45e642a5..f322adc93 100644 --- a/src/main/java/emu/grasscutter/plugin/Plugin.java +++ b/src/main/java/emu/grasscutter/plugin/Plugin.java @@ -37,7 +37,7 @@ public abstract class Plugin { this.identifier = identifier; this.classLoader = classLoader; - this.dataFolder = new File(PLUGINS_FOLDER, identifier.name); + this.dataFolder = new File(PLUGIN(), identifier.name); this.logger = LoggerFactory.getLogger(identifier.name); if(!this.dataFolder.exists() && !this.dataFolder.mkdirs()) { diff --git a/src/main/java/emu/grasscutter/plugin/PluginManager.java b/src/main/java/emu/grasscutter/plugin/PluginManager.java index 5d58744a4..f6f1cfbf7 100644 --- a/src/main/java/emu/grasscutter/plugin/PluginManager.java +++ b/src/main/java/emu/grasscutter/plugin/PluginManager.java @@ -34,7 +34,7 @@ public final class PluginManager { * Loads plugins from the config-specified directory. */ private void loadPlugins() { - File pluginsDir = new File(Utils.toFilePath(PLUGINS_FOLDER)); + File pluginsDir = new File(Utils.toFilePath(PLUGIN())); if(!pluginsDir.exists() && !pluginsDir.mkdirs()) { Grasscutter.getLogger().error("Failed to create plugins directory: " + pluginsDir.getAbsolutePath()); return; diff --git a/src/main/java/emu/grasscutter/server/game/GameSession.java b/src/main/java/emu/grasscutter/server/game/GameSession.java index b981455d4..e91392f52 100644 --- a/src/main/java/emu/grasscutter/server/game/GameSession.java +++ b/src/main/java/emu/grasscutter/server/game/GameSession.java @@ -140,7 +140,7 @@ public class GameSession extends KcpChannel { } public void replayPacket(int opcode, String name) { - String filePath = PACKETS_FOLDER + name; + String filePath = PACKET(name); File p = new File(filePath); if (!p.exists()) return; diff --git a/src/main/java/emu/grasscutter/server/http/HttpServer.java b/src/main/java/emu/grasscutter/server/http/HttpServer.java index 898a3a17e..dc005e249 100644 --- a/src/main/java/emu/grasscutter/server/http/HttpServer.java +++ b/src/main/java/emu/grasscutter/server/http/HttpServer.java @@ -141,7 +141,7 @@ public final class HttpServer { public static class DefaultRequestRouter implements Router { @Override public void applyRoutes(Express express, Javalin handle) { express.get("/", (request, response) -> { - File file = new File(HTTP_STATIC_FILES.errorFile); + File file = new File(HTTP_STATIC_FILES.indexFile); if(!file.exists()) response.send(""" diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java new file mode 100644 index 000000000..2ef1cd7e4 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCreateVehicleReq.java @@ -0,0 +1,21 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.CreateVehicleReqOuterClass; + +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketCreateVehicleRsp; + +import emu.grasscutter.utils.Position; + +@Opcodes(PacketOpcodes.CreateVehicleReq) +public class HandlerCreateVehicleReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + CreateVehicleReqOuterClass.CreateVehicleReq req = CreateVehicleReqOuterClass.CreateVehicleReq.parseFrom(payload); + session.send(new PacketCreateVehicleRsp(session.getPlayer(), req.getVehicleId(), req.getPointId(), new Position(req.getPos()), new Position(req.getRot()))); + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java index 587cf7ce1..9d7dc8443 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerSceneInitFinishReq.java @@ -9,12 +9,12 @@ import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketHostPlayerNotify; import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneInfoNotify; import emu.grasscutter.server.packet.send.PacketPlayerGameTimeNotify; +import emu.grasscutter.server.packet.send.PacketPlayerWorldSceneInfoListNotify; import emu.grasscutter.server.packet.send.PacketSceneAreaWeatherNotify; import emu.grasscutter.server.packet.send.PacketSceneInitFinishRsp; import emu.grasscutter.server.packet.send.PacketScenePlayerInfoNotify; import emu.grasscutter.server.packet.send.PacketSceneTeamUpdateNotify; import emu.grasscutter.server.packet.send.PacketSceneTimeNotify; -import emu.grasscutter.server.packet.send.PacketSceneUnlockInfoNotify; import emu.grasscutter.server.packet.send.PacketServerTimeNotify; import emu.grasscutter.server.packet.send.PacketSyncScenePlayTeamEntityNotify; import emu.grasscutter.server.packet.send.PacketSyncTeamEntityNotify; @@ -30,7 +30,7 @@ public class HandlerSceneInitFinishReq extends PacketHandler { session.send(new PacketServerTimeNotify()); session.send(new PacketWorldPlayerInfoNotify(session.getPlayer().getWorld())); session.send(new PacketWorldDataNotify(session.getPlayer().getWorld())); - session.send(new PacketSceneUnlockInfoNotify()); + session.send(new PacketPlayerWorldSceneInfoListNotify()); session.send(new BasePacket(PacketOpcodes.SceneForceUnlockNotify)); session.send(new PacketHostPlayerNotify(session.getPlayer().getWorld())); diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleSpawnReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleSpawnReq.java deleted file mode 100644 index 2d259f738..000000000 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerVehicleSpawnReq.java +++ /dev/null @@ -1,21 +0,0 @@ -package emu.grasscutter.server.packet.recv; - -import emu.grasscutter.net.packet.Opcodes; -import emu.grasscutter.net.packet.PacketHandler; -import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.VehicleSpawnReqOuterClass; - -import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.server.packet.send.PacketVehicleSpawnRsp; - -import emu.grasscutter.utils.Position; - -@Opcodes(PacketOpcodes.VehicleSpawnReq) -public class HandlerVehicleSpawnReq extends PacketHandler { - - @Override - public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { - VehicleSpawnReqOuterClass.VehicleSpawnReq req = VehicleSpawnReqOuterClass.VehicleSpawnReq.parseFrom(payload); - session.send(new PacketVehicleSpawnRsp(session.getPlayer(), req.getVehicleId(), req.getPointId(), new Position(req.getPos()), new Position(req.getRot()))); - } -} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleSpawnRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java similarity index 87% rename from src/main/java/emu/grasscutter/server/packet/send/PacketVehicleSpawnRsp.java rename to src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java index fe8b2a1f1..d5a4b65b8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketVehicleSpawnRsp.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketCreateVehicleRsp.java @@ -10,7 +10,7 @@ import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.VehicleMemberOuterClass.VehicleMember; -import emu.grasscutter.net.proto.VehicleSpawnRspOuterClass.VehicleSpawnRsp; +import emu.grasscutter.net.proto.CreateVehicleRspOuterClass.CreateVehicleRsp; import emu.grasscutter.utils.Position; @@ -19,11 +19,11 @@ import java.util.List; import static emu.grasscutter.net.proto.VehicleInteractTypeOuterClass.VehicleInteractType.VEHICLE_INTERACT_OUT; -public class PacketVehicleSpawnRsp extends BasePacket { +public class PacketCreateVehicleRsp extends BasePacket { - public PacketVehicleSpawnRsp(Player player, int vehicleId, int pointId, Position pos, Position rot) { - super(PacketOpcodes.VehicleSpawnRsp); - VehicleSpawnRsp.Builder proto = VehicleSpawnRsp.newBuilder(); + public PacketCreateVehicleRsp(Player player, int vehicleId, int pointId, Position pos, Position rot) { + super(PacketOpcodes.CreateVehicleRsp); + CreateVehicleRsp.Builder proto = CreateVehicleRsp.newBuilder(); // Eject vehicle members and Kill previous vehicles if there are any List previousVehicles = player.getScene().getEntities().values().stream() diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java similarity index 66% rename from src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java rename to src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java index 223efc776..e06d7dab8 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketSceneUnlockInfoNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketPlayerWorldSceneInfoListNotify.java @@ -2,15 +2,15 @@ package emu.grasscutter.server.packet.send; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; -import emu.grasscutter.net.proto.SceneUnlockInfoNotifyOuterClass.SceneUnlockInfoNotify; +import emu.grasscutter.net.proto.PlayerWorldSceneInfoListNotifyOuterClass.PlayerWorldSceneInfoListNotify; import emu.grasscutter.net.proto.SceneUnlockInfoOuterClass.SceneUnlockInfo; -public class PacketSceneUnlockInfoNotify extends BasePacket { +public class PacketPlayerWorldSceneInfoListNotify extends BasePacket { - public PacketSceneUnlockInfoNotify() { - super(PacketOpcodes.SceneUnlockInfoNotify); // Rename opcode later + public PacketPlayerWorldSceneInfoListNotify() { + super(PacketOpcodes.PlayerWorldSceneInfoListNotify); // Rename opcode later - SceneUnlockInfoNotify proto = SceneUnlockInfoNotify.newBuilder() + PlayerWorldSceneInfoListNotify proto = PlayerWorldSceneInfoListNotify.newBuilder() .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(1)) .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(3).addSceneTagIdList(102).addSceneTagIdList(113).addSceneTagIdList(117)) .addUnlockInfos(SceneUnlockInfo.newBuilder().setSceneId(4).addSceneTagIdList(106).addSceneTagIdList(109)) diff --git a/src/main/java/emu/grasscutter/utils/ConfigContainer.java b/src/main/java/emu/grasscutter/utils/ConfigContainer.java index 9b5711a8d..c73e21892 100644 --- a/src/main/java/emu/grasscutter/utils/ConfigContainer.java +++ b/src/main/java/emu/grasscutter/utils/ConfigContainer.java @@ -136,8 +136,9 @@ public class ConfigContainer { public int bindPort = 22102; /* This is the port used in the default region. */ public int accessPort = 0; + public boolean enableScriptInBigWorld = false; - + public boolean enableConsole = true; public GameOptions gameOptions = new GameOptions(); public JoinOptions joinOptions = new JoinOptions(); public ConsoleAccount serverAccount = new ConsoleAccount(); diff --git a/src/main/java/emu/grasscutter/utils/Crypto.java b/src/main/java/emu/grasscutter/utils/Crypto.java index 41150ed13..1772e26de 100644 --- a/src/main/java/emu/grasscutter/utils/Crypto.java +++ b/src/main/java/emu/grasscutter/utils/Crypto.java @@ -20,11 +20,11 @@ public final class Crypto { public static byte[] ENCRYPT_SEED_BUFFER = new byte[0]; public static void loadKeys() { - DISPATCH_KEY = FileUtils.read(KEYS_FOLDER + "/dispatchKey.bin"); - DISPATCH_SEED = FileUtils.read(KEYS_FOLDER + "/dispatchSeed.bin"); + DISPATCH_KEY = FileUtils.read(KEY("dispatchKey.bin")); + DISPATCH_SEED = FileUtils.read(KEY("dispatchSeed.bin")); - ENCRYPT_KEY = FileUtils.read(KEYS_FOLDER + "/secretKey.bin"); - ENCRYPT_SEED_BUFFER = FileUtils.read(KEYS_FOLDER + "/secretKeyBuffer.bin"); + ENCRYPT_KEY = FileUtils.read(KEY("secretKey.bin")); + ENCRYPT_SEED_BUFFER = FileUtils.read(KEY("secretKeyBuffer.bin")); } public static void xor(byte[] packet, byte[] key) { @@ -40,7 +40,7 @@ public final class Crypto { public static void extractSecretKeyBuffer(byte[] data) { try { GetPlayerTokenRsp p = GetPlayerTokenRsp.parseFrom(data); - FileUtils.write(KEYS_FOLDER + "/secretKeyBuffer.bin", p.getSecretKeyBytes().toByteArray()); + FileUtils.write(KEY("/secretKeyBuffer.bin"), p.getSecretKeyBytes().toByteArray()); Grasscutter.getLogger().info("Secret Key: " + p.getSecretKey()); } catch (Exception e) { Grasscutter.getLogger().error("Crypto error.", e); @@ -50,7 +50,7 @@ public final class Crypto { public static void extractDispatchSeed(String data) { try { QueryCurrRegionHttpRsp p = QueryCurrRegionHttpRsp.parseFrom(Base64.getDecoder().decode(data)); - FileUtils.write(KEYS_FOLDER + "/dispatchSeed.bin", p.getRegionInfo().getSecretKey().toByteArray()); + FileUtils.write(KEY("/dispatchSeed.bin"), p.getRegionInfo().getSecretKey().toByteArray()); } catch (Exception e) { Grasscutter.getLogger().error("Crypto error.", e); } diff --git a/src/main/resources/languages/en-US.json b/src/main/resources/languages/en-US.json index 3ac759d6b..65111c363 100644 --- a/src/main/resources/languages/en-US.json +++ b/src/main/resources/languages/en-US.json @@ -1,387 +1,396 @@ -{ - "messages": { - "game": { - "port_bind": "Game Server started on port %s", - "connect": "Client connected from %s", - "disconnect": "Client disconnected from %s", - "game_update_error": "An error occurred during game update.", - "command_error": "Command error:" - }, - "dispatch": { - "port_bind": "[Dispatch] Dispatch server started on port %s", - "request": "[Dispatch] Client %s %s request: %s", - "keystore": { - "general_error": "[Dispatch] Error while loading keystore!", - "password_error": "[Dispatch] Unable to load keystore. Trying default keystore password...", - "no_keystore_error": "[Dispatch] No SSL cert found! Falling back to HTTP server.", - "default_password": "[Dispatch] The default keystore password was loaded successfully. Please consider setting the password to 123456 in config.json." - }, - "authentication": { - "default_unable_to_verify": "[Authentication] Something called the verifyUser method which is unavailable in the default authentication handler" - }, - "no_commands_error": "Commands are not supported in dispatch only mode.", - "unhandled_request_error": "[Dispatch] Potential unhandled %s request: %s", - "account": { - "login_attempt": "[Dispatch] Client %s is trying to log in", - "login_success": "[Dispatch] Client %s logged in as %s", - "login_token_attempt": "[Dispatch] Client %s is trying to log in via token", - "login_token_error": "[Dispatch] Client %s failed to log in via token", - "login_token_success": "[Dispatch] Client %s logged in via token as %s", - "combo_token_success": "[Dispatch] Client %s succeed to exchange combo token", - "combo_token_error": "[Dispatch] Client %s failed to exchange combo token", - "account_login_create_success": "[Dispatch] Client %s failed to log in: Account %s created", - "account_login_create_error": "[Dispatch] Client %s failed to log in: Account create failed", - "account_login_exist_error": "[Dispatch] Client %s failed to log in: Account no found", - "account_cache_error": "Game account cache information error", - "session_key_error": "Wrong session key.", - "username_error": "Username not found.", - "username_create_error": "Username not found, create failed." - }, - "router_error": "[Dispatch] Unable to attach router." - }, - "status": { - "free_software": "Grasscutter is FREE software. If you have paid for this, you may have been scammed. Homepage: https://github.com/Grasscutters/Grasscutter", - "starting": "Starting Grasscutter...", - "shutdown": "Shutting down...", - "done": "Done! For help, type \"help\"", - "error": "An error occurred.", - "welcome": "Welcome to Grasscutter", - "run_mode_error": "Invalid server run mode: %s.", - "run_mode_help": "Server run mode must be 'HYBRID', 'DISPATCH_ONLY', or 'GAME_ONLY'. Unable to start Grasscutter...", - "create_resources": "Creating resources folder...", - "resources_error": "Place a copy of 'BinOutput' and 'ExcelBinOutput' in the resources folder.", - "version": "Grasscutter version: %s-%s" - } - }, - "commands": { - "generic": { - "not_specified": "No command specified.", - "unknown_command": "Unknown command: %s", - "permission_error": "You do not have permission to run this command.", - "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.", - "avatarId": "Invalid avatarId.", - "avatarLevel": "Invalid avatarLevel.", - "entityId": "Invalid entityId.", - "itemId": "Invalid itemId.", - "itemLevel": "Invalid itemLevel.", - "itemRefinement": "Invalid itemRefinement.", - "playerId": "Invalid playerId.", - "uid": "Invalid UID." - } - }, - "execution": { - "uid_error": "Invalid UID.", - "player_exist_error": "Player not found.", - "player_offline_error": "Player is not online.", - "item_id_error": "Invalid item ID.", - "item_player_exist_error": "Invalid item or UID.", - "entity_id_error": "Invalid entity ID.", - "player_exist_offline_error": "Player not found or is not online.", - "argument_error": "Invalid arguments.", - "clear_target": "Target cleared.", - "set_target": "Subsequent commands will target @%s by default.", - "need_target": "This command requires a target UID. Add a <@UID> argument or set a persistent target with /target @UID." - }, - "status": { - "enabled": "Enabled", - "disabled": "Disabled", - "help": "Help", - "success": "Success" - }, - "account": { - "modify": "Modify user accounts", - "invalid": "Invalid UID.", - "exists": "Account already exists.", - "create": "Account created with UID %s.", - "delete": "Account deleted.", - "no_account": "Account not found.", - "command_usage": "Usage: account [uid]", - "description": "Modify user accounts" - }, - "broadcast": { - "command_usage": "Usage: broadcast ", - "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.", - "description": "Changes your scene" - }, - "clear": { - "command_usage": "Usage: clear ", - "weapons": "Cleared weapons for %s.", - "artifacts": "Cleared artifacts for %s.", - "materials": "Cleared materials for %s.", - "furniture": "Cleared furniture for %s.", - "displays": "Cleared displays for %s.", - "virtuals": "Cleared virtuals 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.", - "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", - "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.", - "description": "Gives all items" - }, - "giveArtifact": { - "usage": "Usage: giveart|gart [player] [[,]]... [level]", - "id_error": "Invalid artifact ID.", - "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.", - "description": "Gives the player a specified character" - }, - "give": { - "usage": "Usage: give [amount] [level]", - "refinement_only_applicable_weapons": "Refinement is only applicable to weapons.", - "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", - "description": "Gives an item to you or the specified player" - }, - "godmode": { - "success": "Godmode is now %s for %s.", - "description": "Prevents you from taking damage. Defaults to toggle." - }, - "nostamina": { - "success": "NoStamina is now %s for %s.", - "description": "Keep your endurance to the maximum." - }, - "heal": { - "success": "All characters have been healed.", - "description": "Heal all characters in your current team." - }, - "join": { - "usage": "Usage: join [AvatarIDs] such as\"join 10000038 10000039\"", - "description": "force join avatar into your team" - }, - "kick": { - "player_kick_player": "Player [%s:%s] has kicked 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", - "description": "Kill all entities" - }, - "killCharacter": { - "usage": "Usage: /killcharacter [playerId]", - "success": "Killed %s's current character.", - "description": "Kills the players current character" - }, - "language": { - "current_language": "current language is %s", - "language_changed": "language changed to %s", - "language_not_found": "currently, server does not have that language: %s", - "description": "display or change current language" - }, - "list": { - "success": "There are %s player(s) online:", - "description": "List online players" - }, - "permission": { - "usage": "Usage: permission ", - "add": "Permission added.", - "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.", - "description": "Grants or removes a permission for a user" - }, - "position": { - "success": "Coordinates: %s, %s, %s\nScene id: %s", - "description": "Get coordinates." - }, - "quest": { - "description": "Add or finish quests", - "usage": "quest [quest id]", - "added": "Quest %s added", - "finished": "Finished quest %s", - "not_found": "Quest not found", - "invalid_id": "Invalid quest id" - }, - "reload": { - "reload_start": "Reloading config.", - "reload_done": "Reload complete.", - "description": "Reload server config" - }, - "remove": { - "usage": "Usage: remove [indexOfYourTeam] index start from 1", - "invalid_index": "The index number is illegal. It starts from 1 and the maximum value is the number of roles in the team", - "description": "force remove avatar into your team. Such as `remove 1 2`." - }, - "resetConst": { - "reset_all": "Reset all avatars' constellations.", - "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 ", - "description": "Reset target player's shop refresh time." - }, - "sendMail": { - "usage": "Usage: give [player] [amount]", - "user_not_exist": "The user with an id of '%s' does not exist", - "start_composition": "Starting composition of message.\nPlease use `/sendmail ` to continue.\nYou can use `/sendmail stop` at any time", - "templates": "Mail templates coming soon implemented...", - "invalid_arguments": "Invalid arguments.\nUsage `/sendmail <userId|all|help> [templateId]`", - "send_cancel": "Message sending cancelled", - "send_done": "Message sent to user %s!", - "send_all_done": "Message sent to all users!", - "not_composition_end": "Message composition not at final stage.\nPlease use `/sendmail %s` or `/sendmail stop` to cancel", - "please_use": "Please use `/sendmail %s`", - "set_title": "Message title set as '%s'.\nUse '/sendmail <content>' to continue.", - "set_contents": "Message contents set as '%s'.\nUse '/sendmail <sender>' to continue.", - "set_message_sender": "Message sender set as '%s'.\nUse '/sendmail <itemId|itemName|finish> [amount] [level]' to continue.", - "send": "Attached %s of %s (level %s) to the message.\nContinue adding more items or use `/sendmail finish` to send the message.", - "invalid_arguments_please_use": "Invalid arguments \n Please use `/sendmail %s`", - "title": "<title>", - "message": "<message>", - "sender": "<sender>", - "arguments": "<itemId|itemName|finish> [amount] [level]", - "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 <player> <message>", - "success": "Message sent.", - "description": "Sends a message to a player as the server" - }, - "setFetterLevel": { - "usage": "Usage: setfetterlevel <level>", - "range_error": "Fetter level must be between 0 and 10.", - "success": "Fetter level set to %s", - "level_error": "Invalid fetter level.", - "description": "Sets your fetter level for your current active character" - }, - "setStats": { - "usage_console": "Usage: setstats|stats @<UID> <stat> <value>", - "usage_ingame": "Usage: setstats|stats [@UID] <stat> <value>", - "help_message": "\n\tValues for <stat>: hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Elemental DMG Bonus: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) Elemental RES: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys\n", - "value_error": "Invalid stat value.", - "uid_error": "Invalid UID.", - "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.", - "description": "Set fight property for your current active character" - }, - "setWorldLevel": { - "usage": "Usage: setworldlevel <level>", - "value_error": "World level must be between 0-8", - "success": "World level set to %s.", - "invalid_world_level": "Invalid world level.", - "description": "Sets your world level (Relog to see proper effects)" - }, - "spawn": { - "usage": "Usage: spawn <entityId> [amount] [level(monster only)]", - "success": "Spawned %s of %s.", - "description": "Spawns an entity near you" - }, - "stop": { - "success": "Server shutting down...", - "description": "Stops the server" - }, - "talent": { - "usage_1": "To set talent level: /talent set <talentID> <value>", - "usage_2": "Another way to set talent level: /talent <n or e or q> <value>", - "usage_3": "To get talent ID: /talent getid", - "lower_16": "Invalid talent level. Level should be lower than 16", - "set_id": "Set talent to %s.", - "set_atk": "Set talent Normal ATK to %s.", - "set_e": "Set talent E to %s.", - "set_q": "Set talent Q to %s.", - "invalid_skill_id": "Invalid skill ID.", - "set_this": "Set this talent to %s.", - "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.", - "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.", - "description": "Teleports all players in your world to your position" - }, - "teleport": { - "usage_server": "Usage: /tp @<player id> <x> <y> <z> [scene id]", - "usage": "Usage: /tp [@<player id>] <x> <y> <z> [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", - "description": "Change the player's position." - }, - "tower": { - "unlock_done": "Abyss Corridor's Floors are all unlocked now." - }, - "weather": { - "usage": "Usage: weather <weatherId> [climateId]", - "success": "Changed weather to %s with climate %s", - "invalid_id": "Invalid ID.", - "description": "Changes the weather." - }, - "drop": { - "command_usage": "Usage: drop <itemId|itemName> [amount]", - "success": "Dropped %s of %s.", - "description": "Drops an item near you" - }, - "help": { - "usage": "Usage: ", - "aliases": "Aliases: ", - "available_commands": "Available commands: ", - "description": "Sends the help message or shows information about a specified command" - }, - "restart": { - "description": "Restarts the current session" - }, - "unlocktower": { - "success": "unlock done", - "description": "Unlock all levels of tower" - }, - "resetshop": { - "description": "reset shop" - } - }, - "gacha": { - "details": { - "title": "Banner Details", - "available_five_stars": "Available 5-star Items", - "available_four_stars": "Available 4-star Items", - "available_three_stars": "Available 3-star Items", - "template_missing": "data/gacha_details.html is missing." - } - } -} +{ + "messages": { + "game": { + "port_bind": "Game Server started on port %s", + "connect": "Client connected from %s", + "disconnect": "Client disconnected from %s", + "game_update_error": "An error occurred during game update.", + "command_error": "Command error:" + }, + "dispatch": { + "port_bind": "[Dispatch] Dispatch server started on port %s", + "request": "[Dispatch] Client %s %s request: %s", + "keystore": { + "general_error": "[Dispatch] Error while loading keystore!", + "password_error": "[Dispatch] Unable to load keystore. Trying default keystore password...", + "no_keystore_error": "[Dispatch] No SSL cert found! Falling back to HTTP server.", + "default_password": "[Dispatch] The default keystore password was loaded successfully. Please consider setting the password to 123456 in config.json." + }, + "authentication": { + "default_unable_to_verify": "[Authentication] Something called the verifyUser method which is unavailable in the default authentication handler" + }, + "no_commands_error": "Commands are not supported in dispatch only mode.", + "unhandled_request_error": "[Dispatch] Potential unhandled %s request: %s", + "account": { + "login_attempt": "[Dispatch] Client %s is trying to log in", + "login_success": "[Dispatch] Client %s logged in as %s", + "login_token_attempt": "[Dispatch] Client %s is trying to log in via token", + "login_token_error": "[Dispatch] Client %s failed to log in via token", + "login_token_success": "[Dispatch] Client %s logged in via token as %s", + "combo_token_success": "[Dispatch] Client %s succeed to exchange combo token", + "combo_token_error": "[Dispatch] Client %s failed to exchange combo token", + "account_login_create_success": "[Dispatch] Client %s failed to log in: Account %s created", + "account_login_create_error": "[Dispatch] Client %s failed to log in: Account create failed", + "account_login_exist_error": "[Dispatch] Client %s failed to log in: Account no found", + "account_cache_error": "Game account cache information error", + "session_key_error": "Wrong session key.", + "username_error": "Username not found.", + "username_create_error": "Username not found, create failed." + }, + "router_error": "[Dispatch] Unable to attach router." + }, + "status": { + "free_software": "Grasscutter is FREE software. If you have paid for this, you may have been scammed. Homepage: https://github.com/Grasscutters/Grasscutter", + "starting": "Starting Grasscutter...", + "shutdown": "Shutting down...", + "done": "Done! For help, type \"help\"", + "error": "An error occurred.", + "welcome": "Welcome to Grasscutter", + "run_mode_error": "Invalid server run mode: %s.", + "run_mode_help": "Server run mode must be 'HYBRID', 'DISPATCH_ONLY', or 'GAME_ONLY'. Unable to start Grasscutter...", + "create_resources": "Creating resources folder...", + "resources_error": "Place a copy of 'BinOutput' and 'ExcelBinOutput' in the resources folder.", + "version": "Grasscutter version: %s-%s" + } + }, + "commands": { + "generic": { + "not_specified": "No command specified.", + "unknown_command": "Unknown command: %s", + "permission_error": "You do not have permission to run this command.", + "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.", + "avatarId": "Invalid avatarId.", + "avatarLevel": "Invalid avatarLevel.", + "entityId": "Invalid entityId.", + "itemId": "Invalid itemId.", + "itemLevel": "Invalid itemLevel.", + "itemRefinement": "Invalid itemRefinement.", + "playerId": "Invalid playerId.", + "uid": "Invalid UID." + } + }, + "execution": { + "uid_error": "Invalid UID.", + "player_exist_error": "Player not found.", + "player_offline_error": "Player is not online.", + "item_id_error": "Invalid item ID.", + "item_player_exist_error": "Invalid item or UID.", + "entity_id_error": "Invalid entity ID.", + "player_exist_offline_error": "Player not found or is not online.", + "argument_error": "Invalid arguments.", + "clear_target": "Target cleared.", + "set_target": "Subsequent commands will target @%s by default.", + "need_target": "This command requires a target UID. Add a <@UID> argument or set a persistent target with /target @UID." + }, + "status": { + "enabled": "Enabled", + "disabled": "Disabled", + "help": "Help", + "success": "Success" + }, + "account": { + "modify": "Modify user accounts", + "invalid": "Invalid UID.", + "exists": "Account already exists.", + "create": "Account created with UID %s.", + "delete": "Account deleted.", + "no_account": "Account not found.", + "command_usage": "Usage: account <create|delete> <username> [uid]", + "description": "Modify user accounts" + }, + "broadcast": { + "command_usage": "Usage: broadcast <message>", + "message_sent": "Message sent.", + "description": "Sends a message to all the players" + }, + "changescene": { + "usage": "Usage: changescene <sceneId>", + "already_in_scene": "You are already in that scene.", + "success": "Changed to scene %s.", + "exists_error": "The specified scene does not exist.", + "description": "Changes your scene" + }, + "clear": { + "command_usage": "Usage: clear <all|wp|art|mat>", + "weapons": "Cleared weapons for %s.", + "artifacts": "Cleared artifacts for %s.", + "materials": "Cleared materials for %s.", + "furniture": "Cleared furniture for %s.", + "displays": "Cleared displays for %s.", + "virtuals": "Cleared virtuals for %s.", + "everything": "Cleared everything for %s.", + "description": "Deletes unequipped unlocked items, including yellow rarity ones from your inventory" + }, + "coop": { + "usage": "Usage: coop <playerId> <target playerId>", + "success": "Summoned %s to %s's world.", + "description": "Forces someone to join the world of others" + }, + "enter_dungeon": { + "usage": "Usage: enterdungeon <dungeon id>", + "changed": "Changed to dungeon %s", + "not_found_error": "Dungeon does not exist", + "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.", + "description": "Gives all items" + }, + "giveArtifact": { + "usage": "Usage: giveart|gart [player] <artifactId> <mainPropId> [<appendPropId>[,<times>]]... [level]", + "id_error": "Invalid artifact ID.", + "success": "Given %s to %s.", + "description": "Gives the player a specified artifact" + }, + "giveChar": { + "usage": "Usage: givechar <player> <itemId|itemName> [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.", + "description": "Gives the player a specified character" + }, + "give": { + "usage": "Usage: give <player> <itemId|itemName> [amount] [level]", + "refinement_only_applicable_weapons": "Refinement is only applicable to weapons.", + "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", + "description": "Gives an item to you or the specified player" + }, + "godmode": { + "success": "Godmode is now %s for %s.", + "description": "Prevents you from taking damage. Defaults to toggle." + }, + "nostamina": { + "success": "NoStamina is now %s for %s.", + "description": "Keep your endurance to the maximum." + }, + "heal": { + "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]", + "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", + "description": "Kill all entities" + }, + "killCharacter": { + "usage": "Usage: /killcharacter [playerId]", + "success": "Killed %s's current character.", + "description": "Kills the players current character" + }, + "language": { + "current_language": "current language is %s", + "language_changed": "language changed to %s", + "language_not_found": "currently, server does not have that language: %s", + "description": "display or change current language" + }, + "list": { + "success": "There are %s player(s) online:", + "description": "List online players" + }, + "permission": { + "usage": "Usage: permission <add|remove> <username> <permission>", + "add": "Permission added.", + "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.", + "description": "Grants or removes a permission for a user" + }, + "position": { + "success": "Coordinates: %s, %s, %s\nScene id: %s", + "description": "Get coordinates." + }, + "quest": { + "description": "Add or finish quests", + "usage": "quest <add|finish> [quest id]", + "added": "Quest %s added", + "finished": "Finished quest %s", + "not_found": "Quest not found", + "invalid_id": "Invalid quest id" + }, + "reload": { + "reload_start": "Reloading config.", + "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.", + "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 <player id>", + "description": "Reset target player's shop refresh time." + }, + "sendMail": { + "usage": "Usage: give [player] <itemId|itemName> [amount]", + "user_not_exist": "The user with an id of '%s' does not exist", + "start_composition": "Starting composition of message.\nPlease use `/sendmail <title>` to continue.\nYou can use `/sendmail stop` at any time", + "templates": "Mail templates coming soon implemented...", + "invalid_arguments": "Invalid arguments.\nUsage `/sendmail <userId|all|help> [templateId]`", + "send_cancel": "Message sending cancelled", + "send_done": "Message sent to user %s!", + "send_all_done": "Message sent to all users!", + "not_composition_end": "Message composition not at final stage.\nPlease use `/sendmail %s` or `/sendmail stop` to cancel", + "please_use": "Please use `/sendmail %s`", + "set_title": "Message title set as '%s'.\nUse '/sendmail <content>' to continue.", + "set_contents": "Message contents set as '%s'.\nUse '/sendmail <sender>' to continue.", + "set_message_sender": "Message sender set as '%s'.\nUse '/sendmail <itemId|itemName|finish> [amount] [level]' to continue.", + "send": "Attached %s of %s (level %s) to the message.\nContinue adding more items or use `/sendmail finish` to send the message.", + "invalid_arguments_please_use": "Invalid arguments \n Please use `/sendmail %s`", + "title": "<title>", + "message": "<message>", + "sender": "<sender>", + "arguments": "<itemId|itemName|finish> [amount] [level]", + "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 <player> <message>", + "success": "Message sent.", + "description": "Sends a message to a player as the server" + }, + "setFetterLevel": { + "usage": "Usage: setfetterlevel <level>", + "range_error": "Fetter level must be between 0 and 10.", + "success": "Fetter level set to %s", + "level_error": "Invalid fetter level.", + "description": "Sets your fetter level for your current active character" + }, + "setStats": { + "usage_console": "Usage: setstats|stats @<UID> <stat> <value>", + "usage_ingame": "Usage: setstats|stats [@UID] <stat> <value>", + "help_message": "\n\tValues for <stat>: hp | maxhp | def | atk | em | er | crate | cdmg | cdr | heal | heali | shield | defi\n\t(cont.) Elemental DMG Bonus: epyro | ecryo | ehydro | egeo | edendro | eelectro | ephys\n\t(cont.) Elemental RES: respyro | rescryo | reshydro | resgeo | resdendro | reselectro | resphys\n", + "value_error": "Invalid stat value.", + "uid_error": "Invalid UID.", + "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.", + "description": "Set fight property for your current active character" + }, + "setWorldLevel": { + "usage": "Usage: setworldlevel <level>", + "value_error": "World level must be between 0-8", + "success": "World level set to %s.", + "invalid_world_level": "Invalid world level.", + "description": "Sets your world level (Relog to see proper effects)" + }, + "spawn": { + "usage": "Usage: spawn <entityId> [amount] [level(monster only)]", + "success": "Spawned %s of %s.", + "description": "Spawns an entity near you" + }, + "stop": { + "success": "Server shutting down...", + "description": "Stops the server" + }, + "talent": { + "usage_1": "To set talent level: /talent set <talentID> <value>", + "usage_2": "Another way to set talent level: /talent <n or e or q> <value>", + "usage_3": "To get talent ID: /talent getid", + "lower_16": "Invalid talent level. Level should be lower than 16", + "set_id": "Set talent to %s.", + "set_atk": "Set talent Normal ATK to %s.", + "set_e": "Set talent E to %s.", + "set_q": "Set talent Q to %s.", + "invalid_skill_id": "Invalid skill ID.", + "set_this": "Set this talent to %s.", + "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.", + "description": "Set talent level for your current active character" + }, + "team": { + "usage": "Usage: team <add|remove|set> [avatarId,...] [index|first|last|index-index,...]", + "invalid_usage": "invalid usage", + "add_usage": "usage(add): team add <avatarId,...> [index]", + "invalid_index": "index is invalid", + "add_too_much": "server is only allow you to have at most %d avatar(s) in your team", + "failed_to_add_avatar": "failed to add avatar by id: %s", + "remove_usage": "usage(remove): team remove <index|first|last|index-index,...>", + "failed_parse_index": "failed to parse index: %s", + "remove_too_much": "you can't remove so many avatars, your team list will be empty for this", + "ignore_index": "ignored index(es): %s", + "set_usage": "usage(set): team set <index> <avatarId>", + "index_out_of_range": "index your specified is out of range", + "failed_parse_avatar_id": "failed to parse avatar id: %s", + "avatar_already_in_team": "avatar is already in team", + "avatar_not_found": "avatar not found: %d", + "description": "modify your team manually" + }, + "teleportAll": { + "success": "Summoned all players to your location.", + "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 @<player id> <x> <y> <z> [scene id]", + "usage": "Usage: /tp [@<player id>] <x> <y> <z> [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", + "description": "Change the player's position." + }, + "tower": { + "unlock_done": "Abyss Corridor's Floors are all unlocked now." + }, + "weather": { + "usage": "Usage: weather <weatherId> [climateId]", + "success": "Changed weather to %s with climate %s", + "invalid_id": "Invalid ID.", + "description": "Changes the weather." + }, + "drop": { + "command_usage": "Usage: drop <itemId|itemName> [amount]", + "success": "Dropped %s of %s.", + "description": "Drops an item near you" + }, + "help": { + "usage": "Usage: ", + "aliases": "Aliases: ", + "available_commands": "Available commands: ", + "description": "Sends the help message or shows information about a specified command" + }, + "restart": { + "description": "Restarts the current session" + }, + "unlocktower": { + "success": "unlock done", + "description": "Unlock all levels of tower" + }, + "resetshop": { + "description": "reset shop" + } + }, + "gacha": { + "details": { + "title": "Banner Details", + "available_five_stars": "Available 5-star Items", + "available_four_stars": "Available 4-star Items", + "available_three_stars": "Available 3-star Items", + "template_missing": "data/gacha_details.html is missing." + } + } +} diff --git a/src/main/resources/languages/zh-CN.json b/src/main/resources/languages/zh-CN.json index ceec64d9b..cd572c095 100644 --- a/src/main/resources/languages/zh-CN.json +++ b/src/main/resources/languages/zh-CN.json @@ -1,385 +1,394 @@ -{ - "messages": { - "game": { - "port_bind": "游戏服务器已在端口 %s 上启动", - "connect": "客户端 %s 已连接", - "disconnect": "客户端 %s 已断开连接", - "game_update_error": "游戏更新时发生错误", - "command_error": "命令发生错误:" - }, - "dispatch": { - "port_bind": "[Dispatch] 服务器已在端口 %s 上启动", - "request": "[Dispatch] 客户端 %s 请求:%s %s", - "keystore": { - "general_error": "[Dispatch] 加载 keystore 文件时发生错误!", - "password_error": "[Dispatch] 加载 keystore 失败。正在尝试使用 keystore 默认密码...", - "no_keystore_error": "[Dispatch] 未找到 SSL 证书!已降级到 HTTP 模式", - "default_password": "[Dispatch] 成功加载 keystore 默认密码。请考虑将 config.json 的默认密码设置为 123456" - }, - "authentication": { - "default_unable_to_verify": "[Authentication] 称为 verifyUser 的方法在默认验证程序中不可用" - }, - "no_commands_error": "此命令不适用于 Dispatch-only 模式", - "unhandled_request_error": "[Dispatch] 潜在的未处理请求:%s %s", - "account": { - "login_attempt": "[Dispatch] 客户端 %s 正在尝试登录", - "login_success": "[Dispatch] 客户端 %s 已登录,UID 为 %s", - "login_token_attempt": "[Dispatch] 客户端 %s 正在尝试使用 token 登录", - "login_token_error": "[Dispatch] 客户端 %s 使用 token 登录失败", - "login_token_success": "[Dispatch] 客户端 %s 已通过 token 登录,UID 为 %s", - "combo_token_success": "[Dispatch] 客户端 %s 交换 token 成功", - "combo_token_error": "[Dispatch] 客户端 %s 交换 token 失败", - "account_login_create_success": "[Dispatch] 客户端 %s 登录失败: 已注册 UID 为 %s 的账号", - "account_login_create_error": "[Dispatch] 客户端 %s 登录失败:账号创建失败。", - "account_login_exist_error": "[Dispatch] 客户端 %s 登录失败:账号不存在", - "account_cache_error": "游戏账号缓存信息错误", - "session_key_error": "会话密钥错误。", - "username_error": "未找到此用户名。", - "username_create_error": "未找到用户名,建立连接失败。" - } - }, - "status": { - "free_software": "Grasscutter 是免费开源软件,遵循 AGPL-3.0 license。如果你是付费购买的,那你已经被骗了。项目地址:https://github.com/Grasscutters/Grasscutter", - "starting": "正在启动 Grasscutter...", - "shutdown": "正在关闭...", - "done": "加载完成!输入 \"help\" 查看命令列表", - "error": "发生了一个错误。", - "welcome": "欢迎使用 Grasscutter!珍惜这段美妙的旅途吧!", - "run_mode_error": "无效的服务器运行模式:%s。", - "run_mode_help": "服务器运行模式必须为 HYBRID、DISPATCH_ONLY 或 GAME_ONLY。Grasscutter 启动失败...", - "create_resources": "正在创建 resources 目录...", - "resources_error": "请将 BinOutput 和 ExcelBinOutput 复制到 resources 目录。", - "version": "Grasscutter 版本: %s-%s" - } - }, - "commands": { - "generic": { - "not_specified": "没有指定命令。", - "unknown_command": "未知的命令:%s", - "permission_error": "哼哼哼!你没有执行此命令的权限!请联系服务器管理员解决!", - "console_execute_error": "此命令只能在服务器控制台执行呐~", - "player_execute_error": "此命令只能在游戏内执行哦~", - "command_exist_error": "这条命令...好像找不到呢?", - "no_description_specified": "没有指定说明", - "invalid": { - "amount": "无效的数量。", - "artifactId": "无效的圣遗物ID。", - "avatarId": "无效的角色ID。", - "avatarLevel": "无效的角色等级。", - "entityId": "无效的实体ID。", - "itemId": "无效的物品ID。", - "itemLevel": "无效的物品等级。", - "itemRefinement": "无效的物品精炼等级。", - "playerId": "无效的玩家ID。", - "uid": "无效的UID。" - } - }, - "execution": { - "uid_error": "无效的UID。", - "player_exist_error": "玩家不存在。", - "player_offline_error": "玩家已离线。", - "item_id_error": "无效的物品ID。", - "item_player_exist_error": "无效的物品/玩家UID。", - "entity_id_error": "无效的实体ID。", - "player_exist_offline_error": "玩家不存在或已离线。", - "argument_error": "无效的参数。", - "clear_target": "目标已清除。", - "set_target": "随后的的命令都会以 @%s 为预设。", - "need_target": "此命令需要一个目标 UID。添加 <@UID> 参数或使用 /target @UID 来指定默认目标。" - }, - "status": { - "enabled": "已启用", - "disabled": "未启用", - "help": "帮助", - "success": "成功" - }, - "account": { - "modify": "修改用户账号", - "invalid": "无效的UID。", - "exists": "账号已存在。", - "create": "已创建账号,UID 为 %s。", - "delete": "账号已删除。", - "no_account": "账号不存在。", - "command_usage": "用法:account <create|delete> <用户名> [UID]", - "description": "创建或删除账号" - }, - "broadcast": { - "command_usage": "用法:broadcast <消息>", - "message_sent": "公告已发送。", - "description": "向所有玩家发送公告" - }, - "changescene": { - "usage": "用法:changescene <场景ID>", - "already_in_scene": "你已经在这个场景中了。", - "success": "已切换至场景 %s。", - "exists_error": "此场景不存在。", - "description": "切换指定场景" - }, - "clear": { - "command_usage": "用法:clear <all|wp|art|mat>\nall: 所有, wp: 武器, art: 圣遗物, mat: 材料", - "weapons": "已清除 %s 的武器。", - "artifacts": "已清除 %s 的圣遗物。", - "materials": "已清除 %s 的材料。", - "furniture": "已清除 %s 的尘歌壶家具。", - "displays": "已清空 %s 的屏幕。", - "virtuals": "已清除 %s 的所有货币和经验值。", - "everything": "已清除 %s 的所有物品。", - "description": "从你的背包中删除所有未装备且已解锁的物品,包括稀有物品" - }, - "coop": { - "usage": "用法:coop <玩家ID> <目标玩家ID>", - "success": "已强制传送 %s 到 %s 的世界。", - "description": "强制传送指定用户到他人的世界" - }, - "enter_dungeon": { - "usage": "用法:enterdungeon <秘境ID>", - "changed": "已进入秘境 %s。", - "not_found_error": "此秘境不存在。", - "in_dungeon_error": "你已经在秘境中了。", - "description": "进入指定秘境" - }, - "giveAll": { - "usage": "用法:giveall [玩家] [数量]", - "started": "正在给予全部物品...", - "success": "已给予 %s 全部物品。", - "invalid_amount_or_playerId": "无效的数量/玩家ID。", - "description": "给予所有物品" - }, - "nostamina": { - "success": "NoStamina %s 对于 %s.", - "description": "保持你的体力处于最高状态。" - }, - "giveArtifact": { - "usage": "用法:giveart|gart [玩家] <圣遗物ID> <主词条ID> [<副词条ID>[,<强化次数>]]... [等级]", - "id_error": "无效的圣遗物ID。", - "success": "已将 %s 给予 %s。", - "description": "给予指定圣遗物" - }, - "giveChar": { - "usage": "用法:givechar <玩家> <角色ID|角色名> [数量]", - "given": "已将角色 %s [等级 %s] 给与 %s。", - "invalid_avatar_id": "无效的角色ID。", - "invalid_avatar_level": "无效的角色等级。", - "invalid_avatar_or_player_id": "无效的角色ID/玩家ID。", - "description": "给予指定角色" - }, - "give": { - "usage": "用法:give <玩家> <物品ID|物品名> [数量] [等级] [精炼等级]", - "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 个给予 %s。", - "description": "给予指定物品" - }, - "godmode": { - "success": "上帝模式已设为 %s。[用户:%s]", - "description": "防止你受到伤害" - }, - "heal": { - "success": "已治疗所有角色。", - "description": "治疗当前队伍的角色" - }, - "join": { - "usage": "用法:join <角色IDs> 例如\"join 10000038 10000039\"空格分开", - "description": "强制将角色加入到当前队伍中" - }, - "kick": { - "player_kick_player": "玩家 [%s:%s] 已将 [%s:%s] 踢出。", - "server_kick_player": "正在踢出玩家 [%s:%s]...", - "description": "从服务器内踢出指定玩家" - }, - "kill": { - "usage": "用法:killall [玩家UID] [场景ID]", - "scene_not_found_in_player_world": "未在玩家世界中找到此场景。", - "kill_monsters_in_scene": "已杀死场景 %s 中的 %s 个怪物。", - "description": "杀死所有怪物" - }, - "killCharacter": { - "usage": "用法:/killcharacter [玩家ID]", - "success": "已杀死 %s 当前角色。", - "description": "杀死当前角色" - }, - "language": { - "current_language": "当前语言是: %s", - "language_changed": "语言切换至: %s", - "language_not_found": "目前服务端没有这种语言: %s", - "description": "显示或切换当前语言" - }, - "list": { - "success": "目前在线人数:%s", - "description": "查看所有玩家" - }, - "permission": { - "usage": "用法:permission <add|remove> <用户名> <权限>", - "add": "权限已添加。", - "has_error": "此玩家已拥有此权限!", - "remove": "权限已移除。", - "not_have_error": "此玩家未拥有权限!", - "account_error": "账号不存在。", - "description": "添加或移除指定玩家的权限" - }, - "position": { - "success": "坐标:%s, %s, %s\n场景ID:%s", - "description": "获取所在位置" - }, - "quest": { - "description": "添加或完成任务", - "usage": "quest <add|finish> [任务ID]", - "added": "已添加任务 %s", - "finished": "已完成任务 %s", - "not_found": "未找到任务", - "invalid_id": "无效的任务ID" - }, - "reload": { - "reload_start": "正在重载配置文件和数据。", - "reload_done": "重载完成。", - "description": "重载配置文件和数据" - }, - "remove": { - "usage": "用法: remove [多个角色在队伍中的序号] 序号从1开始", - "invalid_index": "序号不合法,从1开始,最大值为队内角色数量", - "description": "强制将某个角色从当前队伍中移除。例如`remove 1 2`表示将1号和2号角色从队伍中移除" - }, - "resetConst": { - "reset_all": "重置所有角色的命座。", - "success": "已重置 %s 的命座,重新登录后生效。", - "description": "重置当前角色的命之座,执行命令后需重新登录以生效" - }, - "resetShopLimit": { - "usage": "用法:/resetshop <玩家ID>", - "description": "重置所选玩家的商店刷新时间" - }, - "sendMail": { - "usage": "用法:give [玩家] <物品ID|物品名称> [数量]", - "user_not_exist": "ID '%s' 的用户不存在。", - "start_composition": "发送邮件流程。\n请使用`/sendmail <标题>`前进到下一步。\n你可以在任何时间使用`/sendmail stop`来停止发送。", - "templates": "邮件模板尚未实装...", - "invalid_arguments": "无效的参数。\n指令使用方法 `/sendmail <用户ID|all|help> [模板ID]`", - "send_cancel": "取消发送邮件", - "send_done": "已将邮件发送给 %s!", - "send_all_done": "邮件已发送给所有人!", - "not_composition_end": "现在邮件发送未到最后阶段。\n请使用 `/sendmail %s` 继续发送邮件,或使用 `/sendmail stop` 来停止发送邮件。", - "please_use": "请使用 `/sendmail %s`", - "set_title": "成功将邮件标题设置为 '%s'。\n使用 '/sendmail <正文>' 来设置邮件内容。", - "set_contents": "成功将邮件内容设置为 '%s'。\n使用 '/sendmail <发件人>' 来设置发件人。", - "set_message_sender": "发件人已设置为 '%s'。\n使用 '/sendmail <物品ID|物品名称|finish> [数量] [等级]' 来添加附件。", - "send": "已添加 %s 个 %s (等级 %s) 邮件附件。\n如果没有要继续添加的附件请使用 `/sendmail finish` 来发送邮件。", - "invalid_arguments_please_use": "错误的参数 \n请使用 `/sendmail %s`", - "title": "<标题>", - "message": "<正文>", - "sender": "<发件人>", - "arguments": "<物品ID|物品名称|finish> [数量] [等级]", - "error": "错误:无效的编写阶段 %s。需要 StackTrace 请查看服务器控制台。", - "description": "向指定用户发送邮件。此命令的用法可根据附加的参数而变化" - }, - "sendMessage": { - "usage": "用法:sendmessage <玩家> <消息>", - "success": "消息已发送。", - "description": "向指定玩家发送消息" - }, - "setFetterLevel": { - "usage": "用法:setfetterlevel <好感度等级>", - "range_error": "好感度等级必须在 0 到 10 之间。", - "success": "好感度已设为 %s 级。", - "level_error": "无效的好感度等级。", - "description": "设置当前角色的好感度等级" - }, - "setStats": { - "usage_console": "用法:setstats|stats @<UID> <属性> <数值>", - "usage_ingame": "用法:setstats|stats [@UID] <属性> <数值>", - "help_message": "\n可更改的属性列表:hp (生命值)| maxhp (最大生命值) | def(防御力) | atk (攻击力)| em (元素精通) | er (元素充能效率) | crate(暴击率) | cdmg (暴击伤害)| cdr (冷却缩减) | heal(治疗加成)| heali (受治疗加成)| shield (护盾强效)| defi (无视防御)\n(续) 元素增伤:epyro (火) | ecryo (冰) | ehydro (水) | egeo (岩) | edendro (草) | eelectro (雷) | ephys (物理)\n(续) 元素抗性:respyro (火) | rescryo (冰) | reshydro (水) | resgeo (岩) | resdendro (草) | reselectro (雷) | resphys (物理)\n", - "value_error": "无效的属性值。", - "uid_error": "无效的UID。", - "player_error": "玩家不存在或已离线。", - "set_self": "%s 已设为 %s。", - "set_for_uid": "%s [来自 %s] 已设为 %s。", - "set_max_hp": "最大生命值已设为 %s。", - "description": "设置当前角色的属性" - }, - "setWorldLevel": { - "usage": "用法:setworldlevel <等级>", - "value_error": "世界等级必须设置在0-8之间。", - "success": "世界等级已设为 %s。", - "invalid_world_level": "无效的世界等级。", - "description": "设置世界等级,执行命令后需重新登录以生效" - }, - "spawn": { - "usage": "用法:spawn <实体ID> [数量] [等级(仅怪物)]", - "success": "已生成 %s 个 %s。", - "description": "在你附近生成一个生物" - }, - "stop": { - "success": "正在关闭服务器...", - "description": "停止服务器" - }, - "talent": { - "usage_1": "设置天赋等级:/talent set <天赋ID> <数值>", - "usage_2": "另一种设置天赋等级的方法:/talent <n (普通攻击) | e (元素战技) | q (元素爆发)> <数值>", - "usage_3": "获取天赋ID:/talent getid", - "lower_16": "无效的天赋等级,天赋等级应小于等于15。", - "set_id": "将天赋等级设为 %s。", - "set_atk": "将普通攻击等级设为 %s。", - "set_e": "将元素战技等级设为 %s。", - "set_q": "将元素爆发等级设为 %s。", - "invalid_skill_id": "无效的技能ID。", - "set_this": "将天赋等级设为 %s。", - "invalid_level": "无效的天赋等级。", - "normal_attack_id": "普通攻击的 ID 为 %s。", - "e_skill_id": "元素战技ID %s。", - "q_skill_id": "元素爆发ID %s。", - "description": "设置当前角色的天赋等级" - }, - "teleportAll": { - "success": "已将所有玩家传送到你的位置。", - "error": "你只能在多人游戏状态下执行此命令。", - "description": "将你世界中的所有玩家传送到你所在的位置" - }, - "teleport": { - "usage_server": "用法:/tp @<玩家ID> <x> <y> <z> [场景ID]", - "usage": "用法:/tp [@<玩家ID>] <x> <y> <z> [场景ID]", - "specify_player_id": "你必须指定一个玩家ID。", - "invalid_position": "无效的位置。", - "success": "传送 %s 到坐标 %s,%s,%s,场景为 %s。", - "description": "改变指定玩家的位置" - }, - "tower": { - "unlock_done": "深境回廊的所有层已全部解锁。" - }, - "weather": { - "usage": "用法:weather <天气ID> [气候ID]", - "success": "已更改天气为 %s,气候为 %s。", - "invalid_id": "无效的天气ID。", - "description": "更改天气" - }, - "drop": { - "command_usage": "用法:drop <物品ID|物品名称> [数量]", - "success": "已丢下 %s 个 %s。", - "description": "在你附近丢下一个物品" - }, - "help": { - "usage": "用法:", - "aliases": "别名:", - "available_commands": "可用命令:", - "description": "发送帮助信息或显示指定命令的信息" - }, - "restart": { - "description": "重新启动服务器" - }, - "unlocktower": { - "success": "解锁完成。", - "description": "解锁深境螺旋的所有层" - }, - "resetshop": { - "description": "重置商店刷新时间" - } - }, - "gacha": { - "details": { - "title": "祈愿详情", - "available_five_stars": "可获得的5星物品", - "available_four_stars": "可获得的4星物品", - "available_three_stars": "可获得的3星物品" - } - } -} +{ + "messages": { + "game": { + "port_bind": "游戏服务器已在端口 %s 上启动", + "connect": "客户端 %s 已连接", + "disconnect": "客户端 %s 已断开连接", + "game_update_error": "游戏更新时发生错误", + "command_error": "命令发生错误:" + }, + "dispatch": { + "port_bind": "[Dispatch] 服务器已在端口 %s 上启动", + "request": "[Dispatch] 客户端 %s 请求:%s %s", + "keystore": { + "general_error": "[Dispatch] 加载 keystore 文件时发生错误!", + "password_error": "[Dispatch] 加载 keystore 失败。正在尝试使用 keystore 默认密码...", + "no_keystore_error": "[Dispatch] 未找到 SSL 证书!已降级到 HTTP 模式", + "default_password": "[Dispatch] 成功加载 keystore 默认密码。请考虑将 config.json 的默认密码设置为 123456" + }, + "authentication": { + "default_unable_to_verify": "[Authentication] 称为 verifyUser 的方法在默认验证程序中不可用" + }, + "no_commands_error": "此命令不适用于 Dispatch-only 模式", + "unhandled_request_error": "[Dispatch] 潜在的未处理请求:%s %s", + "account": { + "login_attempt": "[Dispatch] 客户端 %s 正在尝试登录", + "login_success": "[Dispatch] 客户端 %s 已登录,UID 为 %s", + "login_token_attempt": "[Dispatch] 客户端 %s 正在尝试使用 token 登录", + "login_token_error": "[Dispatch] 客户端 %s 使用 token 登录失败", + "login_token_success": "[Dispatch] 客户端 %s 已通过 token 登录,UID 为 %s", + "combo_token_success": "[Dispatch] 客户端 %s 交换 token 成功", + "combo_token_error": "[Dispatch] 客户端 %s 交换 token 失败", + "account_login_create_success": "[Dispatch] 客户端 %s 登录失败: 已注册 UID 为 %s 的账号", + "account_login_create_error": "[Dispatch] 客户端 %s 登录失败:账号创建失败。", + "account_login_exist_error": "[Dispatch] 客户端 %s 登录失败:账号不存在", + "account_cache_error": "游戏账号缓存信息错误", + "session_key_error": "会话密钥错误。", + "username_error": "未找到此用户名。", + "username_create_error": "未找到用户名,建立连接失败。" + } + }, + "status": { + "free_software": "Grasscutter 是免费开源软件,遵循 AGPL-3.0 license。如果你是付费购买的,那你已经被骗了。项目地址:https://github.com/Grasscutters/Grasscutter", + "starting": "正在启动 Grasscutter...", + "shutdown": "正在关闭...", + "done": "加载完成!输入 \"help\" 查看命令列表", + "error": "发生了一个错误。", + "welcome": "欢迎使用 Grasscutter!珍惜这段美妙的旅途吧!", + "run_mode_error": "无效的服务器运行模式:%s。", + "run_mode_help": "服务器运行模式必须为 HYBRID、DISPATCH_ONLY 或 GAME_ONLY。Grasscutter 启动失败...", + "create_resources": "正在创建 resources 目录...", + "resources_error": "请将 BinOutput 和 ExcelBinOutput 复制到 resources 目录。", + "version": "Grasscutter 版本: %s-%s" + } + }, + "commands": { + "generic": { + "not_specified": "没有指定命令。", + "unknown_command": "未知的命令:%s", + "permission_error": "哼哼哼!你没有执行此命令的权限!请联系服务器管理员解决!", + "console_execute_error": "此命令只能在服务器控制台执行呐~", + "player_execute_error": "此命令只能在游戏内执行哦~", + "command_exist_error": "这条命令...好像找不到呢?", + "no_description_specified": "没有指定说明", + "invalid": { + "amount": "无效的数量。", + "artifactId": "无效的圣遗物ID。", + "avatarId": "无效的角色ID。", + "avatarLevel": "无效的角色等级。", + "entityId": "无效的实体ID。", + "itemId": "无效的物品ID。", + "itemLevel": "无效的物品等级。", + "itemRefinement": "无效的物品精炼等级。", + "playerId": "无效的玩家ID。", + "uid": "无效的UID。" + } + }, + "execution": { + "uid_error": "无效的UID。", + "player_exist_error": "玩家不存在。", + "player_offline_error": "玩家已离线。", + "item_id_error": "无效的物品ID。", + "item_player_exist_error": "无效的物品/玩家UID。", + "entity_id_error": "无效的实体ID。", + "player_exist_offline_error": "玩家不存在或已离线。", + "argument_error": "无效的参数。", + "clear_target": "目标已清除。", + "set_target": "随后的的命令都会以 @%s 为预设。", + "need_target": "此命令需要一个目标 UID。添加 <@UID> 参数或使用 /target @UID 来指定默认目标。" + }, + "status": { + "enabled": "已启用", + "disabled": "未启用", + "help": "帮助", + "success": "成功" + }, + "account": { + "modify": "修改用户账号", + "invalid": "无效的UID。", + "exists": "账号已存在。", + "create": "已创建账号,UID 为 %s。", + "delete": "账号已删除。", + "no_account": "账号不存在。", + "command_usage": "用法:account <create|delete> <用户名> [UID]", + "description": "创建或删除账号" + }, + "broadcast": { + "command_usage": "用法:broadcast <消息>", + "message_sent": "公告已发送。", + "description": "向所有玩家发送公告" + }, + "changescene": { + "usage": "用法:changescene <场景ID>", + "already_in_scene": "你已经在这个场景中了。", + "success": "已切换至场景 %s。", + "exists_error": "此场景不存在。", + "description": "切换指定场景" + }, + "clear": { + "command_usage": "用法:clear <all|wp|art|mat>\nall: 所有, wp: 武器, art: 圣遗物, mat: 材料", + "weapons": "已清除 %s 的武器。", + "artifacts": "已清除 %s 的圣遗物。", + "materials": "已清除 %s 的材料。", + "furniture": "已清除 %s 的尘歌壶家具。", + "displays": "已清空 %s 的屏幕。", + "virtuals": "已清除 %s 的所有货币和经验值。", + "everything": "已清除 %s 的所有物品。", + "description": "从你的背包中删除所有未装备且已解锁的物品,包括稀有物品" + }, + "coop": { + "usage": "用法:coop <玩家ID> <目标玩家ID>", + "success": "已强制传送 %s 到 %s 的世界。", + "description": "强制传送指定用户到他人的世界" + }, + "enter_dungeon": { + "usage": "用法:enterdungeon <秘境ID>", + "changed": "已进入秘境 %s。", + "not_found_error": "此秘境不存在。", + "in_dungeon_error": "你已经在秘境中了。", + "description": "进入指定秘境" + }, + "giveAll": { + "usage": "用法:giveall [玩家] [数量]", + "started": "正在给予全部物品...", + "success": "已给予 %s 全部物品。", + "invalid_amount_or_playerId": "无效的数量/玩家ID。", + "description": "给予所有物品" + }, + "nostamina": { + "success": "NoStamina %s 对于 %s.", + "description": "保持你的体力处于最高状态。" + }, + "giveArtifact": { + "usage": "用法:giveart|gart [玩家] <圣遗物ID> <主词条ID> [<副词条ID>[,<强化次数>]]... [等级]", + "id_error": "无效的圣遗物ID。", + "success": "已将 %s 给予 %s。", + "description": "给予指定圣遗物" + }, + "giveChar": { + "usage": "用法:givechar <玩家> <角色ID|角色名> [数量]", + "given": "已将角色 %s [等级 %s] 给与 %s。", + "invalid_avatar_id": "无效的角色ID。", + "invalid_avatar_level": "无效的角色等级。", + "invalid_avatar_or_player_id": "无效的角色ID/玩家ID。", + "description": "给予指定角色" + }, + "give": { + "usage": "用法:give <玩家> <物品ID|物品名> [数量] [等级] [精炼等级]", + "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 个给予 %s。", + "description": "给予指定物品" + }, + "godmode": { + "success": "上帝模式已设为 %s。[用户:%s]", + "description": "防止你受到伤害" + }, + "heal": { + "success": "已治疗所有角色。", + "description": "治疗当前队伍的角色" + }, + "kick": { + "player_kick_player": "玩家 [%s:%s] 已将 [%s:%s] 踢出。", + "server_kick_player": "正在踢出玩家 [%s:%s]...", + "description": "从服务器内踢出指定玩家" + }, + "kill": { + "usage": "用法:killall [玩家UID] [场景ID]", + "scene_not_found_in_player_world": "未在玩家世界中找到此场景。", + "kill_monsters_in_scene": "已杀死场景 %s 中的 %s 个怪物。", + "description": "杀死所有怪物" + }, + "killCharacter": { + "usage": "用法:/killcharacter [玩家ID]", + "success": "已杀死 %s 当前角色。", + "description": "杀死当前角色" + }, + "language": { + "current_language": "当前语言是: %s", + "language_changed": "语言切换至: %s", + "language_not_found": "目前服务端没有这种语言: %s", + "description": "显示或切换当前语言" + }, + "list": { + "success": "目前在线人数:%s", + "description": "查看所有玩家" + }, + "permission": { + "usage": "用法:permission <add|remove> <用户名> <权限>", + "add": "权限已添加。", + "has_error": "此玩家已拥有此权限!", + "remove": "权限已移除。", + "not_have_error": "此玩家未拥有权限!", + "account_error": "账号不存在。", + "description": "添加或移除指定玩家的权限" + }, + "position": { + "success": "坐标:%s, %s, %s\n场景ID:%s", + "description": "获取所在位置" + }, + "quest": { + "description": "添加或完成任务", + "usage": "quest <add|finish> [任务ID]", + "added": "已添加任务 %s", + "finished": "已完成任务 %s", + "not_found": "未找到任务", + "invalid_id": "无效的任务ID" + }, + "reload": { + "reload_start": "正在重载配置文件和数据。", + "reload_done": "重载完成。", + "description": "重载配置文件和数据" + }, + "resetConst": { + "reset_all": "重置所有角色的命座。", + "success": "已重置 %s 的命座,重新登录后生效。", + "description": "重置当前角色的命之座,执行命令后需重新登录以生效" + }, + "resetShopLimit": { + "usage": "用法:/resetshop <玩家ID>", + "description": "重置所选玩家的商店刷新时间" + }, + "sendMail": { + "usage": "用法:give [玩家] <物品ID|物品名称> [数量]", + "user_not_exist": "ID '%s' 的用户不存在。", + "start_composition": "发送邮件流程。\n请使用`/sendmail <标题>`前进到下一步。\n你可以在任何时间使用`/sendmail stop`来停止发送。", + "templates": "邮件模板尚未实装...", + "invalid_arguments": "无效的参数。\n指令使用方法 `/sendmail <用户ID|all|help> [模板ID]`", + "send_cancel": "取消发送邮件", + "send_done": "已将邮件发送给 %s!", + "send_all_done": "邮件已发送给所有人!", + "not_composition_end": "现在邮件发送未到最后阶段。\n请使用 `/sendmail %s` 继续发送邮件,或使用 `/sendmail stop` 来停止发送邮件。", + "please_use": "请使用 `/sendmail %s`", + "set_title": "成功将邮件标题设置为 '%s'。\n使用 '/sendmail <正文>' 来设置邮件内容。", + "set_contents": "成功将邮件内容设置为 '%s'。\n使用 '/sendmail <发件人>' 来设置发件人。", + "set_message_sender": "发件人已设置为 '%s'。\n使用 '/sendmail <物品ID|物品名称|finish> [数量] [等级]' 来添加附件。", + "send": "已添加 %s 个 %s (等级 %s) 邮件附件。\n如果没有要继续添加的附件请使用 `/sendmail finish` 来发送邮件。", + "invalid_arguments_please_use": "错误的参数 \n请使用 `/sendmail %s`", + "title": "<标题>", + "message": "<正文>", + "sender": "<发件人>", + "arguments": "<物品ID|物品名称|finish> [数量] [等级]", + "error": "错误:无效的编写阶段 %s。需要 StackTrace 请查看服务器控制台。", + "description": "向指定用户发送邮件。此命令的用法可根据附加的参数而变化" + }, + "sendMessage": { + "usage": "用法:sendmessage <玩家> <消息>", + "success": "消息已发送。", + "description": "向指定玩家发送消息" + }, + "setFetterLevel": { + "usage": "用法:setfetterlevel <好感度等级>", + "range_error": "好感度等级必须在 0 到 10 之间。", + "success": "好感度已设为 %s 级。", + "level_error": "无效的好感度等级。", + "description": "设置当前角色的好感度等级" + }, + "setStats": { + "usage_console": "用法:setstats|stats @<UID> <属性> <数值>", + "usage_ingame": "用法:setstats|stats [@UID] <属性> <数值>", + "help_message": "\n可更改的属性列表:hp (生命值)| maxhp (最大生命值) | def(防御力) | atk (攻击力)| em (元素精通) | er (元素充能效率) | crate(暴击率) | cdmg (暴击伤害)| cdr (冷却缩减) | heal(治疗加成)| heali (受治疗加成)| shield (护盾强效)| defi (无视防御)\n(续) 元素增伤:epyro (火) | ecryo (冰) | ehydro (水) | egeo (岩) | edendro (草) | eelectro (雷) | ephys (物理)\n(续) 元素抗性:respyro (火) | rescryo (冰) | reshydro (水) | resgeo (岩) | resdendro (草) | reselectro (雷) | resphys (物理)\n", + "value_error": "无效的属性值。", + "uid_error": "无效的UID。", + "player_error": "玩家不存在或已离线。", + "set_self": "%s 已设为 %s。", + "set_for_uid": "%s [来自 %s] 已设为 %s。", + "set_max_hp": "最大生命值已设为 %s。", + "description": "设置当前角色的属性" + }, + "setWorldLevel": { + "usage": "用法:setworldlevel <等级>", + "value_error": "世界等级必须设置在0-8之间。", + "success": "世界等级已设为 %s。", + "invalid_world_level": "无效的世界等级。", + "description": "设置世界等级,执行命令后需重新登录以生效" + }, + "spawn": { + "usage": "用法:spawn <实体ID> [数量] [等级(仅怪物)]", + "success": "已生成 %s 个 %s。", + "description": "在你附近生成一个生物" + }, + "stop": { + "success": "正在关闭服务器...", + "description": "停止服务器" + }, + "talent": { + "usage_1": "设置天赋等级:/talent set <天赋ID> <数值>", + "usage_2": "另一种设置天赋等级的方法:/talent <n (普通攻击) | e (元素战技) | q (元素爆发)> <数值>", + "usage_3": "获取天赋ID:/talent getid", + "lower_16": "无效的天赋等级,天赋等级应小于等于15。", + "set_id": "将天赋等级设为 %s。", + "set_atk": "将普通攻击等级设为 %s。", + "set_e": "将元素战技等级设为 %s。", + "set_q": "将元素爆发等级设为 %s。", + "invalid_skill_id": "无效的技能ID。", + "set_this": "将天赋等级设为 %s。", + "invalid_level": "无效的天赋等级。", + "normal_attack_id": "普通攻击的 ID 为 %s。", + "e_skill_id": "元素战技ID %s。", + "q_skill_id": "元素爆发ID %s。", + "description": "设置当前角色的天赋等级" + }, + "team": { + "usage": "用法: team <add|remove|set> [avatarId,...] [index|first|last|index-index,...]", + "invalid_usage": "无效用法", + "add_usage": "用法(add): team add <avatarId,...> [index]", + "invalid_index": "无效索引", + "add_too_much": "服务端仅允许你队伍里至多有%d名角色", + "failed_to_add_avatar": "无法根据id %s 添加角色", + "remove_usage": "用法(remove): team remove <index|first|last|index-index,...>", + "failed_parse_index": "无法解析索引: %s", + "remove_too_much": "你不能删除那么多角色,你的队伍列表将会变空", + "ignore_index": "忽略的索引列表: %s", + "set_usage": "用法(set): team set <index> <avatarId>", + "index_out_of_range": "你指定的索引超出了范围", + "failed_parse_avatar_id": "无法解析的角色id: %s", + "avatar_already_in_team": "角色已经在你的队伍中了", + "avatar_not_found": "无法找到该角色: %d", + "description": "手动修改你的队伍" + }, + "teleportAll": { + "success": "已将所有玩家传送到你的位置。", + "error": "你只能在多人游戏状态下执行此命令。", + "description": "将你世界中的所有玩家传送到你所在的位置" + }, + "teleport": { + "usage_server": "用法:/tp @<玩家ID> <x> <y> <z> [场景ID]", + "usage": "用法:/tp [@<玩家ID>] <x> <y> <z> [场景ID]", + "specify_player_id": "你必须指定一个玩家ID。", + "invalid_position": "无效的位置。", + "success": "传送 %s 到坐标 %s,%s,%s,场景为 %s。", + "description": "改变指定玩家的位置" + }, + "tower": { + "unlock_done": "深境回廊的所有层已全部解锁。" + }, + "weather": { + "usage": "用法:weather <天气ID> [气候ID]", + "success": "已更改天气为 %s,气候为 %s。", + "invalid_id": "无效的天气ID。", + "description": "更改天气" + }, + "drop": { + "command_usage": "用法:drop <物品ID|物品名称> [数量]", + "success": "已丢下 %s 个 %s。", + "description": "在你附近丢下一个物品" + }, + "help": { + "usage": "用法:", + "aliases": "别名:", + "available_commands": "可用命令:", + "description": "发送帮助信息或显示指定命令的信息" + }, + "restart": { + "description": "重新启动服务器" + }, + "unlocktower": { + "success": "解锁完成。", + "description": "解锁深境螺旋的所有层" + }, + "resetshop": { + "description": "重置商店刷新时间" + } + }, + "gacha": { + "details": { + "title": "祈愿详情", + "available_five_stars": "可获得的5星物品", + "available_four_stars": "可获得的4星物品", + "available_three_stars": "可获得的3星物品" + } + } +}