using BrewMonster.Assets.PerfectWorld.Scripts.UI; using BrewMonster.Scripts.Managers; using CSNetwork.GPDataType; using PerfectWorld.Scripts; using System; using System.Collections.Generic; using System.Runtime.InteropServices; using BrewMonster.Scripts; namespace BrewMonster { public partial class CECHostPlayer { // Shortcut sets (converted from C++: m_aSCSets1[NUM_HOSTSCSETS1], m_aSCSets2[NUM_HOSTSCSETS2], m_aSCSetSysMod[NUM_SYSMODSETS]) public CECShortcutSet[] m_aSCSets1 = new CECShortcutSet[HostCfgConstants.NUM_HOSTSCSETS1]; // SC set 1 public CECShortcutSet[] m_aSCSets2 = new CECShortcutSet[HostCfgConstants.NUM_HOSTSCSETS2]; // SC set 2 public CECShortcutSet[] m_aSCSetSysMod = new CECShortcutSet[HostCfgConstants.NUM_SYSMODSETS]; // System module shortcut sets public int[] m_aFashionSCSets = new int[HostCfgConstants.SIZE_FASHIONSCSET]; // Auto fashion shortcut sets (indices) // 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 // C++: Host config constants (version, shortcut set counts/sizes) private static class HostCfgConstants { public const int HOSTCFG_VERSION = 11; public const int NUM_HOSTSCSETS1 = 5; // expanded from 3 to 5 (2009.05.27) public const int NUM_HOSTSCSETS2 = 3; public const int SIZE_HOSTSCSET1 = 9; // expanded from 6 to 9 (2009.05.27) public const int SIZE_HOSTSCSET2 = 8; public const int NUM_SYSMODSETS = 4; // System module shortcut sets count public const int SIZE_SYSMODSCSET = 4; // System module shortcut set size (first 4 slots) public const int SIZE_FASHIONSCSET = 240; } // Load configs data (shortcut, etc.) from specified buffer // Converted from: bool CECHostPlayer::LoadConfigData(const void* pDataBuf) public bool LoadConfigData(byte[] dataBuf) { if (dataBuf == null || dataBuf.Length < sizeof(uint)) return false; int offset = 0; // Version number uint dwVer = GPDataTypeHelper.FromBytes(dataBuf, offset); offset += sizeof(uint); if (dwVer > HostCfgConstants.HOSTCFG_VERSION) { return false; } // Load shortcut configs... int iHostSCSets1 = (dwVer <= 4) ? 3 : HostCfgConstants.NUM_HOSTSCSETS1; for (int i = 0; i < iHostSCSets1; i++) { if (offset >= dataBuf.Length) return false; if (m_aSCSets1[i] == null) { m_aSCSets1[i] = new CECShortcutSet(); m_aSCSets1[i].Init(HostCfgConstants.SIZE_HOSTSCSET1); } if (!m_aSCSets1[i].LoadConfigData(dataBuf, dwVer, ref offset)) return false; } for (int i = 0; i < HostCfgConstants.NUM_HOSTSCSETS2; i++) { if (offset >= dataBuf.Length) break; // No more data; tolerate truncated optional parts if (m_aSCSets2[i] == null) { m_aSCSets2[i] = new CECShortcutSet(); m_aSCSets2[i].Init(HostCfgConstants.SIZE_HOSTSCSET2); } if (!m_aSCSets2[i].LoadConfigData(dataBuf, dwVer, ref offset)) return false; } // Load auto fashion shortcut sets // Load auto fashion shortcut sets // if(dwVer > 5) if (dwVer > 5) { // int size = 0; // if (dwVer == 6) size = 120; else size = HostCfgConstants.SIZE_FASHIONSCSET; int size = (dwVer == 6) ? 120 : HostCfgConstants.SIZE_FASHIONSCSET; // for (i=0; i < size; i++) for (int i = 0; i < size; i++) { // if (dwVer <= 8 && (i % 6 == 5)) continue; if (dwVer <= 8 && (i % 6 == 5)) continue; // m_aFashionSCSets[i] = *((int*)pData); pData += sizeof(int); if (offset + sizeof(int) > dataBuf.Length) return false; m_aFashionSCSets[i] = GPDataTypeHelper.FromBytes(dataBuf, offset); offset += sizeof(int); } } // Load system module shortcut sets // Load system module shortcut sets // if(dwVer > 10) if (dwVer > 10) { // for (i=0; i < NUM_SYSMODSETS; i++) for (int iSysMod = 0; iSysMod < HostCfgConstants.NUM_SYSMODSETS; iSysMod++) { // (C#: bounds check; C++ advances pData so no separate check) if (offset >= dataBuf.Length) return false; // (C#: lazy init; C++ assumes array already allocated) if (m_aSCSetSysMod[iSysMod] == null) { m_aSCSetSysMod[iSysMod] = new CECShortcutSet(); m_aSCSetSysMod[iSysMod].Init(HostCfgConstants.SIZE_SYSMODSCSET); } // int iSize; // if (!m_aSCSetSysMod[i]->LoadConfigData(pData, &iSize, dwVer)) return false; if (!m_aSCSetSysMod[iSysMod].LoadConfigData(dataBuf, dwVer, ref offset)) return false; // if (i==0) // 如果第一个4个位置均为空,则初始化默认快捷键 | If the first 4 slots are all empty, init default shortcuts if (iSysMod == 0) { // CECShortcutSet *pSCS = m_aSCSetSysMod[0]; CECShortcutSet pSCS = m_aSCSetSysMod[0]; // int ksc = 0; // for (ksc = 0;kscGetShortcutNum();ksc++) { if (pSCS->GetShortcut(ksc)) break; } int ksc; for (ksc = 0; ksc < pSCS.GetShortcutNum(); ksc++) { if (pSCS.GetShortcut(ksc) != null) break; } // if (ksc == pSCS->GetShortcutNum()) if (ksc == pSCS.GetShortcutNum()) { // int c = CECUIConfig::Instance().GetGameUI().nDefaultSystemModuleIndex.size(); // c = min(c,4); var defaultList = CECUIConfig.Instance.GetGameUI().nDefaultSystemModuleIndex; int c = (defaultList != null) ? defaultList.Count : 0; c = Math.Min(c, 4); // for (int i=0;iCreateSystemModuleShortcut(i, CECUIConfig::Instance().GetGameUI().nDefaultSystemModuleIndex[i]); for (int j = 0; j < c; j++) pSCS.CreateSystemModuleShortcut(j, defaultList[j]); } } // pData += iSize; (C#: offset updated by LoadConfigData ref) } } // Notes: // - Auto fashion sets, system module shortcut sets, booth packs, and AutoYinpiao // sections from native are not loaded here in this Unity port yet. // The native format appends these after the two shortcut-set groups. // We intentionally ignore them safely for now. return true; } /// /// Save host config (shortcut sets, etc.) to buffer. When pData is null, only outputs size in iHostSize. /// 保存主机配置(快捷键组等)到缓冲区。pData 为 null 时仅输出 iHostSize。 /// /// When pData is not null, write at this index. 写入时的起始下标。 public bool SaveConfigData(byte[] pData, ref int iHostSize, int writeOffset = 0) { var list = new List(); list.AddRange(BitConverter.GetBytes(HostCfgConstants.HOSTCFG_VERSION)); for (int i = 0; i < m_aSCSets1.Length; i++) { if (m_aSCSets1[i] == null || !m_aSCSets1[i].SaveConfigData(out byte[] buf)) continue; list.AddRange(buf); } for (int i = 0; i < m_aSCSets2.Length; i++) { if (m_aSCSets2[i] == null || !m_aSCSets2[i].SaveConfigData(out byte[] buf)) continue; list.AddRange(buf); } // Save auto fashion shortcut sets | 保存自动时装快捷键组 // if(pDataBuf) // { // for (i=0; i < SIZE_FASHIONSCSET; i++) // { // *((int*)pData) = m_aFashionSCSets[i]; // if(pData) // pData += sizeof (int); // } // } // iTotalSize += sizeof(int) * SIZE_FASHIONSCSET; for (int i = 0; i < HostCfgConstants.SIZE_FASHIONSCSET; i++) { list.AddRange(BitConverter.GetBytes(m_aFashionSCSets[i])); } // Save system module shortcut sets | 保存系统模块快捷键组 // for (i=0; i < NUM_SYSMODSETS; i++) // { // m_aSCSetSysMod[i]->SaveConfigData(pData, &iSize); // iTotalSize += iSize; // if (pData) // pData += iSize; // } for (int i = 0; i < HostCfgConstants.NUM_SYSMODSETS; i++) { if (m_aSCSetSysMod[i] == null || !m_aSCSetSysMod[i].SaveConfigData(out byte[] buf)) continue; list.AddRange(buf); } // Save Booth Buy and Sell Pack // 保存摆摊收购包与出售包 // CECDealInventory *pBoothPacks[2] = {GetBoothBuyPack(), GetBoothSellPack()}; CECDealInventory[] pBoothPacks = new CECDealInventory[] { GetBoothBuyPack(), GetBoothSellPack() }; // for (int k=0 ; k < sizeof(pBoothPacks)/sizeof(pBoothPacks[0]); ++k) for (int k = 0; k < pBoothPacks.Length; ++k) { // CECDealInventory *pBoothPack = pBoothPacks[k]; CECDealInventory pBoothPack = pBoothPacks[k]; // bool isBuyPack = (pBoothPack == GetBoothBuyPack()); bool isBuyPack = (pBoothPack == GetBoothBuyPack()); // DWORD dwSize = pBoothPack->GetSize(); uint dwSize = (uint)(pBoothPack != null ? pBoothPack.GetSize() : 0); // if (pData) { *((DWORD *)pData) = dwSize; pData += sizeof(DWORD); list.AddRange(BitConverter.GetBytes(dwSize)); // // BoothItem temp; for (DWORD i = 0; i < dwSize; ++ i) if (pBoothPack != null) { for (uint i = 0; i < dwSize; ++i) { // ::ZeroMemory(&temp, sizeof(temp)); BoothItem temp = default; // const CECDealInventory::ITEMINFO &ii = pBoothPack->GetItemInfo(i); CECDealInventory_ITEMINFO ii = pBoothPack.GetItemInfo((int)i); // CECIvtrItem* pItem1 = pBoothPack->GetItem(i); EC_IvtrItem pItem1 = pBoothPack.GetItem((int)i); // if (pItem1) { CECIvtrItem* pItem2 = m_pPack->GetItem(ii.iOrigin); if (pItem1 != null) { // CECIvtrItem* pItem2 = m_pPack->GetItem(ii.iOrigin); EC_IvtrItem pItem2 = m_pPack.GetItem(ii.iOrigin, false); // if (pItem2 && pItem2->GetTemplateID() == pItem1->GetTemplateID()) if (pItem2 != null && pItem2.GetTemplateID() == pItem1.GetTemplateID()) { // temp.idItem = pItem1->GetTemplateID(); temp.iOrigin = ii.iOrigin; temp.idItem = (uint)pItem1.GetTemplateID(); temp.iOrigin = (uint)ii.iOrigin; // temp.iUnitPrice = pItem1->GetUnitPrice(); temp.iUnitPrice = (uint)pItem1.GetUnitPrice(); // temp.iAmount = isBuyPack ? ii.iAmount : a_Min(ii.iAmount, pItem2->GetCount()); temp.iAmount = isBuyPack ? (uint)ii.iAmount : (uint)Math.Min(ii.iAmount, pItem2.GetCount()); } } // // *((BoothItem *)pData) = temp; pData += sizeof(temp); list.AddRange(BitConverter.GetBytes(temp.idItem)); list.AddRange(BitConverter.GetBytes(temp.iOrigin)); list.AddRange(BitConverter.GetBytes(temp.iAmount)); list.AddRange(BitConverter.GetBytes(temp.iUnitPrice)); } } // } iTotalSize += sizeof(DWORD) + dwSize * sizeof(BoothItem); } iHostSize = list.Count; if (pData != null && writeOffset >= 0 && writeOffset + iHostSize <= pData.Length) Buffer.BlockCopy(list.ToArray(), 0, pData, writeOffset, iHostSize); return true; } // C++: GetBoothBuyPack() / GetBoothSellPack() // 获取摆摊收购包 / 摆摊出售包 public CECDealInventory GetBoothBuyPack() => m_pBoothBPack; public CECDealInventory GetBoothSellPack() => m_pBoothSPack; bool CreateInventories() { // only use to init the booth inventories if (m_pBoothBPack == null) { m_pBoothBPack = new CECDealInventory(); m_pBoothBPack.Init(InventoryConst.IVTRSIZE_BOOTHBPACK); } if (m_pBoothSPack == null) { m_pBoothSPack = new CECDealInventory(); m_pBoothSPack.Init(InventoryConst.IVTRSIZE_BOOTHSPACK); } return true; } } // C++: struct BoothItem (save format for booth buy/sell pack item) // 摆摊买卖包单项保存结构 [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct BoothItem { public uint idItem; public uint iOrigin; public uint iAmount; public uint iUnitPrice; } // C++: CECDealInventory::ITEMINFO (EC_DealInventory.h) // 物品附加信息 [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct CECDealInventory_ITEMINFO { public int iOrigin; // 原始位置 Original position in player's normal pack public int iAmount; // 数量 Amount [MarshalAs(UnmanagedType.Bool)] public bool bDelete; // true 时物品对象可释放 true, item object can be released public int iFlag; // 物品标志 Item flag } // C++: CECDealInventory (EC_DealInventory.h / EC_DealInventory.cpp) – minimal view for SaveConfigData // 交易/摆摊背包,仅提供保存配置所需的接口 public class CECDealInventory : EC_Inventory { private readonly List m_aItems = new List(); private readonly List m_aItemInfo = new List(); 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; } }