no message

This commit is contained in:
sk 2024-09-29 10:16:57 +08:00
parent 025dbd8691
commit e8c4f4489f
2 changed files with 250 additions and 274 deletions

View File

@ -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

View File

@ -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,
}
}
func (this *BagMgr) Shutdown() {
module.UnregisteModule(this)
// 对账时间戳初始化
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)
}
// ===========================================================================
// 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)
}