using UnityEngine; using UnityEngine.Events; [DisallowMultipleComponent] public sealed class RocketAssemblyWorkstationView : MonoBehaviour { [SerializeField] private NetworkRocketAssemblyWorkstation workstation; [Header("State Events")] [SerializeField] private UnityEvent onLoading; [SerializeField] private UnityEvent onAssemblyStarted; [SerializeField] private UnityEvent onValidOutputReady; [SerializeField] private UnityEvent onDefectiveOutputReady; [Header("Blueprint and Slot Events")] [SerializeField] private UnityEvent onRecipeNameChanged; [SerializeField] private UnityEvent onBlueprintTitleChanged; [SerializeField] private UnityEvent onBlueprintImageChanged; [SerializeField] private UnityEvent onRequiredPartCountChanged; [SerializeField] private UnityEvent onOccupiedSlotCountChanged; [SerializeField] private UnityEvent onCanStartChanged; [Header("Continuous Progress")] [SerializeField] private UnityEvent onAssemblyProgress; private RocketAssemblyWorkstationState previousState; private bool previousDefectiveResult; private bool hasAppliedState; public NetworkRocketAssemblyWorkstation Workstation => workstation; private void Reset() => workstation = GetComponentInParent(); private void Awake() { if (workstation == null) workstation = GetComponentInParent(); } private void OnEnable() { if (workstation != null) { workstation.Changed += Apply; Apply(); } } private void Start() => Apply(); private void OnDisable() { if (workstation != null) workstation.Changed -= Apply; hasAppliedState = false; } private void Update() { if (workstation != null && workstation.IsOperating) onAssemblyProgress?.Invoke(workstation.AssemblyProgress); } public void Apply() { if (workstation == null || !workstation.IsSpawned) return; ApplyRecipeAndSlots(); RocketAssemblyWorkstationState currentState = workstation.State; bool defectiveResult = workstation.LastCompletedAssemblyWasDefective; if (hasAppliedState && currentState == previousState && defectiveResult == previousDefectiveResult) { return; } previousState = currentState; previousDefectiveResult = defectiveResult; hasAppliedState = true; switch (currentState) { case RocketAssemblyWorkstationState.Assembling: onAssemblyStarted?.Invoke(); onAssemblyProgress?.Invoke(workstation.AssemblyProgress); break; case RocketAssemblyWorkstationState.OutputReady: onAssemblyProgress?.Invoke(1f); if (defectiveResult) onDefectiveOutputReady?.Invoke(); else onValidOutputReady?.Invoke(); break; default: onAssemblyProgress?.Invoke(0f); onLoading?.Invoke(); break; } } [ContextMenu("Preview/Loading")] private void PreviewLoading() { onAssemblyProgress?.Invoke(0f); onLoading?.Invoke(); } [ContextMenu("Preview/Assembly Started")] private void PreviewAssemblyStarted() { onAssemblyProgress?.Invoke(0f); onAssemblyStarted?.Invoke(); } [ContextMenu("Preview/Assembly 50 Percent")] private void PreviewAssemblyHalfway() => onAssemblyProgress?.Invoke(0.5f); [ContextMenu("Preview/Valid Output")] private void PreviewValidOutput() { onAssemblyProgress?.Invoke(1f); onValidOutputReady?.Invoke(); } [ContextMenu("Preview/Defective Output")] private void PreviewDefectiveOutput() { onAssemblyProgress?.Invoke(1f); onDefectiveOutputReady?.Invoke(); } private void ApplyRecipeAndSlots() { RocketAssemblyRecipe recipe = workstation.SelectedRecipe; onRecipeNameChanged?.Invoke(recipe != null ? recipe.DisplayName : string.Empty); onBlueprintTitleChanged?.Invoke(recipe != null ? recipe.BlueprintTitle : string.Empty); onBlueprintImageChanged?.Invoke(recipe != null ? recipe.BlueprintImage : null); onRequiredPartCountChanged?.Invoke(recipe != null ? recipe.RequiredPartCount : 0); onOccupiedSlotCountChanged?.Invoke(workstation.OccupiedSlotCount); onCanStartChanged?.Invoke(workstation.CanStartAssembly); } }