WIP: prepare config before send to Server

This commit is contained in:
MinhHai
2026-02-24 14:29:09 +07:00
parent 125229cae5
commit f183544b4d
5 changed files with 316 additions and 9 deletions
@@ -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;
@@ -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 布局保存未实现)。
/// </summary>
/// 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<CDlgHomeBase*>( 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()
+2 -2
View File
@@ -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;
+156 -3
View File
@@ -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<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
@@ -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<EC_IvtrItem> m_aItems = new List<EC_IvtrItem>();
// 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 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<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);
}
}
}
+2 -1
View File
@@ -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();
}