507 lines
16 KiB
C#
507 lines
16 KiB
C#
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using BrewMonster.Network;
|
|
using PerfectWorld.Scripts.Managers.BrewMonster.Managers;
|
|
using PerfectWorld.Scripts.Managers;
|
|
using CSNetwork.GPDataType;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using BrewMonster;
|
|
using TMPro;
|
|
using BrewMonster.Managers;
|
|
using BrewMonster.Scripts.Managers;
|
|
using ModelRenderer.Scripts.Common;
|
|
using BrewMonster.Scripts;
|
|
|
|
public class pickupItem : MonoBehaviour
|
|
{
|
|
// Singleton instance
|
|
private static pickupItem _instance;
|
|
public static pickupItem Instance
|
|
{
|
|
get
|
|
{
|
|
if (_instance == null)
|
|
{
|
|
_instance = FindFirstObjectByType<pickupItem>();
|
|
if (_instance == null)
|
|
{
|
|
// Create a new GameObject with pickupItem component if none exists
|
|
GameObject pickupManager = new GameObject("PickupManager");
|
|
_instance = pickupManager.AddComponent<pickupItem>();
|
|
DontDestroyOnLoad(pickupManager);
|
|
}
|
|
}
|
|
return _instance;
|
|
}
|
|
}
|
|
|
|
// Dictionary to store created cubes with their matter IDs
|
|
private Dictionary<int, GameObject> matterGameObjects = new Dictionary<int, GameObject>();
|
|
|
|
// Dictionary to track pending pickups by TID
|
|
private Dictionary<int, int> pendingPickups = new Dictionary<int, int>(); // TID -> MatterID
|
|
|
|
// Set to track items that have been picked up by the player (to prevent respawn)
|
|
private HashSet<int> pickedUpItems = new HashSet<int>(); // MID of picked up items
|
|
|
|
// Reference to the matter manager
|
|
private EC_ManMatter matterManager;
|
|
|
|
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
|
void Start()
|
|
{
|
|
// Ensure this is the singleton instance
|
|
if (_instance == null)
|
|
{
|
|
_instance = this;
|
|
DontDestroyOnLoad(gameObject);
|
|
}
|
|
else if (_instance != this)
|
|
{
|
|
// If another instance already exists, destroy this one
|
|
Destroy(gameObject);
|
|
return;
|
|
}
|
|
|
|
// Get reference to matter manager
|
|
if (EC_ManMessageMono.Instance != null)
|
|
{
|
|
matterManager = EC_ManMessageMono.Instance.GetECManMatter;
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("EC_ManMessageMono.Instance is null - matter manager not available");
|
|
}
|
|
|
|
// Subscribe to matter enter world events
|
|
SubscribeToMatterEvents();
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
// Check for mouse clicks on cubes
|
|
if (Input.GetMouseButtonDown(0))
|
|
{
|
|
if (CECUIManager.IsPointerOverInteractiveUI())
|
|
return;
|
|
|
|
var uiMan = EC_Game.GetGameRun()?.GetUIManager();
|
|
if (uiMan != null && uiMan.IsWorldInteractionBlockedByUI())
|
|
return;
|
|
|
|
HandleCubeClick();
|
|
}
|
|
}
|
|
|
|
private void SubscribeToMatterEvents()
|
|
{
|
|
// We'll need to hook into the matter manager's events
|
|
// For now, we'll check for new matters in Update
|
|
}
|
|
|
|
private void HandleCubeClick()
|
|
{
|
|
// Find the main camera
|
|
Camera mainCamera = Camera.main;
|
|
if (mainCamera == null)
|
|
{
|
|
mainCamera = FindFirstObjectByType<Camera>();
|
|
}
|
|
|
|
if (mainCamera == null)
|
|
{
|
|
Debug.LogWarning("No camera found for raycast");
|
|
return;
|
|
}
|
|
|
|
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
|
|
RaycastHit hit;
|
|
|
|
if (Physics.Raycast(ray, out hit))
|
|
{
|
|
GameObject clickedObject = hit.collider.gameObject;
|
|
|
|
// Check if the clicked object is one of our matter cubes
|
|
foreach (var kvp in matterGameObjects)
|
|
{
|
|
if (kvp.Value == clickedObject)
|
|
{
|
|
int matterId = kvp.Key;
|
|
SendPickupCommand(matterId);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SendPickupCommand(int matterId)
|
|
{
|
|
if (matterManager != null)
|
|
{
|
|
var matterData = matterManager.GetMatterData(matterId);
|
|
if (matterData.HasValue)
|
|
{
|
|
// Track this pickup request
|
|
pendingPickups[(int)matterData.Value.tid] = matterId;
|
|
|
|
UnityGameSession.RequestPickupItem((int)matterData.Value.mid, (int)matterData.Value.tid);
|
|
Debug.Log($"Pickup request sent for matter - MID: {matterData.Value.mid}, TID: {matterData.Value.tid}");
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"No matter data found for matter ID: {matterId}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Matter manager is null - cannot send pickup command");
|
|
}
|
|
}
|
|
|
|
public void CreateMatterCube(int matterId)
|
|
{
|
|
if (matterManager == null) return;
|
|
|
|
var matterData = matterManager.GetMatterData(matterId);
|
|
if (!matterData.HasValue) return;
|
|
|
|
// Check if this item was previously picked up by the player
|
|
if (pickedUpItems.Contains(matterId))
|
|
{
|
|
Debug.Log($"Skipping cube creation for matter {matterId} - item was previously picked up by player");
|
|
return;
|
|
}
|
|
|
|
// Check if cube already exists
|
|
if (matterGameObjects.ContainsKey(matterId))
|
|
{
|
|
Debug.Log($"Cube for matter {matterId} already exists");
|
|
return;
|
|
}
|
|
|
|
// Create cube GameObject
|
|
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
|
cube.name = $"Matter_{matterData.Value.mid}_TID_{matterData.Value.tid}";
|
|
cube.transform.localScale = new Vector3(1f, 1f, 1f);
|
|
// Position the cube based on matter position
|
|
Vector3 position = new Vector3(
|
|
matterData.Value.pos.x,
|
|
matterData.Value.pos.y,
|
|
matterData.Value.pos.z
|
|
);
|
|
cube.transform.position = position;
|
|
|
|
// Add a collider if it doesn't have one
|
|
if (cube.GetComponent<Collider>() == null)
|
|
{
|
|
cube.AddComponent<BoxCollider>();
|
|
}
|
|
|
|
// Create text object to display item name above the cube
|
|
CreateItemNameText(cube, matterData.Value.tid);
|
|
|
|
// Add a script to handle click events
|
|
MatterCubeClickHandler clickHandler = cube.AddComponent<MatterCubeClickHandler>();
|
|
clickHandler.Initialize(matterId, this);
|
|
|
|
// Store reference to the cube
|
|
matterGameObjects[matterId] = cube;
|
|
|
|
//Debug.Log($"Created cube for matter {matterId} at position {position}");
|
|
}
|
|
|
|
public async void CreateMatterModelObject(info_matter info)
|
|
{
|
|
DATA_TYPE dataType = DATA_TYPE.DT_INVALID;
|
|
var matterData = ElementDataManProvider.GetElementDataMan().get_data_ptr((uint)info.tid, ID_SPACE.ID_SPACE_ESSENCE, ref dataType);
|
|
BMLogger.Log($"CreateMatterModelObject():: tid: {info.tid}, mid: {info.mid}, pos: {info.pos.x}, {info.pos.y}, {info.pos.z}");
|
|
if (matterData != null)
|
|
{
|
|
var matterType = matterData.GetType();
|
|
var fileMatterField = matterType.GetField("file_matter", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
|
|
if (fileMatterField != null)
|
|
{
|
|
var fileMatterValue = fileMatterField.GetValue(matterData);
|
|
string filePath = ByteToStringUtils.ByteArrayToCP936String((byte[])fileMatterValue);
|
|
|
|
var matterPrefab = await AddressableManager.Instance.LoadPrefabAsync(AFile.NormalizePath(filePath.ToLower(), true));
|
|
if (matterPrefab != null)
|
|
{
|
|
var matterObject = Instantiate(matterPrefab);
|
|
matterObject.transform.position = new Vector3(info.pos.x, info.pos.y, info.pos.z);
|
|
matterObject.transform.localScale = new Vector3(1f, 1f, 1f);
|
|
matterObject.transform.localRotation = Quaternion.identity;
|
|
matterObject.SetActive(true);
|
|
|
|
// Add a collider if it doesn't have one
|
|
if (matterObject.GetComponent<Collider>() == null)
|
|
{
|
|
var collider = matterObject.AddComponent<BoxCollider>();
|
|
collider.size = matterObject.GetComponentInChildren<MeshRenderer>().bounds.size;
|
|
}
|
|
|
|
// Create text object to display item name above the cube
|
|
CreateItemNameText(matterObject, info.tid);
|
|
|
|
// Add a script to handle click events
|
|
MatterCubeClickHandler clickHandler = matterObject.AddComponent<MatterCubeClickHandler>();
|
|
clickHandler.Initialize(info.mid, this);
|
|
|
|
// Store reference to the cube
|
|
matterGameObjects[info.mid] = matterObject;
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"Failed to load matter prefab from path: {filePath}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"file_matter field not found on matter data type {matterType.FullName}");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CreateMatterCube(info.mid);
|
|
}
|
|
}
|
|
|
|
private void CreateItemNameText(GameObject cube, int tid)
|
|
{
|
|
// Create a child GameObject for the text
|
|
GameObject textObject = new GameObject("ItemNameText");
|
|
textObject.transform.SetParent(cube.transform);
|
|
|
|
// Position the text above the cube
|
|
textObject.transform.localPosition = new Vector3(0, 1.2f, 0); // Above the cube
|
|
|
|
// Add TextMeshPro component
|
|
TextMeshPro textMesh = textObject.AddComponent<TextMeshPro>();
|
|
|
|
// Get the item name
|
|
string itemName = EC_IvtrItemUtils.Instance.ResolveItemName(tid);
|
|
if (string.IsNullOrEmpty(itemName))
|
|
{
|
|
itemName = $"Item {tid}";
|
|
}
|
|
|
|
// Configure the text
|
|
textMesh.text = itemName;
|
|
textMesh.fontSize = 10f;
|
|
textMesh.color = Color.white;
|
|
textMesh.alignment = TextAlignmentOptions.Center;
|
|
|
|
// Make the text face the camera
|
|
textObject.AddComponent<Billboard>();
|
|
|
|
// Add a background for better visibility
|
|
GameObject background = new GameObject("TextBackground");
|
|
background.transform.SetParent(textObject.transform);
|
|
background.transform.localPosition = Vector3.zero;
|
|
background.transform.localScale = new Vector3(2f, 0.8f, 0.1f);
|
|
|
|
// Add a simple quad renderer for background
|
|
MeshRenderer bgRenderer = background.AddComponent<MeshRenderer>();
|
|
MeshFilter bgFilter = background.AddComponent<MeshFilter>();
|
|
|
|
// Create a simple quad mesh for the background
|
|
Mesh quadMesh = new Mesh();
|
|
quadMesh.vertices = new Vector3[]
|
|
{
|
|
new Vector3(-0.5f, -0.5f, 0),
|
|
new Vector3(0.5f, -0.5f, 0),
|
|
new Vector3(0.5f, 0.5f, 0),
|
|
new Vector3(-0.5f, 0.5f, 0)
|
|
};
|
|
quadMesh.triangles = new int[] { 0, 1, 2, 0, 2, 3 };
|
|
quadMesh.uv = new Vector2[]
|
|
{
|
|
new Vector2(0, 0),
|
|
new Vector2(1, 0),
|
|
new Vector2(1, 1),
|
|
new Vector2(0, 1)
|
|
};
|
|
quadMesh.RecalculateNormals();
|
|
|
|
bgFilter.mesh = quadMesh;
|
|
|
|
// Create a simple material for the background
|
|
Material bgMaterial = new Material(Shader.Find("Standard"));
|
|
bgMaterial.color = new Color(0, 0, 0, 0.7f); // Semi-transparent black
|
|
bgRenderer.material = bgMaterial;
|
|
|
|
}
|
|
|
|
public void RemoveMatterObject(int matterId)
|
|
{
|
|
if (matterGameObjects.ContainsKey(matterId))
|
|
{
|
|
GameObject cube = matterGameObjects[matterId];
|
|
if (cube != null)
|
|
{
|
|
Destroy(cube);
|
|
}
|
|
matterGameObjects.Remove(matterId);
|
|
}
|
|
}
|
|
|
|
public void UpdateMatterObjects()
|
|
{
|
|
if (matterManager == null) return;
|
|
|
|
// Get all current matter IDs
|
|
// info_matter[] allMatterInfo = matterManager.GetAllMatterInfo();
|
|
|
|
// // Create cubes for new matters (but skip items previously picked up by player)
|
|
// foreach (info_matter info in allMatterInfo)
|
|
// {
|
|
// if (!matterGameObjects.ContainsKey(info.mid) && !pickedUpItems.Contains(info.mid))
|
|
// {
|
|
// CreateMatterModelObject(info);
|
|
// }
|
|
// }
|
|
|
|
// Remove cubes for matters that no longer exist
|
|
List<int> matterToRemove = new List<int>();
|
|
foreach (var kvp in matterGameObjects)
|
|
{
|
|
if (!matterManager.HasMatterData(kvp.Key))
|
|
{
|
|
matterToRemove.Add(kvp.Key);
|
|
}
|
|
}
|
|
|
|
foreach (int matterId in matterToRemove)
|
|
{
|
|
RemoveMatterObject(matterId);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when a pickup is successful. Removes the cube for the picked up item.
|
|
/// </summary>
|
|
/// <param name="tid">Template ID of the picked up item</param>
|
|
public void OnPickupSuccess(int tid)
|
|
{
|
|
if (pendingPickups.ContainsKey(tid))
|
|
{
|
|
int matterId = pendingPickups[tid];
|
|
|
|
// Track this item as picked up by the player
|
|
pickedUpItems.Add(matterId);
|
|
|
|
// Remove the cube
|
|
RemoveMatterObject(matterId);
|
|
|
|
// Remove from pending pickups
|
|
pendingPickups.Remove(tid);
|
|
|
|
Debug.Log($"Successfully picked up item with TID: {tid}, removed cube for matter ID: {matterId}");
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"Received pickup success for TID {tid} but no pending pickup found");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when a pickup fails. Removes the pending pickup tracking.
|
|
/// </summary>
|
|
/// <param name="tid">Template ID of the failed pickup</param>
|
|
public void OnPickupFailed(int tid)
|
|
{
|
|
if (pendingPickups.ContainsKey(tid))
|
|
{
|
|
pendingPickups.Remove(tid);
|
|
Debug.Log($"Pickup failed for TID: {tid}, removed from pending pickups");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears the tracking of picked up items. Call this when player changes areas or logs out.
|
|
/// </summary>
|
|
public void ClearPickedUpItemsTracking()
|
|
{
|
|
pickedUpItems.Clear();
|
|
Debug.Log("Cleared picked up items tracking");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the count of items that have been picked up by the player.
|
|
/// </summary>
|
|
/// <returns>Number of items picked up</returns>
|
|
public int GetPickedUpItemsCount()
|
|
{
|
|
return pickedUpItems.Count;
|
|
}
|
|
|
|
|
|
private void OnDestroy()
|
|
{
|
|
// Clean up all matter cubes
|
|
foreach (var kvp in matterGameObjects)
|
|
{
|
|
if (kvp.Value != null)
|
|
{
|
|
Destroy(kvp.Value);
|
|
}
|
|
}
|
|
matterGameObjects.Clear();
|
|
|
|
// Clean up pending pickups
|
|
pendingPickups.Clear();
|
|
|
|
// Clean up picked up items tracking
|
|
pickedUpItems.Clear();
|
|
}
|
|
}
|
|
|
|
// Helper class to handle click events on matter cubes
|
|
public class MatterCubeClickHandler : MonoBehaviour
|
|
{
|
|
private int matterId;
|
|
private pickupItem pickupItemScript;
|
|
|
|
public void Initialize(int id, pickupItem script)
|
|
{
|
|
matterId = id;
|
|
pickupItemScript = script;
|
|
}
|
|
|
|
private void OnMouseDown()
|
|
{
|
|
if (pickupItemScript != null)
|
|
{
|
|
pickupItemScript.SendPickupCommand(matterId);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Simple Billboard component to make text always face the camera
|
|
public class Billboard : MonoBehaviour
|
|
{
|
|
private Camera mainCamera;
|
|
|
|
void Start()
|
|
{
|
|
mainCamera = Camera.main;
|
|
if (mainCamera == null)
|
|
{
|
|
mainCamera = FindFirstObjectByType<Camera>();
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (mainCamera != null)
|
|
{
|
|
// Make the text face the camera
|
|
transform.LookAt(mainCamera.transform);
|
|
transform.Rotate(0, 180, 0); // Flip to face the camera properly
|
|
}
|
|
}
|
|
}
|