Merge remote-tracking branch 'origin/feat/inport-props' into feat/craft-discovery

# Conflicts:
#	Assets/External/Animated PBR Chest Demo/Materials/WoodChest.mat
#	Packages/com.distantlands.cozy.core/Content/Integration/Import for BiRP.unitypackage.meta
#	Packages/com.distantlands.cozy.core/Content/Integration/Import for HDRP.unitypackage.meta
#	Packages/com.distantlands.cozy.core/Content/Integration/Import for URP.unitypackage.meta
This commit is contained in:
2026-07-25 19:42:26 +02:00
954 changed files with 999772 additions and 26193 deletions
@@ -0,0 +1,80 @@
using UnityEngine;
using Ashwild.Interaction;
namespace Ashwild.Crafting
{
/// <summary>
/// A world workstation the player interacts with to open the crafting panel with this station's
/// recipes unlocked. It declares which station it is and nothing more: the recipe catalog, the
/// filtering and the craft itself all stay in <see cref="CraftingManager"/>, which this simply hands
/// the station type to.
///
/// Multiplayer: deliberately a plain MonoBehaviour, NOT a NetworkBehaviour. Unlike a chest or a
/// cooking station it owns no shared state — a craft only consumes and produces in the crafting
/// player's own (client-authoritative) inventory — so two players using the same bench at once can
/// never clobber each other and there is strictly nothing to replicate. The object it sits on is
/// still a networked build (it carries BuiltStructure like any placed structure); this component
/// just does not participate in that.
/// </summary>
[DisallowMultipleComponent]
public class CraftingStation : MonoBehaviour, IInteractable
{
#region Serialized Fields
[Header("Station")]
[Tooltip("Recipes requiring this exact station become craftable while its panel is open.")]
[SerializeField] private CraftingStationType stationType = CraftingStationType.Workbench;
[Tooltip("Name shown in the interaction prompt.")]
[SerializeField] private string displayName = "Établi";
#endregion
#region Public API
/// <summary>
/// Which station this is — the key CraftingManager filters recipes against.
/// </summary>
public CraftingStationType StationType => stationType;
#endregion
#region Unity Lifecycle
/// <summary>
/// Warns early when the station is left on None, which would unlock nothing beyond hand crafting
/// and read as a broken bench in game.
/// </summary>
private void Awake()
{
if (stationType == CraftingStationType.None)
Debug.LogError($"[CraftingStation] '{name}' has its station type left on None — it will unlock no recipe.", this);
}
#endregion
#region IInteractable
/// <summary>
/// Prompt shown while aiming at the station.
/// </summary>
public string InteractionPrompt => $"Utiliser {displayName}";
/// <summary>
/// Opens the crafting panel bound to this station. Runs on the interacting client only — nothing
/// here is replicated, every player browses their own panel.
/// </summary>
public void Interact()
{
if (CraftingManager.Instance == null)
{
Debug.LogError("[CraftingStation] No CraftingManager in the scene — cannot open the crafting panel.", this);
return;
}
CraftingManager.Instance.OpenStation(this);
}
#endregion
}
}