diff --git a/game/builtin/item_container.go b/game/builtin/item_container.go index d1b7798..0d8284b 100644 --- a/game/builtin/item_container.go +++ b/game/builtin/item_container.go @@ -91,9 +91,9 @@ func (slf *ItemContainer[ItemID, Item]) ExistItemWithID(id ItemID) bool { return len(slf.itemIdGuidRef[id]) > 0 } -func (slf *ItemContainer[ItemID, Item]) AddItem(item Item, count *huge.Int) error { +func (slf *ItemContainer[ItemID, Item]) AddItem(item Item, count *huge.Int) (guid int64, err error) { if count.LessThanOrEqualTo(huge.IntZero) { - return ErrCannotAddNegativeOrZeroItem + return 0, ErrCannotAddNegativeOrZeroItem } for guid := range slf.itemIdGuidRef[item.GetID()] { member := slf.items[guid] @@ -102,13 +102,13 @@ func (slf *ItemContainer[ItemID, Item]) AddItem(item Item, count *huge.Int) erro continue } member.count.Add(count) - return nil + return guid, nil } } if slf.size >= slf.GetSizeLimit() { - return ErrItemContainerIsFull + return 0, ErrItemContainerIsFull } - guid := slf.guid.Add(1) + guid = slf.guid.Add(1) slf.items[guid] = &ItemContainerMember[ItemID, Item]{ item: item, guid: guid, @@ -137,7 +137,7 @@ func (slf *ItemContainer[ItemID, Item]) AddItem(item Item, count *huge.Int) erro } guids[guid] = true slf.size++ - return nil + return guid, nil } func (slf *ItemContainer[ItemID, Item]) DeductItem(guid int64, count *huge.Int) error { @@ -197,3 +197,69 @@ func (slf *ItemContainer[ItemID, Item]) DeductItem(guid int64, count *huge.Int) return nil } } + +func (slf *ItemContainer[ItemID, Item]) TransferTo(guid int64, count *huge.Int, target game.ItemContainer[ItemID, Item]) error { + if target == nil { + return ErrItemContainerNotExist + } + if count.LessThanOrEqualTo(huge.IntZero) { + return ErrCannotAddNegativeOrZeroItem + } + member, err := slf.GetItem(guid) + if err != nil { + return err + } + if err = slf.CheckDeductItem(guid, count); err != nil { + return err + } + if err = target.CheckAllowAdd(member.GetItem(), count); err != nil { + return err + } + _ = slf.DeductItem(guid, count) + _, _ = target.AddItem(member.GetItem(), count) + return nil +} + +func (slf *ItemContainer[ItemID, Item]) CheckAllowAdd(item Item, count *huge.Int) error { + if count.LessThanOrEqualTo(huge.IntZero) { + return ErrCannotAddNegativeOrZeroItem + } + for guid := range slf.itemIdGuidRef[item.GetID()] { + member := slf.items[guid] + if member.GetItem().IsSame(item) { + if stackLimit := slf.stackLimit[item.GetID()]; stackLimit != nil && member.count.Copy().Add(count).GreaterThan(stackLimit) { + continue + } + return nil + } + } + if slf.size >= slf.GetSizeLimit() { + return ErrItemContainerIsFull + } + return nil +} + +func (slf *ItemContainer[ItemID, Item]) CheckDeductItem(guid int64, count *huge.Int) error { + if !slf.ExistItem(guid) { + return ErrItemNotExist + } + member := slf.items[guid] + if member.count.GreaterThanOrEqualTo(count) { + return nil + } else { + var need = count.Copy() + var guids = slf.itemIdGuidRef[member.GetID()] + for guid := range guids { + member := slf.items[guid] + if need.GreaterThanOrEqualTo(member.count) { + need.Sub(member.count) + } else { + need = huge.IntZero + } + } + if need.GreaterThan(huge.IntZero) { + return ErrItemInsufficientQuantity + } + return nil + } +} diff --git a/game/builtin/item_container_errors.go b/game/builtin/item_container_errors.go index 8c22915..d6eb432 100644 --- a/game/builtin/item_container_errors.go +++ b/game/builtin/item_container_errors.go @@ -7,4 +7,5 @@ var ( ErrItemNotExist = errors.New("item not exist") ErrItemInsufficientQuantity = errors.New("item insufficient quantity") ErrItemContainerIsFull = errors.New("item container is full") + ErrItemContainerNotExist = errors.New("item container not exist") ) diff --git a/game/item_container.go b/game/item_container.go index 825f464..af7da5a 100644 --- a/game/item_container.go +++ b/game/item_container.go @@ -29,7 +29,13 @@ type ItemContainer[ItemID comparable, I Item[ItemID]] interface { // ExistItemWithID 是否存在特定ID的物品 ExistItemWithID(id ItemID) bool // AddItem 添加物品 - AddItem(item I, count *huge.Int) error + AddItem(item I, count *huge.Int) (guid int64, err error) // DeductItem 扣除特定物品数量,当数量为0将被移除,数量不足时将不进行任何改变 DeductItem(guid int64, count *huge.Int) error + // TransferTo 转移特定物品到另一个容器中 + TransferTo(guid int64, count *huge.Int, target ItemContainer[ItemID, I]) error + // CheckAllowAdd 检查是否允许添加特定物品 + CheckAllowAdd(item I, count *huge.Int) error + // CheckDeductItem 检查是否允许扣除特定物品 + CheckDeductItem(guid int64, count *huge.Int) error }