diff --git a/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs b/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs new file mode 100644 index 0000000000..74266efb0c --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs @@ -0,0 +1,741 @@ +using BrewMonster.Network; +using BrewMonster.Scripts.Managers; +using CSNetwork.C2SCommand; +using CSNetwork.Protocols; +using CSNetwork.S2CCommand; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace BrewMonster.Common +{ + using CounterTable = Dictionary; + public class CECC2SCmdCache + { + public struct presentInfo + { + public int roleid; + public int mailid; + public int itemid; + public int index; + public int slot; + }; + + int m_idLastPickUpItem; // ID of picked up item last time + int m_idLastSelTarget; // ID of selected item last time + bool m_bGetExpProps; + bool m_bEnterSanctuary; + + CounterTable m_CounterMap = new CounterTable(); + CounterTable m_CounterMap2 = new CounterTable(); + + List m_UseItemCmdList = new List(); + List m_GetPlayerBriefInfoList = new List(); + List m_PlayerBaseInfoList = new List(); + List m_EnterSanctuaryList = new List(); + List m_PresentInfoList = new List(); + + public CECC2SCmdCache() + { + m_idLastPickUpItem = 0; + m_idLastSelTarget = 0; + m_bGetExpProps = false; + m_bEnterSanctuary = false; + InitCounters(); + } + + // Initialize counters + bool InitCounters() + { + // 'Use item' command time counter + CECCounter pCnt = new CECCounter(); + pCnt.SetPeriod(200); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.USE_ITEM)) + { + m_CounterMap[(int)CommandID.USE_ITEM] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.USE_ITEM, pCnt); + } + + // 'Pickup item' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(500); + if (m_CounterMap.ContainsKey((int)CommandID.PICKUP)) + { + m_CounterMap[(int)CommandID.PICKUP] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.PICKUP, pCnt); + } + + // 'Select target' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(250); + if (m_CounterMap.ContainsKey((int)CommandID.SELECT_TARGET)) + { + m_CounterMap[(int)CommandID.SELECT_TARGET] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.SELECT_TARGET, pCnt); + } + + // 'Get extend properties' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(2000); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.GET_EXT_PROP)) + { + m_CounterMap[(int)CommandID.GET_EXT_PROP] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.GET_EXT_PROP, pCnt); + } + + // 'Cast skill' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(200); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.CAST_SKILL)) + { + m_CounterMap[(int)CommandID.CAST_SKILL] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.CAST_SKILL, pCnt); + } + + // 'Revive ask' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(500); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.REVIVE_VILLAGE)) + { + m_CounterMap[(int)CommandID.REVIVE_VILLAGE] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.REVIVE_VILLAGE, pCnt); + } + + // 'Enter sanctuary' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(2000); + if (m_CounterMap.ContainsKey((int)CommandID.ENTER_SANCTUARY)) + { + m_CounterMap[(int)CommandID.ENTER_SANCTUARY] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.ENTER_SANCTUARY, pCnt); + } + + // 'Enter instance' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(2000); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.ENTER_INSTANCE)) + { + m_CounterMap[(int)CommandID.ENTER_INSTANCE] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.ENTER_INSTANCE, pCnt); + } + + // 'Rush fly' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(500); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.ACTIVE_RUSH_FLY)) + { + m_CounterMap[(int)CommandID.ACTIVE_RUSH_FLY] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.ACTIVE_RUSH_FLY, pCnt); + } + + // 'Cancel action' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(200); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.CANCEL_ACTION)) + { + m_CounterMap[(int)CommandID.CANCEL_ACTION] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.CANCEL_ACTION, pCnt); + } + + // 'Control pet' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(400); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.PET_CTRL)) + { + m_CounterMap[(int)CommandID.PET_CTRL] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.PET_CTRL, pCnt); + } + + // 'Hello' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(2000); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.SEVNPC_HELLO)) + { + m_CounterMap[(int)CommandID.SEVNPC_HELLO] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.SEVNPC_HELLO, pCnt); + } + + // 'Present' command time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(1000); + pCnt.Reset(true); + if (m_CounterMap.ContainsKey((int)CommandID.PLAYER_GIVE_PRESENT)) + { + m_CounterMap[(int)CommandID.PLAYER_GIVE_PRESENT] = pCnt; + } + else + { + m_CounterMap.Add((int)CommandID.PLAYER_GIVE_PRESENT, pCnt); + } + + // 'GetPlayerBriefInfo' time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(2000); + pCnt.Reset(true); + if (m_CounterMap2.ContainsKey((int)ProtocolType.PROTOCOL_GETPLAYERBRIEFINFO)) + { + m_CounterMap2[(int)ProtocolType.PROTOCOL_GETPLAYERBRIEFINFO] = pCnt; + } + else + { + m_CounterMap2.Add((int)ProtocolType.PROTOCOL_GETPLAYERBRIEFINFO, pCnt); + } + + // 'PlayerBaseInfo' time counter + pCnt = new CECCounter(); + pCnt.SetPeriod(2000); + pCnt.Reset(true); + if (m_CounterMap2.ContainsKey((int)ProtocolType.PROTOCOL_PLAYERBASEINFO)) + { + m_CounterMap2[(int)ProtocolType.PROTOCOL_PLAYERBASEINFO] = pCnt; + } + else + { + m_CounterMap2.Add((int)ProtocolType.PROTOCOL_PLAYERBASEINFO, pCnt); + } + + pCnt = new CECCounter(); + pCnt.SetPeriod(10 * 1000); + pCnt.Reset(true); + if (m_CounterMap2.ContainsKey((int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETMAP)) + { + m_CounterMap2[(int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETMAP] = pCnt; + } + else + { + m_CounterMap2.Add((int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETMAP, pCnt); + } + + pCnt = new CECCounter(); + pCnt.SetPeriod(10 * 1000); + pCnt.Reset(true); + if (m_CounterMap2.ContainsKey((int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETRECORD)) + { + m_CounterMap2[(int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETRECORD] = pCnt; + } + else + { + m_CounterMap2.Add((int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETRECORD, pCnt); + } + return true; + } + + // Remove all un-sent commands in cache + public void RemoveAllCmds() + { + m_UseItemCmdList.Clear(); + + // 重置 C2S 命令计时器 + m_CounterMap[(int)CommandID.USE_ITEM].Reset(true); + + m_EnterSanctuaryList.Clear(); + m_CounterMap[(int)CommandID.ENTER_SANCTUARY].Reset(true); + m_bEnterSanctuary = false; + + m_PresentInfoList.Clear(); + m_CounterMap[(int)CommandID.PLAYER_GIVE_PRESENT].Reset(true); + + // 重置协议计时器 + m_GetPlayerBriefInfoList.Clear(); + m_CounterMap2[(int)ProtocolType.PROTOCOL_GETPLAYERBRIEFINFO].Reset(true); + + m_PlayerBaseInfoList.Clear(); + m_CounterMap2[(int)ProtocolType.PROTOCOL_PLAYERBASEINFO].Reset(true); + + m_CounterMap2[(int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETMAP].Reset(true); + m_CounterMap2[(int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETRECORD].Reset(true); + } + + // Tick routine + public bool Tick(float dwDeltaTime) + { + float dwRealTime = Time.realtimeSinceStartup; + + foreach (var item in m_CounterMap) + { + item.Value.IncCounter(dwRealTime); + } + foreach (var item in m_CounterMap2) + { + item.Value.IncCounter(dwRealTime); + } + + // Try to send 'use item' command in cache + SendCachedCmdUseItem(); + + // Try to send 'get extend properties' command + SendCachedCmdGetExtProp(); + + // Try to send 'GetPlayerBriefInfo' + SendCachedGetPlayerBriefInfo(); + // Try to send 'PlayerBaseInfo' + SendCachedPlayerBaseInfo(); + // Try to send 'PresentInfo' + SendCachedPresentInfo(); + + if (m_bEnterSanctuary) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.ENTER_SANCTUARY]; + if (pCnt.IsFull()) + { + for (int i = 0; i < m_EnterSanctuaryList.Count; i++) + { + int id = m_EnterSanctuaryList[i]; + UnityGameSession.Instance.GameSession.c2s_SendCmdEnterSanctuary(id); + } + + m_EnterSanctuaryList.Clear(); + m_bEnterSanctuary = false; + } + } + + return true; + } + + // Send 'use item' command + void SendCachedCmdUseItem() + { + CECCounter pCnt = m_CounterMap[(int)CommandID.USE_ITEM]; + if (!pCnt.IsFull() || m_UseItemCmdList.Count == 0) + return; + + pCnt.Reset(); + + // Send the first item + cmd_use_item Cmd = m_UseItemCmdList[0]; + UnityGameSession.Instance.GameSession.c2s_SendCmdUseItem(Cmd.where, (byte)Cmd.index, Cmd.item_id, Cmd.byCount); + m_UseItemCmdList.Clear(); + } + + // Send cached 'get extend properties' command + void SendCachedCmdGetExtProp() + { + CECCounter pCnt = m_CounterMap[(int)CommandID.GET_EXT_PROP]; + if (!m_bGetExpProps || !pCnt.IsFull()) + return; + + pCnt.Reset(); + + m_bGetExpProps = false; + UnityGameSession.Instance.GameSession.c2s_SendCmdGetExtProps(); + } + + // Send cached 'GetPlayerBriefInfo' command + void SendCachedGetPlayerBriefInfo() + { + CECCounter pCnt = m_CounterMap2[(int)ProtocolType.PROTOCOL_GETPLAYERBRIEFINFO]; + if (!pCnt.IsFull() || m_GetPlayerBriefInfoList.Count == 0) + return; + + pCnt.Reset(); + + getplayerbriefinfo p = m_GetPlayerBriefInfoList[0]; + if (p.Playerlist.Count != 0) + { + // 获取第一个玩家id并向服务器发送协议 + getplayerbriefinfo temp = p; + temp.Playerlist.Clear(); + temp.Playerlist.Add(p.Playerlist[0]); + UnityGameSession.Instance.GameSession.SendProtocol(temp); + + // 从列表中清除 + p.Playerlist.Remove(p.Playerlist[0]); + } + + if (p.Playerlist.Count == 0) + m_GetPlayerBriefInfoList.Remove(p); + } + + // Remove the cached 'PlayerBaseInfo' request + public void RemovePlayerBaseInfo(int iRoleID) + { + int pos = m_PlayerBaseInfoList.Find(x => x == iRoleID); + if (pos != 0) + { + m_PlayerBaseInfoList.RemoveAt(pos); + } + } + + // Send cached 'PlayerBaseInfo' protocol + void SendCachedPlayerBaseInfo() + { + CECCounter pCnt = m_CounterMap2[(int)ProtocolType.PROTOCOL_PLAYERBASEINFO]; + if (!pCnt.IsFull() || m_PlayerBaseInfoList.Count == 0) + return; + + pCnt.Reset(); + + List aRoles = new List(); + for (int i = 0; i < m_PlayerBaseInfoList.Count; i++) + { + aRoles.Add(m_PlayerBaseInfoList[i]); + } + + UnityGameSession.Instance.GameSession.GetRoleBaseInfo(aRoles.Count, aRoles); + } + + void SendCachedPresentInfo() + { + CECCounter pCnt = m_CounterMap[(int)CommandID.PLAYER_GIVE_PRESENT]; + if (!pCnt.IsFull() || m_PresentInfoList.Count == 0) + return; + + pCnt.Reset(); + + presentInfo info = m_PresentInfoList[0]; + UnityGameSession.Instance.GameSession.c2s_SendCmdGivePresent(info.roleid, info.mailid, info.itemid, info.index, info.slot); + m_PresentInfoList.Remove(info); + } + + // Send commands ... + public void SendCmdUseItem(byte byPackage, byte bySlot, int tid, byte byCount) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.USE_ITEM]; + if (m_UseItemCmdList.Count == 0 && pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdUseItem(byPackage, bySlot, tid, byCount); + return; + } + + cmd_use_item Cmd = new cmd_use_item(); + if (m_UseItemCmdList.Count == 0) + { + Cmd.where = byPackage; + Cmd.index = bySlot; + Cmd.item_id = tid; + Cmd.byCount = byCount; + m_UseItemCmdList.Add(Cmd); + return; + } + int idx = -1; + for (int i = 0; i < m_UseItemCmdList.Count; i++) + { + Cmd = m_UseItemCmdList[i]; + + if (Cmd.where == byPackage && Cmd.index == bySlot) + { + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + EC_Inventory pPack = pHost.GetPack(byPackage); + if (pPack == null) return; + EC_IvtrItem pItem = pPack.GetItem(bySlot); + if (pItem == null || !pItem.CheckUseCondition()) + return; + + int iTotal = Cmd.byCount + byCount; + if (iTotal >= pItem.GetCount()) + iTotal = pItem.GetCount(); + + AAssist.a_ClampRoof(ref iTotal, 255); + + Cmd.byCount = (byte)iTotal; + break; + } + idx++; + } + if (idx < 0) + { + Cmd = new cmd_use_item(); + Cmd.where = byPackage; + Cmd.index = bySlot; + Cmd.item_id = tid; + Cmd.byCount = byCount; + m_UseItemCmdList.Add(Cmd); + } + + // Try to send command in cache + SendCachedCmdUseItem(); + } + /* Send 'pick up item' command + + The strategy to send 'pick up item' command: + + 1. if the item is just the one which was to be picked up, check whether + enough time has passed since last command was sent. If true, send + command again, otherwise just throw command + 2. if the item isn't the one which was to be picked up, send command + directly. + */ + public void SendCmdPickUp(int idItem, int tid) + { + //StackChecker::ACTrace(5); + + CECCounter pCnt = m_CounterMap[(int)CommandID.PICKUP]; + if (m_idLastPickUpItem != idItem || pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.RequestPickupItem(idItem, tid); + m_idLastPickUpItem = idItem; + } + } + + // Send 'select target' command + // The strategy to send 'select target' command is like as SendCmdPickUp() + public void SendCmdSelectTarget(int id) + { + // Set selection first before server returns, so as to reduce the player waiting time. + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + pHost.SetSelectedTarget(id); + + CECCounter pCnt = m_CounterMap[(int)CommandID.SELECT_TARGET]; + if (m_idLastSelTarget != id || pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdSelectTarget(id); + m_idLastSelTarget = id; + } + } + + // Send 'get extend properties' command + public void SendCmdExtProps() + { + // If there is already a request waiting, return directly + if (m_bGetExpProps) + return; + + CECCounter pCnt = m_CounterMap[(int)CommandID.GET_EXT_PROP]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdGetExtProps(); + return; + } + + m_bGetExpProps = true; + } + + // Send 'revive ask' command + public void SendCmdReviveVillage(int param = 0) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.REVIVE_VILLAGE]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdReviveVillage(param); + } + } + + // Send 'revive ask' command + public void SendCmdReviveItem(int param = 0) + { + // This command merge time counter with REVIVE_VILLAGE + CECCounter pCnt = m_CounterMap[(int)CommandID.REVIVE_VILLAGE]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdReviveItem(param); + } + } + + // Send 'cast skill' command + public void SendCmdCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.CAST_SKILL]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdCastSkill(idSkill, byPVPMask, iNumTarget, aTargets); + } + } + + // Send 'cast instant skill' command + public void SendCmdCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.CAST_SKILL]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdCastInstantSkill(idSkill, byPVPMask, iNumTarget, aTargets); + } + } + + // Send 'enter sanctuary' command + void SendCmdEnterSanctuary(int id) + { + for (int i = 0; i < m_EnterSanctuaryList.Count; i++) + { + if (m_EnterSanctuaryList[i] == id) return; + } + + // Delay this command some time + m_bEnterSanctuary = true; + CECCounter pCnt = m_CounterMap[(int)CommandID.ENTER_SANCTUARY]; + pCnt.Reset(); + m_EnterSanctuaryList.Add(id); + } + + // Send 'enter instance' commnad + void SendCmdEnterInstance(int iTransIdx, int idInst) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.ENTER_INSTANCE]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdEnterInstance(iTransIdx, idInst); + } + } + + void SendCmdActiveRushFly(bool bActive) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.ACTIVE_RUSH_FLY]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdActiveRushFly(bActive); + } + } + + public void SendCmdCancelAction() + { + CECCounter pCnt = m_CounterMap[(int)CommandID.CANCEL_ACTION]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdCancelAction(); + } + } + void SendCmdPetCtrl(int idTarget, int cmd, byte[] pParamBuf, int iParamLen) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.PET_CTRL]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdPetCtrl(idTarget, cmd, pParamBuf, iParamLen); + } + } + + public void SendCmdNPCSevHello(int nid) + { + CECCounter pCnt = m_CounterMap[(int)CommandID.SEVNPC_HELLO]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + UnityGameSession.Instance.GameSession.c2s_SendCmdNPCSevHello(nid); + } + } + + void SendCmdFactionPVPQueryInfo(int idFaction) + { + int piMax = -1; + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + if (pHost.GetCoolTime((int)CSNetwork.GPDataType.CoolTimeIndex.GP_CT_QUERY_MAFIA_PVP_INFO, ref piMax) == 0) + { + UnityGameSession.Instance.GameSession.c2s_SendCmdQueryFactionPVPInfo(idFaction); + } + } + + // Send protocols ... + void SendGetPlayerBriefInfo(int iNumPlayer, int[] aIDs, int iReason) + { + if (iNumPlayer == 0 || aIDs == null || aIDs.Length == 0) + return; + + // 1.合并添加到列表 + getplayerbriefinfo p = new getplayerbriefinfo(); + p.Roleid = EC_Game.GetGameRun().GetHostPlayer().GetCharacterID(); + p.Reason = (byte)iReason; + for (int i = 0; i < iNumPlayer; ++i) + { + if (aIDs[i] != 0) + p.Playerlist.Add(aIDs[i]); + } + if (p.Playerlist.Count > 0) + m_GetPlayerBriefInfoList.Add(p); + + // 2.检查并发送 + SendCachedGetPlayerBriefInfo(); + } + + void SendGetPlayerBaseInfo(int iNumRole, int[] aRoleIDs) + { + if (iNumRole == 0 || aRoleIDs == null || aRoleIDs.Length == 0) + return; + + for (int i = 0; i < iNumRole; i++) + { + if (aRoleIDs[i] != 0) + m_PlayerBaseInfoList.Add(aRoleIDs[i]); + } + + SendCachedPlayerBaseInfo(); + } + + void SendGivePresentProtocol(int roleid, int mailid, int itemid, int index, int slot) + { + presentInfo info = new presentInfo(); + info.roleid = roleid; + info.mailid = mailid; + info.itemid = itemid; + info.index = index; + info.slot = slot; + m_PresentInfoList.Add(info); + } + void SendFactionPVPGetMap() + { + CECCounter pCnt = m_CounterMap2[(int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETMAP]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + factionresourcebattlegetmap p = new factionresourcebattlegetmap(); + p.Roleid = EC_Game.GetGameRun().GetHostPlayer().GetCharacterID(); + UnityGameSession.Instance.GameSession.SendProtocol(p); + } + } + void SendFactionPVPGetRank() + { + CECCounter pCnt = m_CounterMap2[(int)ProtocolType.PROTOCOL_FACTIONRESOURCEBATTLEGETRECORD]; + if (pCnt.IsFull()) + { + pCnt.Reset(); + factionresourcebattlegetrecord p = new factionresourcebattlegetrecord(); + p.Roleid = EC_Game.GetGameRun().GetHostPlayer().GetCharacterID(); + UnityGameSession.Instance.GameSession.SendProtocol(p); + } + } + } +} diff --git a/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs.meta b/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs.meta new file mode 100644 index 0000000000..8a09afb3b8 --- /dev/null +++ b/Assets/PerfectWorld/Scripts/Common/EC_C2SCmdCache.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: a442b391d3e801346ac42d47da8c93b2 \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs index eb87632482..8324928321 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_ManPlayer.cs @@ -509,6 +509,7 @@ namespace PerfectWorld.Scripts.Managers if (pHost != null && pHost.GetSelectedTarget() == cid) pHost.SelectTarget(0); + UnityGameSession.Instance.GetC2SCmdCache().RemovePlayerBaseInfo(cid); // Release player resource if (pPlayer != null) { @@ -522,49 +523,6 @@ namespace PerfectWorld.Scripts.Managers } } - //private cmd_object_move ConvertToStruct(byte[] bytes) - //{ - // if (bytes.Length < Marshal.SizeOf()) - // { - // return default; - // } - - // cmd_object_move result = new cmd_object_move(); - // int preLenghtData = 0; - // int lenghtDataType = Marshal.SizeOf(); - // byte[] arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.id = BitConverter.ToInt32(arrByteData); - - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.dest_X = BitConverter.ToSingle(arrByteData); - - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.dest_Y = BitConverter.ToSingle(arrByteData); - - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.dest_Z = BitConverter.ToSingle(arrByteData); - - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.use_time = BitConverter.ToUInt16(arrByteData); - - // preLenghtData += lenghtDataType; - // lenghtDataType = Marshal.SizeOf(); - // arrByteData = GetBytes(bytes, lenghtDataType, preLenghtData); - // result.sSpeed = BitConverter.ToInt16(arrByteData); - - // preLenghtData += lenghtDataType; - // result.move_mode = bytes[preLenghtData + 1]; - // return result; - //} - private byte[] GetBytes(byte[] bytes, int length, int index) { byte[] arrByteData = new byte[length]; @@ -596,7 +554,7 @@ namespace PerfectWorld.Scripts.Managers case long value when value == EC_MsgDef.MSG_PM_PLAYERBASEINFO: cid = (int)((playerbaseinfo_re)Msg.dwParam1).Player.id; // Xo谩 kh峄廼 cache - //g_pGame.GetGameSession().GetC2SCmdCache().RemovePlayerBaseInfo(cid); + UnityGameSession.Instance.GetC2SCmdCache().RemovePlayerBaseInfo(cid); break; /*case long value when value == EC_MsgDef.MSG_PM_PLAYERCUSTOM: diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs index bb517a689b..d44e949500 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommand.cs @@ -1501,6 +1501,75 @@ namespace CSNetwork.S2CCommand public ushort index; public int item_id; }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_player_give_present + { + public int roleid; //脭霉脫猫露脭脧贸碌脛roleid + public int mail_id; //脣梅脠隆脦茂脝路脫脢录镁碌脛脣梅脪媒拢卢脙禄脫脨碌脛禄掳脦陋-1 + public int goods_id; //脭霉脫猫脦茂脝路碌脛id + public int goods_index; //脭霉脫猫脦茂脝路脭脷脡脤鲁脟脰脨碌脛脣梅脪媒 + public int goods_slot; //脭霉脫猫脦茂脝路碌脛脧煤脢脹脨脜脧垄脣梅脪媒 + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_enter_sanctuary + { + public int id; // self id or pet id. + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_enter_instance + { + public int iTransIndex; + public int idInst; + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_active_rush_fly + { + public int is_active; + }; + + /* Categories of pet_cmd: + pet_cmd = 1 Attack the specified target, requires a valid target. + Parameter: char, pvp mask for attack protection status. + + pet_cmd = 2 Change pet follow behavior, target is ignored. + Parameter: int + 0 = follow the player (default) + 1 = stay at current position + When this command is issued, it attempts to interrupt the pet鈥檚 current action + and perform the newly assigned follow behavior. + + pet_cmd = 3 Change pet combat behavior, target is ignored. + Parameter: int + 0 = Defensive mode 鈥 counterattack when hit, and counterattack when the owner is hit + (currently not implemented) + 1 = Aggressive mode 鈥 automatically attacks enemies within range + 2 = Passive mode 鈥 will not react unless commanded by the player + + pet_cmd = 4 Request pet to use a skill; target represents the skill鈥檚 target. + Parameter: int 鈥 ID of the skill to use + Parameter: char 鈥 pvp mask for attack protection status + + pet_cmd = 5 Request pet to auto-cast a skill, target ignored. + Parameter: int 鈥 ID of the skill to auto-cast + if the skill ID is 0, auto-casting is disabled. + */ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_pet_ctrl + { + public int target; // The target of the operation. If no target is required, set the command鈥檚 target to 0. + public int pet_cmd; // Control commands for the pet + //char buf[]; // Parameters of the pet control commands + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct cmd_query_faction_pvp_info + { + public int faction_id; + }; } // Player and NPC state \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs index d9fa291d2d..705cfde58e 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/C2SCommand/C2SCommandFactory.cs @@ -268,29 +268,7 @@ namespace CSNetwork.C2SCommand }; return SerializeCommand(CommandID.STOP_MOVE, cmd); } - public static Octets CreatePlayerCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int aTargets) - { - var cmd = new CMD_CastSkill - { - skillId = idSkill, - pvpMask = byPVPMask, - targetCount = (byte)iNumTarget, - targets = null - }; - if (iNumTarget > 0) - { - if (iNumTarget > 0) - { - cmd.targets = new int[iNumTarget]; - cmd.targets[0] = aTargets; - } - } - - var cmdBuf = SerializeCommand(CommandID.CAST_SKILL, cmd); - return cmdBuf; - } - - public static Octets CreatePlayerCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int aTargets) + public static Octets CreatePlayerCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) { var cmd = new CMD_CastSkill { @@ -302,7 +280,32 @@ namespace CSNetwork.C2SCommand if (iNumTarget > 0) { cmd.targets = new int[iNumTarget]; - cmd.targets[0] = aTargets; + for (int i = 0; i < iNumTarget; i++) + { + cmd.targets[i] = aTargets[i]; + } + } + + var cmdBuf = SerializeCommand(CommandID.CAST_SKILL, cmd); + return cmdBuf; + } + + public static Octets CreatePlayerCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) + { + var cmd = new CMD_CastSkill + { + skillId = idSkill, + pvpMask = byPVPMask, + targetCount = (byte)iNumTarget, + targets = null + }; + if (iNumTarget > 0) + { + cmd.targets = new int[iNumTarget]; + for(int i = 0; i < iNumTarget; i++) + { + cmd.targets[i] = aTargets[i]; + } } var cmdBuf = SerializeCommand(CommandID.CAST_INSTANT_SKILL, cmd); @@ -821,5 +824,55 @@ namespace CSNetwork.C2SCommand pCmd.byCount = byCount; return SerializeCommand(CommandID.USE_ITEM, pCmd); } + + public static Octets CreateGivePresentCmd(int roleid, int mail_id, int goods_id, int goods_index, int goods_slot) + { + cmd_player_give_present pCmd = new cmd_player_give_present(); + pCmd.roleid = roleid; + pCmd.mail_id = mail_id; + pCmd.goods_id = goods_id; + pCmd.goods_index = goods_index; + pCmd.goods_slot = goods_slot; + return SerializeCommand(CommandID.PLAYER_GIVE_PRESENT, pCmd); + } + + public static Octets CreateEnterSanctuaryCmd(int id) + { + cmd_enter_sanctuary pCmd = new cmd_enter_sanctuary(); + pCmd.id = id; + return SerializeCommand(CommandID.ENTER_SANCTUARY, pCmd); + } + + public static Octets CreateEnterInstanceCmd(int iTransIdx, int idInst) + { + cmd_enter_instance pCmd = new cmd_enter_instance(); + pCmd.iTransIndex = iTransIdx; + pCmd.idInst = idInst; + return SerializeCommand(CommandID.ENTER_INSTANCE, pCmd); + } + + public static Octets CreateActiveRushFlyCmd(bool bActive) + { + cmd_active_rush_fly pCmd = new cmd_active_rush_fly(); + pCmd.is_active = bActive ? 1 : 0; + return SerializeCommand(CommandID.ACTIVE_RUSH_FLY, pCmd); + } + + public static Octets CreatePetCtrlCmd(int idTarget, int cmd, byte[] pParamBuf, int iParamLen) + { + cmd_pet_ctrl pCmd = new cmd_pet_ctrl(); + pCmd.target = idTarget; + pCmd.pet_cmd = cmd; + var tempOctets = SerializeCommand(CommandID.PET_CTRL, pCmd); + tempOctets.Insert(tempOctets.Size + 1, pParamBuf); + return tempOctets; + } + + public static Octets CreateQueryFactionPVPInfo(int faction_id) + { + cmd_query_faction_pvp_info pCmd = new cmd_query_faction_pvp_info(); + pCmd.faction_id = faction_id; + return SerializeCommand(CommandID.QUERY_MAFIA_PVP_INFO, pCmd); + } } } diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs index 06c17191f5..adef4669ff 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs @@ -1,1475 +1,1521 @@ -using BrewMonster; -using BrewMonster.Managers; -using BrewMonster.Network; -using BrewMonster.Scripts.Skills; -using BrewMonster.UI; -using CSNetwork.C2SCommand; -using CSNetwork.GPDataType; -using CSNetwork.Protocols; -using CSNetwork.Protocols.RPCData; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using UnityEngine; -using CommandID = CSNetwork.GPDataType.CommandID; - -namespace CSNetwork -{ - public class GameSession : IDisposable - { - private static IPrefixedLogger - _logger = LoggerFactory.GetLogger(nameof(GameSession)); // Get class-specific logger - - private NetworkManager _networkManager; - private string _host; - private int _port; - private string _username; - private string _password; - private int _currentUserId = -1; // To store the UserID after successful login - private int m_iCharID; - private int m_idLastSelTarget = 0; // ID of selected item last time - - CECStringTab m_ErrorMsgs; - - // State management for async operations and callbacks - private Action _loginCallback; - private Action> _roleListCallback; - private List _accumulatedRoles; - private Action _selectRoleCallback; - private RoleInfo _selectedRole; - public bool IsConnected => _networkManager?.IsConnected ?? false; - public static SynchronizationContext Context; - -#if UNITY_EDITOR - public bool isDebug; - public bool IsDebug - { - get => isDebug; - set => isDebug = value; - } -#endif - - - public GameSession() - { - _networkManager = new NetworkManager(); - _networkManager.ProtocolReceived += OnProtocolReceived; - _networkManager.ErrorOccurred += OnErrorOccurred; - _networkManager.Disconnected += OnDisconnected; - } - - public void SetLogPath(string path) - { - LoggerFactory.SetFileLoggerImplementation(new FileLogger()); - _logger = LoggerFactory.GetCustomLogger(path, nameof(GameSession) + GetHashCode(), LoggerType.File); - _networkManager.SetLogPath(path); - } - - /// - /// Connects to the game server asynchronously. - /// - /// Server hostname or IP address. - /// Server port. - /// Task representing the asynchronous connect operation. Check IsConnected property or handle Disconnected event for status. - public async Task ConnectAsync(string host, int port) - { - if (IsConnected) - { - _logger.Log(LogType.Warning, "ConnectAsync called but already connected."); - return; - } - - _host = host; - _port = port; - _logger.Log(LogType.Info, $"Attempting to connect to {_host}:{_port}..."); - try - { - await _networkManager.ConnectAsync(_host, _port); - if (IsConnected) - { - _logger.Log(LogType.Info, "Connection established."); - } - else - { - _logger.Log(LogType.Warning, - "Connection failed after ConnectAsync completed (check NetworkManager logs/events)."); - } - } - catch (Exception ex) - { - _logger.Log(LogType.Error, $"Connection exception: {ex.Message}"); - _logger.LogException(ex); - OnDisconnected(); - } - } - - - public void Disconnect() - { - _networkManager.Disconnect(); - } - - /// - /// Initiates the login process asynchronously. - /// - /// Account username. - /// Account password. - /// Action invoked with true on successful login (OnlineAnnounce received), false otherwise. - public void LoginAsync(string username, string password, Action callback) - { - if (!IsConnected) - { - _logger.Log(LogType.Warning, "LoginAsync called but not connected."); - callback?.Invoke(false); - return; - } - - if (_loginCallback != null) - { - _logger.Log(LogType.Warning, "LoginAsync called while another login is already in progress."); - callback?.Invoke(false); - return; - } - - _username = username; - _password = password; - _loginCallback = callback; - _currentUserId = -1; // Reset user ID - - _logger.Log(LogType.Info, $"Initiating login for user '{_username}'..."); - } - - /// - /// Initiates fetching the role list asynchronously. Requires successful login. - /// - /// Action invoked with the complete list of roles, or null/empty list on failure. - public void GetRoleListAsync(Action> callback) - { - if (!IsConnected) - { - _logger.Log(LogType.Warning, "GetRoleListAsync called but not connected."); - callback?.Invoke(null); - return; - } - - if (_currentUserId == -1) - { - _logger.Log(LogType.Warning, "GetRoleListAsync called but not logged in."); - callback?.Invoke(null); - return; - } - - if (_roleListCallback != null) - { - _logger.Log(LogType.Warning, - "GetRoleListAsync called while another role list retrieval is already in progress."); - callback?.Invoke(null); - return; - } - - _roleListCallback = callback; - _accumulatedRoles = new List(); - _logger.Log(LogType.Info, "Requesting role list..."); - RequestRoleListInternal(); - } - - public RoleInfo GetRoleInfo() - { - return _selectedRole; - } - - public void SelectRoleAsync(RoleInfo role, Action callback) - { - _selectedRole = role; - _selectRoleCallback = callback; - SetCharacterID(role.roleid); - SendProtocol(new selectrole() - { - Roleid = role.roleid, - Flag = 0 - }); - } - - public void EnterWorldAsync(RoleInfo role, Action callback) - { - SendProtocol(new enterworld() - { - Roleid = _selectedRole.roleid, - Provider_link_id = 0, - }, callback); - } - - public void RequestDropIvtrItem(byte index, int amount) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.CreateDropIvtrItem(index, amount); - SendProtocol(gamedatasendRequest); - } - - public void RequestDropEquipItem(byte index) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.CreateDropEquipItem(index); - SendProtocol(gamedatasendRequest); - } - - public void RequestPickupItem(int idItem, int tid) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.CreatePickupItem(idItem, tid); - SendProtocol(gamedatasendRequest); - } - - public void c2s_SendCmdGetIvtrDetailData(byte byPackage, Action callback) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdGetIvtrDetailData(byPackage); - SendProtocol(gamedatasendRequest, callback); - } - - public void c2s_SendCmdQueryCashInfo() - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdQueryCashInfo(); - SendProtocol(gamedatasendRequest); - } - - public void c2s_SendCmdOpenFashionTrash(string password) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdOpenFashionTrash(password); - SendProtocol(gamedatasendRequest); - } - - public void c2s_SendCmdEquipItem(byte iIvtrIdx, byte iEquipIdx, Action callback) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdEquipItem(iIvtrIdx, iEquipIdx); - SendProtocol(gamedatasendRequest, callback); - } - - public void c2s_SendCmdReviveVillage(int param = 0) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); - SendProtocol(gamedatasendRequest); - } - public void c2s_SendCmdReviveItem(int param = 0) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); - SendProtocol(gamedatasendRequest); - } - public void RequestReviveByPlayer(int param = 0) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); - SendProtocol(gamedatasendRequest); - } - - - public void c2s_SendCmdMallShopping(uint count, CMD_MallShopping.goods[] goodsArray) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.CreateGetMallShopping(count, goodsArray); - SendProtocol(gamedatasendRequest); - } - public void c2s_SendCmdGatherMaterial(int idMatter, int iToolPack, int idToolIndex, int idTool, int idTask) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdGatherMaterial(idMatter, iToolPack, idToolIndex, idTool, idTask); - SendProtocol(gamedatasendRequest); - } - - public void RequestOwnItemInfoAsync( - byte byPackage, - byte bySlot, - int type, - int expire_date, - int state, - uint count, - ushort crc, - ushort content_length, - byte[] content, - Action callback) - { - gamedatasend gamedatasendRequest = new gamedatasend(); - gamedatasendRequest.Data = C2SCommandFactory.CreateOwnItemInfo(byPackage, bySlot, type, expire_date, state, - count, crc, content_length, content); - SendProtocol(gamedatasendRequest, callback); - } - - // --- Protocol Sending --- - public void SendProtocol(Protocol protocol, Action complete = null) - { - if (IsConnected) - { - _logger.Log(LogType.Debug, - $"Sending protocol: {protocol.GetType().Name} (Detail: {protocol.ToString})"); - _networkManager.Send(protocol); - complete?.Invoke(); - } - else - { - _logger.Log(LogType.Warning, $"Cannot send protocol ({protocol.GetType().Name}), not connected."); - } - } - - // --- Event Handlers (from NetworkManager) --- - - private void OnProtocolReceived(Protocol protocol) - { - _logger.Log(LogType.Debug, $"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})"); - if (protocol is null) - return; - - - // Route protocol to appropriate handler - switch (protocol.GetPType()) - { - case ProtocolType.PROTOCOL_CHALLENGE: - HandleChallenge((challenge)protocol); - break; - case ProtocolType.PROTOCOL_KEYEXCHANGE: - HandleKeyExchange((KeyExchange)protocol); - break; - case ProtocolType.PROTOCOL_ONLINEANNOUNCE: - HandleOnlineAnnounce((onlineannounce)protocol); - break; - case ProtocolType.PROTOCOL_ROLELIST_RE: - HandleRoleListResponse((RoleListResponse)protocol); - break; - // Add cases for other protocols GameSession might need to handle - case ProtocolType.PROTOCOL_SELECTROLE_RE: - HandleSelectRoleResponse((SelectRole_Re)protocol); - //_networkManager.IgnoreBytes = 2; - break; - case ProtocolType.PROTOCOL_S2CGAMEDATASEND: - case ProtocolType.PROTOCOL_GAMEDATASEND: - HandleServerDataSend((gamedatasend)protocol); - break; - case ProtocolType.PROTOCOL_CHATMESSAGE: - _logger.Log(LogType.Warning, $"HoangDev :ProtocolType.PROTOCOL_CHATMESSAGE {protocol.GetPType()}"); - OnPrtcChatMessage(protocol, false); - break; - case ProtocolType.PROTOCOL_PLAYERBASEINFO_RE: - OnPrtcPlayerBaseInfoRe(protocol); - break; - case ProtocolType.PROTOCOL_GETUICONFIG_RE: OnPrtcGetConfigRe(protocol); break; - - case ProtocolType.PROTOCOL_AUTOTEAMSETGOAL_RE: - { - // CECAutoTeam pAutoTeam = CECGameRun.Instance.GetHostPlayer().GetAutoTeam(); - // if( pAutoTeam !=null) - // pAutoTeam.OnPrtcAutoTeamSetGoalRe((AutoTeamSetGoal_Re)protocol); - } - break; - - default: - _logger.Log(LogType.Warning, $"Received unhandled protocol type: {protocol.GetPType()}"); - break; - } - } - - private void HandleServerDataSend(gamedatasend protocol) - { - int lenghtHeader = Marshal.SizeOf(); - var pDataBuf = new byte[protocol.Data.ByteArray.Length - lenghtHeader]; - var byteArrHeader = new byte[lenghtHeader]; - long dwDataSize = protocol.Data.Size; - - if (dwDataSize < Marshal.SizeOf()) - { - _logger.Error($"### GameDataSend: size invalid {dwDataSize}"); - return; - } - - dwDataSize -= Marshal.SizeOf(); // subtract the header size (ushort) - for (int i = 0; i < protocol.Data.ByteArray.Length; i++) - { - if (i < lenghtHeader) - { - byteArrHeader[i] = protocol.Data.ByteArray[i]; - } - else - { - pDataBuf[i - lenghtHeader] = protocol.Data.ByteArray[i]; - } - } - - var pCmdHeader = BitConverter.ToUInt16(byteArrHeader); - //sss -#if UNITY_EDITOR - if (isDebug) - { - BMLogger.LogError($"### GameDataSend: CMDID {pCmdHeader}"); - } -#endif - int iHostID = _selectedRole.roleid; - switch (pCmdHeader) - { - case CommandID.PLAYER_INFO_2: - case CommandID.PLAYER_INFO_3: - case CommandID.PLAYER_INFO_4: - case CommandID.PLAYER_INFO_2_LIST: - case CommandID.PLAYER_INFO_3_LIST: - case CommandID.PLAYER_INFO_23_LIST: - - break; - - case CommandID.PLAYER_INFO_1: - case CommandID.PLAYER_ENTER_WORLD: - case CommandID.PLAYER_ENTER_SLICE: - case CommandID.PLAYER_INFO_1_LIST: - case CommandID.PLAYER_INFO_00: - case CommandID.SELF_INFO_1: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERINFO, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, - pCmdHeader, iHostID); - break; - case CommandID.OBJECT_MOVE: - int lenghtDataType = Marshal.SizeOf(); - byte[] arrByteData = GetBytes(pDataBuf, lenghtDataType, 0); - int idObjMove = BitConverter.ToInt32(arrByteData); - if (ISPLAYERID(idObjMove)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERMOVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, - pDataBuf, pCmdHeader, iHostID); - } - else if (ISNPCID(idObjMove)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, - pCmdHeader); - } - - break; - case CommandID.OBJECT_STOP_MOVE: - { - int id1 = GPDataTypeHelper.FromBytes(pDataBuf); - - if (ISPLAYERID(id1)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERSTOPMOVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, - pDataBuf, pCmdHeader); - } - else if (ISNPCID(id1)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCSTOPMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, - pCmdHeader); - } - - break; - } - case CommandID.OBJECT_LEAVE_SLICE: - { - int id = GPDataTypeHelper.FromBytes(pDataBuf); - if (ISPLAYERID(id)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERRUNOUT, (int)MANAGER_INDEX.MAN_PLAYER, -1, - pDataBuf, pCmdHeader); - } - else if (ISNPCID(id)) - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCRUNOUT, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, - pCmdHeader); - } - - break; - } - case CommandID.OWN_IVTR_DATA: - case CommandID.OWN_IVTR_DETAIL_DATA: - case CommandID.GET_OWN_MONEY: - case CommandID.CHANGE_IVTR_SIZE: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, iHostID); - break; - case CommandID.EXG_IVTR_ITEM: - case CommandID.MOVE_IVTR_ITEM: - case CommandID.PLAYER_DROP_ITEM: - case CommandID.EXG_EQUIP_ITEM: - case CommandID.EQUIP_ITEM: - case CommandID.MOVE_EQUIP_ITEM: - case CommandID.UNFREEZE_IVTR_SLOT: - case CommandID.PLAYER_EQUIP_TRASHBOX_ITEM: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ITEMOPERATION, (int)MANAGER_INDEX.MAN_PLAYER, 0, - pDataBuf, pCmdHeader); - break; - case CommandID.PLAYER_CASH: - { - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, iHostID); - break; - } - case CommandID.MATTER_INFO_LIST: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERINFO, (int)MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.MATTER_ENTER_WORLD: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERENTWORLD, (int)MANAGER_INDEX.MAN_MATTER, 0, - pDataBuf, pCmdHeader); - break; - case CommandID.PICKUP_ITEM: - case CommandID.HOST_OBTAIN_ITEM: - case CommandID.PRODUCE_ONCE: - case CommandID.TASK_DELIVER_ITEM: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPITEM, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.MATTER_PICKUP: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PICKUPMATTER, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.PICKUP_MONEY: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPMONEY, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.HOST_CORRECT_POS: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CORRECTPOS, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, iHostID); - break; - case CommandID.OWN_ITEM_INFO: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_OWNITEMINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, iHostID); - break; - case CommandID.PLAYER_DIED: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDIED, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.HOST_DIED: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_DIED, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.PLAYER_REVIVE: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERREVIVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.NOTIFY_HOSTPOS: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_GOTO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.NPC_ENTER_SLICE: - case CommandID.NPC_INFO_LIST: - case CommandID.NPC_INFO_00: - case CommandID.NPC_ENTER_WORLD: - case CommandID.NPC_VISIBLE_TID_NOTIFY: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCINFO, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, - pCmdHeader, dwDataSize); - break; - case CommandID.TASK_DATA: - case CommandID.TASK_VAR_DATA: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TASKDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader, dwDataSize); - break; - case CommandID.BE_HURT: - case CommandID.HURT_RESULT: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_HURTRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.OBJECT_ATTACK_RESULT: - //int id = GPDataTypeHelper.FromBytes(pDataBuf); - cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes(pDataBuf); - //BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id)); - - if (ISPLAYERID(pCmdAtk.attacker_id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERATKRESULT, MANAGER_INDEX.MAN_PLAYER, -1, - pDataBuf, pCmdHeader); - else if (ISNPCID(pCmdAtk.attacker_id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCATKRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - break; - case CommandID.HOST_ATTACKRESULT: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.HOST_ATTACKED: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATTACKED, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - - case CommandID.ERROR_MESSAGE: - { - int errRaw = BitConverter.ToInt32(pDataBuf, 0); - // Note: _logger may be configured as a file logger via SetLogPath(), so also log to console for visibility. - _logger.Info($"### GameDataSend: ERROR_MESSAGE: {errRaw}"); -#if UNITY_EDITOR - BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE: {errRaw}"); -#endif - cmd_error_msg pCmd = GPDataTypeHelper.FromBytes(pDataBuf); -#if UNITY_EDITOR - BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE parsed iMessage={pCmd.iMessage}"); -#endif - - if (pCmd.iMessage != 0) - { - // string szMsg = m_ErrorMsgs.GetWideString(pCmd.iMessage); - // if (string.IsNullOrEmpty(szMsg)) - // BMLogger.LogError("SERVER - unknown error !"); - //else if (pCmd.iMessage != 2) - //g_pGame.GetGameRun().AddChatMessage(szMsg, GP_CHAT_MISC); - } - - if (pCmd.iMessage == 2) - { - // Attack target is too far - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TARGETISFAR, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - } - else if (pCmd.iMessage == 20) - { - // Failed to cast skill - //pGameRun.PostMessage(MSG_PM_CASTSKILL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd); - } - else if (pCmd.iMessage == 133 || pCmd.iMessage == 134) - { - // deal failed - //pGameRun.PostMessage(MSG_HST_BUY_SELL_FAIL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd); - } - else if (pCmd.iMessage == 158) - { - // 碌卤脟掳禄茫脗脢虏禄露脭拢卢脰脴脨脗脠隆禄茫脗脢 - //c2s_CmdGetCashMoneyRate(); - } - else if (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().IsInKingService()*/) - { - /* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan(); - if (pGameUI) - pGameUI.EndNPCService();*/ - } - else if - (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().GetOfflineShopCtrl().GetNPCSevFlag() != COfflineShopCtrl::NPCSEV_NULL*/ - ) - { - /* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan(); - if (pGameUI) - pGameUI.EndNPCService();*/ - } - else if (pCmd.iMessage == 175) - { - //c2s_CmdQueryParallelWorld(); - } - else if (pCmd.iMessage == 6) - { - //AP_ActionEvent(AP_EVENT_CANNOTPICKUP); - } - - break; - } - case CommandID.SELECT_TARGET: - case CommandID.UNSELECT: - - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SELTARGET, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.NPC_DIED: - case CommandID.NPC_DIED2: - - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCDIED, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - break; - case CommandID.OBJECT_DISAPPEAR: - { - int lenghtDataType1 = Marshal.SizeOf(); - byte[] arrByteData1 = GetBytes(pDataBuf, lenghtDataType1, 0); - int objectId = BitConverter.ToInt32(arrByteData1); - if (ISPLAYERID(objectId)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDISAPPEAR, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(objectId)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCDISAPPEAR, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - else if (ISMATTERID(objectId)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERDISAPPEAR, MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, pCmdHeader); - - break; - } - case CommandID.SELF_INFO_00: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_INFO00, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, - pCmdHeader); - break; - case CommandID.NPC_GREETING: - { - // If this greeting is from the skill-learn NPC, record it (C++ skill dialog relies on this). - try - { - cmd_npc_greeting greet = GPDataTypeHelper.FromBytes(pDataBuf); - CECHostSkillModel.Instance.OnNpcGreeting(greet.idObject); - } - catch (Exception ex) - { - _logger.Log(LogType.Warning, $"Failed to parse NPC_GREETING payload: {ex.Message}"); - } - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_NPCGREETING, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - } - case CommandID.ACTIVATE_WAYPOINT: - case CommandID.WAYPOINT_LIST: - - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_WAYPOINT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.SERVER_TIME: - { - cmd_server_time pcmd_server_time = GPDataTypeHelper.FromBytes(pDataBuf); - EC_ManMessage.PostMessage(EC_MsgDef.MSG_SERVERTIME, -1, 0, pcmd_server_time.time, pcmd_server_time.timebias); - break; - } - case CommandID.SCENE_SERVICE_NPC_LIST: - { - CECHostSkillModel.Instance.RecvNPCServiceList(protocol.Data); - break; - } - case CommandID.SKILL_DATA: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.OBJECT_CAST_SKILL: - case CommandID.OBJECT_CAST_INSTANT_SKILL: - case CommandID.OBJECT_CAST_POS_SKILL: - { - cmd_object_cast_skill pCmd2 = GPDataTypeHelper.FromBytes(pDataBuf,true); - if (ISPLAYERID(pCmd2.caster)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(pCmd2.caster)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCCASTSKILL, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - - break; - } - case CommandID.LEVEL_UP: - { - cmd_level_up pCmdLevelUp = GPDataTypeHelper.FromBytes(pDataBuf); ; - if (ISPLAYERID(pCmdLevelUp.id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERLEVELUP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(pCmdLevelUp.id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCLEVELUP, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - break; - } - case CommandID.HOST_START_ATTACK: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_STARTATTACK, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); - break; - case CommandID.HOST_STOPATTACK: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_STOPATTACK, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); - break; - case CommandID.HOST_SKILL_ATTACK_RESULT: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.CHANGE_FACE_START: - case CommandID.CHANGE_FACE_END: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CHANGEFACE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); - break; - case CommandID.ENCHANT_RESULT: - cmd_enchant_result pCmd3 = GPDataTypeHelper.FromBytes(pDataBuf); - if (ISPLAYERID(pCmd3.caster)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_ENCHANTRESULT, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - else if (ISNPCID(pCmd3.caster)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_ENCHANTRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); - break; - case CommandID.SKILL_PERFORM: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.SET_COOLDOWN: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SETCOOLTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.COMBO_SKILL_PREPARE: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COMBO_SKILL_PREPARE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); - break; - case CommandID.PLAYER_EXT_PROP_BASE: - case CommandID.PLAYER_EXT_PROP_MOVE: - case CommandID.PLAYER_EXT_PROP_ATK: - case CommandID.PLAYER_EXT_PROP_DEF: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEREXTPROP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.OWN_EXT_PROP: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_OWNEXTPROP, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.OBJECT_DO_EMOTE: - case CommandID.OBJECT_EMOTE_RESTORE: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDOEMOTE, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.OUT_OF_SIGHT_LIST: - { - cmd_out_of_sight_list pCmd5 = default; - pCmd5.uCount = GPDataTypeHelper.FromBytes(pDataBuf); - int offset2 = sizeof(uint); - pCmd5.idList = new int[pCmd5.uCount]; - for (int i = 0; i < pCmd5.uCount; i++) - { - pCmd5.idList[i] = GPDataTypeHelper.FromBytes(pDataBuf, offset2); - offset2 += 4;//sizeof int; - } - - for (uint n = 0; n < pCmd5.uCount; n++) - { - if (ISPLAYERID(pCmd5.idList[n])) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEROUTOFVIEW, MANAGER_INDEX.MAN_PLAYER, -1, pCmd5.idList[n], pCmdHeader); - else if (ISNPCID(pCmd5.idList[n])) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCOUTOFVIEW, MANAGER_INDEX.MAN_NPC, 0, pCmd5.idList[n], pCmdHeader); - else if (ISMATTERID(pCmd5.idList[n])) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTEROUTOFVIEW, MANAGER_INDEX.MAN_MATTER, 0, pCmd5.idList[n], pCmdHeader); - } - - break; - } - case CommandID.PLAYER_GATHER_START: - case CommandID.PLAYER_GATHER_STOP: - case CommandID.MINE_GATHERED: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERGATHER, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - case CommandID.COOLTIME_DATA: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COOLTIMEDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.OBJECT_TAKEOFF: - { - cmd_object_takeoff pCmdTakeOff = GPDataTypeHelper.FromBytes((byte[])pDataBuf); - if (ISPLAYERID(pCmdTakeOff.object_id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - } - case CommandID.OBJECT_LANDING: - { - cmd_object_landing pCmdLanding = GPDataTypeHelper.FromBytes((byte[])pDataBuf); - if (ISPLAYERID(pCmdLanding.object_id)) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); - break; - } - case CommandID.HOST_RUSH_FLY: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.FLYSWORD_TIME: - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_FLYSWORDTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - case CommandID.PRODUCE_START: - case CommandID.PRODUCE_END: - case CommandID.PRODUCE_NULL: - // Post MSG_HST_PRODUCEITEM message with command ID as parameter (matches C++ behavior) - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PRODUCEITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - - - case CommandID.LEARN_SKILL: - BMLogger.LogError("### GameDataSend: LEARN_SKILL"); - EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_LEARNSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); - break; - default: -#if UNITY_EDITOR - if (isDebug) - { - BMLogger.LogError($"### GameDataSend: Unhandled CMDID {pCmdHeader} (payloadBytes={pDataBuf?.Length ?? 0})"); - } -#endif - break; - } - } - - - private void HandleSelectRoleResponse(SelectRole_Re protocol) - { - _logger.Info($"Select role response {protocol.result}"); - _selectRoleCallback?.Invoke(_selectedRole); - } - - private void OnErrorOccurred(string errorMessage) - { - _logger.Log(LogType.Error, $"Network Error: {errorMessage}"); - FailLoginInProgress(errorMessage); - FailRoleListInProgress(errorMessage); - } - - private void OnDisconnected() - { - _logger.Log(LogType.Info, "Disconnected from server."); - _currentUserId = -1; - FailLoginInProgress("Disconnected"); - FailRoleListInProgress("Disconnected"); - } - - // --- Protocol Handling Logic --- - - private void HandleChallenge(challenge challenge) - { - if (_loginCallback == null || string.IsNullOrEmpty(_username)) - { - _logger.Log(LogType.Warning, "Received Challenge but not expecting it or username not set."); - return; - } - - _logger.Log(LogType.Info, "Handling Challenge..."); - - response response = new response(); - byte[] usernameBytes = Encoding.ASCII.GetBytes(_username); - byte[] passwordBytes = Encoding.ASCII.GetBytes(_password); - response.identity.Replace(usernameBytes); - response.Setup(new Octets(usernameBytes), new Octets(passwordBytes), challenge.nonce); - - uint clientId = 0xffffffff; - byte[] clientIdBytes = BitConverter.GetBytes(clientId); - response.cli_fingerprint.Replace(clientIdBytes); - response.use_token = 0; - - _networkManager.SetNonce(response.response_data); - SendProtocol(response); - _logger.Log(LogType.Info, "Sent Response."); - } - - private void HandleKeyExchange(KeyExchange keyExchange) - { - if (_loginCallback == null || string.IsNullOrEmpty(_username)) - { - _logger.Log(LogType.Warning, "Received KeyExchange but not expecting it."); - return; - } - - _logger.Log(LogType.Info, "Handling KeyExchange..."); - keyExchange.Setup(_networkManager, _username); - keyExchange.Blkickuser = 1; - SendProtocol(keyExchange); - _logger.Log(LogType.Info, "Sent KeyExchange acknowledgment/response."); - } - - private void HandleOnlineAnnounce(onlineannounce announce) - { - if (_loginCallback == null) - { - _logger.Log(LogType.Warning, "Received OnlineAnnounce but not expecting it."); - return; - } - - _logger.Log(LogType.Info, $"Login successful! UserID: {announce.Userid}, LocalSID: {announce.Localsid}"); - _currentUserId = announce.Userid; - - var callback = _loginCallback; - _loginCallback = null; - callback?.Invoke(true); - } - - private void RequestRoleListInternal(int lastHandle = -1) - { - rolelist rolelistRequest = new rolelist(); - rolelistRequest.Userid = _currentUserId; - rolelistRequest.Localsid = 0; - rolelistRequest.Handle = lastHandle; - - SendProtocol(rolelistRequest); - - - //gamedatasend gamedatasendRequest = new gamedatasend(); - //gamedatasendRequest.Data = C2SCommandFactory.CreatePlayerMove(); - - //SendProtocol(gamedatasendRequest); - } - - private void HandleRoleListResponse(RoleListResponse response) - { - if (_roleListCallback == null || _accumulatedRoles == null) - { - _logger.Log(LogType.Warning, "Received RoleListResponse but not expecting it."); - return; - } - - _logger.Log(LogType.Debug, - $"Received RoleListResponse. Handle: {response.handle}, Result: {response.result}, Count: {response.rolelist.Count}"); - - if (response.result == 0) - { - _accumulatedRoles.AddRange(response.rolelist); - - foreach (var role in response.rolelist) - { - try - { - string roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); - _logger.Log(LogType.Info, $" - Role ID: {role.roleid}, Name: {roleName}, Level: {role.level}"); - } - catch (Exception ex) - { - _logger.Log(LogType.Error, $" - Error decoding role name: {ex.Message}"); - _logger.LogException(ex); - } - } - - if (response.handle != -1) - { - _logger.Log(LogType.Debug, $"Requesting next batch of roles (handle: {response.handle})..."); - RequestRoleListInternal(response.handle); - } - else - { - _logger.Log(LogType.Info, $"Finished fetching roles. Total count: {_accumulatedRoles.Count}"); - var callback = _roleListCallback; - var result = _accumulatedRoles; - _roleListCallback = null; - _accumulatedRoles = null; - callback?.Invoke(result); - } - } - else - { - _logger.Log(LogType.Error, $"Role list retrieval failed. Result code: {response.result}"); - FailRoleListInProgress($"Role list retrieval failed (Result: {response.result})"); - } - } - - // --- Helper methods for failure handling --- - private void FailLoginInProgress(string reason) - { - if (_loginCallback != null) - { - _logger.Log(LogType.Error, $"Login failed: {reason}"); - var callback = _loginCallback; - _loginCallback = null; - callback?.Invoke(false); - } - } - - private void FailRoleListInProgress(string reason) - { - if (_roleListCallback != null) - { - _logger.Log(LogType.Error, $"Role list retrieval failed: {reason}"); - var callback = _roleListCallback; - _roleListCallback = null; - _accumulatedRoles = null; - callback?.Invoke(null); - } - } - - // --- IDisposable Implementation --- - private bool disposedValue = false; - - protected virtual void Dispose(bool disposing) - { - if (!disposedValue) - { - if (disposing) - { - if (_networkManager != null) - { - _logger.Log(LogType.Info, "[DUCK] Disposing GameSession and disconnecting..."); - _networkManager.ProtocolReceived -= OnProtocolReceived; - _networkManager.ErrorOccurred -= OnErrorOccurred; - _networkManager.Disconnected -= OnDisconnected; - _networkManager.Disconnect(); - _networkManager.Dispose(); - _networkManager = null; - } - - _loginCallback = null; - _roleListCallback = null; - _accumulatedRoles = null; - } - - disposedValue = true; - } - } - - public void Dispose() - { - Dispose(true); - // GC.SuppressFinalize(this); - } - - public bool ISPLAYERID(int id) - { - return id != 0 && (id & 0x80000000) == 0; - } - public bool ISNPCID(int id) => ((id & 0x80000000) != 0) && ((id & 0x40000000) == 0); - public bool ISMATTERID(int id) => ((id) & 0xC0000000) == 0xC0000000; - private byte[] GetBytes(byte[] bytes, int length, int index) - { - byte[] arrByteData = new byte[length]; - for (int i = 0; i < length; i++) - { - arrByteData[i] = bytes[i + index]; - } - - return arrByteData; - } - - public void c2s_CmdPlayerMove(in Vector3 vCurPos, in Vector3 vDest, - int iTime, float fSpeed, int iMoveMode, ushort wStamp) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerMove(vCurPos, vDest, (ushort)iTime, fSpeed, (byte)iMoveMode, wStamp); - SendProtocol(gamedatasend); - } - public void c2s_CmdCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int aTargets) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerCastSkill(idSkill, byPVPMask, iNumTarget, aTargets); - - SendProtocol(gamedatasend); - } - - public void c2s_CmdCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int aTargets) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerCastInstantSkill(idSkill, byPVPMask, iNumTarget, aTargets); - - SendProtocol(gamedatasend); - } - - public void c2s_CmdCastPosSkill(int idSkill, Vector3 vDest, byte byPVPMask, int iNumTarget, int aTargets) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerCastPosSkill(idSkill, vDest, byPVPMask, iNumTarget, aTargets); - - SendProtocol(gamedatasend); - } - public void c2s_SendCmdContinueAction() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.CONTINUE_ACTION); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdStopMove(in Vector3 vDest, float fSpeed, int iMoveMode, - byte byDir, ushort wStamp, int iTime) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = - C2SCommandFactory.CreatePlayerStop(vDest, fSpeed, (byte)iMoveMode, byDir, wStamp, (ushort)iTime); - SendProtocol(gamedatasend); - } - - public void c2s_CmdSendEnterPKPrecinctint() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.ENTER_PK_PROTECTED); - SendProtocol(gamedatasend); - } - public void SendChatData(byte cChannel, in string szMsg, int iPack, int iSlot) - { - publicchat publicChat = new publicchat(); - publicChat.Channel = cChannel; - publicChat.Roleid = m_iCharID; - - byte[] unicodeBytes = Encoding.Unicode.GetBytes(szMsg); - publicChat.Msg.Replace(unicodeBytes); - _logger.Log(LogType.Warning, $"HoangDev : publicChat {publicChat}"); - SendProtocol(publicChat); - } - public void LoadConfigData() - { - getuiconfig p = new getuiconfig(); - p.Roleid = m_iCharID; - SendProtocol(p); - } - private void SetCharacterID(int iCharID) - { - m_iCharID = iCharID; - } - - private void OnPrtcChatMessage(Protocol pProtocol, bool bCalledagain) - { - chatmessage p = (chatmessage)pProtocol; - - string strTemp = System.Text.Encoding.Unicode.GetString(p.Msg.ToArray(), 0, p.Msg.Length); - - _logger.Log(LogType.Warning, $"HoangDev : OnPrtcChatMessage :{strTemp}"); - EventBus.Publish(new ChatMessageEvent(strTemp)); - } - - public struct ChatMessageEvent - { - public string context; - - public ChatMessageEvent(string context) - { - this.context = context; - } - } - public void OnPrtcGetConfigRe(Protocol pProtocol) - { - getuiconfig_re p = (getuiconfig_re)pProtocol; - if (p.Result != (int)ErrCode.ERR_SUCCESS) - BMLogger.LogError("CECGameSession::OnPrtcGetConfigRe, link return error code of " + p.Result); - else - { - if (!CECGameRun.Instance.LoadConfigsFromServer(p.UiConfig.RawBuffer, p.UiConfig.Size)) - { - // if load failed then use current setting directly - //TODO : fix later - EC_Game.GetConfigs().ApplyUserSetting(); - } - - // Now, Get config data request is sent after all host initial data ready. - // so when we receive this reply, we can do some last work before game - // really starts. Maybe it's not the best place to do these work, but - // now we do it here. - // Enalbe game UI - CECGameUIMan pGameUI = (CECGameUIMan)EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); - if (pGameUI != null) - { - pGameUI.EnableUI(true); - - // Get referral name for adding friend or other display - //TODO: a Hung lam phan select role info di - /* RoleInfo info = EC_Game.GetGameRun().GetSelectedRoleInfo(); - if (info.referrer_role > 0) - GetPlayerBriefInfo(1, info.referrer_role, 2);*/ - } - - CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); - pHost.OnAllInitDataReady(); - - /* if (pHost.IsGM()) - { - CDlgCountryMap pDlgCountryMap = (CDlgCountryMap)pGameUI.GetDialog("Win_CountryMap"); - pDlgCountryMap.GetConfig(); - } - - g_pGame.GetConfigs().ApplyOptimizeSetting(); - - if (g_pGame.GetConfigs().IsMiniClient()) - CECMCDownload::GetInstance().SendGetDownloadOK();*/ - } - } - private void OnPrtcPlayerBaseInfoRe(Protocol pProtocol) - { - playerbaseinfo_re p = (playerbaseinfo_re)pProtocol; - BMLogger.Log($"OnPrtcPlayerBaseInfoRe: {p.Roleid} {p.Player.cls} {p.Player.gender}"); - EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERBASEINFO, MANAGER_INDEX.MAN_PLAYER, -1, p); - } - - public void c2s_CmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask(idTask, idStorage, idRefreshItem); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdGetAllData(bool byPack, bool byEquip, bool byTask) - { - gamedatasend gamedatasend = new gamedatasend(); - - gamedatasend.Data = C2SCommandFactory.CreateGetAllDataCommand(byPack, byEquip, byTask); - _logger.Log(LogType.Warning, $"[Dat]- SendCmdGetAllData {byPack},{byEquip},{byTask}"); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevHello(int nid) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevHelloDataCommand(nid); - SendProtocol(gamedatasend); - } - - public void c2s_CmdNormalAttack(byte byPVPMask) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNormalAttackDataCmd(byPVPMask); - SendProtocol(gamedatasend); - } - - public void c2s_CmdCancelAction() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.CANCEL_ACTION); - SendProtocol(gamedatasend); - } - - public void c2s_CmdUnselect() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.UNSELECT); - SendProtocol(gamedatasend); - } - - public void c2s_CmdSelectTarget(int idTarget) - { - // Set selection first before server returns, so as to reduce the player waiting time. - CECHostPlayer pHost = EC_ManMessageMono.Instance.GetECManPlayer.GetHostPlayer(); - pHost.SetSelectedTarget(idTarget); - - if (m_idLastSelTarget != idTarget) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateSelectTarget(idTarget); - SendProtocol(gamedatasend); - m_idLastSelTarget = idTarget; - } - } - - public void c2s_SendCmdNPCSevWaypoint() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevWaypointCmd(NPC_service_type.GP_NPCSEV_WAYPOINT, 0); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdNPCSevMakeItem(int idSkill, int idItem, uint dwCount) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevMakeItemCmd(idSkill, idItem, dwCount); - SendProtocol(gamedatasend); - } - public void GetRoleBaseInfo(int iNumRole, List aRoleIDs) - { - int iNumLimit = 128; - playerbaseinfo p = null; - int iCount = 0; - - while (iCount < iNumRole) - { - p = new(); - p.Roleid = _selectedRole.roleid; - - int iNumSend = iNumLimit; - if (iCount + iNumLimit > iNumRole) - iNumSend = iNumRole - iCount; - - if (iNumSend > 0) - { - p.playerList = new(); - for (int i = 0; i < iNumSend; i++) - p.playerList.Add(aRoleIDs[iCount + i]); - - SendProtocol(p); - } - - - iCount += iNumSend; - } - } - - public void c2s_SendCmdGetOtherEquip(int iNumID, List aIDs) - { - // int iNumLimit = 250; - // int iCount = 0; - - // while (iCount < iNumID) - // { - // int iNumSend = iNumLimit; - // if (iCount + iNumLimit > iNumID) - // iNumSend = iNumID - iCount; - - // if (iNumSend > 0) - // { - // } - // } - } - - public void c2s_SendCmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask( - idTask, - idStorage, - idRefreshItem); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevReturnTask(int idTask, int iChoice) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevReturnTaskCmd( - idTask, - iChoice); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevTaskMatter(int idTask) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevTaskMatterCmd(idTask); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevLearnSkill(int idSkill) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevLearnSkillCmd(idSkill); - BMLogger.LogError("HoangDev : c2s_SendCmdNPCSevLearnSkill gamedatasend.Data : " + gamedatasend.Data.Size); - BMLogger.LogError("HoangDev : c2s_SendCmdNPCSevLearnSkill idSkill : " + idSkill); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevBuy(int itemNum, C2SCommand.npc_trade_item[] items) - { - if (itemNum <= 0 || items == null || items.Length < itemNum) - return; - - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevBuyCmd(itemNum, items); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdNPCSevSell(int itemNum, C2SCommand.npc_sell_item[] items) - { - if (itemNum <= 0 || items == null || items.Length < itemNum) - return; - - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNPCSevSellCmd(itemNum, items); - SendProtocol(gamedatasend); - } - - public void GetRoleCustomizeData(int iNumRole, List aRoleIDs) - { - if (iNumRole <= 0 || aRoleIDs == null || aRoleIDs.Count == 0) return; - - int iNumLimit = 240; - int iCount = 0; - - while (iCount < iNumRole) - { - getcustomdata p = new(); - p.Roleid = _selectedRole.roleid; - - int iNumSend = iNumLimit; - if (iCount + iNumLimit > iNumRole) - iNumSend = iNumRole - iCount; - - for (int i = 0; i < iNumSend; i++) - p.playerlist.Add(aRoleIDs[iCount + i]); - - SendProtocol(p); - - iCount += iNumSend; - } - } - public void c2s_SendCmdEmoteAction(uint wPose) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateEmoteActionCmd((int)wPose); - SendProtocol(gamedatasend); - } - public void c2s_SendCmdTaskNotify(byte[] pData, uint dwDataSize) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateTaskNotifyCmd( pData, dwDataSize); - BMLogger.Log($"[MH Task] c2s_SendCmdTaskNotify Command ID : {pData[0]} Size: {dwDataSize}"); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdStandUp() - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.STAND_UP); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdAutoTeamSetGoal(int type, int goal_id, int op) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateAutoTeamSetGoalCommand(type,goal_id, op); - SendProtocol(gamedatasend); - } - - public void c2s_CmdGoto(float x, float y, float z) - { - c2s_SendCmdGoto(x, y, z); - } - - // Send C2S::GOTO command data - void c2s_SendCmdGoto(float x, float y, float z) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateGoToCommed( x, y, z); - SendProtocol(gamedatasend); - } - - public void c2s_SendCmdUseItem(byte byPackage, byte bySlot, int tid, byte byCount) - { - gamedatasend gamedatasend = new gamedatasend(); - gamedatasend.Data = C2SCommandFactory.CreateUseItemCmd(byPackage, bySlot, tid, byCount); - SendProtocol(gamedatasend); - } - } +using BrewMonster; +using BrewMonster.Common; +using BrewMonster.Managers; +using BrewMonster.Network; +using BrewMonster.Scripts.Skills; +using BrewMonster.UI; +using CSNetwork.C2SCommand; +using CSNetwork.GPDataType; +using CSNetwork.Protocols; +using CSNetwork.Protocols.RPCData; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; +using CommandID = CSNetwork.GPDataType.CommandID; + +namespace CSNetwork +{ + public class GameSession : IDisposable + { + private static IPrefixedLogger + _logger = LoggerFactory.GetLogger(nameof(GameSession)); // Get class-specific logger + + private NetworkManager _networkManager; + private string _host; + private int _port; + private string _username; + private string _password; + private int _currentUserId = -1; // To store the UserID after successful login + private int m_iCharID; + private int m_idLastSelTarget = 0; // ID of selected item last time + + CECStringTab m_ErrorMsgs; + + // State management for async operations and callbacks + private Action _loginCallback; + private Action> _roleListCallback; + private List _accumulatedRoles; + private Action _selectRoleCallback; + private RoleInfo _selectedRole; + public bool IsConnected => _networkManager?.IsConnected ?? false; + public static SynchronizationContext Context; + private CECC2SCmdCache m_CmdCache; // C2S command cache +#if UNITY_EDITOR + public bool isDebug; + public bool IsDebug + { + get => isDebug; + set => isDebug = value; + } +#endif + public CECC2SCmdCache CmdCache { get => m_CmdCache; } + + + public GameSession() + { + _networkManager = new NetworkManager(); + m_CmdCache = new CECC2SCmdCache(); + _networkManager.ProtocolReceived += OnProtocolReceived; + _networkManager.ErrorOccurred += OnErrorOccurred; + _networkManager.Disconnected += OnDisconnected; + } + + public void SetLogPath(string path) + { + LoggerFactory.SetFileLoggerImplementation(new FileLogger()); + _logger = LoggerFactory.GetCustomLogger(path, nameof(GameSession) + GetHashCode(), LoggerType.File); + _networkManager.SetLogPath(path); + } + + /// + /// Connects to the game server asynchronously. + /// + /// Server hostname or IP address. + /// Server port. + /// Task representing the asynchronous connect operation. Check IsConnected property or handle Disconnected event for status. + public async Task ConnectAsync(string host, int port) + { + if (IsConnected) + { + _logger.Log(LogType.Warning, "ConnectAsync called but already connected."); + return; + } + + _host = host; + _port = port; + _logger.Log(LogType.Info, $"Attempting to connect to {_host}:{_port}..."); + try + { + await _networkManager.ConnectAsync(_host, _port); + if (IsConnected) + { + _logger.Log(LogType.Info, "Connection established."); + } + else + { + _logger.Log(LogType.Warning, + "Connection failed after ConnectAsync completed (check NetworkManager logs/events)."); + } + } + catch (Exception ex) + { + _logger.Log(LogType.Error, $"Connection exception: {ex.Message}"); + _logger.LogException(ex); + OnDisconnected(); + } + } + + + public void Disconnect() + { + _networkManager.Disconnect(); + } + + /// + /// Initiates the login process asynchronously. + /// + /// Account username. + /// Account password. + /// Action invoked with true on successful login (OnlineAnnounce received), false otherwise. + public void LoginAsync(string username, string password, Action callback) + { + if (!IsConnected) + { + _logger.Log(LogType.Warning, "LoginAsync called but not connected."); + callback?.Invoke(false); + return; + } + + if (_loginCallback != null) + { + _logger.Log(LogType.Warning, "LoginAsync called while another login is already in progress."); + callback?.Invoke(false); + return; + } + + _username = username; + _password = password; + _loginCallback = callback; + _currentUserId = -1; // Reset user ID + + _logger.Log(LogType.Info, $"Initiating login for user '{_username}'..."); + } + + /// + /// Initiates fetching the role list asynchronously. Requires successful login. + /// + /// Action invoked with the complete list of roles, or null/empty list on failure. + public void GetRoleListAsync(Action> callback) + { + if (!IsConnected) + { + _logger.Log(LogType.Warning, "GetRoleListAsync called but not connected."); + callback?.Invoke(null); + return; + } + + if (_currentUserId == -1) + { + _logger.Log(LogType.Warning, "GetRoleListAsync called but not logged in."); + callback?.Invoke(null); + return; + } + + if (_roleListCallback != null) + { + _logger.Log(LogType.Warning, + "GetRoleListAsync called while another role list retrieval is already in progress."); + callback?.Invoke(null); + return; + } + + _roleListCallback = callback; + _accumulatedRoles = new List(); + _logger.Log(LogType.Info, "Requesting role list..."); + RequestRoleListInternal(); + } + + public RoleInfo GetRoleInfo() + { + return _selectedRole; + } + + public void SelectRoleAsync(RoleInfo role, Action callback) + { + _selectedRole = role; + _selectRoleCallback = callback; + SetCharacterID(role.roleid); + SendProtocol(new selectrole() + { + Roleid = role.roleid, + Flag = 0 + }); + } + + public void EnterWorldAsync(RoleInfo role, Action callback) + { + SendProtocol(new enterworld() + { + Roleid = _selectedRole.roleid, + Provider_link_id = 0, + }, callback); + } + + public void RequestDropIvtrItem(byte index, int amount) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.CreateDropIvtrItem(index, amount); + SendProtocol(gamedatasendRequest); + } + + public void RequestDropEquipItem(byte index) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.CreateDropEquipItem(index); + SendProtocol(gamedatasendRequest); + } + + public void RequestPickupItem(int idItem, int tid) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.CreatePickupItem(idItem, tid); + SendProtocol(gamedatasendRequest); + } + + public void c2s_SendCmdGetIvtrDetailData(byte byPackage, Action callback) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdGetIvtrDetailData(byPackage); + SendProtocol(gamedatasendRequest, callback); + } + + public void c2s_SendCmdQueryCashInfo() + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdQueryCashInfo(); + SendProtocol(gamedatasendRequest); + } + + public void c2s_SendCmdOpenFashionTrash(string password) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdOpenFashionTrash(password); + SendProtocol(gamedatasendRequest); + } + + public void c2s_SendCmdEquipItem(byte iIvtrIdx, byte iEquipIdx, Action callback) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdEquipItem(iIvtrIdx, iEquipIdx); + SendProtocol(gamedatasendRequest, callback); + } + + public void c2s_SendCmdReviveVillage(int param = 0) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); + SendProtocol(gamedatasendRequest); + } + public void c2s_SendCmdReviveItem(int param = 0) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); + SendProtocol(gamedatasendRequest); + } + public void RequestReviveByPlayer(int param = 0) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.c2s_SendCmdReviveVillage(param); + SendProtocol(gamedatasendRequest); + } + + + public void c2s_SendCmdMallShopping(uint count, CMD_MallShopping.goods[] goodsArray) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.CreateGetMallShopping(count, goodsArray); + SendProtocol(gamedatasendRequest); + } + public void c2s_SendCmdGatherMaterial(int idMatter, int iToolPack, int idToolIndex, int idTool, int idTask) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = CSNetwork.C2SCommand.C2SCommandFactory.c2s_SendCmdGatherMaterial(idMatter, iToolPack, idToolIndex, idTool, idTask); + SendProtocol(gamedatasendRequest); + } + + public void RequestOwnItemInfoAsync( + byte byPackage, + byte bySlot, + int type, + int expire_date, + int state, + uint count, + ushort crc, + ushort content_length, + byte[] content, + Action callback) + { + gamedatasend gamedatasendRequest = new gamedatasend(); + gamedatasendRequest.Data = C2SCommandFactory.CreateOwnItemInfo(byPackage, bySlot, type, expire_date, state, + count, crc, content_length, content); + SendProtocol(gamedatasendRequest, callback); + } + + // --- Protocol Sending --- + public void SendProtocol(Protocol protocol, Action complete = null) + { + if (IsConnected) + { + _logger.Log(LogType.Debug, + $"Sending protocol: {protocol.GetType().Name} (Detail: {protocol.ToString})"); + _networkManager.Send(protocol); + complete?.Invoke(); + } + else + { + _logger.Log(LogType.Warning, $"Cannot send protocol ({protocol.GetType().Name}), not connected."); + } + } + + // --- Event Handlers (from NetworkManager) --- + + private void OnProtocolReceived(Protocol protocol) + { + _logger.Log(LogType.Debug, $"Received protocol: {protocol.GetType().Name} (Type: {protocol.Type})"); + if (protocol is null) + return; + + + // Route protocol to appropriate handler + switch (protocol.GetPType()) + { + case ProtocolType.PROTOCOL_CHALLENGE: + HandleChallenge((challenge)protocol); + break; + case ProtocolType.PROTOCOL_KEYEXCHANGE: + HandleKeyExchange((KeyExchange)protocol); + break; + case ProtocolType.PROTOCOL_ONLINEANNOUNCE: + HandleOnlineAnnounce((onlineannounce)protocol); + break; + case ProtocolType.PROTOCOL_ROLELIST_RE: + HandleRoleListResponse((RoleListResponse)protocol); + break; + // Add cases for other protocols GameSession might need to handle + case ProtocolType.PROTOCOL_SELECTROLE_RE: + HandleSelectRoleResponse((SelectRole_Re)protocol); + //_networkManager.IgnoreBytes = 2; + break; + case ProtocolType.PROTOCOL_S2CGAMEDATASEND: + case ProtocolType.PROTOCOL_GAMEDATASEND: + HandleServerDataSend((gamedatasend)protocol); + break; + case ProtocolType.PROTOCOL_CHATMESSAGE: + _logger.Log(LogType.Warning, $"HoangDev :ProtocolType.PROTOCOL_CHATMESSAGE {protocol.GetPType()}"); + OnPrtcChatMessage(protocol, false); + break; + case ProtocolType.PROTOCOL_PLAYERBASEINFO_RE: + OnPrtcPlayerBaseInfoRe(protocol); + break; + case ProtocolType.PROTOCOL_GETUICONFIG_RE: OnPrtcGetConfigRe(protocol); break; + + case ProtocolType.PROTOCOL_AUTOTEAMSETGOAL_RE: + { + // CECAutoTeam pAutoTeam = CECGameRun.Instance.GetHostPlayer().GetAutoTeam(); + // if( pAutoTeam !=null) + // pAutoTeam.OnPrtcAutoTeamSetGoalRe((AutoTeamSetGoal_Re)protocol); + } + break; + + default: + _logger.Log(LogType.Warning, $"Received unhandled protocol type: {protocol.GetPType()}"); + break; + } + } + + private void HandleServerDataSend(gamedatasend protocol) + { + int lenghtHeader = Marshal.SizeOf(); + var pDataBuf = new byte[protocol.Data.ByteArray.Length - lenghtHeader]; + var byteArrHeader = new byte[lenghtHeader]; + long dwDataSize = protocol.Data.Size; + + if (dwDataSize < Marshal.SizeOf()) + { + _logger.Error($"### GameDataSend: size invalid {dwDataSize}"); + return; + } + + dwDataSize -= Marshal.SizeOf(); // subtract the header size (ushort) + for (int i = 0; i < protocol.Data.ByteArray.Length; i++) + { + if (i < lenghtHeader) + { + byteArrHeader[i] = protocol.Data.ByteArray[i]; + } + else + { + pDataBuf[i - lenghtHeader] = protocol.Data.ByteArray[i]; + } + } + + var pCmdHeader = BitConverter.ToUInt16(byteArrHeader); + //sss +#if UNITY_EDITOR + if (isDebug) + { + BMLogger.LogError($"### GameDataSend: CMDID {pCmdHeader}"); + } +#endif + int iHostID = _selectedRole.roleid; + switch (pCmdHeader) + { + case CommandID.PLAYER_INFO_2: + case CommandID.PLAYER_INFO_3: + case CommandID.PLAYER_INFO_4: + case CommandID.PLAYER_INFO_2_LIST: + case CommandID.PLAYER_INFO_3_LIST: + case CommandID.PLAYER_INFO_23_LIST: + + break; + + case CommandID.PLAYER_INFO_1: + case CommandID.PLAYER_ENTER_WORLD: + case CommandID.PLAYER_ENTER_SLICE: + case CommandID.PLAYER_INFO_1_LIST: + case CommandID.PLAYER_INFO_00: + case CommandID.SELF_INFO_1: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERINFO, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, + pCmdHeader, iHostID); + break; + case CommandID.OBJECT_MOVE: + int lenghtDataType = Marshal.SizeOf(); + byte[] arrByteData = GetBytes(pDataBuf, lenghtDataType, 0); + int idObjMove = BitConverter.ToInt32(arrByteData); + if (ISPLAYERID(idObjMove)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERMOVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, + pDataBuf, pCmdHeader, iHostID); + } + else if (ISNPCID(idObjMove)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, + pCmdHeader); + } + + break; + case CommandID.OBJECT_STOP_MOVE: + { + int id1 = GPDataTypeHelper.FromBytes(pDataBuf); + + if (ISPLAYERID(id1)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERSTOPMOVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, + pDataBuf, pCmdHeader); + } + else if (ISNPCID(id1)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCSTOPMOVE, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, + pCmdHeader); + } + + break; + } + case CommandID.OBJECT_LEAVE_SLICE: + { + int id = GPDataTypeHelper.FromBytes(pDataBuf); + if (ISPLAYERID(id)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERRUNOUT, (int)MANAGER_INDEX.MAN_PLAYER, -1, + pDataBuf, pCmdHeader); + } + else if (ISNPCID(id)) + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCRUNOUT, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, + pCmdHeader); + } + + break; + } + case CommandID.OWN_IVTR_DATA: + case CommandID.OWN_IVTR_DETAIL_DATA: + case CommandID.GET_OWN_MONEY: + case CommandID.CHANGE_IVTR_SIZE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, iHostID); + break; + case CommandID.EXG_IVTR_ITEM: + case CommandID.MOVE_IVTR_ITEM: + case CommandID.PLAYER_DROP_ITEM: + case CommandID.EXG_EQUIP_ITEM: + case CommandID.EQUIP_ITEM: + case CommandID.MOVE_EQUIP_ITEM: + case CommandID.UNFREEZE_IVTR_SLOT: + case CommandID.PLAYER_EQUIP_TRASHBOX_ITEM: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ITEMOPERATION, (int)MANAGER_INDEX.MAN_PLAYER, 0, + pDataBuf, pCmdHeader); + break; + case CommandID.PLAYER_CASH: + { + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_IVTRINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, iHostID); + break; + } + case CommandID.MATTER_INFO_LIST: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERINFO, (int)MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.MATTER_ENTER_WORLD: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERENTWORLD, (int)MANAGER_INDEX.MAN_MATTER, 0, + pDataBuf, pCmdHeader); + break; + case CommandID.PICKUP_ITEM: + case CommandID.HOST_OBTAIN_ITEM: + case CommandID.PRODUCE_ONCE: + case CommandID.TASK_DELIVER_ITEM: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPITEM, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.MATTER_PICKUP: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PICKUPMATTER, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.PICKUP_MONEY: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PICKUPMONEY, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.HOST_CORRECT_POS: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CORRECTPOS, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, iHostID); + break; + case CommandID.OWN_ITEM_INFO: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_OWNITEMINFO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, iHostID); + break; + case CommandID.PLAYER_DIED: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDIED, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.HOST_DIED: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_DIED, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.PLAYER_REVIVE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERREVIVE, (int)MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.NOTIFY_HOSTPOS: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_GOTO, (int)MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.NPC_ENTER_SLICE: + case CommandID.NPC_INFO_LIST: + case CommandID.NPC_INFO_00: + case CommandID.NPC_ENTER_WORLD: + case CommandID.NPC_VISIBLE_TID_NOTIFY: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCINFO, (int)MANAGER_INDEX.MAN_NPC, 0, pDataBuf, + pCmdHeader, dwDataSize); + break; + case CommandID.TASK_DATA: + case CommandID.TASK_VAR_DATA: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TASKDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader, dwDataSize); + break; + case CommandID.BE_HURT: + case CommandID.HURT_RESULT: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_HURTRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.OBJECT_ATTACK_RESULT: + //int id = GPDataTypeHelper.FromBytes(pDataBuf); + cmd_object_atk_result pCmdAtk = GPDataTypeHelper.FromBytes(pDataBuf); + //BMLogger.LogError($"OBJECT_ATTACK_RESULT: npc ? " + ISNPCID(id)); + + if (ISPLAYERID(pCmdAtk.attacker_id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERATKRESULT, MANAGER_INDEX.MAN_PLAYER, -1, + pDataBuf, pCmdHeader); + else if (ISNPCID(pCmdAtk.attacker_id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCATKRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + break; + case CommandID.HOST_ATTACKRESULT: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATKRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.HOST_ATTACKED: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_ATTACKED, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + + case CommandID.ERROR_MESSAGE: + { + int errRaw = BitConverter.ToInt32(pDataBuf, 0); + // Note: _logger may be configured as a file logger via SetLogPath(), so also log to console for visibility. + _logger.Info($"### GameDataSend: ERROR_MESSAGE: {errRaw}"); +#if UNITY_EDITOR + BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE: {errRaw}"); +#endif + cmd_error_msg pCmd = GPDataTypeHelper.FromBytes(pDataBuf); +#if UNITY_EDITOR + BMLogger.LogError($"### GameDataSend: ERROR_MESSAGE parsed iMessage={pCmd.iMessage}"); +#endif + + if (pCmd.iMessage != 0) + { + // string szMsg = m_ErrorMsgs.GetWideString(pCmd.iMessage); + // if (string.IsNullOrEmpty(szMsg)) + // BMLogger.LogError("SERVER - unknown error !"); + //else if (pCmd.iMessage != 2) + //g_pGame.GetGameRun().AddChatMessage(szMsg, GP_CHAT_MISC); + } + + if (pCmd.iMessage == 2) + { + // Attack target is too far + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_TARGETISFAR, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + } + else if (pCmd.iMessage == 20) + { + // Failed to cast skill + //pGameRun.PostMessage(MSG_PM_CASTSKILL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd); + } + else if (pCmd.iMessage == 133 || pCmd.iMessage == 134) + { + // deal failed + //pGameRun.PostMessage(MSG_HST_BUY_SELL_FAIL, MAN_PLAYER, 0, (DWORD)pDataBuf, pCmdHeader.cmd); + } + else if (pCmd.iMessage == 158) + { + // 碌卤脟掳禄茫脗脢虏禄露脭拢卢脰脴脨脗脠隆禄茫脗脢 + //c2s_CmdGetCashMoneyRate(); + } + else if (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().IsInKingService()*/) + { + /* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan(); + if (pGameUI) + pGameUI.EndNPCService();*/ + } + else if + (pCmd.iMessage == 108 /*&& pGameRun.GetHostPlayer().GetOfflineShopCtrl().GetNPCSevFlag() != COfflineShopCtrl::NPCSEV_NULL*/ + ) + { + /* CECGameUIMan* pGameUI = pGameRun.GetUIManager().GetInGameUIMan(); + if (pGameUI) + pGameUI.EndNPCService();*/ + } + else if (pCmd.iMessage == 175) + { + //c2s_CmdQueryParallelWorld(); + } + else if (pCmd.iMessage == 6) + { + //AP_ActionEvent(AP_EVENT_CANNOTPICKUP); + } + + break; + } + case CommandID.SELECT_TARGET: + case CommandID.UNSELECT: + + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SELTARGET, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.NPC_DIED: + case CommandID.NPC_DIED2: + + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCDIED, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + break; + case CommandID.OBJECT_DISAPPEAR: + { + int lenghtDataType1 = Marshal.SizeOf(); + byte[] arrByteData1 = GetBytes(pDataBuf, lenghtDataType1, 0); + int objectId = BitConverter.ToInt32(arrByteData1); + if (ISPLAYERID(objectId)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDISAPPEAR, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + else if (ISNPCID(objectId)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCDISAPPEAR, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + else if (ISMATTERID(objectId)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTERDISAPPEAR, MANAGER_INDEX.MAN_MATTER, 0, pDataBuf, pCmdHeader); + + break; + } + case CommandID.SELF_INFO_00: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_INFO00, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, + pCmdHeader); + break; + case CommandID.NPC_GREETING: + { + // If this greeting is from the skill-learn NPC, record it (C++ skill dialog relies on this). + try + { + cmd_npc_greeting greet = GPDataTypeHelper.FromBytes(pDataBuf); + CECHostSkillModel.Instance.OnNpcGreeting(greet.idObject); + } + catch (Exception ex) + { + _logger.Log(LogType.Warning, $"Failed to parse NPC_GREETING payload: {ex.Message}"); + } + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_NPCGREETING, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + } + case CommandID.ACTIVATE_WAYPOINT: + case CommandID.WAYPOINT_LIST: + + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_WAYPOINT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.SERVER_TIME: + { + cmd_server_time pcmd_server_time = GPDataTypeHelper.FromBytes(pDataBuf); + EC_ManMessage.PostMessage(EC_MsgDef.MSG_SERVERTIME, -1, 0, pcmd_server_time.time, pcmd_server_time.timebias); + break; + } + case CommandID.SCENE_SERVICE_NPC_LIST: + { + CECHostSkillModel.Instance.RecvNPCServiceList(protocol.Data); + break; + } + case CommandID.SKILL_DATA: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.OBJECT_CAST_SKILL: + case CommandID.OBJECT_CAST_INSTANT_SKILL: + case CommandID.OBJECT_CAST_POS_SKILL: + { + cmd_object_cast_skill pCmd2 = GPDataTypeHelper.FromBytes(pDataBuf,true); + if (ISPLAYERID(pCmd2.caster)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + else if (ISNPCID(pCmd2.caster)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCCASTSKILL, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + + break; + } + case CommandID.LEVEL_UP: + { + cmd_level_up pCmdLevelUp = GPDataTypeHelper.FromBytes(pDataBuf); ; + if (ISPLAYERID(pCmdLevelUp.id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERLEVELUP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + else if (ISNPCID(pCmdLevelUp.id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCLEVELUP, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + break; + } + case CommandID.HOST_START_ATTACK: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_STARTATTACK, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); + break; + case CommandID.HOST_STOPATTACK: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_STOPATTACK, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); + break; + case CommandID.HOST_SKILL_ATTACK_RESULT: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SKILLRESULT, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.CHANGE_FACE_START: + case CommandID.CHANGE_FACE_END: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_CHANGEFACE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); + break; + case CommandID.ENCHANT_RESULT: + cmd_enchant_result pCmd3 = GPDataTypeHelper.FromBytes(pDataBuf); + if (ISPLAYERID(pCmd3.caster)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_ENCHANTRESULT, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + else if (ISNPCID(pCmd3.caster)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_ENCHANTRESULT, MANAGER_INDEX.MAN_NPC, 0, pDataBuf, pCmdHeader); + break; + case CommandID.SKILL_PERFORM: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_CASTSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.SET_COOLDOWN: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_SETCOOLTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.COMBO_SKILL_PREPARE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COMBO_SKILL_PREPARE, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader, dwDataSize); + break; + case CommandID.PLAYER_EXT_PROP_BASE: + case CommandID.PLAYER_EXT_PROP_MOVE: + case CommandID.PLAYER_EXT_PROP_ATK: + case CommandID.PLAYER_EXT_PROP_DEF: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEREXTPROP, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.OWN_EXT_PROP: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_OWNEXTPROP, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.OBJECT_DO_EMOTE: + case CommandID.OBJECT_EMOTE_RESTORE: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERDOEMOTE, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.OUT_OF_SIGHT_LIST: + { + cmd_out_of_sight_list pCmd5 = default; + pCmd5.uCount = GPDataTypeHelper.FromBytes(pDataBuf); + int offset2 = sizeof(uint); + pCmd5.idList = new int[pCmd5.uCount]; + for (int i = 0; i < pCmd5.uCount; i++) + { + pCmd5.idList[i] = GPDataTypeHelper.FromBytes(pDataBuf, offset2); + offset2 += 4;//sizeof int; + } + + for (uint n = 0; n < pCmd5.uCount; n++) + { + if (ISPLAYERID(pCmd5.idList[n])) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYEROUTOFVIEW, MANAGER_INDEX.MAN_PLAYER, -1, pCmd5.idList[n], pCmdHeader); + else if (ISNPCID(pCmd5.idList[n])) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_NM_NPCOUTOFVIEW, MANAGER_INDEX.MAN_NPC, 0, pCmd5.idList[n], pCmdHeader); + else if (ISMATTERID(pCmd5.idList[n])) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_MM_MATTEROUTOFVIEW, MANAGER_INDEX.MAN_MATTER, 0, pCmd5.idList[n], pCmdHeader); + } + + break; + } + case CommandID.PLAYER_GATHER_START: + case CommandID.PLAYER_GATHER_STOP: + case CommandID.MINE_GATHERED: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERGATHER, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + case CommandID.COOLTIME_DATA: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_COOLTIMEDATA, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.OBJECT_TAKEOFF: + { + cmd_object_takeoff pCmdTakeOff = GPDataTypeHelper.FromBytes((byte[])pDataBuf); + if (ISPLAYERID(pCmdTakeOff.object_id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + } + case CommandID.OBJECT_LANDING: + { + cmd_object_landing pCmdLanding = GPDataTypeHelper.FromBytes((byte[])pDataBuf); + if (ISPLAYERID(pCmdLanding.object_id)) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, -1, pDataBuf, pCmdHeader); + break; + } + case CommandID.HOST_RUSH_FLY: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERFLY, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.FLYSWORD_TIME: + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_FLYSWORDTIME, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + case CommandID.PRODUCE_START: + case CommandID.PRODUCE_END: + case CommandID.PRODUCE_NULL: + // Post MSG_HST_PRODUCEITEM message with command ID as parameter (matches C++ behavior) + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_PRODUCEITEM, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + + + case CommandID.LEARN_SKILL: + BMLogger.LogError("### GameDataSend: LEARN_SKILL"); + EC_ManMessage.PostMessage(EC_MsgDef.MSG_HST_LEARNSKILL, MANAGER_INDEX.MAN_PLAYER, 0, pDataBuf, pCmdHeader); + break; + default: +#if UNITY_EDITOR + if (isDebug) + { + BMLogger.LogError($"### GameDataSend: Unhandled CMDID {pCmdHeader} (payloadBytes={pDataBuf?.Length ?? 0})"); + } +#endif + break; + } + } + + + private void HandleSelectRoleResponse(SelectRole_Re protocol) + { + _logger.Info($"Select role response {protocol.result}"); + _selectRoleCallback?.Invoke(_selectedRole); + } + + private void OnErrorOccurred(string errorMessage) + { + _logger.Log(LogType.Error, $"Network Error: {errorMessage}"); + FailLoginInProgress(errorMessage); + FailRoleListInProgress(errorMessage); + } + + private void OnDisconnected() + { + _logger.Log(LogType.Info, "Disconnected from server."); + _currentUserId = -1; + FailLoginInProgress("Disconnected"); + FailRoleListInProgress("Disconnected"); + // Clear command cache + m_CmdCache.RemoveAllCmds(); + } + + // --- Protocol Handling Logic --- + + private void HandleChallenge(challenge challenge) + { + if (_loginCallback == null || string.IsNullOrEmpty(_username)) + { + _logger.Log(LogType.Warning, "Received Challenge but not expecting it or username not set."); + return; + } + + _logger.Log(LogType.Info, "Handling Challenge..."); + + response response = new response(); + byte[] usernameBytes = Encoding.ASCII.GetBytes(_username); + byte[] passwordBytes = Encoding.ASCII.GetBytes(_password); + response.identity.Replace(usernameBytes); + response.Setup(new Octets(usernameBytes), new Octets(passwordBytes), challenge.nonce); + + uint clientId = 0xffffffff; + byte[] clientIdBytes = BitConverter.GetBytes(clientId); + response.cli_fingerprint.Replace(clientIdBytes); + response.use_token = 0; + + _networkManager.SetNonce(response.response_data); + SendProtocol(response); + _logger.Log(LogType.Info, "Sent Response."); + } + + private void HandleKeyExchange(KeyExchange keyExchange) + { + if (_loginCallback == null || string.IsNullOrEmpty(_username)) + { + _logger.Log(LogType.Warning, "Received KeyExchange but not expecting it."); + return; + } + + _logger.Log(LogType.Info, "Handling KeyExchange..."); + keyExchange.Setup(_networkManager, _username); + keyExchange.Blkickuser = 1; + SendProtocol(keyExchange); + _logger.Log(LogType.Info, "Sent KeyExchange acknowledgment/response."); + } + + private void HandleOnlineAnnounce(onlineannounce announce) + { + if (_loginCallback == null) + { + _logger.Log(LogType.Warning, "Received OnlineAnnounce but not expecting it."); + return; + } + + _logger.Log(LogType.Info, $"Login successful! UserID: {announce.Userid}, LocalSID: {announce.Localsid}"); + _currentUserId = announce.Userid; + + var callback = _loginCallback; + _loginCallback = null; + callback?.Invoke(true); + } + + private void RequestRoleListInternal(int lastHandle = -1) + { + rolelist rolelistRequest = new rolelist(); + rolelistRequest.Userid = _currentUserId; + rolelistRequest.Localsid = 0; + rolelistRequest.Handle = lastHandle; + + SendProtocol(rolelistRequest); + + + //gamedatasend gamedatasendRequest = new gamedatasend(); + //gamedatasendRequest.Data = C2SCommandFactory.CreatePlayerMove(); + + //SendProtocol(gamedatasendRequest); + } + + private void HandleRoleListResponse(RoleListResponse response) + { + if (_roleListCallback == null || _accumulatedRoles == null) + { + _logger.Log(LogType.Warning, "Received RoleListResponse but not expecting it."); + return; + } + + _logger.Log(LogType.Debug, + $"Received RoleListResponse. Handle: {response.handle}, Result: {response.result}, Count: {response.rolelist.Count}"); + + if (response.result == 0) + { + _accumulatedRoles.AddRange(response.rolelist); + + foreach (var role in response.rolelist) + { + try + { + string roleName = Encoding.UTF8.GetString(role.name.ByteArray, 0, role.name.Length); + _logger.Log(LogType.Info, $" - Role ID: {role.roleid}, Name: {roleName}, Level: {role.level}"); + } + catch (Exception ex) + { + _logger.Log(LogType.Error, $" - Error decoding role name: {ex.Message}"); + _logger.LogException(ex); + } + } + + if (response.handle != -1) + { + _logger.Log(LogType.Debug, $"Requesting next batch of roles (handle: {response.handle})..."); + RequestRoleListInternal(response.handle); + } + else + { + _logger.Log(LogType.Info, $"Finished fetching roles. Total count: {_accumulatedRoles.Count}"); + var callback = _roleListCallback; + var result = _accumulatedRoles; + _roleListCallback = null; + _accumulatedRoles = null; + callback?.Invoke(result); + } + } + else + { + _logger.Log(LogType.Error, $"Role list retrieval failed. Result code: {response.result}"); + FailRoleListInProgress($"Role list retrieval failed (Result: {response.result})"); + } + } + + // --- Helper methods for failure handling --- + private void FailLoginInProgress(string reason) + { + if (_loginCallback != null) + { + _logger.Log(LogType.Error, $"Login failed: {reason}"); + var callback = _loginCallback; + _loginCallback = null; + callback?.Invoke(false); + } + } + + private void FailRoleListInProgress(string reason) + { + if (_roleListCallback != null) + { + _logger.Log(LogType.Error, $"Role list retrieval failed: {reason}"); + var callback = _roleListCallback; + _roleListCallback = null; + _accumulatedRoles = null; + callback?.Invoke(null); + } + } + + // --- IDisposable Implementation --- + private bool disposedValue = false; + + protected virtual void Dispose(bool disposing) + { + if (!disposedValue) + { + if (disposing) + { + if (_networkManager != null) + { + _logger.Log(LogType.Info, "[DUCK] Disposing GameSession and disconnecting..."); + _networkManager.ProtocolReceived -= OnProtocolReceived; + _networkManager.ErrorOccurred -= OnErrorOccurred; + _networkManager.Disconnected -= OnDisconnected; + _networkManager.Disconnect(); + _networkManager.Dispose(); + _networkManager = null; + } + + _loginCallback = null; + _roleListCallback = null; + _accumulatedRoles = null; + } + + disposedValue = true; + } + } + + public void Dispose() + { + Dispose(true); + // GC.SuppressFinalize(this); + } + + public bool ISPLAYERID(int id) + { + return id != 0 && (id & 0x80000000) == 0; + } + public bool ISNPCID(int id) => ((id & 0x80000000) != 0) && ((id & 0x40000000) == 0); + public bool ISMATTERID(int id) => ((id) & 0xC0000000) == 0xC0000000; + private byte[] GetBytes(byte[] bytes, int length, int index) + { + byte[] arrByteData = new byte[length]; + for (int i = 0; i < length; i++) + { + arrByteData[i] = bytes[i + index]; + } + + return arrByteData; + } + + public void c2s_CmdPlayerMove(in Vector3 vCurPos, in Vector3 vDest, + int iTime, float fSpeed, int iMoveMode, ushort wStamp) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerMove(vCurPos, vDest, (ushort)iTime, fSpeed, (byte)iMoveMode, wStamp); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerCastSkill(idSkill, byPVPMask, iNumTarget, aTargets); + + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerCastInstantSkill(idSkill, byPVPMask, iNumTarget, aTargets); + + SendProtocol(gamedatasend); + } + + public void c2s_CmdCastPosSkill(int idSkill, Vector3 vDest, byte byPVPMask, int iNumTarget, int aTargets) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerCastPosSkill(idSkill, vDest, byPVPMask, iNumTarget, aTargets); + + SendProtocol(gamedatasend); + } + public void c2s_SendCmdContinueAction() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.CONTINUE_ACTION); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdStopMove(in Vector3 vDest, float fSpeed, int iMoveMode, + byte byDir, ushort wStamp, int iTime) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = + C2SCommandFactory.CreatePlayerStop(vDest, fSpeed, (byte)iMoveMode, byDir, wStamp, (ushort)iTime); + SendProtocol(gamedatasend); + } + + public void c2s_CmdSendEnterPKPrecinctint() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.ENTER_PK_PROTECTED); + SendProtocol(gamedatasend); + } + public void SendChatData(byte cChannel, in string szMsg, int iPack, int iSlot) + { + publicchat publicChat = new publicchat(); + publicChat.Channel = cChannel; + publicChat.Roleid = m_iCharID; + + byte[] unicodeBytes = Encoding.Unicode.GetBytes(szMsg); + publicChat.Msg.Replace(unicodeBytes); + _logger.Log(LogType.Warning, $"HoangDev : publicChat {publicChat}"); + SendProtocol(publicChat); + } + public void LoadConfigData() + { + getuiconfig p = new getuiconfig(); + p.Roleid = m_iCharID; + SendProtocol(p); + } + private void SetCharacterID(int iCharID) + { + m_iCharID = iCharID; + } + + private void OnPrtcChatMessage(Protocol pProtocol, bool bCalledagain) + { + chatmessage p = (chatmessage)pProtocol; + + string strTemp = System.Text.Encoding.Unicode.GetString(p.Msg.ToArray(), 0, p.Msg.Length); + + _logger.Log(LogType.Warning, $"HoangDev : OnPrtcChatMessage :{strTemp}"); + EventBus.Publish(new ChatMessageEvent(strTemp)); + } + + public struct ChatMessageEvent + { + public string context; + + public ChatMessageEvent(string context) + { + this.context = context; + } + } + public void OnPrtcGetConfigRe(Protocol pProtocol) + { + getuiconfig_re p = (getuiconfig_re)pProtocol; + if (p.Result != (int)ErrCode.ERR_SUCCESS) + BMLogger.LogError("CECGameSession::OnPrtcGetConfigRe, link return error code of " + p.Result); + else + { + if (!CECGameRun.Instance.LoadConfigsFromServer(p.UiConfig.RawBuffer, p.UiConfig.Size)) + { + // if load failed then use current setting directly + //TODO : fix later + EC_Game.GetConfigs().ApplyUserSetting(); + } + + // Now, Get config data request is sent after all host initial data ready. + // so when we receive this reply, we can do some last work before game + // really starts. Maybe it's not the best place to do these work, but + // now we do it here. + // Enalbe game UI + CECGameUIMan pGameUI = (CECGameUIMan)EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); + if (pGameUI != null) + { + pGameUI.EnableUI(true); + + // Get referral name for adding friend or other display + //TODO: a Hung lam phan select role info di + /* RoleInfo info = EC_Game.GetGameRun().GetSelectedRoleInfo(); + if (info.referrer_role > 0) + GetPlayerBriefInfo(1, info.referrer_role, 2);*/ + } + + CECHostPlayer pHost = EC_Game.GetGameRun().GetHostPlayer(); + pHost.OnAllInitDataReady(); + + /* if (pHost.IsGM()) + { + CDlgCountryMap pDlgCountryMap = (CDlgCountryMap)pGameUI.GetDialog("Win_CountryMap"); + pDlgCountryMap.GetConfig(); + } + + g_pGame.GetConfigs().ApplyOptimizeSetting(); + + if (g_pGame.GetConfigs().IsMiniClient()) + CECMCDownload::GetInstance().SendGetDownloadOK();*/ + } + } + private void OnPrtcPlayerBaseInfoRe(Protocol pProtocol) + { + playerbaseinfo_re p = (playerbaseinfo_re)pProtocol; + BMLogger.Log($"OnPrtcPlayerBaseInfoRe: {p.Roleid} {p.Player.cls} {p.Player.gender}"); + EC_ManMessage.PostMessage(EC_MsgDef.MSG_PM_PLAYERBASEINFO, MANAGER_INDEX.MAN_PLAYER, -1, p); + } + + public void c2s_CmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask(idTask, idStorage, idRefreshItem); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdGetAllData(bool byPack, bool byEquip, bool byTask) + { + gamedatasend gamedatasend = new gamedatasend(); + + gamedatasend.Data = C2SCommandFactory.CreateGetAllDataCommand(byPack, byEquip, byTask); + _logger.Log(LogType.Warning, $"[Dat]- SendCmdGetAllData {byPack},{byEquip},{byTask}"); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevHello(int nid) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevHelloDataCommand(nid); + SendProtocol(gamedatasend); + } + + public void c2s_CmdNormalAttack(byte byPVPMask) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNormalAttackDataCmd(byPVPMask); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdCancelAction() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.CANCEL_ACTION); + SendProtocol(gamedatasend); + } + + public void c2s_CmdUnselect() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(CSNetwork.C2SCommand.CommandID.UNSELECT); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdSelectTarget(int idTarget) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateSelectTarget(idTarget); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevWaypoint() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevWaypointCmd(NPC_service_type.GP_NPCSEV_WAYPOINT, 0); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdNPCSevMakeItem(int idSkill, int idItem, uint dwCount) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevMakeItemCmd(idSkill, idItem, dwCount); + SendProtocol(gamedatasend); + } + public void GetRoleBaseInfo(int iNumRole, List aRoleIDs) + { + int iNumLimit = 128; + playerbaseinfo p = null; + int iCount = 0; + + while (iCount < iNumRole) + { + p = new(); + p.Roleid = _selectedRole.roleid; + + int iNumSend = iNumLimit; + if (iCount + iNumLimit > iNumRole) + iNumSend = iNumRole - iCount; + + if (iNumSend > 0) + { + p.playerList = new(); + for (int i = 0; i < iNumSend; i++) + p.playerList.Add(aRoleIDs[iCount + i]); + + SendProtocol(p); + } + + + iCount += iNumSend; + } + } + + public void c2s_SendCmdGetOtherEquip(int iNumID, List aIDs) + { + // int iNumLimit = 250; + // int iCount = 0; + + // while (iCount < iNumID) + // { + // int iNumSend = iNumLimit; + // if (iCount + iNumLimit > iNumID) + // iNumSend = iNumID - iCount; + + // if (iNumSend > 0) + // { + // } + // } + } + + public void c2s_SendCmdNPCSevAcceptTask(int idTask, int idStorage, int idRefreshItem) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateCmdNPCSevAcceptTask( + idTask, + idStorage, + idRefreshItem); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevReturnTask(int idTask, int iChoice) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevReturnTaskCmd( + idTask, + iChoice); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevTaskMatter(int idTask) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevTaskMatterCmd(idTask); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevLearnSkill(int idSkill) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevLearnSkillCmd(idSkill); + BMLogger.LogError("HoangDev : c2s_SendCmdNPCSevLearnSkill gamedatasend.Data : " + gamedatasend.Data.Size); + BMLogger.LogError("HoangDev : c2s_SendCmdNPCSevLearnSkill idSkill : " + idSkill); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevBuy(int itemNum, C2SCommand.npc_trade_item[] items) + { + if (itemNum <= 0 || items == null || items.Length < itemNum) + return; + + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevBuyCmd(itemNum, items); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdNPCSevSell(int itemNum, C2SCommand.npc_sell_item[] items) + { + if (itemNum <= 0 || items == null || items.Length < itemNum) + return; + + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNPCSevSellCmd(itemNum, items); + SendProtocol(gamedatasend); + } + + public void GetRoleCustomizeData(int iNumRole, List aRoleIDs) + { + if (iNumRole <= 0 || aRoleIDs == null || aRoleIDs.Count == 0) return; + + int iNumLimit = 240; + int iCount = 0; + + while (iCount < iNumRole) + { + getcustomdata p = new(); + p.Roleid = _selectedRole.roleid; + + int iNumSend = iNumLimit; + if (iCount + iNumLimit > iNumRole) + iNumSend = iNumRole - iCount; + + for (int i = 0; i < iNumSend; i++) + p.playerlist.Add(aRoleIDs[iCount + i]); + + SendProtocol(p); + + iCount += iNumSend; + } + } + public void c2s_SendCmdEmoteAction(uint wPose) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateEmoteActionCmd((int)wPose); + SendProtocol(gamedatasend); + } + public void c2s_SendCmdTaskNotify(byte[] pData, uint dwDataSize) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateTaskNotifyCmd( pData, dwDataSize); + BMLogger.Log($"[MH Task] c2s_SendCmdTaskNotify Command ID : {pData[0]} Size: {dwDataSize}"); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdStandUp() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.STAND_UP); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdAutoTeamSetGoal(int type, int goal_id, int op) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateAutoTeamSetGoalCommand(type,goal_id, op); + SendProtocol(gamedatasend); + } + + public void c2s_CmdGoto(float x, float y, float z) + { + c2s_SendCmdGoto(x, y, z); + } + + // Send C2S::GOTO command data + void c2s_SendCmdGoto(float x, float y, float z) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateGoToCommed( x, y, z); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdUseItem(byte byPackage, byte bySlot, int tid, byte byCount) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateUseItemCmd(byPackage, bySlot, tid, byCount); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdGetExtProps() + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateNakeCmd(C2SCommand.CommandID.GET_EXT_PROP); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdGivePresent(int roleid, int mail_id, int goods_id, int goods_index, int goods_slot) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateGivePresentCmd(roleid, mail_id, goods_id, goods_index, goods_slot); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdEnterSanctuary(int id) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateEnterSanctuaryCmd(id); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdEnterInstance(int iTransIdx, int idInst) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateEnterInstanceCmd(iTransIdx, idInst); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdActiveRushFly(bool bActive) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateActiveRushFlyCmd(bActive); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdPetCtrl(int idTarget, int cmd, byte[] pParamBuf, int iParamLen) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreatePetCtrlCmd(idTarget, cmd, pParamBuf, iParamLen); + SendProtocol(gamedatasend); + } + + public void c2s_SendCmdQueryFactionPVPInfo(int faction_id) + { + gamedatasend gamedatasend = new gamedatasend(); + gamedatasend.Data = C2SCommandFactory.CreateQueryFactionPVPInfo(faction_id); + SendProtocol(gamedatasend); + } + } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getplayerbriefinfo.cs b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getplayerbriefinfo.cs index 7e3e343026..dc384847ad 100644 --- a/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getplayerbriefinfo.cs +++ b/Assets/PerfectWorld/Scripts/Network/CSNetwork/Protocols/getplayerbriefinfo.cs @@ -8,7 +8,7 @@ namespace CSNetwork.Protocols public int Roleid { get; set; } public int Localsid { get; set; } public byte Reason { get; set; } - + public List Playerlist { get; set; } public getplayerbriefinfo() : base(ProtocolType.PROTOCOL_GETPLAYERBRIEFINFO) { @@ -18,7 +18,8 @@ namespace CSNetwork.Protocols { Roleid = Roleid, Localsid = Localsid, - Reason = Reason + Reason = Reason, + Playerlist = Playerlist }; public override void Marshal(OctetsStream os) @@ -26,6 +27,7 @@ namespace CSNetwork.Protocols os.Write(Roleid); os.Write(Localsid); os.Write(Reason); + os.WriteListInt(Playerlist); } public override void Unmarshal(OctetsStream os) @@ -33,6 +35,7 @@ namespace CSNetwork.Protocols Roleid = os.ReadInt32(); Localsid = os.ReadInt32(); Reason = os.ReadByte(); + os.ReadListInt(Playerlist); } public override int PriorPolicy() => 1; diff --git a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs index 207861fd6b..04382a78c6 100644 --- a/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs +++ b/Assets/PerfectWorld/Scripts/Network/UnityGameSession.cs @@ -33,13 +33,16 @@ namespace BrewMonster.Network private string _password = ""; CECStubbornFactionInfoSender m_stubbornFactionInfoSender; - + public GameSession GameSession { get => _gameSession; } + public CECC2SCmdCache GetC2SCmdCache() { return _gameSession.CmdCache; } #if UNITY_EDITOR public bool isDebg; private bool lastDebug; + + public void OnValidate() { - if (isDebg != lastDebug) + if (_gameSession != null && isDebg != lastDebug) { _gameSession.IsDebug = isDebg; lastDebug = isDebg; @@ -79,14 +82,14 @@ namespace BrewMonster.Network Instance._ip = ip; Instance._port = port; } - public static void c2s_CmdCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int aTargets) + public static void c2s_CmdCastSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) { - Instance._gameSession.c2s_CmdCastSkill(idSkill, byPVPMask, iNumTarget, aTargets); + Instance._gameSession.CmdCache.SendCmdCastSkill(idSkill, byPVPMask, iNumTarget, aTargets); } - public static void c2s_CmdCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int aTargets) + public static void c2s_CmdCastInstantSkill(int idSkill, byte byPVPMask, int iNumTarget, int[] aTargets) { - Instance._gameSession.c2s_CmdCastInstantSkill(idSkill, byPVPMask, iNumTarget, aTargets); + Instance._gameSession.CmdCache.SendCmdCastInstantSkill(idSkill, byPVPMask, iNumTarget, aTargets); } public static void c2s_CmdCastPosSkill(int idSkill, Vector3 vDest, byte byPVPMask, int iNumTarget, int aTargets) @@ -196,7 +199,7 @@ namespace BrewMonster.Network } public static void RequestPickupItem(int idItem, int tid) { - Instance._gameSession.RequestPickupItem(idItem, tid); + Instance._gameSession.CmdCache.SendCmdPickUp(idItem, tid); } public static void RequestDropIvrtItem(byte index, int amount) { @@ -214,13 +217,13 @@ namespace BrewMonster.Network { Instance._gameSession.c2s_SendCmdContinueAction(); } - public static void RequestReviveBase() + public static void c2s_CmdReviveVillage() { - Instance._gameSession.c2s_SendCmdReviveVillage(); + Instance._gameSession.CmdCache.SendCmdReviveVillage(); } - public static void RequestReviveItem() + public static void c2s_CmdReviveItem() { - Instance._gameSession.c2s_SendCmdReviveItem(); + Instance._gameSession.CmdCache.SendCmdReviveItem(); } public static void RequestReviveByPlayer() { @@ -269,7 +272,7 @@ namespace BrewMonster.Network } public static void c2s_CmdNPCSevHello(int nid) { - Instance._gameSession.c2s_SendCmdNPCSevHello(nid); + Instance._gameSession.CmdCache.SendCmdNPCSevHello(nid); } public static void c2s_CmdNormalAttack(byte byPVPMask) @@ -279,7 +282,7 @@ namespace BrewMonster.Network public static void c2s_CmdCancelAction() { - Instance._gameSession.c2s_CmdCancelAction(); + Instance._gameSession.CmdCache.SendCmdCancelAction(); } public static void c2s_CmdUnselect() @@ -289,7 +292,7 @@ namespace BrewMonster.Network public static void c2s_CmdSelectTarget(int idTarget) { - Instance._gameSession.c2s_CmdSelectTarget(idTarget); + Instance._gameSession.CmdCache.SendCmdSelectTarget(idTarget); } public static void c2s_CmdNPCSevWaypoint() { @@ -405,22 +408,38 @@ namespace BrewMonster.Network } actDone?.Invoke(true); } + void OnDestroy() { _gameSession.Disconnect(); _gameSession.Dispose(); CECNPC.ReleaseStaticRes(); } - - + public static void c2s_CmdGoto(float x, float y, float z) { Instance._gameSession.c2s_CmdGoto(x, y, z); } - public static void c2s_CmdUseItem(byte byPackage, byte bySlot, int tid, byte byCount) + public static void c2s_SendCmdUseItem(byte byPackage, byte bySlot, int tid, byte byCount) { - Instance._gameSession.c2s_SendCmdUseItem(byPackage, bySlot, tid, byCount); + Instance._gameSession.CmdCache.SendCmdUseItem(byPackage, bySlot, tid, byCount); + } + + // Send C2S::GET_EXT_PROP commadn data + public static void c2s_SendCmdGetExtProps() + { + Instance._gameSession.CmdCache.SendCmdExtProps(); + } + + public static void c2s_SendCmdGivePresent(int roleid, int mail_id, int goods_id, int goods_index, int goods_slot) + { + Instance._gameSession.c2s_SendCmdGivePresent(roleid, mail_id, goods_id, goods_index, goods_slot); + } + + public void Update() + { + _gameSession?.CmdCache?.Tick(Time.deltaTime); } } } \ No newline at end of file diff --git a/Assets/PerfectWorld/Scripts/UI/Popup/RevivePopup.cs b/Assets/PerfectWorld/Scripts/UI/Popup/RevivePopup.cs index 438494e8c3..7fe7124e7c 100644 --- a/Assets/PerfectWorld/Scripts/UI/Popup/RevivePopup.cs +++ b/Assets/PerfectWorld/Scripts/UI/Popup/RevivePopup.cs @@ -27,12 +27,12 @@ namespace BrewMonster private void ReviveInBase() { - UnityGameSession.RequestReviveBase(); + UnityGameSession.c2s_CmdReviveVillage(); } private void ReviveByItem() { - UnityGameSession.RequestReviveItem(); + UnityGameSession.c2s_CmdReviveItem(); } private void ReviveByPlayer() diff --git a/Assets/Scripts/CECHostPlayer.cs b/Assets/Scripts/CECHostPlayer.cs index f3e760c2d8..f6e7227a3e 100644 --- a/Assets/Scripts/CECHostPlayer.cs +++ b/Assets/Scripts/CECHostPlayer.cs @@ -23,6 +23,7 @@ using System.Runtime.InteropServices; using System.Text; using UnityEngine; using UnityEngine.UI; +using static BrewMonster.Scripts.Managers.EC_Inventory; using Host_work_ID = BrewMonster.Scripts.CECHPWork.Host_work_ID; using Trace_reason = BrewMonster.CECHPWorkTrace.Trace_reason; @@ -158,6 +159,8 @@ namespace BrewMonster private UnityEngine.InputSystem.Mouse m_cachedMouse; private UnityEngine.InputSystem.Keyboard m_cachedKeyboard; + int[] targetsCastSkill; + public bool IsChangingFace() { return m_bChangingFace; @@ -3910,7 +3913,10 @@ namespace BrewMonster // Handle instant skills if (m_pPrepSkill.IsInstant()) { - UnityGameSession.c2s_CmdCastInstantSkill(m_pPrepSkill.GetSkillID(), byPVPMask, 1, idTarget); + int countTarget = 1; + targetsCastSkill = new int[countTarget]; + targetsCastSkill[0] = idTarget; + UnityGameSession.c2s_CmdCastInstantSkill(m_pPrepSkill.GetSkillID(), byPVPMask, countTarget, targetsCastSkill); m_pPrepSkill = null; } // Handle flash move skills (鐬Щ鎶鑳) @@ -4080,7 +4086,10 @@ namespace BrewMonster { // Regular skill casting byte byPVPMask2 = glb_BuildPVPMask(bForceAttack); - UnityGameSession.c2s_CmdCastSkill(m_pPrepSkill.GetSkillID(), byPVPMask2, 1, idTarget); + int targets = 1; + targetsCastSkill = new int[targets]; + targetsCastSkill[0] = idTarget; + UnityGameSession.c2s_CmdCastSkill(m_pPrepSkill.GetSkillID(), byPVPMask2, targets, targetsCastSkill); } return true; @@ -5924,13 +5933,13 @@ namespace BrewMonster // Get cool time public int GetCoolTime(int iIndex, ref int piMax /* NULL */) { - // if (iIndex >= 0 && iIndex < GP_CT_MAX) - // { - // if (piMax>0) - // piMax = m_aCoolTimes[iIndex].iMaxTime; - // - // return m_aCoolTimes[iIndex].iCurTime; - // } + if (iIndex >= 0 && iIndex < (int)CoolTimeIndex.GP_CT_MAX) + { + if (piMax > 0) + piMax = m_aCoolTimes[iIndex].iMaxTime; + + return m_aCoolTimes[iIndex].iCurTime; + } return 0; } @@ -6702,7 +6711,7 @@ namespace BrewMonster return false; } - UnityGameSession.c2s_CmdUseItem(InventoryConst.IVTRTYPE_EQUIPPACK, InventoryConst.EQUIPIVTR_FLYSWORD, pItem.GetTemplateID(), 1); + UnityGameSession.c2s_SendCmdUseItem(InventoryConst.IVTRTYPE_EQUIPPACK, InventoryConst.EQUIPIVTR_FLYSWORD, pItem.GetTemplateID(), 1); return true; } @@ -6754,6 +6763,27 @@ namespace BrewMonster m_bRushFly = pCmd.is_active != 0 ? true : false; } } + + public EC_Inventory GetPack(int iPack) + { + EC_Inventory pInventory = null; + switch (iPack) + { + case Inventory_type.IVTRTYPE_PACK: pInventory = m_pPack; break; + case Inventory_type.IVTRTYPE_EQUIPPACK: pInventory = m_pEquipPack; break; + case Inventory_type.IVTRTYPE_TASKPACK: pInventory = m_pTaskPack; break; + //case Inventory_type.IVTRTYPE_TRASHBOX: pInventory = m_pTrashBoxPack; break; + //case Inventory_type.IVTRTYPE_TRASHBOX2: pInventory = m_pTrashBoxPack2; break; + //case Inventory_type.IVTRTYPE_TRASHBOX3: pInventory = m_pTrashBoxPack3; break; + //case Inventory_type.IVTRTYPE_ACCOUNT_BOX: pInventory = m_pAccountBoxPack; break; + //case Inventory_type.IVTRTYPE_GENERALCARD_BOX: pInventory = m_pGeneralCardPack; break; + //case IVTRTYPE_PACK_CLIENT_GENERALCAR.IVTRTYPE_CLIENT_GENERALCARD_PACK: pInventory = m_pClientGenCardPack; break; + default: + return null; + } + return pInventory; + } + public int GetEquippedSuiteItem(int idSuite, ref int[] aItems) { int i, iItemCnt = 0;