物品容器基本实现
This commit is contained in:
parent
eb31ec3982
commit
32f3083e87
|
@ -0,0 +1,105 @@
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kercylan98/minotaur/game"
|
||||||
|
"github.com/kercylan98/minotaur/utils/huge"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewItemContainer[ItemID comparable, Item game.Item[ItemID]]() *ItemContainer[ItemID, Item] {
|
||||||
|
return &ItemContainer[ItemID, Item]{
|
||||||
|
items: map[ItemID]map[int64]*itemContainerInfo[ItemID, Item]{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ItemContainer[ItemID comparable, Item game.Item[ItemID]] struct {
|
||||||
|
sizeLimit int
|
||||||
|
size int
|
||||||
|
expandSize int
|
||||||
|
items map[ItemID]map[int64]*itemContainerInfo[ItemID, Item]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *ItemContainer[ItemID, Item]) GetSize() int {
|
||||||
|
return slf.size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *ItemContainer[ItemID, Item]) SetExpandSize(size int) {
|
||||||
|
slf.expandSize = size
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *ItemContainer[ItemID, Item]) GetSizeLimit() int {
|
||||||
|
return slf.sizeLimit + slf.expandSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *ItemContainer[ItemID, Item]) AddItem(item Item, count *huge.Int) error {
|
||||||
|
if count.LessThanOrEqualTo(huge.IntZero) {
|
||||||
|
return ErrCannotAddNegativeItem
|
||||||
|
}
|
||||||
|
infos, exist := slf.items[item.GetID()]
|
||||||
|
if !exist {
|
||||||
|
infos = map[int64]*itemContainerInfo[ItemID, Item]{}
|
||||||
|
slf.items[item.GetID()] = infos
|
||||||
|
|
||||||
|
}
|
||||||
|
info, exist := infos[item.GetGUID()]
|
||||||
|
if !exist {
|
||||||
|
if slf.GetSizeLimit() >= slf.GetSize() {
|
||||||
|
return ErrItemContainerIsFull
|
||||||
|
}
|
||||||
|
infos[item.GetGUID()] = &itemContainerInfo[ItemID, Item]{
|
||||||
|
item: item,
|
||||||
|
count: count,
|
||||||
|
}
|
||||||
|
slf.size++
|
||||||
|
} else {
|
||||||
|
info.count = info.count.Add(count)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *ItemContainer[ItemID, Item]) DeductItem(id ItemID, count *huge.Int) error {
|
||||||
|
return slf.DeductItemWithGuid(id, -1, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *ItemContainer[ItemID, Item]) DeductItemWithGuid(id ItemID, guid int64, count *huge.Int) error {
|
||||||
|
infos, exist := slf.items[id]
|
||||||
|
if !exist || len(infos) == 0 {
|
||||||
|
return ErrItemNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
var backupInfos = make(map[int64]*itemContainerInfo[ItemID, Item])
|
||||||
|
var pending = count.Copy()
|
||||||
|
var deductSize int
|
||||||
|
for g, info := range infos {
|
||||||
|
if g != guid && guid >= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
info.bakCount = info.count.Copy()
|
||||||
|
backupInfos[g] = info
|
||||||
|
|
||||||
|
if pending.GreaterThanOrEqualTo(info.count) {
|
||||||
|
pending = pending.Sub(info.count)
|
||||||
|
info.count = huge.IntZero
|
||||||
|
} else {
|
||||||
|
info.count = info.count.Sub(pending)
|
||||||
|
pending = huge.IntZero
|
||||||
|
}
|
||||||
|
|
||||||
|
if info.count.EqualTo(huge.IntZero) {
|
||||||
|
delete(infos, guid)
|
||||||
|
deductSize++
|
||||||
|
}
|
||||||
|
if pending.EqualTo(huge.IntZero) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pending.GreaterThan(huge.IntZero) {
|
||||||
|
for g, info := range backupInfos {
|
||||||
|
infos[g] = info
|
||||||
|
info.count = info.bakCount
|
||||||
|
info.bakCount = nil
|
||||||
|
}
|
||||||
|
return ErrItemInsufficientQuantity
|
||||||
|
}
|
||||||
|
slf.size -= deductSize
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrCannotAddNegativeItem = errors.New("cannot add items with negative quantities")
|
||||||
|
ErrItemNotExist = errors.New("item not exist")
|
||||||
|
ErrItemInsufficientQuantity = errors.New("item insufficient quantity")
|
||||||
|
ErrItemContainerIsFull = errors.New("item container is full")
|
||||||
|
)
|
|
@ -0,0 +1,12 @@
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kercylan98/minotaur/game"
|
||||||
|
"github.com/kercylan98/minotaur/utils/huge"
|
||||||
|
)
|
||||||
|
|
||||||
|
type itemContainerInfo[ItemID comparable, Item game.Item[ItemID]] struct {
|
||||||
|
item Item
|
||||||
|
count *huge.Int
|
||||||
|
bakCount *huge.Int
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package builtin
|
||||||
|
|
||||||
|
import "github.com/kercylan98/minotaur/game"
|
||||||
|
|
||||||
|
type ItemContainerOption[ItemID comparable, Item game.Item[ItemID]] func(container ItemContainer[ItemID, Item])
|
||||||
|
|
||||||
|
// WithItemContainerSizeLimit 通过特定的物品容器非堆叠数量上限创建物品容器
|
||||||
|
func WithItemContainerSizeLimit[ItemID comparable, Item game.Item[ItemID]](sizeLimit int) ItemContainerOption[ItemID, Item] {
|
||||||
|
return func(container ItemContainer[ItemID, Item]) {
|
||||||
|
if sizeLimit <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
container.sizeLimit = sizeLimit
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
type Item[ID comparable] interface {
|
||||||
|
// GetID 获取物品ID
|
||||||
|
GetID() ID
|
||||||
|
// GetGUID 获取物品GUID
|
||||||
|
// - 用于标识同一件物品不同的特征
|
||||||
|
// - 负数的GUID在内置功能中可能会被用于特殊判定,如果需要负数建议另外对特殊功能进行实现
|
||||||
|
GetGUID() int64
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package game
|
||||||
|
|
||||||
|
import "github.com/kercylan98/minotaur/utils/huge"
|
||||||
|
|
||||||
|
// ItemContainer 物品容器
|
||||||
|
type ItemContainer[ItemID comparable, I Item[ItemID]] interface {
|
||||||
|
// GetSize 获取容器物品非堆叠数量
|
||||||
|
GetSize() int
|
||||||
|
// GetSizeLimit 获取容器物品非堆叠数量上限
|
||||||
|
GetSizeLimit() int
|
||||||
|
// SetExpandSize 设置拓展非堆叠数量上限
|
||||||
|
SetExpandSize(size int)
|
||||||
|
|
||||||
|
// AddItem 添加物品
|
||||||
|
// - 当物品guid相同时,如果相同物品id及guid的堆叠数量未达到上限,将增加数量,否则增加非堆叠数量
|
||||||
|
// - 当物品guid不同时,堆叠将不可用,每次都将增加非堆叠数量
|
||||||
|
AddItem(item I, count *huge.Int) error
|
||||||
|
// DeductItem 扣除特定物品数量,当数量为0将被移除,数量不足时将不进行任何改变
|
||||||
|
// - 将查找特定id的物品,无论guid是否相同,都有可能被扣除直到达到扣除数量
|
||||||
|
// - 当count为负数时,由于负负得正,无论guid是否相同,都有可能被增加物品数量直到达到扣除数量
|
||||||
|
DeductItem(id ItemID, count *huge.Int) error
|
||||||
|
// DeductItemWithGuid 更为精准的扣除特定物品数量,可参考 DeductItem
|
||||||
|
DeductItemWithGuid(id ItemID, guid int64, count *huge.Int) error
|
||||||
|
}
|
Loading…
Reference in New Issue