From e8c4f4489fdeda52c4ede98cc9d248920be38f41 Mon Sep 17 00:00:00 2001 From: sk <123456@qq.com> Date: Sun, 29 Sep 2024 10:16:57 +0800 Subject: [PATCH] no message --- model/baginfo.go | 27 +-- worldsrv/bagmgr.go | 497 ++++++++++++++++++++++----------------------- 2 files changed, 250 insertions(+), 274 deletions(-) diff --git a/model/baginfo.go b/model/baginfo.go index 0c80863..a32f549 100644 --- a/model/baginfo.go +++ b/model/baginfo.go @@ -8,6 +8,12 @@ import ( "mongo.games.com/goserver/core/logger" ) +type Item struct { + ItemId int32 // 物品ID + ItemNum int64 // 物品数量 + ObtainTime int64 //获取的时间 +} + type BagInfo struct { BagId bson.ObjectId `bson:"_id"` SnId int32 //玩家账号直接在这里生成 @@ -19,20 +25,11 @@ type BagInfo struct { GainWay int32 `bson:"-"` } -type Item struct { - ItemId int32 // 物品ID - ItemNum int64 // 物品数量 - ObtainTime int64 //获取的时间 -} type GetBagInfoArgs struct { Plt string SnId int32 } -func NewBagInfo(sid int32, plt string) *BagInfo { - return &BagInfo{BagId: bson.NewObjectId(), SnId: sid, Platform: plt, BagItem: make(map[int32]*Item)} -} - func GetBagInfo(sid int32, plt string) (*BagInfo, error) { if rpcCli == nil { return nil, ErrRPClientNoConn @@ -76,18 +73,6 @@ func SaveDBBagItem(args *BagInfo) error { return nil } -func SaveToDelBackupBagItem(args *BagInfo) error { - if rpcCli == nil { - return ErrRPClientNoConn - } - ret := false - err := rpcCli.CallWithTimeout("BagSvc.UpdateBag", args, &ret, time.Second*30) - if err != nil { - return err - } - return nil -} - type AddItemParam struct { Platform string SnId int32 diff --git a/worldsrv/bagmgr.go b/worldsrv/bagmgr.go index 01a13e0..637d0fb 100644 --- a/worldsrv/bagmgr.go +++ b/worldsrv/bagmgr.go @@ -10,7 +10,6 @@ import ( "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/i18n" "mongo.games.com/goserver/core/logger" - "mongo.games.com/goserver/core/module" "mongo.games.com/goserver/core/task" "mongo.games.com/game/common" @@ -24,10 +23,22 @@ import ( "mongo.games.com/game/worldsrv/internal" ) -func init() { - module.RegisteModule(BagMgrSingleton, time.Second, 0) - internal.RegisterPlayerLoad(BagMgrSingleton) +const ( + BagItemMax int32 = 200 +) +// 道具功能 Function +const ( + ItemCanUse = iota //可以使用 + ItemCanGive //可以赠送 + ItemCanSell //可以出售 + ItemCanExchange //可以兑换 + ItemCanFen //可以分解 + ItemMax +) + +func init() { + internal.RegisterPlayerLoad(BagMgrSingleton) BagMgrSingleton.AddOnChangeFuncs(func(param *model.ChangeItemParam) { p := PlayerMgrSington.GetPlayerBySnId(param.SnId) if p == nil { @@ -138,20 +149,6 @@ func init() { }) } -const ( - BagItemMax int32 = 200 -) - -// 道具功能 Function -const ( - ItemCanUse = iota //可以使用 - ItemCanGive //可以赠送 - ItemCanSell //可以出售 - ItemCanExchange //可以兑换 - ItemCanFen //可以分解 - ItemMax -) - type Item struct { ItemId int32 // 物品ID ItemNum int64 // 物品数量 @@ -186,11 +183,7 @@ func NewBagInfo(platform string, snid int32) *BagInfo { } } -// BagMgrSingleton 背包管理器 -var BagMgrSingleton = &BagMgr{ - PlayerBag: make(map[int32]*BagInfo), -} - +// BagMgr 玩家背包 type BagMgr struct { PlayerBag map[int32]*BagInfo // snid:背包 @@ -198,20 +191,241 @@ type BagMgr struct { onChangeFuncs []func(param *model.ChangeItemParam) } -func (this *BagMgr) ModuleName() string { - return "BagMgr" +// BagMgrSingleton 背包管理器 +var BagMgrSingleton = &BagMgr{ + PlayerBag: make(map[int32]*BagInfo), } -func (this *BagMgr) Init() { +// ============================================================================ +// implement IPlayerLoad +//============================================================================= + +type LoadData struct { + BagInfo *model.BagInfo } -func (this *BagMgr) Update() { +func (this *BagMgr) Load(platform string, snid int32, player any) *internal.PlayerLoadReplay { + // 加载道具 + bagInfo, err := model.GetBagInfo(snid, platform) + if err != nil { + return &internal.PlayerLoadReplay{ + Platform: platform, + Snid: snid, + Err: err, + Data: nil, + } + } + + // 对账时间戳初始化 + if bagInfo.Ts == 0 { + bagInfo.Ts = time.Now().UnixNano() + } + + return &internal.PlayerLoadReplay{ + Platform: platform, + Snid: snid, + Err: err, + Data: &LoadData{ + BagInfo: bagInfo, + }, + } } -func (this *BagMgr) Shutdown() { - module.UnregisteModule(this) +func (this *BagMgr) Callback(player any, ret *internal.PlayerLoadReplay) { + if ret == nil || ret.Data == nil { + return + } + + data, ok := ret.Data.(*LoadData) + if !ok || data == nil || data.BagInfo == nil { + return + } + + // 背包数据 + newBagInfo := NewBagInfo(ret.Platform, ret.Snid) + newBagInfo.Ts = data.BagInfo.Ts + for k, bi := range data.BagInfo.BagItem { + item := srvdata.GameItemMgr.Get(ret.Platform, bi.ItemId) + if item != nil { + if bi.ItemNum > 0 { + newBagInfo.BagItem[k] = &Item{ + ItemId: bi.ItemId, + ItemNum: bi.ItemNum, + ObtainTime: bi.ObtainTime, + } + } + } else { + logger.Logger.Error("InitBagInfo err: item is nil. ItemId:", bi.ItemId) + } + } + this.PlayerBag[ret.Snid] = newBagInfo } +type LoadAfterData struct { + GameID []int32 + ItemLogs []*model.ItemLog + StarTs, EndTs int64 +} + +func (this *BagMgr) LoadAfter(platform string, snid int32) *internal.PlayerLoadReplay { + var err error + // 查询最近游戏 + gameID := model.GetRecentGame(platform, snid) + + // 道具变更记录 + endTs := time.Now().UnixNano() + var itemLogs []*model.ItemLog + itemLogs, err = model.GetItemLog(platform, snid, this.PlayerBag[snid].Ts) + if err != nil { + logger.Logger.Errorf("LoadAfter GetItemLog err: %v", err) + return &internal.PlayerLoadReplay{ + Platform: platform, + Snid: snid, + Err: err, + Data: nil, + } + } + + return &internal.PlayerLoadReplay{ + Platform: platform, + Snid: snid, + Err: nil, + Data: &LoadAfterData{ + GameID: gameID, + ItemLogs: itemLogs, + StarTs: this.PlayerBag[snid].Ts, + EndTs: endTs, + }, + } +} + +func (this *BagMgr) CallbackAfter(ret *internal.PlayerLoadReplay) { + if ret == nil { + return + } + if ret.Err != nil { + logger.Logger.Error("BagMgr LoadAfter err:", ret.Err) + return + } + + param, ok := ret.Data.(*LoadAfterData) + if !ok { + logger.Logger.Errorf("BagMgr LoadAfter BUGE 1") + return + } + + p := PlayerMgrSington.GetPlayerBySnId(ret.Snid) + if p == nil { + logger.Logger.Errorf("BagMgr LoadAfter BUGE 2") + return + } + + // 最近游戏 + p.GameID = param.GameID + + // 道具变更记录 + bagInfo := this.PlayerBag[p.SnId] + if bagInfo != nil { + changeItems := make(map[int32]struct{}) + for _, v := range param.ItemLogs { + if v == nil { + continue + } + if v.Ts > param.StarTs && v.Ts <= param.EndTs { + bagInfo.dirty = true + num := v.Count + if v.LogType == 1 { + num = -num + } + if v.Ts > bagInfo.Ts { + bagInfo.Ts = v.Ts + } + if v.Offline == 0 { + // 在线数据恢复 + logger.Logger.Tracef("道具恢复 SnId:%v Item:%+v", p.SnId, *v) + if _, ok := bagInfo.BagItem[v.ItemId]; !ok { + bagInfo.BagItem[v.ItemId] = &Item{ + ItemId: v.ItemId, + ItemNum: 0, + ObtainTime: v.CreateTs, + } + } + bagInfo.BagItem[v.ItemId].ItemNum += num + changeItems[v.ItemId] = struct{}{} + } else { + // 离线时的变更 + logger.Logger.Tracef("处理离线道具变化 SnId:%v Item:%v", p.SnId, *v) + this.OnChangeFuncs(&model.ChangeItemParam{ + SnId: p.SnId, + ItemId: v.ItemId, + ItemNum: num, + GainWay: v.TypeId, + RoomConfigId: v.RoomConfigId, + GameId: v.GameId, + GameFreeId: v.GameFreeId, + Cost: v.Cost, + }) + } + } + } + + this.SyncBagData(p.SnId, maps.Keys(changeItems)...) + } +} + +func (this *BagMgr) Save(platform string, snid int32, isSync, force bool) { + bagInfo := this.GetBagInfo(snid) + if bagInfo == nil { + return + } + if !bagInfo.dirty && !force { + return + } + logger.Logger.Tracef("SaveBagData: %+v", *bagInfo) + + var err error + f := func() { + newBagInfo := &model.BagInfo{ + SnId: bagInfo.SnId, + Platform: bagInfo.Platform, + Ts: bagInfo.Ts, + BagItem: make(map[int32]*model.Item), + } + for _, v := range bagInfo.BagItem { + newBagInfo.BagItem[v.ItemId] = &model.Item{ItemId: v.ItemId, ItemNum: v.ItemNum, ObtainTime: v.ObtainTime} + } + err = model.UpBagItem(newBagInfo) + } + + cf := func() { + if err == nil && this.PlayerBag[snid] != nil { + this.PlayerBag[snid].dirty = false + } + } + + if isSync { + f() + cf() + return + } + + task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { + f() + return nil + }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { + cf() + })).StartByExecutor(fmt.Sprintf("Player%v", snid)) +} + +func (this *BagMgr) Release(platform string, snid int32) { + delete(this.PlayerBag, snid) +} + +// =========================================================================== +// other functions +//============================================================================ + +// AddOnChangeFuncs 添加道具变更监听 func (this *BagMgr) AddOnChangeFuncs(f ...func(param *model.ChangeItemParam)) { this.onChangeFuncs = append(this.onChangeFuncs, f...) } @@ -706,7 +920,7 @@ func (this *BagMgr) VerifyUpJybInfo(p *Player, args *model.VerifyUpJybInfoArgs) }), "VerifyUpJybInfo").Start() } -// 兑换话费卡 +// ItemExchangeCard 兑换话费卡 func (this *BagMgr) ItemExchangeCard(p *Player, itemId int32, money, cardType int32, logId string) bool { // 兑换码奖品 var err error @@ -799,226 +1013,3 @@ func (this *BagMgr) ItemExchangeCard(p *Player, itemId int32, money, cardType in }), fmt.Sprintf("ItemExChange%d", p.SnId)).Start() return true } - -// ========================implement IPlayerLoad ============================== - -type LoadData struct { - BagInfo *model.BagInfo -} - -func (this *BagMgr) Load(platform string, snid int32, player any) *internal.PlayerLoadReplay { - // 加载道具 - bagInfo, err := model.GetBagInfo(snid, platform) - if err != nil { - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: err, - Data: nil, - } - } - - // 对账时间戳初始化 - if bagInfo.Ts == 0 { - bagInfo.Ts = time.Now().UnixNano() - } - - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: err, - Data: &LoadData{ - BagInfo: bagInfo, - }, - } -} - -func (this *BagMgr) Callback(player any, ret *internal.PlayerLoadReplay) { - if ret == nil || ret.Data == nil { - return - } - - data, ok := ret.Data.(*LoadData) - if !ok || data == nil || data.BagInfo == nil { - return - } - - // 背包数据 - newBagInfo := NewBagInfo(ret.Platform, ret.Snid) - newBagInfo.Ts = data.BagInfo.Ts - for k, bi := range data.BagInfo.BagItem { - item := srvdata.GameItemMgr.Get(ret.Platform, bi.ItemId) - if item != nil { - if bi.ItemNum > 0 { - newBagInfo.BagItem[k] = &Item{ - ItemId: bi.ItemId, - ItemNum: bi.ItemNum, - ObtainTime: bi.ObtainTime, - } - } - } else { - logger.Logger.Error("InitBagInfo err: item is nil. ItemId:", bi.ItemId) - } - } - this.PlayerBag[ret.Snid] = newBagInfo -} - -type LoadAfterData struct { - GameID []int32 - ItemLogs []*model.ItemLog - StarTs, EndTs int64 -} - -func (this *BagMgr) LoadAfter(platform string, snid int32) *internal.PlayerLoadReplay { - var err error - // 查询最近游戏 - gameID := model.GetRecentGame(platform, snid) - - // 道具变更记录 - endTs := time.Now().UnixNano() - var itemLogs []*model.ItemLog - itemLogs, err = model.GetItemLog(platform, snid, this.PlayerBag[snid].Ts) - if err != nil { - logger.Logger.Errorf("LoadAfter GetItemLog err: %v", err) - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: err, - Data: nil, - } - } - - return &internal.PlayerLoadReplay{ - Platform: platform, - Snid: snid, - Err: nil, - Data: &LoadAfterData{ - GameID: gameID, - ItemLogs: itemLogs, - StarTs: this.PlayerBag[snid].Ts, - EndTs: endTs, - }, - } -} - -func (this *BagMgr) CallbackAfter(ret *internal.PlayerLoadReplay) { - if ret == nil { - return - } - if ret.Err != nil { - logger.Logger.Error("BagMgr LoadAfter err:", ret.Err) - return - } - - param, ok := ret.Data.(*LoadAfterData) - if !ok { - logger.Logger.Errorf("BagMgr LoadAfter BUGE 1") - return - } - - p := PlayerMgrSington.GetPlayerBySnId(ret.Snid) - if p == nil { - logger.Logger.Errorf("BagMgr LoadAfter BUGE 2") - return - } - - // 最近游戏 - p.GameID = param.GameID - - // 道具变更记录 - bagInfo := this.PlayerBag[p.SnId] - if bagInfo != nil { - changeItems := make(map[int32]struct{}) - for _, v := range param.ItemLogs { - if v == nil { - continue - } - if v.Ts > param.StarTs && v.Ts <= param.EndTs { - bagInfo.dirty = true - num := v.Count - if v.LogType == 1 { - num = -num - } - if v.Ts > bagInfo.Ts { - bagInfo.Ts = v.Ts - } - if v.Offline == 0 { - // 在线数据恢复 - logger.Logger.Tracef("道具恢复 SnId:%v Item:%+v", p.SnId, *v) - if _, ok := bagInfo.BagItem[v.ItemId]; !ok { - bagInfo.BagItem[v.ItemId] = &Item{ - ItemId: v.ItemId, - ItemNum: 0, - ObtainTime: v.CreateTs, - } - } - bagInfo.BagItem[v.ItemId].ItemNum += num - changeItems[v.ItemId] = struct{}{} - } else { - // 离线时的变更 - logger.Logger.Tracef("处理离线道具变化 SnId:%v Item:%v", p.SnId, *v) - this.OnChangeFuncs(&model.ChangeItemParam{ - SnId: p.SnId, - ItemId: v.ItemId, - ItemNum: num, - GainWay: v.TypeId, - RoomConfigId: v.RoomConfigId, - GameId: v.GameId, - GameFreeId: v.GameFreeId, - Cost: v.Cost, - }) - } - } - } - - this.SyncBagData(p.SnId, maps.Keys(changeItems)...) - } -} - -func (this *BagMgr) Save(platform string, snid int32, isSync, force bool) { - bagInfo := this.GetBagInfo(snid) - if bagInfo == nil { - return - } - if !bagInfo.dirty && !force { - return - } - logger.Logger.Tracef("SaveBagData: %+v", *bagInfo) - - var err error - f := func() { - newBagInfo := &model.BagInfo{ - SnId: bagInfo.SnId, - Platform: bagInfo.Platform, - Ts: bagInfo.Ts, - BagItem: make(map[int32]*model.Item), - } - for _, v := range bagInfo.BagItem { - newBagInfo.BagItem[v.ItemId] = &model.Item{ItemId: v.ItemId, ItemNum: v.ItemNum, ObtainTime: v.ObtainTime} - } - err = model.UpBagItem(newBagInfo) - } - - cf := func() { - if err == nil && this.PlayerBag[snid] != nil { - this.PlayerBag[snid].dirty = false - } - } - - if isSync { - f() - cf() - return - } - - task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { - f() - return nil - }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { - cf() - })).StartByExecutor(fmt.Sprintf("Player%v", snid)) -} - -func (this *BagMgr) Release(platform string, snid int32) { - delete(this.PlayerBag, snid) -}