feat(item): 实现批量购买物品功能并优化物品添加逻辑

新增 BuyMItem 方法支持批量购买多个物品,并在 Controller 中完善错误处理流程。
修改 ItemAdd 方法以返回添加结果,增强对物品数量限制和异常情况的控制。
调整任务完成时的物品发放逻辑,确保只有成功添加的物品才会被返回给客户端。
修复新手任务中初级体力药剂的数量从 3 改为 5。
将 defer 调用提前执行以避免潜在的数据不一致问题。
```
This commit is contained in:
2025-10-25 15:06:05 +08:00
parent ade9003a11
commit 4306e2db53
5 changed files with 100 additions and 28 deletions

View File

@@ -50,13 +50,16 @@ func (h Controller) BuyItem(data *item.BuyInboundInfo, c *player.Player) (result
if (data.Count * uint32(tt.Price)) <= c.Info.Coins {
c.Info.Coins -= data.Count * uint32(tt.Price)
c.ItemAdd(model.SingleItemInfo{ItemId: data.ItemId, ItemCnt: data.Count})
return &item.BuyOutboundInfo{
ItemId: data.ItemId,
Level: 1,
Count: data.Count,
Coins: c.Info.Coins,
}, 0
r := c.ItemAdd(model.SingleItemInfo{ItemId: data.ItemId, ItemCnt: data.Count})
if len(r) != 0 {
return &item.BuyOutboundInfo{
ItemId: data.ItemId,
Level: 1,
Count: data.Count,
Coins: c.Info.Coins,
}, 0
}
}
}
@@ -77,7 +80,7 @@ func (h Controller) ChangePlayerCloth(data *item.ChangePlayerClothInboundInfo, c
result.ClothList = append(result.ClothList, model.PeopleItemInfo{ID: v, Level: 1})
}
c.Info.Clothes = result.ClothList
defer space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, player common.PlayerI) {
space.GetSpace(c.Info.MapID).User.IterCb(func(playerID uint32, player common.PlayerI) {
// fmt.Println("ChangePlayerCloth", playerID, data.Head.Pack(result))
data.Head.Result = 0
player.SendPack(data.Head.Pack(result))
@@ -140,3 +143,25 @@ func (h Controller) TalkCate(data *item.TalkCateInboundInfo, c *player.Player) (
return result, 0
}
func (h Controller) BuyMItem(data *item.BuyMultiInboundInfo, c *player.Player) (result *item.BuyMultiOutboundInfo, err errorcode.ErrorCode) {
var rrr []model.SingleItemInfo
for _, v := range data.ItemIds {
_, ok := xmlres.ItemsMAP[int(v)]
if ok {
rrr = append(rrr, model.SingleItemInfo{ItemId: uint32(v), ItemCnt: 1})
}
}
r := c.ItemAdd(rrr...)
if len(r) != 0 {
return &item.BuyMultiOutboundInfo{
Coins: c.Info.Coins,
}, 0
}
return &item.BuyMultiOutboundInfo{
Coins: c.Info.Coins,
}, 0
}

View File

@@ -104,7 +104,7 @@ func (h Controller) Complete_Task(data *task.CompleteTaskInboundInfo, c *player.
// out_id=1的奖励物品
result.ItemList = append(result.ItemList,
task.ItemInfo{ItemId: 300001, ItemCount: 5}, // 普通胶囊x5
task.ItemInfo{ItemId: 300011, ItemCount: 3}, // 初级体力药剂x3
task.ItemInfo{ItemId: 300011, ItemCount: 5}, // 初级体力药剂x3
)
// 新手任务4
@@ -548,7 +548,18 @@ func (h Controller) Complete_Task(data *task.CompleteTaskInboundInfo, c *player.
for _, v := range result.ItemList {
ttt = append(ttt, model.SingleItemInfo{ItemId: v.ItemId, ItemCnt: v.ItemCount})
}
c.ItemAdd(ttt...)
r := c.ItemAdd(ttt...)
tempItemList := make([]task.ItemInfo, 0)
for _, v := range result.ItemList {
for _, v1 := range r {
if v1.ItemId == v.ItemId {
tempItemList = append(tempItemList, task.ItemInfo{ItemId: v.ItemId, ItemCount: v.ItemCount})
}
}
}
result.ItemList = tempItemList //临时变量为了防止报错的时候返回数据没问题
return result, 0
}

View File

@@ -19,3 +19,12 @@ type BuyOutboundInfo struct {
//购买的物品等级
Level uint32
}
type BuyMultiInboundInfo struct {
Head player.TomeeHeader `cmd:"2606" struc:"[0]pad"`
ItemListLen uint32 `struc:"sizeof=ItemIds"`
ItemIds []uint32 `json:"itemIds" description:"购买的物品ID列表"` // @UInt Long对应uint64List对应切片
}
type BuyMultiOutboundInfo struct {
//剩余的数量
Coins uint32
}

View File

@@ -3,7 +3,9 @@ package player
import (
"blazing/common/data/share"
"blazing/common/data/xmlres"
"blazing/common/socket/errorcode"
"blazing/common/utils"
"blazing/cool"
"fmt"
"math/rand"
"strings"
@@ -212,21 +214,61 @@ func replaceOneNumber(original [3]int) ([3]int, int, int) {
}
// 添加物品
func (p *Player) ItemAdd(t ...model.SingleItemInfo) {
func (p *Player) ItemAdd(t ...model.SingleItemInfo) (result []model.SingleItemInfo) {
var ttt []model.SingleItemInfo
for _, v := range t {
switch v.ItemId {
case 1: //塞尔豆
p.Info.Coins = p.Info.Coins + v.ItemCnt
case 3: //累计经验
p.Info.ExpPool = p.Info.ExpPool + v.ItemCnt
case 5: //金豆ItemAdd
p.Info.GoldBean = p.Info.GoldBean + v.ItemCnt
default:
ttt = append(ttt, v)
}
}
p.Service.ItemAdd(ttt...)
p.Service.Item(func(rer map[uint32]model.SingleItemInfo) bool {
for _, v := range ttt {
itemx, ok := xmlres.ItemsMAP[int(v.ItemId)]
if !ok {
cool.Loger.Error(context.TODO(), "物品不存在", v.ItemId)
t1 := NewTomeeHeader(2601, p.Info.UserID)
t1.Result = uint32(errorcode.ErrorCodes.ErrBaseItemTypeLimit)
p.SendPack(t1.Pack(nil)) //准备包由各自发,因为协议不一样
continue
}
itemm, ok := rer[v.ItemId]
if !ok {
rer[v.ItemId] = v
result = append(result, v)
continue
}
itemm.ItemCnt += v.ItemCnt
if itemm.ItemCnt > uint32(itemx.Max) {
cool.Loger.Error(context.TODO(), "物品超过拥有最大限制", v.ItemId)
t1 := NewTomeeHeader(2601, p.Info.UserID)
t1.Result = uint32(errorcode.ErrorCodes.ErrTooManyOfItem)
p.SendPack(t1.Pack(nil)) //准备包由各自发,因为协议不一样
continue
}
result = append(result, v)
rer[v.ItemId] = itemm
}
return true
})
return
}

View File

@@ -29,20 +29,5 @@ func (s *UserService) Item(t func(map[uint32]model.SingleItemInfo) bool) {
panic(err)
}
}
func (s *UserService) ItemAdd(t ...model.SingleItemInfo) {
s.Item(func(rer map[uint32]model.SingleItemInfo) bool {
for _, v := range t {
tt, ok := rer[v.ItemId]
if ok {
tt.ItemCnt += v.ItemCnt
rer[v.ItemId] = tt
} else {
rer[v.ItemId] = v
}
}
return true
})
}
// /添加进来的物品一定是保证存在的