Fixed an issue where players could pick up items in the backpack after throwing it.Supports placing items across item containers

修复玩家扔出背包后,再捡起背包内的物品消失的问题。支持跨容器替换物品了。
This commit is contained in:
Cold-Mint 2024-09-28 22:59:25 +08:00
parent 4f2208bd60
commit 31a1d292d8
Signed by: Cold-Mint
GPG Key ID: C5A9BF8A98E0CE99
10 changed files with 100 additions and 66 deletions

View File

@ -170,12 +170,12 @@ public static class Config
///<para>在禁用版本隔离时用的</para>
/// </remarks>
public const string DefaultVersionName = "Default";
/// <summary>
/// <para>EmptyVariant</para>
/// <para>空变量</para>
/// </summary>
public static readonly Variant EmptyVariant = new();
public static readonly Variant EmptyVariant = new();
/// <summary>
@ -216,7 +216,7 @@ public static class Config
/// </summary>
public const string TimeInterval = "TimeInterval";
}
/// <summary>
/// <para>Item data changes the event type</para>
/// <para>物品数据改变事件类型</para>
@ -238,12 +238,17 @@ public static class Config
/// <para>移除</para>
/// </summary>
Remove,
/// <summary>
/// <para>Replace</para>
/// <para>被替换</para>
/// </summary>
Replace
Replace,
/// <summary>
/// <para>Clear</para>
/// <para>被清空</para>
/// </summary>
Clear
}
public enum OsEnum

View File

@ -15,10 +15,7 @@ public partial class HotBar : HBoxContainer
public override void _Ready()
{
base._Ready();
var universalItemContainer = new UniversalItemContainer(Config.HotBarSize)
{
EnablePlaceholder = true
};
var universalItemContainer = new UniversalItemContainer(Config.HotBarSize);
_itemContainer = universalItemContainer;
_itemContainer.SupportSelect = true;
_itemContainerDisplay = new ItemSlotContainerDisplay(this);

View File

@ -4,6 +4,11 @@ namespace ColdMint.scripts.inventory;
public interface IItem
{
/// <summary>
/// <para>The position of the item in the container</para>
/// <para>物品在容器内的位置</para>
/// </summary>
public int Index { get; set; }
/// <summary>
/// <para>ID of current item</para>
/// <para>当前物品的ID</para>

View File

@ -50,8 +50,12 @@ public interface IItemContainer
/// <para>Gets a placeholder object</para>
/// <para>获取占位符对象</para>
/// </summary>
/// <param name="index">
///<para>index</para>
///<para>占位符代替的索引</para>
/// </param>
/// <returns></returns>
IItem? GetPlaceHolderItem();
IItem GetPlaceHolderItem(int index);
/// <summary>
/// <para>Gets the selected location</para>
@ -88,7 +92,13 @@ public interface IItemContainer
/// <returns></returns>
bool ReplaceItem(int index, IItem item);
bool ReplaceItem(IItem oldItem, IItem newItem);
/// <summary>
/// <para>ClearItem</para>
/// <para>清理物品</para>
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
bool ClearItem(int index);
/// <summary>
/// <para>Gets the item in the specified location, equivalent to <see cref="GetItem"/></para>
@ -128,14 +138,6 @@ public interface IItemContainer
/// </returns>
int RemoveItem(int itemIndex, int number);
/// <summary>
/// <para>Remove item</para>
/// <para>移除物品</para>
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
int RemoveItem(IItem item, int number);
/// <summary>
/// <para>Gets the used capacity of the item container</para>
/// <para>获取物品容器已使用的容量</para>

View File

@ -118,12 +118,16 @@ public abstract class ItemContainerDisplayTemplate : IItemContainerDisplay
var item = itemContainer.GetItem(index);
if (item == null)
{
item = itemContainer.GetPlaceHolderItem();
item = itemContainer.GetPlaceHolderItem(index);
}
if (item != null)
if (itemContainer.SupportSelect)
{
item.IsSelect = index == itemContainer.GetSelectIndex();
}
else
{
item.IsSelect = false;
}
itemDisplay.Update(item);
itemDisplay.ShowSelf();
}

View File

@ -78,6 +78,12 @@ public partial class ItemSlotNode : MarginContainer, IItemDisplay
public override void _DropData(Vector2 atPosition, Variant data)
{
//The item is empty and the corresponding item container cannot be retrieved.
//物品为空,无法获取对应的物品容器。
if (Item is null)
{
return;
}
var type = data.VariantType;
if (type == Variant.Type.Nil)
{
@ -89,10 +95,20 @@ public partial class ItemSlotNode : MarginContainer, IItemDisplay
{
return;
}
if (Item is null || Item is PlaceholderItem)
if (Item is PlaceholderItem placeholderItem)
{
sourceItem.ItemContainer?.RemoveItem(sourceItem, -1);
Item?.ItemContainer?.ReplaceItem(Item, sourceItem);
var placeholderItemContainer = placeholderItem.ItemContainer;
var sourceItemContainer = sourceItem.ItemContainer;
var sourceItemIndex = sourceItem.Index;
if (placeholderItemContainer != null)
{
placeholderItemContainer.ReplaceItem(placeholderItem.Index, sourceItem);
}
if (sourceItemContainer != null)
{
sourceItemContainer.ClearItem(sourceItemIndex);
}
}
}

View File

@ -35,18 +35,30 @@ public partial class Packsack : PickAbleTemplate
if (control is PacksackUi packsackUi)
{
packsackUi.Title = Name;
packsackUi.ItemContainer = ItemContainer;
packsackUi.ItemContainer = SelfItemContainer;
}
});
}
public IItemContainer? ItemContainer { get; private set; }
public override void CopyAttributes(Node node)
{
base.CopyAttributes(node);
if (node is Packsack packsack)
{
SelfItemContainer = packsack.SelfItemContainer;
}
}
public IItemContainer? SelfItemContainer { get; set; }
public override void _Ready()
{
base._Ready();
ItemContainer = new UniversalItemContainer(NumberSlots);
ItemContainer.SupportSelect = false;
if (SelfItemContainer == null)
{
SelfItemContainer = new UniversalItemContainer(NumberSlots);
SelfItemContainer.SupportSelect = false;
}
GameSceneDepend.DynamicUiGroup?.RegisterControl(Path, () =>
{
var packedScene = GD.Load<PackedScene>(Path);

View File

@ -8,6 +8,7 @@ namespace ColdMint.scripts.inventory;
/// </summary>
public class PlaceholderItem : IItem
{
public int Index { get; set; }
public string Id { get; set; }
public Texture2D Icon { get; }
public string Name { get; }

View File

@ -110,6 +110,7 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer
var nextAvailableIndex = _nextAvailableIndex;
_itemDictionary[nextAvailableIndex] = item;
item.Index = nextAvailableIndex;
item.ItemContainer = this;
UpdateNextAvailableIndex();
UpdateSelectStatus(nextAvailableIndex, item);
@ -169,6 +170,7 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer
}
var finalNextAvailableIndex = _nextAvailableIndex;
_itemDictionary[finalNextAvailableIndex] = item;
item.Index = finalNextAvailableIndex;
item.ItemContainer = this;
UpdateNextAvailableIndex();
UpdateSelectStatus(finalNextAvailableIndex, item);
@ -182,11 +184,16 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer
}
public bool SupportSelect { get; set; }
public bool EnablePlaceholder { get; set; }
public IItem? GetPlaceHolderItem()
public IItem GetPlaceHolderItem(int index)
{
return EnablePlaceholder ? new PlaceholderItem() : null;
var placeholderItem = new PlaceholderItem
{
Index = index,
ItemContainer = this
};
return placeholderItem;
}
public int GetSelectIndex()
@ -208,6 +215,8 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer
{
var oldItem = GetItem(index);
_itemDictionary[index] = item;
item.Index = index;
item.ItemContainer = this;
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = item,
@ -219,11 +228,24 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer
return true;
}
public bool ReplaceItem(IItem oldItem, IItem newItem)
public bool ClearItem(int index)
{
var index = GetIndexByItem(oldItem);
return index != UnknownIndex && ReplaceItem(index, newItem);
var result = _itemDictionary.Remove(index);
if (result)
{
ItemDataChangeEvent?.Invoke(new ItemDataChangeEvent
{
NewItem = null,
NewIndex = index,
OldIndex = index,
OldItem = null,
Type = Config.ItemDataChangeEventType.Clear
});
}
return result;
}
public int RemoveSelectItem(int number)
{
@ -276,37 +298,6 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer
return removed;
}
public int RemoveItem(IItem item, int number)
{
var index = GetIndexByItem(item);
return index == UnknownIndex ? 0 : RemoveItem(index, number);
}
/// <summary>
/// <para>Find the corresponding index based on the item object</para>
/// <para>根据物品对象查找对应的索引</para>
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private int GetIndexByItem(IItem item)
{
if (totalCapacity <= 0)
{
return UnknownIndex;
}
for (var i = 0; i < totalCapacity; i++)
{
var contains = _itemDictionary.ContainsKey(i);
if (!contains) continue;
if (item == _itemDictionary[i])
{
return i;
}
}
return UnknownIndex;
}
public int GetUsedCapacity()
{
return _itemDictionary.Count;

View File

@ -15,6 +15,7 @@ namespace ColdMint.scripts.pickable;
/// </summary>
public partial class PickAbleTemplate : RigidBody2D, IItem
{
public int Index { get; set; }
//Do not export this field because the ID is specified within yaml.
//不要导出此字段因为ID是在yaml内指定的。
public virtual string Id { get; set; } = "ID";
@ -292,7 +293,7 @@ public partial class PickAbleTemplate : RigidBody2D, IItem
/// <para>请在此函数内复制节点属性</para>
/// </summary>
/// <param name="node"></param>
public void CopyAttributes(Node node)
public virtual void CopyAttributes(Node node)
{
if (node is not PickAbleTemplate pickAbleTemplate)
{