312 lines
12 KiB
C#
312 lines
12 KiB
C#
using BrewMonster;
|
|
using BrewMonster.Network;
|
|
using CSNetwork;
|
|
using CSNetwork.GPDataType;
|
|
using CSNetwork.Protocols;
|
|
using CSNetwork.Protocols.RPCData;
|
|
using PerfectWorld.Scripts.Player;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
|
|
namespace PerfectWorld.Scripts.Managers
|
|
{
|
|
namespace BrewMonster.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>();
|
|
public bool ProcessMessage(ECMSG Msg)
|
|
{
|
|
if (Msg.iSubID == 0)
|
|
{
|
|
switch ((int)Msg.dwMsg)
|
|
{
|
|
case int value when value == EC_MsgDef.MSG_MM_MATTERINFO:
|
|
{
|
|
Debug.Log("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:
|
|
{
|
|
Debug.Log("MATTERENTWORLD");
|
|
OnMsgMatterEnterWorld(Msg);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void OnMsgMatterInfo(ECMSG Msg)
|
|
{
|
|
byte[] data = (byte[])Msg.dwParam1;
|
|
|
|
try
|
|
{
|
|
// Parse the data structure: count + info_matter array
|
|
int offset = 0;
|
|
|
|
// Read count (int)
|
|
int count = BitConverter.ToInt32(data, offset);
|
|
offset += sizeof(int);
|
|
|
|
Debug.Log($"MATTERINFO: Received {count} matter entries");
|
|
|
|
// Parse each info_matter entry
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
// Parse info_matter structure
|
|
info_matter matterInfo = CSNetwork.GPDataType.GPDataTypeHelper.FromBytes<info_matter>(data, offset);
|
|
offset += Marshal.SizeOf(typeof(info_matter));
|
|
|
|
// Store the matter data for later player access
|
|
matterDataStorage[matterInfo.mid] = matterInfo;
|
|
|
|
Debug.Log($"Matter info - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}");
|
|
|
|
// Spawn cube for this matter since it has entered the world
|
|
SpawnMatterCube(matterInfo.mid);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError($"Failed to parse matter info data: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public 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);
|
|
|
|
// Store the matter data for later player access
|
|
matterDataStorage[matterInfo.mid] = matterInfo;
|
|
|
|
Debug.Log($"Matter entered world - ID: {matterInfo.mid}, TID: {matterInfo.tid}, Position: {matterInfo.pos}, State: {matterInfo.state}");
|
|
|
|
// Notify pickupItem to create cube for this matter
|
|
NotifyPickupItem(matterInfo.mid);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError($"Failed to parse matter data: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
private void SpawnMatterCube(int matterId)
|
|
{
|
|
// Check if matter is within 1000 units of the host player
|
|
if (!IsMatterWithinPlayerRange(matterId, 10000f))
|
|
{
|
|
Debug.Log($"Matter {matterId} is too far from player, skipping spawn");
|
|
return;
|
|
}
|
|
|
|
// Find the pickupItem component in the scene and create cube for this specific matter
|
|
pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType<pickupItem>();
|
|
if (pickupScript != null)
|
|
{
|
|
pickupScript.CreateMatterCube(matterId);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("pickupItem component not found in scene - cannot spawn matter cube");
|
|
}
|
|
}
|
|
|
|
private void NotifyPickupItem(int matterId)
|
|
{
|
|
// Check if matter is within 1000 units of the host player
|
|
if (!IsMatterWithinPlayerRange(matterId, 1000f))
|
|
{
|
|
Debug.Log($"Matter {matterId} is too far from player, skipping notification");
|
|
return;
|
|
}
|
|
|
|
// Find the pickupItem component in the scene and update cubes
|
|
pickupItem pickupScript = UnityEngine.Object.FindFirstObjectByType<pickupItem>();
|
|
if (pickupScript != null)
|
|
{
|
|
pickupScript.UpdateMatterCubes();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if a matter is within the specified distance from the host player
|
|
/// </summary>
|
|
/// <param name="matterId">The matter ID to check</param>
|
|
/// <param name="maxDistance">Maximum distance in Unity units</param>
|
|
/// <returns>True if matter is within range, false otherwise</returns>
|
|
private bool IsMatterWithinPlayerRange(int matterId, float maxDistance)
|
|
{
|
|
// Get the matter data
|
|
if (!matterDataStorage.TryGetValue(matterId, out info_matter matterData))
|
|
{
|
|
Debug.LogWarning($"Matter data not found for ID: {matterId}");
|
|
return false;
|
|
}
|
|
|
|
// Get the host player
|
|
var hostPlayer = GameController.Instance?.GetHostPlayer();
|
|
if (hostPlayer == null)
|
|
{
|
|
Debug.LogWarning("Host player not found");
|
|
return false;
|
|
}
|
|
|
|
// Convert matter position to Unity Vector3
|
|
Vector3 matterPosition = new Vector3(matterData.pos.x, matterData.pos.y, matterData.pos.z);
|
|
|
|
// Get player position
|
|
Vector3 playerPosition = hostPlayer.transform.position;
|
|
|
|
// Calculate distance
|
|
float distance = Vector3.Distance(matterPosition, playerPosition);
|
|
|
|
Debug.Log($"Matter {matterId} distance from player: {distance:F2} units (max: {maxDistance})");
|
|
|
|
return distance <= maxDistance;
|
|
}
|
|
|
|
// 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 Dictionary<int, info_matter> GetAllMatterData()
|
|
{
|
|
return new Dictionary<int, info_matter>(matterDataStorage);
|
|
}
|
|
|
|
public bool HasMatterData(int matterId)
|
|
{
|
|
return matterDataStorage.ContainsKey(matterId);
|
|
}
|
|
|
|
public void RemoveMatterData(int matterId)
|
|
{
|
|
if (matterDataStorage.ContainsKey(matterId))
|
|
{
|
|
matterDataStorage.Remove(matterId);
|
|
Debug.Log($"Removed matter data for ID: {matterId}");
|
|
}
|
|
}
|
|
|
|
public int GetMatterCount()
|
|
{
|
|
return matterDataStorage.Count;
|
|
}
|
|
|
|
// Convenience methods to get specific fields from matter data
|
|
public int? GetMatterId(int matterId)
|
|
{
|
|
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.mid : null;
|
|
}
|
|
|
|
public int? GetMatterTid(int matterId)
|
|
{
|
|
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.tid : null;
|
|
}
|
|
|
|
public A3DVECTOR3? GetMatterPosition(int matterId)
|
|
{
|
|
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.pos : null;
|
|
}
|
|
|
|
public byte? GetMatterDir0(int matterId)
|
|
{
|
|
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir0 : null;
|
|
}
|
|
|
|
public byte? GetMatterDir1(int matterId)
|
|
{
|
|
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.dir1 : null;
|
|
}
|
|
|
|
public byte? GetMatterRadius(int matterId)
|
|
{
|
|
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.rad : null;
|
|
}
|
|
|
|
public byte? GetMatterState(int matterId)
|
|
{
|
|
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.state : null;
|
|
}
|
|
|
|
public byte? GetMatterValue(int matterId)
|
|
{
|
|
return matterDataStorage.TryGetValue(matterId, out info_matter data) ? data.value : null;
|
|
}
|
|
|
|
// Get all matter IDs
|
|
public int[] GetAllMatterIds()
|
|
{
|
|
return matterDataStorage.Keys.ToArray();
|
|
}
|
|
|
|
// Find matters by template ID (tid)
|
|
public int[] FindMattersByTid(int tid)
|
|
{
|
|
return matterDataStorage.Where(kvp => kvp.Value.tid == tid).Select(kvp => kvp.Key).ToArray();
|
|
}
|
|
|
|
// Find matters by state
|
|
public int[] FindMattersByState(byte state)
|
|
{
|
|
return matterDataStorage.Where(kvp => kvp.Value.state == state).Select(kvp => kvp.Key).ToArray();
|
|
}
|
|
|
|
// Get matters within a certain distance from a position
|
|
public int[] FindMattersNearPosition(A3DVECTOR3 position, float maxDistance)
|
|
{
|
|
return matterDataStorage.Where(kvp =>
|
|
{
|
|
float distance = (kvp.Value.pos - position).Magnitude();
|
|
return distance <= maxDistance;
|
|
}).Select(kvp => kvp.Key).ToArray();
|
|
}
|
|
}
|
|
}
|
|
} |