Files
test/Assets/PerfectWorld/Scripts/Managers/EC_ManMatter.cs
T
2025-12-02 16:46:47 +07:00

226 lines
7.2 KiB
C#

using BrewMonster;
using BrewMonster.Network;
using BrewMonster.Scripts.World;
using CSNetwork;
using CSNetwork.GPDataType;
using CSNetwork.Protocols;
using CSNetwork.Protocols.RPCData;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace PerfectWorld.Scripts.Managers
{
/// <summary>
/// Matter Manager - Handles matter data storage and provides access to other classes
///
/// Usage Examples:
/// // Get matter manager instance
/// var matterManager = EC_ManMessageMono.Instance.GetECManMatter;
///
/// // Get specific matter data
/// var matterData = matterManager.GetMatterData(12345);
///
/// // Get individual fields
/// int? mid = matterManager.GetMatterId(12345);
/// int? tid = matterManager.GetMatterTid(12345);
/// A3DVECTOR3? pos = matterManager.GetMatterPosition(12345);
/// byte? state = matterManager.GetMatterState(12345);
///
/// // Find matters by criteria
/// int[] mattersByTid = matterManager.FindMattersByTid(100);
/// int[] mattersByState = matterManager.FindMattersByState(1);
/// int[] nearbyMatters = matterManager.FindMattersNearPosition(new A3DVECTOR3(0,0,0), 10.0f);
/// </summary>
[Serializable]
public class EC_ManMatter : IMsgHandler
{
public int HandlerId => (int)MANAGER_INDEX.MAN_MATTER;
// Storage for matter data that players can access later
private Dictionary<int, info_matter> matterDataStorage = new Dictionary<int, info_matter>();
private Dictionary<int, CECMatter> m_MatterTab = new Dictionary<int, CECMatter>();
public bool ProcessMessage(ECMSG Msg)
{
if (Msg.iSubID == 0)
{
switch ((int)Msg.dwMsg)
{
case int value when value == EC_MsgDef.MSG_MM_MATTERINFO:
{
//ENABLE LATER: It fetch all matters in the game world, causing performance issues
OnMsgMatterInfo(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_MM_MATTERENTWORLD:
{
OnMsgMatterEnterWorld(Msg);
break;
}
case int value when value == EC_MsgDef.MSG_MM_MATTERDISAPPEAR:
{
OnMsgMatterDisappear(Msg);
break;
}
}
}
else
{
}
return true;
}
public async void OnMsgMatterInfo(ECMSG Msg)
{
byte[] data = (byte[])Msg.dwParam1;
try
{
// Parse the data structure: count + info_matter array
int offset = 0;
// Read count (ushort)
ushort count = BitConverter.ToUInt16(data, offset);
offset += sizeof(ushort);
// Parse each info_matter entry
for (int i = 0; i < count; i++)
{
// Parse info_matter structure
info_matter info = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes<info_matter>(data, offset);
offset += Marshal.SizeOf(typeof(info_matter));
// Store the matter data for later player access
matterDataStorage[info.mid] = info;
await MatterEnter(info);
}
}
catch (Exception ex)
{
Debug.LogError($"Failed to parse matter info data: {ex.Message}");
}
}
public async void OnMsgMatterEnterWorld(ECMSG Msg)
{
byte[] data = (byte[])Msg.dwParam1;
try
{
// Parse the byte array into info_matter structure
info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes<info_matter>(data);
await MatterEnter(matterInfo);
}
catch (Exception ex)
{
Debug.LogError($"Failed to parse matter data: {ex.Message}");
}
}
public void OnMsgMatterDisappear(ECMSG Msg)
{
byte[] data = (byte[])Msg.dwParam1;
int matterId = BitConverter.ToInt32(data);
MatterLeave(matterId);
}
private async Task<bool> MatterEnter(info_matter info)
{
CECMatter pMatter = GetMatter(info.mid);
if (pMatter != null)
return true;
// Create a new matter
pMatter = await CECMatter.Init(info);
if (pMatter == null)
{
Debug.LogError($"Failed to create matter: {info.mid}");
return false;
}
pMatter.SetBornStamp(CECWorld.Instance.GetBornStamp());
m_MatterTab[info.mid] = pMatter;
return true;
}
// Remove a matter
public void RemoveMatter(int idMatter) { MatterLeave(idMatter); }
public void MatterLeave(int mid)
{
CECMatter pMatter = GetMatter(mid);
if (pMatter != null)
{
UnityEngine.Object.Destroy(pMatter.gameObject);
m_MatterTab.Remove(mid);
}
//TODO: Might need to implement later
/*/
else
{
MatterTable::pair_type Pair = m_DynModelTab.get(mid);
if (Pair.second)
{
pMatter = *Pair.first;
ReleaseMatter(pMatter);
// Remove it from active matter table
m_DynModelTab.erase(mid);
QueueMatterUndoLoad(mid);
}
}
CECPlayerWrapper* pWrapper = CECAutoPolicy::GetInstance().GetPlayerWrapper();
if( pWrapper ) pWrapper->OnObjectDisappear(mid);
//*/
}
// Public methods for players to access matter data
public info_matter? GetMatterData(int matterId)
{
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data : null;
}
public bool HasMatterData(int matterId)
{
return matterDataStorage.ContainsKey(matterId);
}
public CECMatter GetMatter(int mid, uint dwBornStamp = 0)
{
if (m_MatterTab.TryGetValue(mid, out CECMatter matter))
{
if (dwBornStamp != 0)
{
if (matter.GetBornStamp() != dwBornStamp)
{
return null;
}
}
return matter;
}
return null;
}
public CECMatter CreateMatter(info_matter info)
{
return null;
}
}
}