From 399343507042002735cd98028219d8477260cd8f Mon Sep 17 00:00:00 2001 From: Somebody Date: Thu, 11 Jul 2024 17:30:53 +0800 Subject: [PATCH] Feature: I18n for common output & Bug Fix - Fix 8002 in Raid will cause problems - Fix Group loading --- Command/Command/Cmd/CommandRelic.cs | 2 +- Command/Command/CommandManager.cs | 3 +- Common/Configuration/ConfigContainer.cs | 4 + Common/Data/ResourceManager.cs | 83 ++++++++++--------- Common/Database/DatabaseHelper.cs | 5 +- Common/Enums/Rogue/BossDecayEffectTypeEnum.cs | 5 +- Common/Internationalization/I18nManager.cs | 2 +- .../Message/LanguageCHS.cs | 58 +++++++++++++ GameServer/Game/Player/PlayerInstance.cs | 2 +- GameServer/Game/Raid/RaidManager.cs | 36 +++++++- GameServer/Game/Scene/SceneEntityLoader.cs | 31 +++++-- GameServer/Game/Scene/SceneInstance.cs | 12 +++ GameServer/Plugin/PluginManager.cs | 5 +- GameServer/Server/Listener.cs | 4 +- Program/Handbook/HandbookGenerator.cs | 6 +- Program/Program/EntryPoint.cs | 32 +++---- 16 files changed, 215 insertions(+), 75 deletions(-) diff --git a/Command/Command/Cmd/CommandRelic.cs b/Command/Command/Cmd/CommandRelic.cs index 3be62df8..e0ba6e77 100644 --- a/Command/Command/Cmd/CommandRelic.cs +++ b/Command/Command/Cmd/CommandRelic.cs @@ -120,7 +120,7 @@ namespace EggLink.DanhengServer.Command.Cmd var itemData = new ItemData() { ItemId = int.Parse(arg.BasicArgs[0]), - Level = Math.Max(Math.Min(level, 15), 1), + Level = Math.Max(Math.Min(level, 9999), 1), UniqueId = ++player.InventoryManager!.Data.NextUniqueId, MainAffix = mainAffixId, Count = 1, diff --git a/Command/Command/CommandManager.cs b/Command/Command/CommandManager.cs index ba2b5ab3..93198f24 100644 --- a/Command/Command/CommandManager.cs +++ b/Command/Command/CommandManager.cs @@ -38,7 +38,8 @@ namespace EggLink.DanhengServer.Command } } } - Logger.Info($"Register {Commands.Count} commands."); + + Logger.Info(I18nManager.Translate("Server.ServerInfo.RegisterItem", Commands.Count.ToString(), I18nManager.Translate("Word.Command"))); } public void Start() diff --git a/Common/Configuration/ConfigContainer.cs b/Common/Configuration/ConfigContainer.cs index fdc1a2c7..b0e87ce1 100644 --- a/Common/Configuration/ConfigContainer.cs +++ b/Common/Configuration/ConfigContainer.cs @@ -39,6 +39,10 @@ namespace EggLink.DanhengServer.Configuration public string GameServerName { get; set; } = "DanhengServer"; public string GameServerDescription { get; set; } = "A re-implementation of StarRail server"; public int KcpInterval { get; set; } = 40; + public string GetDisplayAddress() + { + return PublicAddress + ":" + PublicPort; + } } public class PathConfig diff --git a/Common/Data/ResourceManager.cs b/Common/Data/ResourceManager.cs index 3db70799..3f57a3d7 100644 --- a/Common/Data/ResourceManager.cs +++ b/Common/Data/ResourceManager.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json.Linq; using EggLink.DanhengServer.Data.Custom; using EggLink.DanhengServer.Data.Excel; using EggLink.DanhengServer.Enums.Rogue; +using EggLink.DanhengServer.Internationalization; namespace EggLink.DanhengServer.Data { @@ -54,7 +55,7 @@ namespace EggLink.DanhengServer.Data var file = new FileInfo(path); if (!file.Exists) { - Logger.Warn($"File {path} not found"); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", fileName, I18nManager.Translate("Word.NotFound"))); continue; } var json = file.OpenText().ReadToEnd(); @@ -109,10 +110,10 @@ namespace EggLink.DanhengServer.Data } catch (Exception ex) { - Logger.Error($"Error in reading {fileName}", ex); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", fileName, I18nManager.Translate("Word.Error")), ex); } } - Logger.Info($"Loaded {count} {cls.Name}s."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", count.ToString(), cls.Name)); } } foreach (var cls in resList) @@ -123,13 +124,13 @@ namespace EggLink.DanhengServer.Data public static void LoadFloorInfo() { - Logger.Info("Loading floor files..."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.FloorInfo"))); DirectoryInfo directory = new(ConfigManager.Config.Path.ResourcePath + "/Config/LevelOutput/RuntimeFloor/"); bool missingGroupInfos = false; if (!directory.Exists) { - Logger.Warn($"Floor infos are missing, please check your resources folder: {ConfigManager.Config.Path.ResourcePath}/Config/LevelOutput/RuntimeFloor. Teleports and natural world spawns may not work!"); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", I18nManager.Translate("Word.FloorInfo"), $"{ConfigManager.Config.Path.ResourcePath}/Config/LevelOutput/RuntimeFloor", I18nManager.Translate("Word.FloorMissingResult"))); return; } // Load floor infos @@ -145,7 +146,7 @@ namespace EggLink.DanhengServer.Data GameData.FloorInfoData.Add(name, info!); } catch (Exception ex) { - Logger.Error("Error in reading" + file.Name, ex); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", file.Name, I18nManager.Translate("Word.Error")), ex); } } @@ -165,13 +166,12 @@ namespace EggLink.DanhengServer.Data if (group != null) { group.Id = groupInfo.ID; - if (!info.Groups.ContainsKey(groupInfo.ID)) - info.Groups.Add(groupInfo.ID, group); + info.Groups.TryAdd(groupInfo.ID, group); group.Load(); } } catch (Exception ex) { - Logger.Error("Error in reading " + file.Name, ex); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", file.Name, I18nManager.Translate("Word.Error")), ex); } if (info.Groups.Count == 0) { @@ -181,18 +181,18 @@ namespace EggLink.DanhengServer.Data info.OnLoad(); } if (missingGroupInfos) - Logger.Warn($"Group infos are missing, please check your resources folder: {ConfigManager.Config.Path.ResourcePath}/Config/LevelOutput/SharedRuntimeGroup. Teleports, monster battles, and natural world spawns may not work!"); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", I18nManager.Translate("Word.FloorGroupInfo"), $"{ConfigManager.Config.Path.ResourcePath}/Config/LevelOutput/SharedRuntimeGroup", I18nManager.Translate("Word.FloorGroupMissingResult"))); - Logger.Info("Loaded " + GameData.FloorInfoData.Count + " floor infos."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", GameData.FloorInfoData.Count.ToString(), I18nManager.Translate("Word.FloorInfo"))); } public static void LoadMissionInfo() { - Logger.Info("Loading mission files..."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.MissionInfo"))); DirectoryInfo directory = new(ConfigManager.Config.Path.ResourcePath + "/Config/Level/Mission"); if (!directory.Exists) { - Logger.Warn($"Mission infos are missing, please check your resources folder: {ConfigManager.Config.Path.ResourcePath}/Config/Level/Mission. Missions may not work!"); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", I18nManager.Translate("Word.MissionInfo"), $"{ConfigManager.Config.Path.ResourcePath}/Config/Level/Mission", I18nManager.Translate("Word.Mission"))); return; } bool missingMissionInfos = false; @@ -250,7 +250,7 @@ namespace EggLink.DanhengServer.Data } } catch (Exception ex) { - Logger.Error("Error in reading " + missionJsonPath, ex); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", missionJsonPath, I18nManager.Translate("Word.Error")), ex); } } } @@ -261,18 +261,18 @@ namespace EggLink.DanhengServer.Data } } if (missingMissionInfos) - Logger.Warn($"Mission infos are missing, please check your resources folder: {ConfigManager.Config.Path.ResourcePath}/Config/Level/Mission. Missions may not work!"); - Logger.Info("Loaded " + count + " mission infos."); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", I18nManager.Translate("Word.MissionInfo"), $"{ConfigManager.Config.Path.ResourcePath}/Config/Level/Mission", I18nManager.Translate("Word.Mission"))); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", count.ToString(), I18nManager.Translate("Word.MissionInfo"))); } public static T? LoadCustomFile(string filetype, string filename) { - Logger.Info($"Loading {filetype} files..."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", filetype)); FileInfo file = new(ConfigManager.Config.Path.ConfigPath + $"/{filename}.json"); T? customFile = default; if (!file.Exists) { - Logger.Warn($"Banner infos are missing, please check your resources folder: {ConfigManager.Config.Path.ConfigPath}/{filename}.json. {filetype} may not work!"); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", filetype, $"{ConfigManager.Config.Path.ConfigPath}/{filename}.json", filetype)); return customFile; } try @@ -289,23 +289,23 @@ namespace EggLink.DanhengServer.Data if (customFile is Dictionary d) { - Logger.Info("Loaded " + d.Count + $" {filetype}s."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", d.Count.ToString(), filetype)); } else if (customFile is Dictionary> di) { - Logger.Info("Loaded " + di.Count + $" {filetype}s."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", di.Count.ToString(), filetype)); } else if (customFile is BannersConfig c) { - Logger.Info("Loaded " + c.Banners.Count + $" {filetype}s."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", c.Banners.Count.ToString(), filetype)); } else if (customFile is RogueMiracleEffectConfig r) { - Logger.Info("Loaded " + r.Miracles.Count + $" {filetype}s."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", r.Miracles.Count.ToString(), filetype)); } else if (customFile is ActivityConfig a) { - Logger.Info("Loaded " + a.ScheduleData.Count + $" {filetype}s."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", a.ScheduleData.Count.ToString(), filetype)); } else { - Logger.Info("Loaded " + filetype + " file."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItem", filetype)); } return customFile; @@ -313,6 +313,7 @@ namespace EggLink.DanhengServer.Data public static void LoadMazeSkill() { + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.MazeSkillInfo"))); var count = 0; foreach (var adventure in GameData.AdventurePlayerData.Values) { @@ -332,18 +333,20 @@ namespace EggLink.DanhengServer.Data } catch (Exception ex) { - Logger.Error("Error in reading " + file.Name, ex); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", adventurePath, I18nManager.Translate("Word.Error")), ex); } } if (count < GameData.AdventurePlayerData.Count) { - Logger.Warn("Maze skill infos are missing, please check your resources folder: " + ConfigManager.Config.Path.ResourcePath + "/Config/ConfigAdventureAbility/LocalPlayer. Maze skills may not work!"); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", I18nManager.Translate("Word.MazeSkillInfo"), $"{ConfigManager.Config.Path.ResourcePath}/Config/Level/AdventureAbility", I18nManager.Translate("Word.MazeSkill"))); } - Logger.Info("Loaded " + count + " maze skill infos."); + + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", count.ToString(), I18nManager.Translate("Word.MazeSkillInfo"))); } public static void LoadDialogueInfo() { + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.DialogueInfo"))); var count = 0; foreach (var dialogue in GameData.RogueNPCDialogueData) { @@ -369,21 +372,22 @@ namespace EggLink.DanhengServer.Data } } catch (Exception ex) { - Logger.Error("Error in reading " + file.Name, ex); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", file.Name, I18nManager.Translate("Word.Error")), ex); } } if (count < GameData.RogueNPCDialogueData.Count) { - Logger.Warn("Dialogue infos are missing, please check your resources folder: " + ConfigManager.Config.Path.ResourcePath + "/Config/Level/RogueDialogue/RogueDialogueEvent. Dialogues may not work!"); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", I18nManager.Translate("Word.DialogueInfo"), $"{ConfigManager.Config.Path.ResourcePath}/Config/Level/Rogue/Dialogue", I18nManager.Translate("Word.Dialogue"))); } - Logger.Info("Loaded " + count + " dialogue infos."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", count.ToString(), I18nManager.Translate("Word.DialogueInfo"))); } public static void LoadPerformanceInfo() { + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.PerformanceInfo"))); var count = 0; foreach (var performance in GameData.PerformanceEData.Values) { @@ -410,7 +414,7 @@ namespace EggLink.DanhengServer.Data } catch (Exception ex) { - Logger.Error("Error in reading " + file.Name, ex); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", file.Name, I18nManager.Translate("Word.Error")), ex); } } @@ -421,11 +425,12 @@ namespace EggLink.DanhengServer.Data //Logger.Warn("Performance infos are missing, please check your resources folder: " + ConfigManager.Config.Path.ResourcePath + "/Config/Level/Mission/*/Act. Performances may not work!"); } - Logger.Info("Loaded " + count + " performance infos."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", count.ToString(), I18nManager.Translate("Word.PerformanceInfo"))); } public static void LoadRogueChestMapInfo() { + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.RogueChestMapInfo"))); var count = 0; var boardList = new List(); foreach (var nousMap in GameData.RogueNousChessBoardData.Values) @@ -464,27 +469,29 @@ namespace EggLink.DanhengServer.Data } catch (Exception ex) { - Logger.Error("Error in reading " + file.Name, ex); + Logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", file.Name, I18nManager.Translate("Word.Error")), ex); } } if (count < boardList.Count) { - Logger.Warn("Chess board infos are missing, please check your resources folder: " + ConfigManager.Config.Path.ResourcePath + "/Config/Gameplays/RogueDLC. Chess rogue may not work!"); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", I18nManager.Translate("Word.RogueChestMapInfo"), $"{ConfigManager.Config.Path.ResourcePath}/Config/Gameplays/RogueDLC", I18nManager.Translate("Word.RogueChestMap"))); } - Logger.Info("Loaded " + count + " board infos."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", count.ToString(), I18nManager.Translate("Word.RogueChestMapInfo"))); } public static void LoadChessRogueRoomData() { + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.ChessRogueRoomInfo"))); var count = 0; FileInfo file = new(ConfigManager.Config.Path.ConfigPath + $"/ChessRogueRoomGen.json"); - List? customFile = default; + List? customFile; if (!file.Exists) { - Logger.Warn($"Banner infos are missing, please check your resources folder: {ConfigManager.Config.Path.ConfigPath}/ChessRogueRoomGen.json. Chess Rogue may not work!"); + Logger.Warn(I18nManager.Translate("Server.ServerInfo.ConfigMissing", I18nManager.Translate("Word.ChessRogueRoomInfo"), $"{ConfigManager.Config.Path.ConfigPath}/ChessRogueRoomGen.json", I18nManager.Translate("Word.ChessRogueRoom"))); + return; } try @@ -538,7 +545,7 @@ namespace EggLink.DanhengServer.Data Logger.Error("Error in reading " + file.Name, ex); } - Logger.Info("Loaded " + count + " room infos."); + Logger.Info(I18nManager.Translate("Server.ServerInfo.LoadedItems", count.ToString(), I18nManager.Translate("Word.ChessRogueRoomInfo"))); } public static void AddRoomToGameData(RogueDLCBlockTypeEnum type, ChessRogueRoomConfig room) diff --git a/Common/Database/DatabaseHelper.cs b/Common/Database/DatabaseHelper.cs index d7a6b085..31c0c266 100644 --- a/Common/Database/DatabaseHelper.cs +++ b/Common/Database/DatabaseHelper.cs @@ -1,6 +1,7 @@ using EggLink.DanhengServer.Database.Inventory; using EggLink.DanhengServer.Database.Mission; using EggLink.DanhengServer.Database.Scene; +using EggLink.DanhengServer.Internationalization; using EggLink.DanhengServer.Util; using SqlSugar; @@ -23,7 +24,7 @@ namespace EggLink.DanhengServer.Database public void Initialize() { - logger.Info("Initializing database..."); + logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.Database"))); var config = ConfigManager.Config; DbType type; string connectionString; @@ -293,7 +294,7 @@ namespace EggLink.DanhengServer.Database } } - logger.Info($"Save database. Using {(DateTime.Now - prev).TotalSeconds.ToString()[..4]} seconds."); + logger.Info(I18nManager.Translate("Server.ServerInfo.SaveDatabase", (DateTime.Now - prev).TotalSeconds.ToString()[..4])); ToSaveUidList.Clear(); } diff --git a/Common/Enums/Rogue/BossDecayEffectTypeEnum.cs b/Common/Enums/Rogue/BossDecayEffectTypeEnum.cs index fb7568f9..f2273d33 100644 --- a/Common/Enums/Rogue/BossDecayEffectTypeEnum.cs +++ b/Common/Enums/Rogue/BossDecayEffectTypeEnum.cs @@ -9,7 +9,8 @@ namespace EggLink.DanhengServer.Enums.Rogue public enum BossDecayEffectTypeEnum { None = 0, - AddMazeBuffList = 1, - RemoveMazeBuffList = 2, + AddMazeBuff = 1, + AddMazeBuffList = 2, + RemoveMazeBuffList = 3, } } diff --git a/Common/Internationalization/I18nManager.cs b/Common/Internationalization/I18nManager.cs index dd01e44b..3da1a48d 100644 --- a/Common/Internationalization/I18nManager.cs +++ b/Common/Internationalization/I18nManager.cs @@ -28,7 +28,7 @@ namespace EggLink.DanhengServer.Internationalization var language = Activator.CreateInstance(languageType) ?? throw new Exception("Language not found"); Language = language; - Logger.Info("Language loaded"); + Logger.Info(Translate("Server.ServerInfo.LoadedItem", Translate("Word.Language"))); } public static string Translate(string key, params string[] args) diff --git a/Common/Internationalization/Message/LanguageCHS.cs b/Common/Internationalization/Message/LanguageCHS.cs index ddb26da5..ca367b8d 100644 --- a/Common/Internationalization/Message/LanguageCHS.cs +++ b/Common/Internationalization/Message/LanguageCHS.cs @@ -33,6 +33,7 @@ namespace EggLink.DanhengServer.Internationalization.Message public class ServerTextCHS { public WebTextCHS Web { get; } = new(); + public ServerInfoTextCHS ServerInfo { get; } = new(); } /// @@ -51,6 +52,38 @@ namespace EggLink.DanhengServer.Internationalization.Message public string Buff { get; } = "祝福"; public string Miracle { get; } = "奇物"; public string Unlock { get; } = "奢侈品"; + + // server info + public string Config { get; } = "配置文件"; + public string Language { get; } = "语言"; + public string Log { get; } = "日志"; + public string GameData { get; } = "游戏数据"; + public string Database { get; } = "数据库"; + public string Command { get; } = "命令"; + public string WebServer { get; } = "Web服务器"; + public string Plugin { get; } = "插件"; + public string Handler { get; } = "包处理器"; + public string Dispatch { get; } = "全局分发"; + public string Game { get; } = "游戏"; + public string Handbook { get; } = "手册"; + public string NotFound { get; } = "未找到"; + public string Error { get; } = "错误"; + public string FloorInfo { get; } = "区域文件"; + public string FloorGroupInfo { get; } = "区域组文件"; + public string FloorMissingResult { get; } = "传送与世界生成"; + public string FloorGroupMissingResult { get; } = "传送、怪物战斗与世界生成"; + public string Mission { get; } = "任务"; + public string MissionInfo { get; } = "任务文件"; + public string MazeSkill { get; } = "角色秘技"; + public string MazeSkillInfo { get; } = "角色秘技文件"; + public string Dialogue { get; } = "模拟宇宙事件"; + public string DialogueInfo { get; } = "模拟宇宙事件文件"; + public string Performance { get; } = "剧情操作"; + public string PerformanceInfo { get; } = "剧情操作文件"; + public string RogueChestMap { get; } = "模拟宇宙地图"; + public string RogueChestMapInfo { get; } = "模拟宇宙地图文件"; + public string ChessRogueRoom { get; } = "模拟宇宙DLC"; + public string ChessRogueRoomInfo { get; } = "模拟宇宙DLC文件"; } #endregion @@ -93,6 +126,31 @@ namespace EggLink.DanhengServer.Internationalization.Message { } + /// + /// path: Server.ServerInfo + /// + public class ServerInfoTextCHS + { + public string Shutdown { get; } = "关闭中…"; + public string CancelKeyPressed { get; } = "已按下取消键 (Ctrl + C),服务器即将关闭…"; + public string StartingServer { get; } = "正在启动 DanhengServer…"; + public string LoadingItem { get; } = "正在加载 {0}…"; + public string RegisterItem { get; } = "注册了 {0} 个 {1}。"; + public string FailedToLoadItem { get; } = "加载 {0} 失败。"; + public string FailedToInitializeItem { get; } = "初始化 {0} 失败。"; + public string FailedToReadItem { get; } = "读取 {0} 失败,文件{1}"; + public string GeneratedItem { get; } = "已生成 {0}。"; + public string LoadedItem { get; } = "已加载 {0}。"; + public string LoadedItems { get; } = "已加载 {0} 个 {1}。"; + public string ServerRunning { get; } = "{0} 服务器正在监听 {1}"; + public string ServerStarted { get; } = "启动完成!用时 {0}s,击败了99%的用户,输入 ‘help’ 来获取命令帮助"; // 玩梗,考虑英语版本将其本土化 + public string MissionEnabled { get; } = "任务系统已启用,此功能仍在开发中,且可能不会按预期工作,如果遇见任何bug,请汇报给开发者。"; + + public string ConfigMissing { get; } = "{0} 缺失,请检查你的资源文件夹:{1},{2} 可能不能使用。"; + public string UnloadedItems { get; } = "卸载了所有 {0}。"; + public string SaveDatabase { get; } = "已保存数据库,用时 {0}s"; + } + #endregion #endregion diff --git a/GameServer/Game/Player/PlayerInstance.cs b/GameServer/Game/Player/PlayerInstance.cs index 67f81af2..f95f9ea4 100644 --- a/GameServer/Game/Player/PlayerInstance.cs +++ b/GameServer/Game/Player/PlayerInstance.cs @@ -579,7 +579,7 @@ namespace EggLink.DanhengServer.Game.Player { SendPacket(new PacketEnterSceneByServerScNotify(instance, storyLineAction)); } - else if (!notSendMove) + else if (sendPacket && !notSendMove) // send move packet { SendPacket(new PacketSceneEntityMoveScNotify(this)); } diff --git a/GameServer/Game/Raid/RaidManager.cs b/GameServer/Game/Raid/RaidManager.cs index 7251a29c..75420073 100644 --- a/GameServer/Game/Raid/RaidManager.cs +++ b/GameServer/Game/Raid/RaidManager.cs @@ -74,7 +74,41 @@ namespace EggLink.DanhengServer.GameServer.Game.Raid else if (excel.TeamType == Enums.Scene.RaidTeamTypeEnum.TrialOnly) { // set lineup - Player.LineupManager!.SetExtraLineup(ExtraLineupType.LineupHeliobus, excel.TrialAvatarList); + List list = [..excel.TrialAvatarList]; + if (list.Count > 0) + { + if (Player.Data.CurrentGender == Gender.Man) + { + foreach (var avatar in excel.TrialAvatarList) + { + if (avatar > 10000) // else is Base Avatar + { + if (avatar.ToString().EndsWith("8002") || + avatar.ToString().EndsWith("8004") || + avatar.ToString().EndsWith("8006")) + { + list.Remove(avatar); + } + } + } + } + else + { + foreach (var avatar in excel.TrialAvatarList) + { + if (avatar > 10000) // else is Base Avatar + { + if (avatar.ToString().EndsWith("8001") || + avatar.ToString().EndsWith("8003") || + avatar.ToString().EndsWith("8005")) + { + list.Remove(avatar); + } + } + } + } + } + Player.LineupManager!.SetExtraLineup(ExtraLineupType.LineupHeliobus, list); Player.SendPacket(new PacketSyncLineupNotify(Player.LineupManager!.GetCurLineup()!)); } else diff --git a/GameServer/Game/Scene/SceneEntityLoader.cs b/GameServer/Game/Scene/SceneEntityLoader.cs index b17f57dc..685dffde 100644 --- a/GameServer/Game/Scene/SceneEntityLoader.cs +++ b/GameServer/Game/Scene/SceneEntityLoader.cs @@ -33,6 +33,8 @@ namespace EggLink.DanhengServer.Game.Scene public void SyncEntity() { + if (Scene.Excel.PlaneType == PlaneTypeEnum.Raid) return; + bool refreshed = false; var oldGroupId = new List(); foreach (var entity in Scene.Entities.Values) @@ -69,6 +71,7 @@ namespace EggLink.DanhengServer.Game.Scene refreshed = true; } } + Scene.Groups.Remove(group.Id); } else if (group.OwnerMainMissionID != 0 && Scene.Player.MissionManager!.GetMainMissionStatus(group.OwnerMainMissionID) != Enums.MissionPhaseEnum.Accept) { @@ -81,6 +84,7 @@ namespace EggLink.DanhengServer.Game.Scene refreshed = true; } } + Scene.Groups.Remove(group.Id); } } else // check if it should be loaded { @@ -89,32 +93,46 @@ namespace EggLink.DanhengServer.Game.Scene addList.AddRange(groupList ?? []); } } - if (refreshed) + if (refreshed && (addList.Count > 0 || removeList.Count > 0)) { - Scene.Player.SendPacket(new PacketSceneGroupRefreshScNotify(null, removeList)); - Scene.Player.SendPacket(new PacketSceneGroupRefreshScNotify(addList, null)); + Scene.Player.SendPacket(new PacketSceneGroupRefreshScNotify(addList, removeList)); } } public virtual List? LoadGroup(GroupInfo info, bool forceLoad = false) { var missionData = Scene.Player.MissionManager!.Data; - - if (!(info.OwnerMainMissionID == 0 || Scene.Player.MissionManager!.GetMainMissionStatus(info.OwnerMainMissionID) == Enums.MissionPhaseEnum.Accept)) + if (info.LoadSide == GroupLoadSideEnum.Client) { return null; } - if ((!info.LoadCondition.IsTrue(missionData) || info.UnloadCondition.IsTrue(missionData, false) || info.ForceUnloadCondition.IsTrue(missionData, false)) && !forceLoad) + if (info.GroupName.Contains("TrainVisitor")) { return null; } + if (Scene.Excel.PlaneType != PlaneTypeEnum.Raid) + { + if (!(info.OwnerMainMissionID == 0 || Scene.Player.MissionManager!.GetMainMissionStatus(info.OwnerMainMissionID) == Enums.MissionPhaseEnum.Accept)) + { + return null; + } + + if ((!info.LoadCondition.IsTrue(missionData) || info.UnloadCondition.IsTrue(missionData, false) || info.ForceUnloadCondition.IsTrue(missionData, false)) && !forceLoad) + { + return null; + } + } + if (Scene.Entities.Values.ToList().FindIndex(x => x.GroupID == info.Id) != -1) // check if group is already loaded { return null; } + // load + Scene.Groups.Add(info.Id); + var entityList = new List(); foreach (var npc in info.NPCList) { @@ -184,6 +202,7 @@ namespace EggLink.DanhengServer.Game.Scene refreshed = true; } } + Scene.Groups.Remove(group.Id); if (refreshed) { diff --git a/GameServer/Game/Scene/SceneInstance.cs b/GameServer/Game/Scene/SceneInstance.cs index 75b69dfc..86d4372a 100644 --- a/GameServer/Game/Scene/SceneInstance.cs +++ b/GameServer/Game/Scene/SceneInstance.cs @@ -35,6 +35,7 @@ namespace EggLink.DanhengServer.Game.Scene public Dictionary AvatarInfo = []; public int LeaderEntityId; public Dictionary Entities = []; + public List Groups = []; public List HealingSprings = []; public SceneEntityLoader? EntityLoader; @@ -270,6 +271,17 @@ namespace EggLink.DanhengServer.Game.Scene groups[groups.FindIndex(x => x.GroupId == entity.Value.GroupID)].EntityList.Add(entity.Value.ToProto()); } + foreach (var groupId in Groups) // Add for empty group + { + if (groups.FindIndex(x => x.GroupId == groupId) == -1) + { + groups.Add(new SceneEntityGroupInfo() + { + GroupId = (uint)groupId + }); + } + } + foreach (var group in groups) { sceneInfo.EntityGroupList.Add(group); diff --git a/GameServer/Plugin/PluginManager.cs b/GameServer/Plugin/PluginManager.cs index 980e304c..f685d826 100644 --- a/GameServer/Plugin/PluginManager.cs +++ b/GameServer/Plugin/PluginManager.cs @@ -1,4 +1,5 @@ -using EggLink.DanhengServer.Plugin.Constructor; +using EggLink.DanhengServer.Internationalization; +using EggLink.DanhengServer.Plugin.Constructor; using EggLink.DanhengServer.Util; using McMaster.NETCore.Plugins; using Newtonsoft.Json; @@ -137,7 +138,7 @@ namespace EggLink.DanhengServer.Plugin UnloadPlugin(plugin); } - logger.Info("Unloaded all plugins"); + logger.Info(I18nManager.Translate("Server.ServerInfo.UnloadedItems", I18nManager.Translate("Word.Plugin"))); } #endregion diff --git a/GameServer/Server/Listener.cs b/GameServer/Server/Listener.cs index 0b5e7b84..bafa22a0 100644 --- a/GameServer/Server/Listener.cs +++ b/GameServer/Server/Listener.cs @@ -1,9 +1,11 @@ using System.Net; using System.Net.Sockets; using EggLink.DanhengServer.Common.Enums; +using EggLink.DanhengServer.Internationalization; using EggLink.DanhengServer.KcpSharp; using EggLink.DanhengServer.Util; using KcpSharp; +using Microsoft.Extensions.Logging; namespace EggLink.DanhengServer.Server { @@ -38,7 +40,7 @@ namespace EggLink.DanhengServer.Server if (UDPListener == null) return; KCPTransport = KcpSocketTransport.CreateMultiplexConnection(UDPClient, 1400); KCPTransport.Start(); - Logger.Info($"Game Server started. Listening on port: {PORT}"); + Logger.Info(I18nManager.Translate("Server.ServerInfo.ServerRunning", I18nManager.Translate("Word.Game"), ConfigManager.Config.GameServer.GetDisplayAddress())); } private static void RegisterConnection(Connection con) diff --git a/Program/Handbook/HandbookGenerator.cs b/Program/Handbook/HandbookGenerator.cs index 322ce944..13772fe6 100644 --- a/Program/Handbook/HandbookGenerator.cs +++ b/Program/Handbook/HandbookGenerator.cs @@ -21,14 +21,14 @@ namespace EggLink.DanhengServer.Handbook var textMapPath = config.Path.ResourcePath + "/TextMap/TextMap" + config.ServerOption.Language + ".json"; if (!File.Exists(textMapPath)) { - Logger.GetByClassName().Error("TextMap file not found: " + textMapPath); + Logger.GetByClassName().Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem", textMapPath, I18nManager.Translate("Word.NotFound"))); return; } var textMap = JsonConvert.DeserializeObject>(File.ReadAllText(textMapPath)); if (textMap == null) { - Logger.GetByClassName().Error("Failed to load TextMap file: " + textMapPath); + Logger.GetByClassName().Error(I18nManager.Translate("Server.ServerInfo.FailedToReadItem",textMapPath, I18nManager.Translate("Word.Error"))); return; } @@ -76,7 +76,7 @@ namespace EggLink.DanhengServer.Handbook builder.AppendLine(); WriteToFile(builder.ToString()); - Logger.GetByClassName().Info("Handbook generated successfully."); + Logger.GetByClassName().Info(I18nManager.Translate("Server.ServerInfo.GeneratedItem", I18nManager.Translate("Word.Handbook"))); } public static void GenerateCmd(StringBuilder builder) diff --git a/Program/Program/EntryPoint.cs b/Program/Program/EntryPoint.cs index 4aa03e8f..de774b3f 100644 --- a/Program/Program/EntryPoint.cs +++ b/Program/Program/EntryPoint.cs @@ -27,11 +27,11 @@ namespace EggLink.DanhengServer.Program public static void Main(string[] args) { AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) => { - Console.WriteLine("Shutting down..."); + logger.Info(I18nManager.Translate("Server.ServerInfo.Shutdown")); PerformCleanup(); }; Console.CancelKeyPress += (sender, eventArgs) => { - Console.WriteLine("Cancel key pressed. Shutting down..."); + logger.Info(I18nManager.Translate("Server.ServerInfo.CancelKeyPressed")); eventArgs.Cancel = true; Environment.Exit(0); }; @@ -51,40 +51,40 @@ namespace EggLink.DanhengServer.Program Logger.SetLogFile(file); // Starting the server - logger.Info("Starting DanhengServer..."); + logger.Info(I18nManager.Translate("Server.ServerInfo.StartingServer")); // Load the config - logger.Info("Loading config..."); + logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.Config"))); try { ConfigManager.LoadConfig(); } catch (Exception e) { - logger.Error("Failed to load config", e); + logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToLoadItem", I18nManager.Translate("Word.Config")), e); Console.ReadLine(); return; } // Load the language - logger.Info("Loading language..."); + logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.Language"))); try { I18nManager.LoadLanguage(); } catch (Exception e) { - logger.Error("Failed to load language", e); + logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToLoadItem", I18nManager.Translate("Word.Language")), e); Console.ReadLine(); return; } // Load the game data - logger.Info("Loading game data..."); + logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.GameData"))); try { ResourceManager.LoadGameData(); } catch (Exception e) { - logger.Error("Failed to load game data", e); + logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToLoadItem", I18nManager.Translate("Word.GameData")), e); Console.ReadLine(); return; } @@ -105,7 +105,7 @@ namespace EggLink.DanhengServer.Program } } catch (Exception e) { - logger.Error("Failed to initialize database", e); + logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToLoadItem", I18nManager.Translate("Word.Database")), e); Console.ReadLine(); return; } @@ -116,20 +116,20 @@ namespace EggLink.DanhengServer.Program CommandManager.RegisterCommand(); } catch (Exception e) { - logger.Error("Failed to initialize command manager", e); + logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToInitializeItem", I18nManager.Translate("Word.Command")), e); Console.ReadLine(); return; } // Load the plugins - logger.Info("Loading plugins..."); + logger.Info(I18nManager.Translate("Server.ServerInfo.LoadingItem", I18nManager.Translate("Word.Plugin"))); try { PluginManager.LoadPlugins(); } catch (Exception e) { - logger.Error("Failed to load plugins", e); + logger.Error(I18nManager.Translate("Server.ServerInfo.FailedToLoadItem", I18nManager.Translate("Word.Plugin")), e); Console.ReadLine(); return; } @@ -212,18 +212,18 @@ namespace EggLink.DanhengServer.Program HandlerManager.Init(); WebProgram.Main([], GetConfig().HttpServer.PublicPort, GetConfig().HttpServer.GetDisplayAddress()); - logger.Info($"Dispatch Server is running on {GetConfig().HttpServer.GetDisplayAddress()}"); + logger.Info(I18nManager.Translate("Server.ServerInfo.ServerRunning", I18nManager.Translate("Word.Dispatch"), GetConfig().HttpServer.GetDisplayAddress())); Listener.StartListener(); var elapsed = DateTime.Now - time; - logger.Info($"Done in {elapsed.TotalSeconds.ToString()[..4]}s! Type '/help' to get help of commands."); + logger.Info(I18nManager.Translate("Server.ServerInfo.ServerStarted", elapsed.TotalSeconds.ToString()[..4])); GenerateLogMap(); if (GetConfig().ServerOption.EnableMission) { - logger.Warn("Mission system is enabled. This is a feature that is still in development and may not work as expected. If you encounter any issues, please report them to the developers."); + logger.Warn(I18nManager.Translate("Server.ServerInfo.MissionEnabled")); } CommandManager.Start(); }