using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using BITKit; using System.Threading.Tasks; using UnityEngine.UIElements; using System.Text; using BITKit.Entities; using System.Linq; using System.Security.Cryptography; using BITFALL.Entities; using BITFALL.Entities.Improvised; using BITFALL.Hotkey; using BITFALL.Items; using BITFALL.Player.Inventory; using BITKit.IO; using BITKit.Selection; using BITKit.UX; using Unity.Mathematics; using YooAsset; namespace BITFALL { [CustomType(typeof(IPlayerInventory))] public class PlayerInventory : EntityInventory,IPlayerInventory { [SerializeField] private int currentMoney; [Header(nameof(PlayerInventory))] [SerializeReference,SubclassSelector] private INetClient netClient; [SerializeReference,SubclassSelector] private INetServer netServer; private INetProvider _clientNetProvider=>netClient as INetProvider; private INetProvider _serverNetProvider=>netServer as INetProvider; [Inject] private ISelector _selector; [Inject(true)] private ImprovisedServiceInterface _improvisedService; [Inject(true)] private IKnockdown _knockdown; [Inject(true)] private IUXPopup _popup; [Inject(true)] private IApplicationFile applicationFile; [Inject(true)] private IHotkeyCollection _hotkeyCollection; private HotkeyProvider? _pickItemHotkey; public override void OnStart() { base.OnStart(); _selector.OnActive += OnActive; _selector.OnSelected += OnSelected; _selector.OnInactive += OnInactive; if (_improvisedService is not null) { _improvisedService.OnUnEquipImprovisedItem += OnUnEquipImprovisedItem; } OnAdd += OnAddItem; OnRemove += OnRemoveItem; OnUsedItem += OnUseItem; applicationFile.AddListener(nameof(PlayerInventory),OnRelease); applicationFile.DataHandle += OnData; OnMoneyChanged?.Invoke(currentMoney); } private void OnInactive(ISelectable obj) { CancelCurrent(); } private void OnSelected(ISelectable obj) { if (obj.Transform.TryGetComponent(out var worldItemObject) && worldItemObject.Item is not null) { if (_pickItemHotkey?.Data == worldItemObject) { return; } CancelCurrent(); _pickItemHotkey = new HotkeyProvider() { Data = worldItemObject, Description = "捡起可互动的物品", Enabled = true, Name = $"捡起:{worldItemObject.Item.Name}", OnPerform = Pick, }; _hotkeyCollection.Register(_pickItemHotkey); void Pick() { if (Add(worldItemObject.Item)) { Destroy(obj.Transform.gameObject); } } } else { CancelCurrent(); } } private void CancelCurrent() { if (_pickItemHotkey is null) return; _hotkeyCollection.UnRegister(_pickItemHotkey); _pickItemHotkey = null; } public override void OnDestroyComponent() { base.OnDestroyComponent(); applicationFile.RemoveListener(nameof(PlayerInventory),OnRelease); applicationFile.DataHandle -= OnData; } private (string, byte[]) OnData() { using var ms = new System.IO.MemoryStream(); using var writer = new System.IO.BinaryWriter(ms); var reportBuilder = new StringBuilder(); var items = GetItems(); writer.Write(items.Length); reportBuilder.AppendLine(items.Length.ToString()); foreach (var item in items) { writer.Write(item.Id); writer.Write(item.AddressablePath); reportBuilder.AppendLine(item.AddressablePath); } BIT4Log.Log(reportBuilder.ToString()); return new(nameof(PlayerInventory),ms.ToArray()); } private void OnRelease(byte[] obj) { using var ms = new System.IO.MemoryStream(obj); using var reader = new System.IO.BinaryReader(ms); dictionary.Clear(); var length = reader.ReadInt32(); for (var i = 0; i < length; i++) { var id = reader.ReadInt32(); var path = reader.ReadString(); var so = YooAssets.LoadAssetSync(path).AssetObject.As(); var item = new ManagedItem(); item.CopyItemsFrom(so); item.Id = id; dictionary.Add(id,item); } RebuildInternal(); } private void OnUseItem(IBasicItem obj) { _popup?.Popup($"使用了[{obj.Name}]"); } private void OnRemoveItem(IBasicItem obj) { _popup?.Popup($"移除了[{obj.Name}]"); } private void OnAddItem(IBasicItem obj) { _popup?.Popup($"捡起了[{obj.Name}]"); } protected override void OnSetAlive(bool alive) { var keepInventory = Data.Get(BITConstant.Environment.sp_keepInventory); if (keepInventory) { } else { base.OnSetAlive(alive); } } private void OnUnEquipImprovisedItem(IBasicItem obj) { Drop(obj); } public override bool Add(IBasicItem item) { var result = base.Add(item); if (result && netClient.IsConnected) { _clientNetProvider.ServerCommand(new WorldItemDespawnCommand() { Id = item.Id, }); } return result; } protected override void Drop(IBasicItem item) { if(netClient.IsConnected) { InvokeOnDrop(item); _clientNetProvider.ServerCommand(new WorldItemSpawnCommand() { Id = item.Id, AddressableId = item.GetAssetable().AddressableId, Position = Transform.position, Rotation = Transform.rotation, }); } else { base.Drop(item); } } private void OnActive(ISelectable obj) { CancelCurrent(); if (obj.Transform.TryGetComponent(out var item)) { var _item = item.Pick(); if(item.GetAssetable().IsImprovised) { if (_knockdown is not null && _knockdown.IsKnockdown) { return; } if (_improvisedService.TryEquipImprovisedItem(_item)) { item.Picked(); } } else if (Add(_item)) { item.Picked(); } } if (obj.Transform.TryGetComponent(out var money)) { Destroy(obj.Transform.gameObject); //currentMoney += money.Money; Transfer(new MonetStrace() { Detail = money.Name, Money = money.Money, }); } } public int Money => currentMoney; public void Transfer(IMoneyStrace strace) { currentMoney += strace.Money; if (string.IsNullOrEmpty(strace.Detail) is false) { _popup?.Popup($"{strace.Detail}:{strace.Money}"); } OnMoneyChanged?.Invoke(currentMoney); OnTransfer?.Invoke(strace); } public event Action OnMoneyChanged; public event Action OnTransfer; public void Drop(IMoneyStrace strace) { var min = Mathf.Min(currentMoney,Mathf.Abs(strace.Money)); if (min <= 0) return; Transfer(new MonetStrace() { Money = -Mathf.Abs(min), Detail = strace.Detail, }); var drop = WorldMoneyService.Singleton.Spawn(min); drop.transform.position = Transform.position; } } #if UNITY_EDITOR [UnityEditor.CustomEditor(typeof(PlayerInventory))] public class EntityPlayerInventoryInspector : BITInspector { public override VisualElement CreateInspectorGUI() { FillDefaultInspector(); CreateSubTitle(Constant.Header.Debug); var serializeLabel = root.Create