diff --git a/Common/Database/DatabaseHelper.cs b/Common/Database/DatabaseHelper.cs index 4269d1f0..65eef6ca 100644 --- a/Common/Database/DatabaseHelper.cs +++ b/Common/Database/DatabaseHelper.cs @@ -234,12 +234,34 @@ public class DatabaseHelper } } - public T GetInstanceOrCreateNew(int uid) where T : class, new() + public T GetInstanceOrCreateNew(int uid) where T : BaseDatabaseDataHelper, new() { var instance = GetInstance(uid); if (instance != null) return instance; - instance = new T(); - (instance as BaseDatabaseDataHelper)!.Uid = uid; + // judge if exists (maybe the instance is not in the map) + + var t = sqlSugarScope?.Queryable() + .Where(x => x.Uid == uid) + .ToList(); + + if (t is { Count: > 0 }) // exists in the database + { + instance = t[0]; + if (!UidInstanceMap.TryGetValue(uid, out var value)) + { + value = []; + UidInstanceMap[uid] = value; + } + + value.Add(instance); // add to the map + return instance; + } + + // create a new instance + instance = new T + { + Uid = uid + }; SaveInstance(instance); return instance; diff --git a/Common/Internationalization/Message/LanguageCHS.cs b/Common/Internationalization/Message/LanguageCHS.cs index ae5e2b08..dd7e3c81 100644 --- a/Common/Internationalization/Message/LanguageCHS.cs +++ b/Common/Internationalization/Message/LanguageCHS.cs @@ -83,6 +83,14 @@ public class WordTextCHS public string ChessRogueRoomInfo => "模拟宇宙DLC文件"; public string SummonUnit => "秘技生成"; public string SummonUnitInfo => "秘技生成文件"; + public string RogueTournRoom => "差分宇宙"; + public string RogueTournRoomInfo => "差分宇宙房间文件"; + public string RogueMagicRoom => "不可知域"; + public string RogueMagicRoomInfo => "不可知域房间文件"; + public string RogueDiceSurface => "骰面效果"; + public string RogueDiceSurfaceInfo => "骰面效果文件"; + public string AdventureModifier => "AdventureModifier"; + public string AdventureModifierInfo => "AdventureModifier文件"; public string DatabaseAccount => "数据库账号"; } diff --git a/Common/Internationalization/Message/LanguageCHT.cs b/Common/Internationalization/Message/LanguageCHT.cs index 12b8a1ca..411fa7fb 100644 --- a/Common/Internationalization/Message/LanguageCHT.cs +++ b/Common/Internationalization/Message/LanguageCHT.cs @@ -81,6 +81,16 @@ public class WordTextCHT public string RogueChestMapInfo => "模擬宇宙地圖文件"; public string ChessRogueRoom => "模擬宇宙DLC"; public string ChessRogueRoomInfo => "模擬宇宙DLC文件"; + public string SummonUnit => "秘技生成"; + public string SummonUnitInfo => "秘技生成文件"; + public string RogueTournRoom => "差分宇宙"; + public string RogueTournRoomInfo => "差分宇宙房間文件"; + public string RogueMagicRoom => "不可知域"; + public string RogueMagicRoomInfo => "不可知域房間文件"; + public string RogueDiceSurface => "骰面效果"; + public string RogueDiceSurfaceInfo => "骰面效果文件"; + public string AdventureModifier => "AdventureModifier"; + public string AdventureModifierInfo => "AdventureModifier文件"; public string DatabaseAccount => "數據庫賬號"; } diff --git a/Common/Internationalization/Message/LanguageEN.cs b/Common/Internationalization/Message/LanguageEN.cs index f4434d0e..b23f7c5a 100644 --- a/Common/Internationalization/Message/LanguageEN.cs +++ b/Common/Internationalization/Message/LanguageEN.cs @@ -63,24 +63,34 @@ public class WordTextEN public string Handbook => "Handbook"; public string NotFound => "Not Found"; public string Error => "Error"; - public string FloorInfo => "Floor Info"; - public string FloorGroupInfo => "Floor Group Info"; + public string FloorInfo => "Floor File"; + public string FloorGroupInfo => "Floor Group File"; public string FloorMissingResult => "Teleportation and World Generation"; public string FloorGroupMissingResult => "Teleportation, Monster Battles, and World Generation"; public string Mission => "Mission"; - public string MissionInfo => "Mission Info"; + public string MissionInfo => "Mission File"; public string SubMission => "Sub Mission"; - public string SubMissionInfo => "Sub Mission Info"; + public string SubMissionInfo => "Sub Mission File"; public string MazeSkill => "Maze Skill"; - public string MazeSkillInfo => "Maze Skill Info"; + public string MazeSkillInfo => "Maze Skill File"; public string Dialogue => "Simulated Universe Event"; - public string DialogueInfo => "Simulated Universe Event Info"; + public string DialogueInfo => "Simulated Universe Event File"; public string Performance => "Performance"; - public string PerformanceInfo => "Performance Info"; + public string PerformanceInfo => "Performance File"; public string RogueChestMap => "Simulated Universe Map"; - public string RogueChestMapInfo => "Simulated Universe Map Info"; + public string RogueChestMapInfo => "Simulated Universe Map File"; public string ChessRogueRoom => "Simulated Universe DLC"; - public string ChessRogueRoomInfo => "Simulated Universe DLC Info"; + public string ChessRogueRoomInfo => "Simulated Universe DLC File"; + public string SummonUnit => "Summon Unit"; + public string SummonUnitInfo => "Summon Unit File"; + public string RogueTournRoom => "Divergent Rogue Room"; + public string RogueTournRoomInfo => "Divergent Rogue Room File"; + public string RogueMagicRoom => "Unknowable Domain Room"; + public string RogueMagicRoomInfo => "Unknowable Domain Room File"; + public string RogueDiceSurface => "Dice Surface Effect"; + public string RogueDiceSurfaceInfo => "Dice Surface Effect File"; + public string AdventureModifier => "AdventureModifier"; + public string AdventureModifierInfo => "AdventureModifier File"; public string DatabaseAccount => "Database Account"; } diff --git a/GameServer/Game/Player/PlayerInstance.cs b/GameServer/Game/Player/PlayerInstance.cs index e2eb4a81..b63b8fba 100644 --- a/GameServer/Game/Player/PlayerInstance.cs +++ b/GameServer/Game/Player/PlayerInstance.cs @@ -224,7 +224,7 @@ public class PlayerInstance(PlayerData data) await QuestManager!.AcceptQuestByCondition(); } - public T InitializeDatabase() where T : class, new() + public T InitializeDatabase() where T : BaseDatabaseDataHelper, new() { var instance = DatabaseHelper.Instance?.GetInstanceOrCreateNew(Uid); return instance!; diff --git a/GameServer/Server/Connection.cs b/GameServer/Server/Connection.cs index ec9ad437..8f01a158 100644 --- a/GameServer/Server/Connection.cs +++ b/GameServer/Server/Connection.cs @@ -1,10 +1,14 @@ using System.Buffers; using System.Net; +using System.Reflection; using EggLink.DanhengServer.GameServer.Game.Player; using EggLink.DanhengServer.GameServer.Server.Packet; using EggLink.DanhengServer.Kcp; using EggLink.DanhengServer.Kcp.KcpSharp; +using EggLink.DanhengServer.Proto; using EggLink.DanhengServer.Util; +using Google.Protobuf; +using Google.Protobuf.Reflection; namespace EggLink.DanhengServer.GameServer.Server; @@ -140,7 +144,57 @@ public class Connection(KcpConversation conversation, IPEndPoint remote) : Danhe break; } - await handler.OnHandle(this, header, payload); + try + { + await handler.OnHandle(this, header, payload); + } + catch + { + // get the packet rsp and set retCode to Retcode.RetFail + var curPacket = LogMap.GetValueOrDefault(opcode); + if (curPacket == null) return; + + var rspName = curPacket.Replace("Cs", "Sc").Replace("Req", "Rsp"); // Get the response packet name + if (rspName == curPacket) return; // do not send rsp when resp name = recv name + var rspOpcode = LogMap.FirstOrDefault(x => x.Value == rspName).Key; // Get the response opcode + + // get proto class + var typ = AppDomain.CurrentDomain.GetAssemblies() + .SingleOrDefault(assembly => assembly.GetName().Name == "DanhengProto")!.GetTypes() + .First(t => t.Name == rspName); //get the type using the packet name + var curTyp = AppDomain.CurrentDomain.GetAssemblies() + .SingleOrDefault(assembly => assembly.GetName().Name == "DanhengProto")!.GetTypes() + .First(t => t.Name == curPacket); //get the type using the packet name + + // create the response packet + if (Activator.CreateInstance(typ) is not IMessage rsp) return; + + // set the retCode to Retcode.RetFail + var retCode = typ.GetProperty("Retcode"); + retCode?.SetValue(rsp, (uint)Retcode.RetFail); + + // get the same field in req and rsp + var descriptor = + curTyp.GetProperty("Descriptor", BindingFlags.Public | BindingFlags.Static)?.GetValue( + null, null) as MessageDescriptor; // get the static property Descriptor + var reqPacket = descriptor?.Parser.ParseFrom(payload); + + foreach (var propertyInfo in curTyp.GetProperties()) + { + var prop = typ.GetProperty(propertyInfo.Name); + if (prop != null && prop.CanWrite) + { + var value = propertyInfo.GetValue(reqPacket); + if (value != null) + prop.SetValue(rsp, value); + } + } + + // send the response packet + var packet = new BasePacket((ushort)rspOpcode); + packet.SetData(rsp); + await SendPacket(packet); + } return; } diff --git a/GameServer/Server/Packet/Recv/Scene/HandlerEnterSceneCsReq.cs b/GameServer/Server/Packet/Recv/Scene/HandlerEnterSceneCsReq.cs index c2d4a40a..27aefa60 100644 --- a/GameServer/Server/Packet/Recv/Scene/HandlerEnterSceneCsReq.cs +++ b/GameServer/Server/Packet/Recv/Scene/HandlerEnterSceneCsReq.cs @@ -10,9 +10,9 @@ public class HandlerEnterSceneCsReq : Handler public override async Task OnHandle(Connection connection, byte[] header, byte[] data) { var req = EnterSceneCsReq.Parser.ParseFrom(data); - var overMapTp = await connection.Player!.EnterScene((int)req.EntryId, (int)req.TeleportId, true, - (int)req.GameStoryLineId, req.IsCloseMap); + var overMapTp = await connection.Player!.EnterScene((int)req.EntryId, (int)req.TeleportId, true, + (int)req.GameStoryLineId, req.IsCloseMap); - await connection.SendPacket(new PacketEnterSceneScRsp(overMapTp, req.IsCloseMap, (int)req.GameStoryLineId)); + await connection.SendPacket(new PacketEnterSceneScRsp(overMapTp, req.IsCloseMap, (int)req.GameStoryLineId)); } } \ No newline at end of file diff --git a/GameServer/Server/Packet/Send/Scene/PacketEnterSceneScRsp.cs b/GameServer/Server/Packet/Send/Scene/PacketEnterSceneScRsp.cs index 751d451c..dd4af825 100644 --- a/GameServer/Server/Packet/Send/Scene/PacketEnterSceneScRsp.cs +++ b/GameServer/Server/Packet/Send/Scene/PacketEnterSceneScRsp.cs @@ -15,6 +15,16 @@ public class PacketEnterSceneScRsp : BasePacket IsOverMap = overMapTp }; + SetData(proto); + } + public PacketEnterSceneScRsp(Retcode retcode) : base( + CmdIds.EnterSceneScRsp) + { + var proto = new EnterSceneScRsp + { + Retcode = (uint)retcode + }; + SetData(proto); } } \ No newline at end of file