using System; using System.Collections.Generic; using System.Linq; using UnityEditor.Tilemaps; public delegate string NameCallback(); public abstract class IInventory { private List changeCallbacks = new List(); public abstract IReadOnlyDictionary Items { get; } public abstract float Capacity { get; set; } public float Load => Items.Sum(kvp => kvp.Value); public float Free => Capacity < 0 ? int.MaxValue : Capacity - Load; public abstract float GetAmount(string item); protected abstract int DoClear(); protected abstract float DoAdd(string item, float amount, bool allowPartialAdd = false); protected abstract float DoRemove(string item, float amount, bool allowPartialRemoval = false); public float Clear() { var cleared = DoClear(); if (cleared > 0) InvokeOnChange(); return cleared; } public float Add(string item, float amount, bool allowPartialAdd = false) { var added = DoAdd(item, amount, allowPartialAdd); if (added > 0) InvokeOnChange(); return added; } public float Remove(string item, float amount, bool allowPartialRemoval = false) { var removed = DoRemove(item, amount, allowPartialRemoval); if (removed > 0) InvokeOnChange(); return removed; } public void RegisterOnChangeCallback(Action callback) { changeCallbacks.Add(callback); } public void UnregisterOnChangeCallback(Action callback) { changeCallbacks.Remove(callback); } protected void InvokeOnChange() { // Debug.Log( // $"Resources: {String.Join("; ", resources.Values.ToArray().Select(r => r.Resource.Name + "=" + r.Amount + (r.Unlocked ? "" : "(locked)")))}" // ); changeCallbacks.ForEach(a => { try { a.Invoke(); } catch { } }); } } [Serializable] public class Inventory2 : IInventory, IDataPersistence { private Dictionary items = new Dictionary(); public Inventory2(float capacity) { _capacity = capacity; } public override IReadOnlyDictionary Items => items; private float _capacity; public override float Capacity { get { return _capacity; } set { _capacity = value; InvokeOnChange(); } } public override string ToString() { return this.ToString(Environment.NewLine); } public string ToString(string delimiter = "\n") { string text = string.Join(delimiter, items); text += delimiter + $"Занято {Load}"; if (Capacity >= 0) text += $", свободно {Capacity - Load}"; return text; } public override float GetAmount(string item) { return items.ContainsKey(item) ? items[item] : 0; } protected override int DoClear() { var itemCount = items.Count; items.Clear(); return itemCount; } protected override float DoAdd(string item, float amount, bool allowPartialAdd = false) { if (!allowPartialAdd && (Capacity >= 0) && (Capacity < Load + amount)) return 0; amount = Math.Min(amount, Free); if (items.ContainsKey(item)) items[item] += amount; else items[item] = amount; return amount; } protected override float DoRemove(string item, float amount, bool allowPartialRemoval = false) { var presentAmount = GetAmount(item); if (!allowPartialRemoval && presentAmount < amount) return 0; amount = Math.Min(amount, presentAmount); items[item] -= amount; if (items[item] == 0) items.Remove(item); return amount; } public void LoadData(InventoryData data) { items = data.items; _capacity = data.capacity; } public void SaveData(InventoryData data) { data.items = new SerializableDictionary(items); data.capacity = _capacity; } public Inventory2 Clone() { var clone = new Inventory2(Capacity); foreach (var kvp in items) clone.items.Add(kvp.Key, kvp.Value); return clone; } public void OverrideItemsFrom(Inventory2 source) { Clear(); foreach (var kvp in source.Items) items.Add(kvp.Key, kvp.Value); } }