using System; using System.Collections; using System.Collections.Generic; using System.Windows.Forms; using BITKit; using BITKit.Entities; using BITKit.Entities.Player; using BITKit.UX; using UnityEngine; // ReSharper disable ConvertToAutoProperty namespace BITFALL.Scene { public class ActionBasedObject : MonoBehaviour,IActionBasedObject,IAction,IDescription { [SerializeReference, SubclassSelector] private IPlayerService playerService; [SerializeReference, SubclassSelector] private ITicker ticker; [SerializeReference, SubclassSelector] private IActionMode actionMode; [SerializeReference, SubclassSelector] private IUXPopup popup; [SerializeReference, SubclassSelector] private IReference actionName; [SerializeReference, SubclassSelector] private IReference completedEnv; [SerializeField] private int priority; public IActionMode ActionMode => actionMode; public IEntity Entity { get; private set; } public float ElapsedTime => Time.time - _startTime; private float _startTime; public event Action OnStarted; public event Action OnTick; public event Action OnCompleted; public event Action OnCanceled; private bool _isTicking; public void Entry(IEntity entity) { if (Entity is not null) throw new InGameException("当前已经有实体在互动"); if (entity.TryGetComponent(out var _override) is false) throw new InGameException("实体没有覆盖组件"); try { _startTime = Time.time; Entity = entity; OnStarted?.Invoke(); } catch (InGameException e) { Entity = null; popup.Popup(e.Message); return; } _override.AddOverride(this,priority); ticker.Add(OnUpdate); _isTicking = true; } private void OnDestroy() { if(_isTicking) ticker.Remove(OnUpdate); } private void OnUpdate(float obj) { try { OnTick?.Invoke(obj); } catch (InGameException e) { popup.Popup(e.Message); OnCanceled?.Invoke(); Cancel(); return; } foreach (var factory in IsCompletedFactory.CastAsFunc()) { try { if (factory() is false) { return; } } catch (InGameException e) { Cancel(); popup.Popup(e.Message); OnCanceled?.Invoke(); return; } catch (Exception) { Cancel(); throw; } } Cancel(); OnCompleted?.Invoke(); if (completedEnv is not null) Data.Set(completedEnv.Value, 1); } public void Cancel() { if (Entity is null) throw new InGameException("当前没有实体在互动"); if (Entity.TryGetComponent(out var _override) is false) throw new InGameException("实体没有覆盖组件"); _override.RemoveOverride(this); if (_isTicking) ticker.Remove(OnUpdate); Entity = null; } public event Func IsCompletedFactory; public void Execute() { Entry(playerService.LocalPlayer); } public string Name=>actionName is null?gameObject.name:actionName.Value; } }