Files
Emberwild/Assets/GAME/Script/Crafting/CraftDiscovery.cs
T

120 lines
3.8 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using FishNet.Object;
using Ashwild.Inventory;
using Ashwild.Player;
namespace Ashwild.Crafting
{
/// <summary>
/// The local player's craft-discovery knowledge: the set of items it has ever acquired.
/// A recipe is only revealed (and only craftable) once its ingredients have been discovered,
/// so the player uncovers crafts by gathering resources rather than seeing the whole catalog
/// at once. Discovery is triggered the first time an item enters the inventory — pickups,
/// harvest drops AND craft results all count, which lets crafting chains reveal step by step.
///
/// This is owner-only local state: each player keeps its own knowledge, and it is never
/// replicated over the wire (no one else needs to read it). It mirrors PlayerInventory's
/// singleton pattern purely for reliable owner gating — set the Instance for the owning
/// client in OnStartNetwork, and gate the component off on remotes via ownerOnlyBehaviours.
/// </summary>
[DisallowMultipleComponent]
public class CraftDiscovery : NetworkBehaviour
{
#region Singleton
/// <summary>
/// The local player's discovery knowledge (set only on the owning client).
/// </summary>
public static CraftDiscovery Instance { get; private set; }
#endregion
#region State
private readonly HashSet<ItemData> discovered = new HashSet<ItemData>();
#endregion
#region Network Lifecycle
/// <summary>
/// Registers the singleton on the owning client only (before LocalPlayerSpawned fires).
/// </summary>
public override void OnStartNetwork()
{
base.OnStartNetwork();
if (base.Owner.IsLocalClient) Instance = this;
}
/// <summary>
/// Clears the singleton when this player leaves the network.
/// </summary>
public override void OnStopNetwork()
{
base.OnStopNetwork();
if (Instance == this) Instance = null;
}
#endregion
#region Unity Lifecycle
/// <summary>
/// Starts tracking every item the local player acquires.
/// </summary>
private void OnEnable()
{
PlayerEvents.ItemAdded += HandleItemAdded;
}
/// <summary>
/// Stops tracking — mirrors OnEnable exactly.
/// </summary>
private void OnDisable()
{
PlayerEvents.ItemAdded -= HandleItemAdded;
}
#endregion
#region Event Handlers
/// <summary>
/// Marks an acquired item as discovered. Guarded to the owning instance so a remote puppet
/// that briefly subscribed before being gated off can never drive discovery on the wrong copy.
/// </summary>
private void HandleItemAdded(ItemData item, int quantity)
{
if (Instance != this) return;
Discover(item);
}
#endregion
#region Public API
/// <summary>
/// Whether the local player has ever acquired this item (and therefore knows it).
/// </summary>
public bool IsDiscovered(ItemData item) => item != null && discovered.Contains(item);
#endregion
#region Internal Helpers
/// <summary>
/// Adds an item to the discovered set the first time it is seen and announces it on the bus
/// so the crafting view can reveal any recipe the item unlocks.
/// </summary>
private void Discover(ItemData item)
{
if (item == null) return;
if (discovered.Add(item))
PlayerEvents.RaiseItemDiscovered(item);
}
#endregion
}
}