From f183544b4dae24960ac2ae7d9e379943a24a2736 Mon Sep 17 00:00:00 2001 From: MinhHai Date: Tue, 24 Feb 2026 14:29:09 +0700 Subject: [PATCH] WIP: prepare config before send to Server --- .../Scripts/Managers/EC_Inventory.cs | 2 +- .../Scripts/UI/GamePlay/EC_GameUIMan.cs | 157 ++++++++++++++++- Assets/Scripts/CECGameRun.cs | 4 +- Assets/Scripts/CECHostPlayer.ConfigData.cs | 159 +++++++++++++++++- Assets/Scripts/CECHostPlayer.Task.cs | 3 +- 5 files changed, 316 insertions(+), 9 deletions(-) diff --git a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs index 0480c3265f..93f3700dce 100644 --- a/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs +++ b/Assets/PerfectWorld/Scripts/Managers/EC_Inventory.cs @@ -60,7 +60,7 @@ namespace BrewMonster.Scripts.Managers } } - public void Resize(int iNewSize) + public virtual void Resize(int iNewSize) { int oldSize = m_aItems.Length; if (iNewSize < 0) iNewSize = 0; diff --git a/Assets/PerfectWorld/Scripts/UI/GamePlay/EC_GameUIMan.cs b/Assets/PerfectWorld/Scripts/UI/GamePlay/EC_GameUIMan.cs index 3192bc83b8..b7224a7d9e 100644 --- a/Assets/PerfectWorld/Scripts/UI/GamePlay/EC_GameUIMan.cs +++ b/Assets/PerfectWorld/Scripts/UI/GamePlay/EC_GameUIMan.cs @@ -164,10 +164,163 @@ namespace BrewMonster.UI /// Get user layout data for saving to server. Stub: returns size 0 (UI layout save not implemented). /// 获取用户布局数据用于保存到服务器。桩:返回长度 0(UI 布局保存未实现)。 /// + /// TODO: NOW, IT ONLY RETURN THE FIXED SIZE OF STRUCTURE. NEED TO IMPLEMENT THE REAL DATA SAVE/LOAD. public void GetUserLayout(byte[] pData, ref uint dwUISize) { - dwUISize = 0; - // When pData != null and dwUISize > 0, would write layout bytes + if( pData != null ) + { + // int i; + // USER_LAYOUT ul; + // char szName[40]; + // PAUICHECKBOX pCheck; + // CECHostPlayer *pHost = g_pGame->GetGameRun()->GetHostPlayer(); + // + // memset(&ul, 0, sizeof(USER_LAYOUT)); + // + // ul.nVersion = LAYOUTDATA_VERSION; + // ul.nMapMode = m_pDlgMiniMap->GetMode(); + // + // ul.bQuickbarPetMode = GetDialog("Win_QuickbarPetV")->IsShow(); + // + // AString dlgName; + // + // dlgName.Format("Win_Quickbar%dHa", SIZE_HOSTSCSET1); + // ul.bQuickbar1Mode = GetDialog(dlgName)->IsShow(); + // for( i = 0; i < NUM_HOSTSCSETS1; i++ ) + // { + // sprintf(szName, "Win_Quickbar%dHb_%d", SIZE_HOSTSCSET1, i+1); + // pCheck = (PAUICHECKBOX)GetDialog(szName)->GetDlgItem("Chk_Normal"); + // ul.bChecked1[i] = pCheck->IsChecked(); + // } + // + // dlgName.Format("Win_Quickbar%dHa", SIZE_HOSTSCSET2); + // ul.bQuickbar2Mode = GetDialog(dlgName)->IsShow(); + // for( i = 0; i < NUM_HOSTSCSETS2; i++ ) + // { + // sprintf(szName, "Win_Quickbar%dHb_%d", SIZE_HOSTSCSET2, i+1); + + // pCheck = (PAUICHECKBOX)GetDialog(szName)->GetDlgItem("Chk_Normal"); + // ul.bChecked2[i] = pCheck->IsChecked(); + // } + // + // m_pDlgTask->SyncTrace(&ul, false); + // ul.bQuickbarShowAll1 = CDlgQuickBar::m_bShowAll1; + // ul.bQuickbarShowAll2 = CDlgQuickBar::m_bShowAll2; + // ul.nQuickbarCurPanel1 = CDlgQuickBar::m_nCurPanel1; + // ul.nQuickbarCurPanel2 = CDlgQuickBar::m_nCurPanel2; + // ul.nQuickbarDisplayPanels1 = CDlgQuickBar::m_nDisplayPanels1; + // ul.nQuickbarDisplayPanels2 = CDlgQuickBar::m_nDisplayPanels2; + // + // ul.nChatWinSize = m_pDlgChat->GetChatWinSize(); + // ul.nCurChatColor = m_pDlgChat->GetChatColor(); + // + // for( i = 0; i < (int)m_pDlgMiniMap->GetMarks().size(); i++ ) + // { + // ul.a_Mark[i].nNPC = m_pDlgMiniMap->GetMarks()[i].nNPC; + // ul.a_Mark[i].vecPos = m_pDlgMiniMap->GetMarks()[i].vecPos; + // ul.a_MarkMapID[i] = (short)m_pDlgMiniMap->GetMarks()[i].mapID; + // a_strncpy(ul.a_Mark[i].szName, m_pDlgMiniMap->GetMarks()[i].strName, CECGAMEUIMAN_MARK_NAME_LEN); + // } + // + // CECFriendMan::GROUP *pGroup; + // CECFriendMan *pMan = g_pGame->GetGameRun()->GetHostPlayer()->GetFriendMan(); + // if (pMan) + // { + // int j(0); + // for( i = 0; i < pMan->GetGroupNum() && j < CECGAMEUIMAN_MAX_GROUPS; i++ ) + // { + // pGroup = pMan->GetGroupByIndex(i); + // if (pGroup->iGroup) + // { + // ul.idGroup[j] = pGroup->iGroup; + // ul.clrGroup[j] = pGroup->color; + // ++ j; + // } + // } + // } + // ul.bAutoReply = m_bAutoReply; + // ul.bOnlineNotify = m_bOnlineNotify; + // ul.bSaveHistory = m_bSaveHistory; + // + // ul.ucCurSystemModuleSC = pHost->GetCurSysModShortcutSetIndex(); // ��ǰʹ�õ�ϵͳģ������ + // + // ul.bSystemModuleQuickBarMini = m_pDlgSysModuleQuickBar->GetMiniMode(); + // + // ul.bMenuMode = m_pDlgSystemb->IsShow(); + // + // ul.bShowCompareDesc = m_bShowItemDescCompare; + // ul.bShowLowHP = m_bShowLowHP; + // ul.bShowTargetOfTarget = m_bShowTargetOfTarget; + // + // memcpy(pvData, &ul, sizeof(USER_LAYOUT)); + // + // POINT ptPos; + // float fx, fy; + // AIniFile theIni; + // char szIniFile[MAX_PATH], szKey[40]; + // A3DVIEWPORTPARAM *p = m_pA3DEngine->GetActiveViewport()->GetParam(); + // + // for( i = 0; i < (int)m_aDialog.size() - 1; i++ ) + // { + // ptPos = m_aDialog[i]->GetPos(); + // + // fx = ptPos.x * 100.0f / p->Width; + // fy = ptPos.y * 100.0f / p->Height; + // + // //�Խ���԰UIλ�ò����� + // /* + // if( dynamic_cast( m_aDialog[i]) != NULL) + // { + // continue; + // } + // */ + // + // sprintf(szKey, "%s_x", m_aDialog[i]->GetName()); + // theIni.WriteFloatValue("Windows", szKey, fx); + // + // sprintf(szKey, "%s_y", m_aDialog[i]->GetName()); + // theIni.WriteFloatValue("Windows", szKey, fy); + // } + // + // // ͬ������ "Win_ELFZoom"��"Win_ELF" ��λ�� + // // + // PAUIDIALOG pDlg(NULL); + // if (GetDialog("Win_ELF")->IsShow()) + // { + // pDlg = GetDialog("Win_ELFZoom"); + // ptPos = GetDialog("Win_ELF")->GetPos(); + // } + // else if (GetDialog("Win_ELFZoom")->IsShow()) + // { + // pDlg = GetDialog("Win_ELF"); + // ptPos = GetDialog("Win_ELFZoom")->GetPos(); + // } + // if (pDlg) + // { + // fx = ptPos.x * 100.0f / p->Width; + // fy = ptPos.y * 100.0f / p->Height; + // + // sprintf(szKey, "%s_x", pDlg->GetName()); + // theIni.WriteFloatValue("Windows", szKey, fx); + // + // sprintf(szKey, "%s_y", pDlg->GetName()); + // theIni.WriteFloatValue("Windows", szKey, fy); + // } + // + // sprintf(szIniFile, "%s\\Userdata\\Layout", af_GetBaseDir()); + // CreateDirectoryA(szIniFile, NULL); + // + // sprintf(szIniFile, "%s\\UserData\\Layout\\%d.ini", + // af_GetBaseDir(), pHost->GetCharacterID()); + // theIni.Save(szIniFile); + // theIni.Close(); + } + else + { + // TODO: NEW STRUCT USER_LAYOUT + // dwSize = sizeof(USER_LAYOUT); + dwUISize = 344; + } } public override void Init() diff --git a/Assets/Scripts/CECGameRun.cs b/Assets/Scripts/CECGameRun.cs index 5b3257e9bf..c0db691a41 100644 --- a/Assets/Scripts/CECGameRun.cs +++ b/Assets/Scripts/CECGameRun.cs @@ -796,7 +796,7 @@ public partial class CECGameRun // iTotalSize += (int)dwUISize; // iTotalSize += sizeof (int); uint dwUISize = 0; - pGameUI.GetUserLayout(null, ref dwUISize); + pGameUI.GetUserLayout(null, ref dwUISize); // TODO: Check if this is needed here iTotalSize += sizeof(int) + (int)dwUISize; // int iSettingSize = 0; @@ -832,7 +832,7 @@ public partial class CECGameRun // pData += dwUISize; Buffer.BlockCopy(BitConverter.GetBytes((int)dwUISize), 0, pDataBuf, offset, sizeof(int)); offset += sizeof(int); - pGameUI.GetUserLayout(pDataBuf, ref dwUISize); + pGameUI.GetUserLayout(pDataBuf, ref dwUISize); // TODO: Check if this is needed here offset += (int)dwUISize; // *((int*)pData) = iSettingSize; diff --git a/Assets/Scripts/CECHostPlayer.ConfigData.cs b/Assets/Scripts/CECHostPlayer.ConfigData.cs index 5a2566acf1..5f3eded878 100644 --- a/Assets/Scripts/CECHostPlayer.ConfigData.cs +++ b/Assets/Scripts/CECHostPlayer.ConfigData.cs @@ -24,6 +24,8 @@ namespace BrewMonster // C++: CECDealInventory* m_pBoothBPack / m_pBoothSPack – booth buy pack and sell pack private CECDealInventory m_pBoothBPack = null; // 摆摊收购包 Booth buy pack private CECDealInventory m_pBoothSPack = null; // 摆摊出售包 Booth sell pack + + BOOTH_AUTO_YINPIAO m_AutoYinpiao; // C++: Host config constants (version, shortcut set counts/sizes) private static class HostCfgConstants @@ -162,6 +164,75 @@ namespace BrewMonster // pData += iSize; (C#: offset updated by LoadConfigData ref) } } + + // Load Saved Booth Buy and Sell Pack + // 加载保存的摆摊收购包与出售包 + // if (dwVer > 7) { struct BoothItem { ... }; BoothItem temp; const int nPacks = 2; ... + if (dwVer > 7) + { + // BoothItem temp; + BoothItem temp; + // const int nPacks = 2; + const int nPacks = 2; + // CECDealInventory *pBoothPacks[nPacks] = {GetBoothBuyPack(), GetBoothSellPack()}; + CECDealInventory[] pBoothPacks = new CECDealInventory[] { GetBoothBuyPack(), GetBoothSellPack() }; + // DWORD nMaxBoothPacks[nPacks] = {IVTRSIZE_BOOTHBPACK_MAX, IVTRSIZE_BOOTHSPACK_MAX}; + uint[] nMaxBoothPacks = new uint[] { InventoryConst.IVTRSIZE_BOOTHBPACK_MAX, InventoryConst.IVTRSIZE_BOOTHSPACK_MAX }; + // for (int k=0 ; k < nPacks; ++k) + for (int k = 0; k < nPacks; ++k) + { + // CECDealInventory *pBoothPack = pBoothPacks[k]; + CECDealInventory pBoothPack = pBoothPacks[k]; + // bool isBuyPack = (pBoothPack == GetBoothBuyPack()); + bool isBuyPack = (pBoothPack == GetBoothBuyPack()); + // DWORD dwCurSize = pBoothPack->GetSize(); + int dwCurSize = (pBoothPack != null) ? pBoothPack.GetSize() : 0; + + // DWORD dwSize = *((DWORD *)pData); pData += sizeof(dwSize); + if (offset + sizeof(uint) > dataBuf.Length) + return false; + uint dwSize = GPDataTypeHelper.FromBytes(dataBuf, offset); + offset += sizeof(uint); + + // ��֤���ݣ��г��������� + // 验证数据,防止越界读取 | Verify data, prevent out-of-bounds read + if (dwSize > nMaxBoothPacks[k]) + { + UnityEngine.Debug.LogWarningFormat("CECHostPlayer::LoadConfigData, Failed because pack {0} size invalid ({1}:{2}).", k, dwSize, nMaxBoothPacks[k]); + return false; + } + + for (uint i = 0; i < dwSize; ++i) + { + // ����İ�����С�ܿ����뵱ǰ������С��ͬ���Ե�ǰ������СΪ׼ + // 保存的包大小可能和当前背包大小不同,以当前背包大小为准 | Saved pack size may differ from current; use current as reference + if (i < (uint)dwCurSize) + { + if (offset + Marshal.SizeOf() > dataBuf.Length) + return false; + temp = GPDataTypeHelper.FromBytes(dataBuf, offset); + + // ��֤��ȡ���ݵĺϷ��� + if (temp.idItem > 0 && + temp.iAmount > 0 && + temp.iUnitPrice >= 0 && + temp.iOrigin >= 0) + { + EC_IvtrItem pItem2 = m_pPack.GetItem((int)temp.iOrigin, false); + if (pItem2 != null && pItem2.GetTemplateID() == (int)temp.idItem) + { + // ��Ʒ�ڵ�ǰ�����鵽������ȷ����ԭ��Ʒͬ����Ʒ + + int iAmount = isBuyPack ? (int)temp.iAmount : EC_Utility.a_Min((int)temp.iAmount, pItem2.GetCount()); + if (pBoothPack != null) + pBoothPack.AddBoothItem(pItem2, (int)temp.iOrigin, iAmount, (int)temp.iUnitPrice); + } + } + } + offset += Marshal.SizeOf(); + } + } + } // Notes: // - Auto fashion sets, system module shortcut sets, booth packs, and AutoYinpiao @@ -283,8 +354,13 @@ namespace BrewMonster } // } iTotalSize += sizeof(DWORD) + dwSize * sizeof(BoothItem); } + + // ��Ʊ�Զ�ת�� + list.AddRange( BitConverter.GetBytes(m_AutoYinpiao.low_money) ); + list.AddRange( BitConverter.GetBytes(m_AutoYinpiao.high_money) ); iHostSize = list.Count; + if (pData != null && writeOffset >= 0 && writeOffset + iHostSize <= pData.Length) Buffer.BlockCopy(list.ToArray(), 0, pData, writeOffset, iHostSize); return true; @@ -342,11 +418,88 @@ namespace BrewMonster // 交易/摆摊背包,仅提供保存配置所需的接口 public class CECDealInventory : EC_Inventory { - private readonly List m_aItems = new List(); + // private readonly List m_aItems = new List(); private readonly List m_aItemInfo = new List(); - public int GetSize() => m_aItems.Count; + // public int GetSize() => m_aItems.Count; public CECDealInventory_ITEMINFO GetItemInfo(int n) => m_aItemInfo[n]; - public EC_IvtrItem GetItem(int i) => (i >= 0 && i < m_aItems.Count) ? m_aItems[i] : null; + // public EC_IvtrItem GetItem(int i) => (i >= 0 && i < m_aItems.Count) ? m_aItems[i] : null; + + // C++: AddBoothItem(pItem, iOrigin, iAmount, iUnitPrice) – add item to booth pack with origin/amount/price + public void AddBoothItem(EC_IvtrItem pItem, int iOrigin, int iAmount, int iUnitPrice) + { + int slot = SearchEmpty(); + if (slot < 0) + return; + while (m_aItemInfo.Count <= slot) + m_aItemInfo.Add(default); + m_aItemInfo[slot] = new CECDealInventory_ITEMINFO { iOrigin = iOrigin, iAmount = iAmount, bDelete = false, iFlag = 0 }; + SetItem(slot, pItem); + if (pItem != null) + pItem.SetUnitPrice(iUnitPrice); + } + + // Resize inventory + // C++: void CECDealInventory::Resize(int iNewSize) + public override void Resize(int iNewSize) + { + // int iOldSize = m_aItemInfo.GetSize(); + int iOldSize = m_aItemInfo.Count; + // if(iNewSize < iOldSize) { for(int i=iNewSize;i iNewSize) + m_aItemInfo.RemoveRange(iNewSize, m_aItemInfo.Count - iNewSize); + while (m_aItemInfo.Count < iNewSize) + m_aItemInfo.Add(default); + + // if(iOldSize < iNewSize) { /* Clear new slots */ for (int i=iOldSize; i < iNewSize; i++) { m_aItemInfo[i].iOrigin = 0; ... } } + if (iOldSize < iNewSize) + { + // Clear new slots + for (int i = iOldSize; i < iNewSize; i++) + { + m_aItemInfo[i] = new CECDealInventory_ITEMINFO + { + iOrigin = 0, + iAmount = 0, + bDelete = false, + iFlag = 0 + }; + } + } + } + } + + // ��̯��Ʊ�Զ�ת�� + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct BOOTH_AUTO_YINPIAO + { + public bool open; + public CECCounter cnt; + public int low_money; + public int high_money; + + // C++: BOOTH_AUTO_YINPIAO() : open(false), low_money(50000000), high_money(100000000) { cnt.SetPeriod(60000); cnt.Reset(true); } + public BOOTH_AUTO_YINPIAO(int i=0) + { + open = false; + low_money = 50000000; + high_money = 100000000; + cnt = new CECCounter(); + cnt.SetPeriod(60000); + cnt.Reset(true); + } } } diff --git a/Assets/Scripts/CECHostPlayer.Task.cs b/Assets/Scripts/CECHostPlayer.Task.cs index cb612dece1..d390461677 100644 --- a/Assets/Scripts/CECHostPlayer.Task.cs +++ b/Assets/Scripts/CECHostPlayer.Task.cs @@ -136,7 +136,8 @@ namespace BrewMonster m_TaskCounter.IncCounter(Time.deltaTime * 1000f)) { m_TaskCounter.Reset(); - TaskClient.OnTaskCheckStatus(m_pTaskInterface); + // TODO: open later + // TaskClient.OnTaskCheckStatus(m_pTaskInterface); // TODO: Update task UI if needed // m_pTaskInterface.UpdateEmotionDlg(); }