using System; using System.Collections.Generic; using BrewMonster.Scripts.Task; using CSNetwork; using CSNetwork.GPDataType; using UnityEngine; using System.Runtime.InteropServices; using BrewMonster.Network; using BrewMonster.UI; using Cysharp.Threading.Tasks; using System.Threading.Tasks; namespace BrewMonster { // ���׶� // Contribution info [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct CONTRIB_INFO { public int consume_contrib; // �����ѵ� // Consume contribution public int exp_contrib; // �ɶһ����ɾ���� // Experience contribution public int cumulate_contrib; // �ۻ�ֵ // Cumulative contribution // public CONTRIB_INFO() // { // consume_contrib = 0; // exp_contrib = 0; // cumulate_contrib = 0; // } } public partial class CECHostPlayer { private int m_idTradePlayer; // ID of player who is trading with us private CECTaskInterface m_pTaskInterface; private int m_iBoothState; // Booth state. 0, none; 1, prepare; 2, open booth; 3, visite other's booth private CONTRIB_INFO m_contribInfo; private CECCounter m_TaskCounter = new CECCounter(); private bool m_bTitleDataReady; private List m_Titles = new(); public CECTaskInterface GetTaskInterface() { return m_pTaskInterface; } // Is host player trading ? public bool IsTrading() { return m_idTradePlayer != 0; } public CONTRIB_INFO GetContribInfo() { return m_contribInfo; } public int GetBoothState() { return m_iBoothState; } public CECShortcutSet GetShortcutSet1(int n) { return m_aSCSets1[n]; } public CECShortcutSet GetShortcutSet2(int n) { return m_aSCSets2[n]; } private async UniTaskVoid OnMsgHstTaskData(ECMSG Msg) { // decode header to distinguish TASK_DATA vs TASK_VAR_DATA // if (!(Msg.dwParam2 is cmd_header header)) // { // Debug.LogError("OnMsgHstTaskData: invalid header"); // return; // } int header = Convert.ToInt32(Msg.dwParam2); byte[] pDataBuf = Msg.dwParam1 as byte[]; if (pDataBuf == null) { Debug.LogError("OnMsgHstTaskData: missing payload buffer"); return; } if (header == CommandID.TASK_DATA) { // Parse aggregated task buffers cmd_task_data pCmd = cmd_task_data.FromBuffer(pDataBuf); // cmd_task_data pCmd = GPDataTypeHelper.FromBytes<cmd_task_data>(pDataBuf); // Release and recreate task interface m_pTaskInterface = null; m_pTaskInterface = new CECTaskInterface(this); var initTask = await m_pTaskInterface.Init( pCmd.active_list, (int)pCmd.active_list_size, pCmd.finished_list, (int)pCmd.finished_list_size, pCmd.finished_time_list, (int)pCmd.finished_time_list_size, pCmd.finished_count, (int)pCmd.finished_count_size, pCmd.storage_task, (int)pCmd.storage_task_size); if (!initTask) { Debug.LogError("CECHostPlayer::OnMsgHstTaskData, failed to initialize task interface"); return; } m_pTaskInterface.CheckPQEnterWorldInit(); // check if player has equipped goblin (not yet implemented in C#) // TODO: implement goblin initialization when equipment system is ready // GET_ALL_DATA end flag tasks were here in C++ (LoadConfigData), omitted in C# UnityGameSession.LoadConfigData(); // Quest trace lists + minimion: apply SyncTrace once active tasks and templates are ready. // 任务追踪:在任务数据与模板就绪后调用 SyncTrace 同步追踪列表与小窗。 var pGameUI = EC_Game.GetGameRun()?.GetUIManager()?.GetInGameUIMan(); pGameUI?.OnHostTaskDataInitialized(m_pTaskInterface); // if (UpdateEquipSkills()) UpdateEquipSkillCoolDown(); // methods not ported yet } else if (header == CommandID.TASK_VAR_DATA) { // Minimal forwarding; original code passes inner data pointer and size cmd_task_var_data pCmd = new cmd_task_var_data(); pCmd.ReadBuffer(pDataBuf); // ASSERT(pCmd); if(m_pTaskInterface!= null) OnServerNotify(m_pTaskInterface, pCmd.data, (int)pCmd.size); else // ASSERT(m_pTaskInterface); BMLogger.LogError($" CECHostPlayer::OnMsgHstTaskData: TASK_VAR_DATA received but m_pTaskInterface is null"); } } private void OnServerNotify(CECTaskInterface pInterface, byte[] data, int size) { TaskClient.OnServerNotify(pInterface, data, (uint)size); } private async UniTask TickTask() { // Update task while (true) { TaskClient.OnTaskCheckStatus(m_pTaskInterface); await Task.Delay(1000); } } public bool IsTitleDataReady() { return m_bTitleDataReady; } // Converted from C++ to C#. Pointer-based parts marked as TODO. private void OnMsgTitle(ECMSG msg) { // TODO: Replace with actual access pattern for your game systems var gameUI = EC_Game.GetGameRun().GetUIManager().GetInGameUIMan(); int header = Convert.ToInt32(msg.dwParam2); byte[] pDataBuf = msg.dwParam1 as byte[]; if (header == CommandID.QUERY_TITLE_RE) { // Replace unsafe pointer cast with proper C# struct deserialization // var cmd = msg.dwParam1 as cmd_query_title_re; var cmd = new cmd_query_title_re(); bool wasRead = cmd.ReadFromBytes(pDataBuf); if (wasRead) { InitTitle(cmd.titlescount, cmd.titles); // TODO: Original code uses pointer arithmetic: // (void*)((unsigned short*)(pCmd->titles) + pCmd->titlescount) // InitTitlePlus(cmd.expirecount, null); // CECUIHelper.OnQueryTitleRe(); } } else if (header == CommandID.CHANGE_CURR_TITLE_RE) { // Replace unsafe pointer cast // var cmd = msg.dwParam1 as cmd_change_curr_title_re; var cmd = GPDataTypeHelper.FromBytes<cmd_query_title_re>(pDataBuf); // if (cmd != null) { // TODO: Update current title in UI // var dlg = gameUI.GetDialog("Win_TitleList") as CDlgTitleList; // SetCurrentTitle(cmd.titleid); // dlg?.Update(); } } else if (header == CommandID.MODIFY_TITLE_NOFIFY) { // Replace unsafe pointer cast // var cmd = msg.dwParam1 as cmd_modify_title_notify; var cmd = GPDataTypeHelper.FromBytes<cmd_modify_title_notify>(pDataBuf); // if (cmd != null) { bool add = cmd.flag != 0; if (add) { // TODO: Update UI to add title // CECUIHelper.AddTitle(cmd.id, cmd.expiretime); // If first title, auto change current title if (m_Titles.Count == 0) { // TODO: Original code calls g_pGame.GetGameSession() // g_pGame.GetGameSession().c2s_CmdChangeTitle(cmd.id); // EC_Game.GetGameSession().c2s_CmdChangeTitle(cmd.id); } } // TODO: Update UI to modify title // ModifyTitle(cmd.id, cmd.expiretime, add); } } } public void InitTitle(int count, ushort[] id) { m_Titles.Clear(); m_bTitleDataReady = true; // if (id == NULL) return; for (int i = 0; i < count; ++i) { m_Titles.Add(new TITLE(id[i], 0)); } } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct TITLE { public ushort id; public int expire_time; public TITLE(ushort _id, int _expire_time) { id = _id; expire_time = _expire_time; } // TITLE(unsigned short _id, int _expire_time):id(_id),expire_time(_expire_time){} // bool operator == (const TITLE& rhs) const {return id == rhs.id;} }; } }