diff --git a/scripts/inventory/HotBar.cs b/scripts/inventory/HotBar.cs index 0cc99dd..84e7a27 100644 --- a/scripts/inventory/HotBar.cs +++ b/scripts/inventory/HotBar.cs @@ -20,7 +20,7 @@ public partial class HotBar : HBoxContainer NodeUtils.DeleteAllChild(this); for (var i = 0; i < Config.HotBarSize; i++) { - _itemContainer.AddItemSlot(this, i); + _itemContainer.AddItemSlot(this); } } diff --git a/scripts/inventory/IItemContainer.cs b/scripts/inventory/IItemContainer.cs index a02e732..1a5a36b 100644 --- a/scripts/inventory/IItemContainer.cs +++ b/scripts/inventory/IItemContainer.cs @@ -34,6 +34,17 @@ public interface IItemContainer : IEnumerable /// bool AddItem(IItem item); + /// + /// Determines the number of items that can be received from the specified pile + /// 判断能从指定物品堆中接收的物品数量 + /// + /// + /// Item stack to add to the current container + /// 向该容器中放入物品的物品堆 + /// + /// + int CanAddItemStack(IItemStack itemStack); + /// /// Add an stack of items to this container /// 向当前容器中存入一堆物品 @@ -179,8 +190,8 @@ public interface IItemContainer : IEnumerable ItemSlotNode? Match(IItemStack stack); /// - /// Match the first item slot that has item stack that satisfies the predicate - /// 匹配首个拥有满足指定条件的物品堆的物品槽 + /// Match the first item slot that satisfies the predicate + /// 匹配首个拥有满足指定条件的物品槽 /// /// /// @@ -188,11 +199,11 @@ public interface IItemContainer : IEnumerable /// 若没有满足条件的槽位,返回null /// /// - ItemSlotNode? Match(Func predicate); + ItemSlotNode? Match(Func predicate); /// - /// Match all item slots that has item stack that satisfies the predicate - /// 匹配所有拥有满足指定条件的物品堆的物品槽 + /// Match all item slots that satisfies the predicate + /// 匹配所有拥有满足指定条件的物品槽 /// /// /// @@ -200,7 +211,7 @@ public interface IItemContainer : IEnumerable /// 包含匹配到的槽位的IEnumerable,当没有满足条件的槽位时为空 /// /// - IEnumerable MatchAll(Func predicate); + IEnumerable MatchAll(Func predicate); /// @@ -208,8 +219,7 @@ public interface IItemContainer : IEnumerable /// 添加物品槽 /// /// - /// - void AddItemSlot(Node rootNode, int index); + void AddItemSlot(Node rootNode); /// /// SelectTheNextItemSlot diff --git a/scripts/inventory/ItemSlotNode.cs b/scripts/inventory/ItemSlotNode.cs index 5425825..2f34170 100644 --- a/scripts/inventory/ItemSlotNode.cs +++ b/scripts/inventory/ItemSlotNode.cs @@ -144,18 +144,6 @@ public partial class ItemSlotNode : MarginContainer UpdateAllDisplay(); } - /// - /// Can the specified item be placed in the item slot? - /// 指定的物品是否可设置在物品槽内? - /// - /// - /// - public bool CanAddItem(IItem item) - { - if (_itemStack == null) return true; - return _itemStack.CanAddItem(item); - } - /// /// /// Set item stack for this slot, this will completely replace current item stack. @@ -177,6 +165,18 @@ public partial class ItemSlotNode : MarginContainer return result; } + /// + /// Can the specified item be placed in the item slot? + /// 指定的物品是否可设置在物品槽内? + /// + /// + /// + public bool CanAddItem(IItem item) + { + if (_itemStack == null) return true; + return _itemStack.CanAddItem(item); + } + /// /// Try to add an item to this slot, if it can't be added to this slot, return false /// 尝试向当前槽位中加入物品,如果该物品不能被放入该槽位,返回false @@ -202,6 +202,21 @@ public partial class ItemSlotNode : MarginContainer return result; } + /// + /// Determines the number of items that can be received from the specified pile + /// 判断能从指定物品堆中接收的物品数量 + /// + /// + /// Item stack to add to the current slot + /// 向该物品槽中放入物品的物品堆 + /// + /// + public int CanAddItemStack(IItemStack itemStack) + { + if (_itemStack is null) return itemStack.Quantity; + return _itemStack.CanTakeFrom(itemStack); + } + /// /// Try to combine an item stack into this slot /// 尝试将一个物品堆合并至该槽位中 diff --git a/scripts/inventory/UniversalItemContainer.cs b/scripts/inventory/UniversalItemContainer.cs index 8605b03..5d47e56 100644 --- a/scripts/inventory/UniversalItemContainer.cs +++ b/scripts/inventory/UniversalItemContainer.cs @@ -22,7 +22,7 @@ public class UniversalItemContainer : IItemContainer { private readonly PackedScene? _itemSlotPackedScene = GD.Load("res://prefab/ui/ItemSlot.tscn"); - private readonly List? _itemSlotNodes = new(); + private readonly List? _itemSlotNodes = []; /// /// Character @@ -55,6 +55,16 @@ public class UniversalItemContainer : IItemContainer return itemSlotNode.AddItem(item); } + public int CanAddItemStack(IItemStack itemStack) + { + var testItem = itemStack.GetItem(); + if (testItem is null) return 0; + var slots = MatchAll(slot => slot.CanAddItem(testItem)); + return + Math.Min(itemStack.Quantity, + slots.Select(slot => slot.CanAddItemStack(itemStack)).Sum()); + } + public bool AddItemStack(IItemStack itemStack) { while (true) @@ -169,14 +179,14 @@ public class UniversalItemContainer : IItemContainer return _itemSlotNodes?.FirstOrDefault(itemSlotNode => itemSlotNode.CanAddItem(stack.GetItem()!)); } - public ItemSlotNode? Match(Func predicate) + public ItemSlotNode? Match(Func predicate) { - return _itemSlotNodes?.FirstOrDefault(node => predicate(node.GetItemStack())); + return _itemSlotNodes?.FirstOrDefault(predicate); } - public IEnumerable MatchAll(Func predicate) + public IEnumerable MatchAll(Func predicate) { - return from node in _itemSlotNodes where predicate(node.GetItemStack()) select node; + return from node in _itemSlotNodes where predicate(node) select node; } @@ -211,7 +221,7 @@ public class UniversalItemContainer : IItemContainer /// Add items tank /// 添加物品槽 /// - public void AddItemSlot(Node rootNode, int index) + public void AddItemSlot(Node rootNode) { if (_itemSlotNodes == null || _itemSlotPackedScene == null) { @@ -224,7 +234,7 @@ public class UniversalItemContainer : IItemContainer return; } - itemSlotNode.IsSelect = index == _selectIndex; + itemSlotNode.IsSelect = (_itemSlotNodes.Count ) == _selectIndex; _itemSlotNodes.Add(itemSlotNode); } diff --git a/scripts/item/Packsack.cs b/scripts/item/Packsack.cs index 1afc8b0..6ac8e91 100644 --- a/scripts/item/Packsack.cs +++ b/scripts/item/Packsack.cs @@ -1,4 +1,5 @@ using ColdMint.scripts.inventory; +using ColdMint.scripts.item.itemStacks; using Godot; @@ -25,8 +26,8 @@ public partial class Packsack : RigidBody2D, IItem public void Destroy() { - if (_itemContainer == null) return; - foreach (var itemSlot in _itemContainer) + if (ItemContainer == null) return; + foreach (var itemSlot in ItemContainer) { itemSlot.ClearSlot(); } @@ -36,16 +37,20 @@ public partial class Packsack : RigidBody2D, IItem public bool CanStackWith(IItem item) => false; - private IItemContainer? _itemContainer; + public IItemStack? SpecialStack() + { + return new PacksackStack(this); + } + + + public IItemContainer? ItemContainer { get; private set; } public override void _Ready() { base._Ready(); - _itemContainer = new UniversalItemContainer(); - } + ItemContainer = new UniversalItemContainer(); - public IItemContainer? GetItemContainer() - { - return _itemContainer; + //Test: Add one ItemSlot for pack + ItemContainer.AddItemSlot(this); } } \ No newline at end of file diff --git a/scripts/item/itemStacks/IItemStack.cs b/scripts/item/itemStacks/IItemStack.cs index 5ba7d17..74c5fc2 100644 --- a/scripts/item/itemStacks/IItemStack.cs +++ b/scripts/item/itemStacks/IItemStack.cs @@ -78,8 +78,8 @@ public interface IItemStack /// 判断能从指定物品堆中接收的物品数量 /// /// - /// 向该物品堆中放入物品的物品堆 /// Item stack to add to the current stack + /// 向该物品堆中放入物品的物品堆 /// /// public int CanTakeFrom(IItemStack itemStack); diff --git a/scripts/item/itemStacks/PacksackStack.cs b/scripts/item/itemStacks/PacksackStack.cs new file mode 100644 index 0000000..a70a22e --- /dev/null +++ b/scripts/item/itemStacks/PacksackStack.cs @@ -0,0 +1,79 @@ +using System; + +using Godot; + +namespace ColdMint.scripts.item.itemStacks; + +/// +/// ItemStack for item. Can add items into pack by stack them to this stack. +/// 用于物品的堆栈。可以将物品堆叠到此堆栈中,从而将物品添加到背包中。 +/// +/// +public class PacksackStack(Packsack packsack) : IItemStack +{ + public int MaxQuantity => 1; + public int Quantity => 1; + public bool Empty { get; private set; } + public Texture2D Icon => packsack.Icon; + public string Name => packsack.Name; + public string? Description => packsack.Description; + + //todo: 只拒绝是背包的物品是权宜之计,应该为物品加入一个“是否可以放入背包”的属性来实现这个判断。 + public bool CanAddItem(IItem item) + { + if (item is Packsack) return false; + return packsack.ItemContainer?.CanAddItem(item) ?? false; + } + + public bool AddItem(IItem item) + { + if (item is Packsack) return false; + return packsack.ItemContainer?.AddItem(item) ?? false; + } + + public int CanTakeFrom(IItemStack itemStack) + { + if (itemStack.GetItem() is Packsack) return 0; + return packsack.ItemContainer?.CanAddItemStack(itemStack) ?? 0; + } + + public bool TakeFrom(IItemStack itemStack) + { + if (itemStack.GetItem() is Packsack) return false; + return packsack.ItemContainer?.AddItemStack(itemStack) ?? false; + } + + public IItem? GetItem() + { + return Empty ? packsack : null; + } + + public IItem? PickItem() + { + if (Empty) return null; + Empty = true; + return packsack; + } + + public IItemStack? PickItems(int value) + { + if (Empty || value == 0) return null; + Empty = true; + return new PacksackStack(packsack); + } + + public int RemoveItem(int number) + { + if (Empty || number == 0) return number; + Empty = true; + packsack.Destroy(); + return Math.Max(0, number - 1); + } + + public void ClearStack() + { + if (Empty) return; + packsack.Destroy(); + Empty = true; + } +} \ No newline at end of file