diff --git a/scripts/character/CharacterTemplate.cs b/scripts/character/CharacterTemplate.cs index 8494134..4422ab2 100644 --- a/scripts/character/CharacterTemplate.cs +++ b/scripts/character/CharacterTemplate.cs @@ -41,14 +41,7 @@ public partial class CharacterTemplate : CharacterBody2D //Item containers are used to store items. //物品容器用于存储物品。 - private IItemContainer? _itemContainer; - - - public IItemContainer? ItemContainer - { - get => _itemContainer; - set => _itemContainer = value; - } + public IItemContainer? ItemContainer { get; set; } //Items currently held //当前持有的物品 @@ -282,14 +275,14 @@ public partial class CharacterTemplate : CharacterBody2D return false; } - if (_itemContainer == null) + if (ItemContainer == null) { return false; } //Get the currently selected node //拿到当前选择的节点 - var itemSlotNode = _itemContainer.GetSelectItemSlotNode(); + var itemSlotNode = ItemContainer.GetSelectItemSlotNode(); if (itemSlotNode == null) { return false; @@ -297,7 +290,7 @@ public partial class CharacterTemplate : CharacterBody2D //First check if we can pick up the item. //先检查我们能否拾起此物品。 - var canPick = _itemContainer.CanAddItem(item); + var canPick = ItemContainer.CanAddItem(item); if (!canPick) { return false; @@ -305,7 +298,7 @@ public partial class CharacterTemplate : CharacterBody2D //Is it successfully added to the container? //再检查是否成功的添加到容器内了? - var addSuccess = _itemContainer.AddItem(item); + var addSuccess = ItemContainer.AddItem(item); if (!addSuccess) { return false; @@ -504,7 +497,7 @@ public partial class CharacterTemplate : CharacterBody2D /// protected virtual void EnterThePickingRangeBody(Node node) { - if (node is not IItem) + if (node is not IItem_New item) { return; } @@ -519,7 +512,7 @@ public partial class CharacterTemplate : CharacterBody2D /// protected virtual void ExitThePickingRangeBody(Node node) { - if (node is not IItem) + if (node is not IItem_New) { return; } @@ -549,12 +542,12 @@ public partial class CharacterTemplate : CharacterBody2D { //If the item container is null, then return //如果物品容器为null,那么返回 - if (_itemContainer == null) + if (ItemContainer == null) { return; } - var len = _itemContainer.GetItemSlotCount(); + var len = ItemContainer.GetItemSlotCount(); if (len == 0) { return; @@ -599,7 +592,7 @@ public partial class CharacterTemplate : CharacterBody2D /// protected void ThrowItem(int index, int number, Vector2 velocity) { - var itemSlotNode = _itemContainer?.GetItemSlotNode(index); + var itemSlotNode = ItemContainer?.GetItemSlotNode(index); var item = itemSlotNode?.GetItem(); diff --git a/scripts/inventory/HotBar.cs b/scripts/inventory/HotBar.cs index 4fb129a..f9dda26 100644 --- a/scripts/inventory/HotBar.cs +++ b/scripts/inventory/HotBar.cs @@ -339,7 +339,7 @@ public partial class HotBar : HBoxContainer, IItemContainer { return false; } - return itemSlotNode.SetItem(item); + return itemSlotNode.ReplaceItemStack(item); } public int GetSelectIndex() @@ -374,7 +374,7 @@ public partial class HotBar : HBoxContainer, IItemContainer foreach (var itemSlotNode in _itemSlotNodes) { - if (itemSlotNode.CanSetItem(item)) + if (itemSlotNode.CanAddItem(item)) { //If there is an item slot to put this item in, then we return it. //如果有物品槽可放置此物品,那么我们返回它。 diff --git a/scripts/inventory/ItemSlotNode.cs b/scripts/inventory/ItemSlotNode.cs index 93a07f5..ea526a6 100644 --- a/scripts/inventory/ItemSlotNode.cs +++ b/scripts/inventory/ItemSlotNode.cs @@ -42,7 +42,49 @@ public partial class ItemSlotNode : MarginContainer /// 获取物品槽内的物品堆 /// /// - public IItemStack GetItemStack() => _itemStack; + public IItemStack? GetItemStack() => _itemStack; + + /// + /// If present, get the item at the top of the item stack in this slot + /// 如果存在,获取该槽位中物品堆顶部的物品 + /// + public IItem_New? GetItem() => _itemStack?.GetItem(); + + /// + /// If present, remove an item in this slot and return it. + /// 如果存在,移除该槽位中的一个物品并将其返回 + /// + /// + public IItem_New? PickItem() + { + if (_itemStack is null) return null; + + var result = _itemStack.PickItem(); + if (_itemStack.Quantity == 0) ClearSlot(); + else UpdateAllDisplay(); + + return result; + } + + /// + /// Remove the specified number of items and return them as a new item stack + /// 取出当前物品槽中指定数量的物品,并作为新的物品堆返回 + /// + /// + /// Quantity to be taken out, inputs below zero represent all items + /// 要取出的数量,小于0的输入代表全部物品 + /// + /// + public IItemStack? PickItems(int value) + { + if (_itemStack is null) return null; + + var result = _itemStack.PickItems(value); + if (_itemStack.Quantity == 0) ClearSlot(); + else UpdateAllDisplay(); + + return result; + } /// /// Removes the specified number of items from the item slot @@ -53,6 +95,9 @@ public partial class ItemSlotNode : MarginContainer /// The remaining number, if the number of items in the current item stack is less than the specified number. Otherwise,0 /// 若物品槽内物品少于指定的数量,返回相差的数量。否则返回0 /// + /// + /// 会将移除的物品从游戏中删除,如果目的并非如此,请考虑使用 + /// public int RemoveItem(int number) { if (_itemStack == null) @@ -64,133 +109,139 @@ public partial class ItemSlotNode : MarginContainer //If the specified number of items is removed, the number of items is less than or equal to 0. Then we empty the inventory. //如果移除指定数量的物品后,物品数量小于或等于0。那么我们清空物品栏。 if (_itemStack.Quantity == 0) ClearSlot(); - else - { - UpdateTooltipText(_itemStack); - UpdateQuantityLabel(_itemStack.Quantity); - } + else UpdateAllDisplay(); return result; - - // var newNumber = _item.Quantity - number; - // if (newNumber <= 0) - // { - // //If the specified number of items is removed, the number of items is less than or equal to 0. Then we return the removal successful and empty the inventory. - // //如果移除指定数量的物品后,物品数量小于或等于0。那么我们返回移除成功,并清空物品栏。 - // ClearItem(); - // return true; - // } - // else - // { - // _item.Quantity = newNumber; - // UpdateTooltipText(_item); - // UpdateQuantityLabel(_item.Quantity); - // return true; - // } } + /// + /// Remove item stack from slot and return it, equivalent to ReplaceItemStack(null) + /// 从当前槽位中移出并返回物品堆,等价于ReplaceItemStack(null) + /// + /// + public IItemStack? RemoveItemStack() => ReplaceItemStack(null); + /// /// Empty the item slot - /// 清空物品槽 + /// 清空当前物品槽 /// /// - ///This method does not calculate how many items should be left. If you want to remove a specified number of items, call the method. - ///此方法不会计算物品应该剩余多少个。若您希望移除指定数量的物品,请调用方法。 + ///This method will remove all items stored in the item slots from the game, if this is not what you want to do, consider using the method. + ///此方法会从游戏中移除储存于物品槽中的所有物品,若这不是您希望的操作,请考虑使用方法。 /// public void ClearSlot() { + _itemStack?.ClearStack(); _itemStack = null; - - if (_iconTextureRect != null) - { - _iconTextureRect.Texture = null; - } - if (_control != null) - { - _control.TooltipText = null; - } - - _quantityLabel?.Hide(); + UpdateAllDisplay(); } - //Todo: I searched until here. - /// /// Can the specified item be placed in the item slot? /// 指定的物品是否可设置在物品槽内? /// /// /// - public bool CanSetItem(IItem item) + public bool CanAddItem(IItem_New item) { - if (_item == null) - { - return true; - } - - //This inventory already has items, but the items in this inventory are not the same as the incoming items - //这个物品栏已经有物品了,但是这个物品栏的物品和传入的物品不一样 - if (_item.Id != item.Id) - { - return false; - } - - var newQuantity = _item.Quantity + item.Quantity; - if (newQuantity > item.MaxStackQuantity) - { - //If the amount of the current item exceeds the maximum stack amount after placing it in this inventory - //如果将当前物品放置到这个物品栏后,数量超过了最大叠加数量 - return false; - } - - return true; + if (_itemStack == null) return true; + return _itemStack.CanAddItem(item); } /// - /// Sets items for the item slot - /// 为物品槽设置物品 + /// + /// Set item stack for this slot, this will completely replace current item stack. + /// If you want the item stack to be added to current stack, use the . + /// + /// 为物品槽设置物品堆,将完全替换掉当前物品堆。如果想要物品堆叠加至该物品堆,请使用 /// - /// - /// - public bool SetItem(IItem item) + /// + /// The item stack that was previously in this slot + /// 该槽位中原本的物品堆 + /// + public IItemStack? ReplaceItemStack(IItemStack? newItemStack) { - if (!CanSetItem(item)) - { - return false; - } + var result = _itemStack; + _itemStack = newItemStack; - if (_item == null) - { - if (item.Icon != null && _iconTextureRect != null) - { - _iconTextureRect.Texture = item.Icon; - } + UpdateAllDisplay(); - _item = item; - UpdateTooltipText(item); - UpdateQuantityLabel(item.Quantity); - return true; + return result; + } + + /// + /// Try to add an item to this slot, if it can't be added to this slot, return false + /// 尝试向当前槽位中加入物品,如果该物品不能被放入该槽位,返回false + /// + public bool AddItem(IItem_New item) + { + bool result; + if (_itemStack is null) + { + _itemStack = IItemStack.FromItem(item); + result = true; } else { - var newQuantity = _item.Quantity + item.Quantity; - _item.Quantity = newQuantity; - UpdateTooltipText(item); - UpdateQuantityLabel(newQuantity); - return true; + result = _itemStack.AddItem(item); } + + if (result) + { + UpdateAllDisplay(); + } + + return result; + } + + /// + /// Try to combine an item stack into this slot + /// 尝试将一个物品堆合并至该槽位中 + /// + /// + /// Number of items remaining in the source item pile after the operation is completed + /// 操作完成后,源物品堆中剩余的物品数 + /// + public int AddItemStack(IItemStack itemStack) + { + int result; + if (_itemStack is null) + { + _itemStack = itemStack; + result = 0; + } + else + { + result = _itemStack.TakeFrom(itemStack); + } + + UpdateAllDisplay(); + return result; + } + + + /// + /// Update all displays of this slot + /// 更新该槽位的一切显示信息 + /// + private void UpdateAllDisplay() + { + UpdateIconTexture(); + UpdateQuantityLabel(); + UpdateTooltipText(); } /// /// Update item tips /// 更新物品的提示内容 /// - /// - private void UpdateTooltipText(IItem item) + private void UpdateTooltipText() { - if (_control == null) + if (_control == null) return; + if (_itemStack == null) { + _control.TooltipText = null; return; } @@ -199,16 +250,16 @@ public partial class ItemSlotNode : MarginContainer var debugText = TranslationServerUtils.Translate("item_prompt_debug"); if (debugText != null) { - _control.TooltipText = string.Format(debugText, item.Id, - TranslationServerUtils.Translate(item.Name), - item.Quantity, item.MaxStackQuantity, item.GetType().Name, - TranslationServerUtils.Translate(item.Description)); + _control.TooltipText = string.Format(debugText, _itemStack.Id, + TranslationServerUtils.Translate(_itemStack.Name), + _itemStack.Quantity, _itemStack.MaxQuantity, _itemStack.GetType().Name, + TranslationServerUtils.Translate(_itemStack.Description)); } } else { - _control.TooltipText = TranslationServerUtils.Translate(item.Name) + "\n" + - TranslationServerUtils.Translate(item.Description); + _control.TooltipText = TranslationServerUtils.Translate(_itemStack.Name) + "\n" + + TranslationServerUtils.Translate(_itemStack.Description); } } @@ -216,28 +267,36 @@ public partial class ItemSlotNode : MarginContainer /// Update quantity label /// 更新数量标签 /// - /// - private void UpdateQuantityLabel(int? quantity) + private void UpdateQuantityLabel() { if (_quantityLabel == null) { return; } - switch (quantity) + switch (_itemStack?.Quantity) { - case null: + case null or 1: _quantityLabel.Hide(); return; - case > 1: - //When the quantity is greater than 1, we display the quantity. - //当数量大于1时,我们显示数量 - _quantityLabel.Text = quantity.ToString(); + default: + //When the quantity is not null or 1, we display the quantity. + //当数量不为null或1时,我们显示数量 + _quantityLabel.Text = _itemStack?.Quantity.ToString(); _quantityLabel.Show(); break; - default: - _quantityLabel.Hide(); - break; + } + } + + /// + /// Update texture of the icon rect + /// 更新显示的物品图标 + /// + private void UpdateIconTexture() + { + if (_iconTextureRect != null) + { + _iconTextureRect.Texture = _itemStack?.Icon; } } diff --git a/scripts/item/IItemStack.cs b/scripts/item/IItemStack.cs index 1ff6bd9..1ebfba7 100644 --- a/scripts/item/IItemStack.cs +++ b/scripts/item/IItemStack.cs @@ -4,6 +4,9 @@ using Godot; namespace ColdMint.scripts.item; +/// +/// Item stack in an inventory slot +/// public interface IItemStack { /// @@ -36,10 +39,81 @@ public interface IItemStack /// string? Description { get; } + /// + /// Determine whether a specified item can be accommodated + /// 判断能否容纳指定物品 + /// + /// + public bool CanAddItem(IItem_New item); /// - /// Removes the specified number of items from current item stack - /// 在当前物品堆移除指定数量的物品 + /// Hold a given item + /// + /// Item to hold by current stack + /// Whether successful + public bool AddItem(IItem_New item); + + /// + /// 判断能从指定物品堆中接收的物品数量 + /// + /// + /// 向该物品堆中放入物品的物品堆 + /// Item stack to add to the current stack + /// + /// + public int CanTakeFrom(IItemStack itemStack); + + /// + /// 将指定物品堆中尽可能多的物品移动至当前物品堆中,被移入当前堆的物品应从原物品堆中移除。 + /// + /// + /// 被移入当前堆的物品堆 + /// + /// + /// 操作结束后原物品堆中剩余的物品数 + /// + public int TakeFrom(IItemStack itemStack); + + /// + /// Get item instance at the top of current stack without removing it from stack + /// 获取当前物品堆顶部的物品实例而不取出该物品 + /// + /// + /// + public IItem_New? GetItem(); + + /// + /// Pop the item instance at the top of current item stack and return it + /// 取出当前物品堆顶部的物品实例并返回该物品 + /// + /// + /// + public IItem_New? PickItem(); + + /// + /// Remove the specified number of items and return them as a new item stack + /// 取出当前堆中指定数量的物品,并作为新的物品堆返回 + /// + /// + /// + /// Quantity to be taken out, inputs below zero represent all items + /// 要取出的数量,小于0的输入代表全部物品 + /// + /// + /// The item stack that is taken out, can be null if out nothing, should not be the current item stack itself + /// 取出的物品堆,没有取出物品时可为null,不应是当前物品堆自身 + /// + public IItemStack? PickItems(int value); + + /// + /// + /// Removes the specified number of items from current item stack,removed items should be removed from the game
+ /// If you don't want remove them from game, consider and + ///
+ /// + /// 在当前物品堆移除指定数量的物品,被移除的物品应当从游戏中移除。
+ /// 如果您不想将它们从游戏中移除,请考虑: + ///
///
/// /// @@ -48,6 +122,11 @@ public interface IItemStack /// public int RemoveItem(int number); + /// + /// Clear current stack, which means should dispose all items inside current stack here + /// + public void ClearStack(); + /// /// Create a new ItemStack with the given item as the first item /// diff --git a/scripts/item/IItem_New.cs b/scripts/item/IItem_New.cs index d98e25d..a046842 100644 --- a/scripts/item/IItem_New.cs +++ b/scripts/item/IItem_New.cs @@ -28,4 +28,9 @@ public interface IItem_New /// Owner of current item, if any /// Target position, such as the position of the cursor when used by the player void Use(Node2D? owner, Vector2 targetGlobalPosition); + + /// + /// Execute when current item be removed from game. + /// + void Destroy(); } \ No newline at end of file diff --git a/scripts/item/SingleItemStack.cs b/scripts/item/SingleItemStack.cs index b853990..d7c3415 100644 --- a/scripts/item/SingleItemStack.cs +++ b/scripts/item/SingleItemStack.cs @@ -1,21 +1,41 @@ -using ColdMint.scripts.inventory; +using System; + +using ColdMint.scripts.inventory; using Godot; namespace ColdMint.scripts.item; /// -/// Item stack in inventory +/// Item stack of single item /// //maybe we'd move this into inventory namespace -public readonly struct SingleItemStack(IItem_New item) : IItemStack +public struct SingleItemStack(IItem_New item) : IItemStack { public IItem_New Item { get; init; } = item; public string Id => Item.Id; public int MaxQuantity => 1; - public int Quantity => 1; + public int Quantity { get; set; } = 1; public Texture2D Icon => Item.Icon; public string Name => Item.Name; public string? Description => Item.Description; + + public bool CanAddItem(IItem_New item) => false; + + public bool AddItem(IItem_New item) => false; + + public int CanTakeFrom(IItemStack itemStack) => 0; + + public int TakeFrom(IItemStack itemStack) => 0; + + public int RemoveItem(int number) + { + + } + + public void ClearStack() + { + throw new System.NotImplementedException(); + } } \ No newline at end of file