Files
test/Assets/PerfectWorld/Scripts/UI/pickupItem.cs
T
2025-11-05 16:08:51 +07:00

440 lines
13 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 BrewMonster;
using TMPro;
using BrewMonster.Managers;
using BrewMonster.Scripts.Managers;
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> matterCubes = 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))
{
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 matterCubes)
{
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[matterData.Value.tid] = matterId;
UnityGameSession.RequestPickupItem(matterData.Value.mid, 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 (matterCubes.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
matterCubes[matterId] = cube;
//Debug.Log($"Created cube for matter {matterId} at position {position}");
}
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.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 RemoveMatterCube(int matterId)
{
if (matterCubes.ContainsKey(matterId))
{
GameObject cube = matterCubes[matterId];
if (cube != null)
{
Destroy(cube);
}
matterCubes.Remove(matterId);
}
}
public void UpdateMatterCubes()
{
if (matterManager == null) return;
// Get all current matter IDs
int[] allMatterIds = matterManager.GetAllMatterIds();
// Create cubes for new matters (but skip items previously picked up by player)
foreach (int matterId in allMatterIds)
{
if (!matterCubes.ContainsKey(matterId) && !pickedUpItems.Contains(matterId))
{
CreateMatterCube(matterId);
}
}
// Remove cubes for matters that no longer exist
List<int> cubesToRemove = new List<int>();
foreach (var kvp in matterCubes)
{
if (!matterManager.HasMatterData(kvp.Key))
{
cubesToRemove.Add(kvp.Key);
}
}
foreach (int matterId in cubesToRemove)
{
RemoveMatterCube(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
RemoveMatterCube(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 matterCubes)
{
if (kvp.Value != null)
{
Destroy(kvp.Value);
}
}
matterCubes.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
}
}
}