120 lines
3.8 KiB
C#
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
|
|
}
|
|
}
|