Merge remote-tracking branch 'origin/develop' into feature/hp_pet
# Conflicts: # Assets/PerfectWorld/Scripts/Network/CSNetwork/GameSession.cs
This commit is contained in:
@@ -20,6 +20,10 @@ public partial class CECGameRun
|
||||
{
|
||||
private static CECGameRun instance;
|
||||
|
||||
#region PROPERTIES AND FIELDS
|
||||
|
||||
private const uint USERCFG_VERSION = 3;
|
||||
|
||||
private GameObject _playerPrefab;
|
||||
private GameObject _monsterPrefab;//CECMonster
|
||||
private GameObject _npcServerPrefab;//CECNPCServer
|
||||
@@ -41,6 +45,10 @@ public partial class CECGameRun
|
||||
|
||||
|
||||
protected CECUIManager m_pUIManager; // UI manager
|
||||
|
||||
CECPendingActionArray m_pendingLogout;
|
||||
|
||||
#endregion
|
||||
|
||||
public CECWorld GetWorld()
|
||||
{
|
||||
@@ -66,6 +74,14 @@ public partial class CECGameRun
|
||||
|
||||
private int m_iDExpEndTime = 0;
|
||||
|
||||
// Cache for SaveConfigsToServer: last sent config data to skip duplicate sends
|
||||
private byte[] m_pCfgDataBuf;
|
||||
private int m_iCfgDataSize;
|
||||
|
||||
// Logout flag (C++: m_iLogoutFlag)
|
||||
private int m_iLogoutFlag = -1;
|
||||
// Selling role ID for role trade (C++: SetSellingRoleID/GetSellingRoleID)
|
||||
private int m_iSellingRoleID;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void AfterSceneLoad()
|
||||
@@ -102,6 +118,10 @@ public partial class CECGameRun
|
||||
AddressableManager.Instance.OnDispose += Dispose;
|
||||
m_pWorld = CECWorld.Instance;
|
||||
StartGame(0, Vector3.zero);
|
||||
|
||||
|
||||
m_pWorld = CECWorld.Instance;
|
||||
m_pendingLogout = new CECPendingActionArray( false);
|
||||
}
|
||||
|
||||
private static void Dispose()
|
||||
@@ -310,8 +330,8 @@ public partial class CECGameRun
|
||||
/// <returns>True if loaded successfully / 加载成功返回true</returns>
|
||||
public bool LoadConfigsFromServer(byte[] pDataBuf, int iDataSize)
|
||||
{
|
||||
const uint USERCFG_VERSION = 3;
|
||||
|
||||
BMLogger.Log($"MH CECGameRun.LoadConfigsFromServer, iDataSize = {iDataSize}");
|
||||
|
||||
if (pDataBuf == null || iDataSize == 0)
|
||||
{
|
||||
BMLogger.LogError("CECGameRun::LoadConfigsFromServer, configs data is empty");
|
||||
@@ -747,10 +767,166 @@ public partial class CECGameRun
|
||||
m_iDExpEndTime = endTime;
|
||||
}
|
||||
public int GetGameState() { return m_iGameState; }
|
||||
public void SaveConfigsToServer()
|
||||
|
||||
// Logout flag: -1 none, 0 exit app, 1 re-select role, 2 goto login (C++: SetLogoutFlag/GetLogoutFlag)
|
||||
public void SetLogoutFlag(int iFlag) { m_iLogoutFlag = iFlag; }
|
||||
public int GetLogoutFlag() { return m_iLogoutFlag; }
|
||||
|
||||
// Selling role ID for role trade (C++: SetSellingRoleID)
|
||||
public void SetSellingRoleID(int roleid) { m_iSellingRoleID = roleid; }
|
||||
public int GetSellingRoleID() { return m_iSellingRoleID; }
|
||||
|
||||
// Save necessary user configs (UI, shortcut, accelerate keys, etc.) to server
|
||||
// ����ֵ: 0(����ʧ��), 1(���������ظ�����), 2(�������������Э��)
|
||||
public uint SaveConfigsToServer()
|
||||
{
|
||||
|
||||
// if (!m_pWorld || !m_pWorld->GetHostPlayer() || !m_pWorld->GetHostPlayer()->HostIsReady() || !m_pUIManager->GetInGameUIMan())
|
||||
// return 0;
|
||||
CECHostPlayer pHost = GetHostPlayer();
|
||||
CECGameUIMan pGameUI = m_pUIManager?.GetInGameUIMan() as CECGameUIMan;
|
||||
if (m_pWorld == null || pHost == null || !pHost.HostIsReady() || pGameUI == null)
|
||||
return 0;
|
||||
|
||||
// g_pGame->GetConfigs()->SaveBlockedID();
|
||||
EC_Game.GetConfigs().SaveBlockedID(); // TODO: Check if this is needed here
|
||||
|
||||
// int iTotalSize = 0;
|
||||
// iTotalSize += sizeof (DWORD);
|
||||
// iTotalSize += sizeof (int);
|
||||
// int iHostSize = 0;
|
||||
// CECHostPlayer* pHost = m_pWorld->GetHostPlayer();
|
||||
// pHost->SaveConfigData(NULL, &iHostSize);
|
||||
// iTotalSize += iHostSize;
|
||||
// iTotalSize += sizeof (int);
|
||||
int iTotalSize = sizeof(uint);
|
||||
iTotalSize += sizeof(int);
|
||||
int iHostSize = 0;
|
||||
pHost.SaveConfigData(null, ref iHostSize);
|
||||
iTotalSize += sizeof(int) + iHostSize;
|
||||
|
||||
// DWORD dwUISize = 0;
|
||||
// CECGameUIMan* pGameUI = (CECGameUIMan*)m_pUIManager->GetInGameUIMan();
|
||||
// pGameUI->GetUserLayout(NULL, dwUISize);
|
||||
// iTotalSize += (int)dwUISize;
|
||||
// iTotalSize += sizeof (int);
|
||||
uint dwUISize = 0;
|
||||
pGameUI.GetUserLayout(null, ref dwUISize); // TODO: Check if this is needed here
|
||||
iTotalSize += sizeof(int) + (int)dwUISize;
|
||||
|
||||
// int iSettingSize = 0;
|
||||
// g_pGame->GetConfigs()->SaveUserConfigData(NULL, &iSettingSize);
|
||||
// iTotalSize += iSettingSize;
|
||||
int iSettingSize = 0;
|
||||
EC_Game.GetConfigs().SaveUserConfigData(null, out iSettingSize);
|
||||
// iTotalSize += sizeof(int) + iSettingSize;
|
||||
iTotalSize += iSettingSize;
|
||||
|
||||
// void* pDataBuf = a_malloctemp(iTotalSize);
|
||||
// if (!pDataBuf) { glb_ErrorOutput(ECERR_NOTENOUGHMEMORY, "CECGameRun::SaveConfigsToServer", __LINE__); return 0; }
|
||||
// BYTE* pData = (BYTE*)pDataBuf;
|
||||
byte[] pDataBuf = new byte[iTotalSize];
|
||||
int offset = 0;
|
||||
|
||||
// *((DWORD*)pData) = USERCFG_VERSION;
|
||||
// pData += sizeof (DWORD);
|
||||
Buffer.BlockCopy(BitConverter.GetBytes(USERCFG_VERSION), 0, pDataBuf, offset, sizeof(uint));
|
||||
offset += sizeof(uint);
|
||||
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after version)");
|
||||
|
||||
// *((int*)pData) = iHostSize;
|
||||
// pData += sizeof (int);
|
||||
// pHost->SaveConfigData(pData, &iHostSize);
|
||||
// pData += iHostSize;
|
||||
Buffer.BlockCopy(BitConverter.GetBytes(iHostSize), 0, pDataBuf, offset, sizeof(int));
|
||||
offset += sizeof(int);
|
||||
pHost.SaveConfigData(pDataBuf, ref iHostSize, offset); // TODO: converted but need to check
|
||||
offset += iHostSize;
|
||||
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after host config, iHostSize={iHostSize})");
|
||||
|
||||
// *((int*)pData) = (int)dwUISize;
|
||||
// pData += sizeof (int);
|
||||
// pGameUI->GetUserLayout(pData, dwUISize);
|
||||
// pData += dwUISize;
|
||||
Buffer.BlockCopy(BitConverter.GetBytes((int)dwUISize), 0, pDataBuf, offset, sizeof(int));
|
||||
offset += sizeof(int);
|
||||
pGameUI.GetUserLayout(pDataBuf, ref dwUISize); // TODO: Check if this is needed here
|
||||
offset += (int)dwUISize;
|
||||
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after UI layout, dwUISize={dwUISize})");
|
||||
|
||||
// *((int*)pData) = iSettingSize;
|
||||
// pData += sizeof (int);
|
||||
// g_pGame->GetConfigs()->SaveUserConfigData(pData, &iSettingSize);
|
||||
// pData += iSettingSize;
|
||||
Buffer.BlockCopy(BitConverter.GetBytes(iSettingSize), 0, pDataBuf, offset, sizeof(int));
|
||||
offset += sizeof(int);
|
||||
EC_Game.GetConfigs().SaveUserConfigData(pDataBuf, offset, out iSettingSize);
|
||||
offset += iSettingSize;
|
||||
BMLogger.Log($"[SaveConfigsToServer] offset={offset} (after user config, iSettingSize={iSettingSize}), iTotalSize={iTotalSize}");
|
||||
|
||||
// if (m_pCfgDataBuf) {
|
||||
// if (m_iCfgDataSize == iTotalSize && !memcmp(m_pCfgDataBuf, pDataBuf, iTotalSize)) { a_freetemp(pDataBuf); return 1; }
|
||||
// a_free(m_pCfgDataBuf); m_pCfgDataBuf = NULL; m_iCfgDataSize = 0;
|
||||
// }
|
||||
if (m_pCfgDataBuf != null && m_iCfgDataSize == iTotalSize)
|
||||
{
|
||||
bool same = true;
|
||||
for (int i = 0; i < iTotalSize && same; i++)
|
||||
same = (m_pCfgDataBuf[i] == pDataBuf[i]);
|
||||
if (same)
|
||||
return 1;
|
||||
}
|
||||
m_pCfgDataBuf = null;
|
||||
m_iCfgDataSize = 0;
|
||||
|
||||
// if ((m_pCfgDataBuf = (BYTE*)a_malloc(iTotalSize))) { memcpy(m_pCfgDataBuf, pDataBuf, iTotalSize); m_iCfgDataSize = iTotalSize; }
|
||||
m_pCfgDataBuf = new byte[iTotalSize];
|
||||
Buffer.BlockCopy(pDataBuf, 0, m_pCfgDataBuf, 0, iTotalSize);
|
||||
m_iCfgDataSize = iTotalSize;
|
||||
|
||||
// DWORD dwCompLen = iTotalSize * 2;
|
||||
// void* pCompBuf = a_malloctemp(dwCompLen);
|
||||
// if (!pCompBuf) { a_freetemp(pDataBuf); glb_ErrorOutput(ECERR_NOTENOUGHMEMORY, "CECGameRun::SaveConfigsToServer", __LINE__); return 0; }
|
||||
// int iVerLen = sizeof (DWORD);
|
||||
// memcpy(pCompBuf, pDataBuf, iVerLen);
|
||||
// BYTE* pSrc = (BYTE*)pDataBuf + iVerLen;
|
||||
// BYTE* pDst = (BYTE*)pCompBuf + iVerLen;
|
||||
// dwCompLen -= iVerLen;
|
||||
// int iRes = AFilePackage::Compress(pSrc, iTotalSize - iVerLen, pDst, &dwCompLen);
|
||||
int iVerLen = sizeof(uint);
|
||||
// int compLen = (iTotalSize - iVerLen) * 2;
|
||||
int compLen = iTotalSize * 2;
|
||||
byte[] pCompBuf = new byte[iVerLen + compLen];
|
||||
compLen -= iVerLen;
|
||||
Buffer.BlockCopy(pDataBuf, 0, pCompBuf, 0, iVerLen);
|
||||
int iRes = AFilePackage.Compress(pDataBuf, iVerLen,iTotalSize - iVerLen, pCompBuf, iVerLen, ref compLen);
|
||||
|
||||
// if (0 == iRes) { g_pGame->GetGameSession()->SaveConfigData(pCompBuf, dwCompLen+iVerLen); iRes = 2; }
|
||||
// else { a_LogOutput(1, "CECGameRun::SaveConfigsToServer, Failed to compress config data (%d:%d)", iRes, iTotalSize); iRes = 0; }
|
||||
// a_freetemp(pDataBuf);
|
||||
// a_freetemp(pCompBuf);
|
||||
// return iRes;
|
||||
if (iRes == 0)
|
||||
{
|
||||
var session = UnityGameSession.Instance?.GameSession;
|
||||
if (session != null)
|
||||
{
|
||||
session.SaveConfigData(pCompBuf, iVerLen + compLen);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
BMLogger.LogWarning($"CECGameRun::SaveConfigsToServer, Failed to compress config data ({iRes}:{iTotalSize})");
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void ReleasePendingActions()
|
||||
{
|
||||
m_pendingLogout.Clear();
|
||||
}
|
||||
|
||||
public CECPendingActionArray GetPendingLogOut(){ return m_pendingLogout; }
|
||||
|
||||
}
|
||||
public enum GameState
|
||||
|
||||
|
||||
@@ -0,0 +1,505 @@
|
||||
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
|
||||
|
||||
BOOTH_AUTO_YINPIAO m_AutoYinpiao;
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
// 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<uint>(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<BoothItem>() > dataBuf.Length)
|
||||
return false;
|
||||
temp = GPDataTypeHelper.FromBytes<BoothItem>(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<BoothItem>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// ��Ʊ�Զ�ת��
|
||||
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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// 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<iOldSize;i++) { if (m_aItems[i] && m_aItemInfo[i].bDelete) delete m_aItems[i]; } }
|
||||
if (iNewSize < iOldSize)
|
||||
{
|
||||
for (int i = iNewSize; i < iOldSize; i++)
|
||||
{
|
||||
if (GetItem(i) != null && m_aItemInfo[i].bDelete)
|
||||
SetItem(i, null); // C#: release reference instead of delete
|
||||
}
|
||||
}
|
||||
|
||||
// CECInventory::Resize(iNewSize);
|
||||
base.Resize(iNewSize);
|
||||
|
||||
// m_aItemInfo.SetSize(iNewSize, 10);
|
||||
if (m_aItemInfo.Count > 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e2dc296cf794870802c33b2b2b8ff28
|
||||
timeCreated: 1770696658
|
||||
@@ -51,10 +51,8 @@ namespace BrewMonster
|
||||
private bool m_bJumpInWater = false;
|
||||
|
||||
public A3DVECTOR3 m_vVelocity; // Velocity
|
||||
|
||||
// Shortcut sets (converted from C++: m_aSCSets1[NUM_HOSTSCSETS1], m_aSCSets2[NUM_HOSTSCSETS2])
|
||||
public CECShortcutSet[] m_aSCSets1 = new CECShortcutSet[HostCfgConstants.NUM_HOSTSCSETS1]; // SC set 1
|
||||
public CECShortcutSet[] m_aSCSets2 = new CECShortcutSet[HostCfgConstants.NUM_HOSTSCSETS2]; // SC set 2
|
||||
|
||||
|
||||
bool m_bChangingFace; // true, host is changing face
|
||||
private int m_iRoleCreateTime;
|
||||
private int m_iRoleLastLoginTime; // Role last login time
|
||||
@@ -298,15 +296,6 @@ namespace BrewMonster
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
@@ -332,6 +321,8 @@ namespace BrewMonster
|
||||
m_PetOptCnt.SetPeriod(1000);
|
||||
m_PetOptCnt.Reset(true);
|
||||
|
||||
|
||||
CreateInventories();
|
||||
// run a process on background to keep track of task status.
|
||||
UniTask.RunOnThreadPool(TickTask, false, this.GetCancellationTokenOnDestroy()).Forget();
|
||||
}
|
||||
@@ -1364,65 +1355,6 @@ namespace BrewMonster
|
||||
return Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
public int GetCharacterID()
|
||||
{
|
||||
return m_PlayerInfo.cid;
|
||||
|
||||
Reference in New Issue
Block a user