353 lines
16 KiB
C#
353 lines
16 KiB
C#
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<uint>(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<int>(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;ksc<pSCS->GetShortcutNum();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;i<c;i++) pSCS->CreateSystemModuleShortcut(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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Save host config (shortcut sets, etc.) to buffer. When pData is null, only outputs size in iHostSize.
|
||
/// 保存主机配置(快捷键组等)到缓冲区。pData 为 null 时仅输出 iHostSize。
|
||
/// </summary>
|
||
/// <param name="writeOffset">When pData is not null, write at this index. 写入时的起始下标。</param>
|
||
public bool SaveConfigData(byte[] pData, ref int iHostSize, int writeOffset = 0)
|
||
{
|
||
var list = new List<byte>();
|
||
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<EC_IvtrItem> m_aItems = new List<EC_IvtrItem>();
|
||
private readonly List<CECDealInventory_ITEMINFO> m_aItemInfo = new List<CECDealInventory_ITEMINFO>();
|
||
|
||
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;
|
||
}
|
||
}
|