game_sync/worldsrv/bagmgr.go

941 lines
26 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"errors"
"fmt"
"math"
"strconv"
"time"
"github.com/globalsign/mgo/bson"
"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"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
"mongo.games.com/game/protocol/bag"
playerproto "mongo.games.com/game/protocol/player"
webapiproto "mongo.games.com/game/protocol/webapi"
"mongo.games.com/game/srvdata"
"mongo.games.com/game/webapi"
"mongo.games.com/game/worldsrv/internal"
)
const (
BagItemMax int32 = 200
)
// 道具功能 Function
const (
ItemCanUse = iota //可以使用
ItemCanGive //可以赠送
ItemCanSell //可以出售
ItemCanExchange //可以兑换
ItemCanFen // 可以分解
ItemMax
)
type Item struct {
ItemId int32 // 物品ID
ItemNum int64 // 物品数量
////数据表数据
Name string // 名称
//ShowLocation []int32 // 显示位置
//Classify []int32 // 分页类型 1道具类 2资源类 3兑换类
//Type int32 // 道具种类 1宠物碎片 2角色碎片
Effect0 []int32 // 竖版道具功能 1使用 2赠送 3出售
Effect []int32 // 横版道具功能 1使用 2赠送 3出售
SaleType int32 // 出售类型
SaleGold int32 // 出售金额
//Composition int32 // 能否叠加 1能 2不能
//CompositionMax int32 // 叠加上限
//Time int32 // 道具时效 0为永久
//Location string // 跳转页面
//Describe string // 道具描述
//数据库数据
ObtainTime int64 //获取的时间
}
type BagInfo struct {
SnId int32 //玩家账号直接在这里生成
Platform string //平台
BagItem map[int32]*Item //背包数据 key为itemId
dirty bool
LogId string `bson:"-"`
}
// BagMgrSingleton 背包管理器
var BagMgrSingleton = &BagMgr{
PlayerBag: make(map[int32]*BagInfo),
}
type BagMgr struct {
PlayerBag map[int32]*BagInfo // snid:背包
}
func (this *BagMgr) ModuleName() string {
return "BagMgr"
}
func (this *BagMgr) Init() {
}
func (this *BagMgr) GetBagInfo(snid int32) *BagInfo {
if v, exist := this.PlayerBag[snid]; exist {
return v
}
return nil
}
// GetItem 获取个人的指定道具信息
func (this *BagMgr) GetItem(snid, itemId int32) *Item {
p := PlayerMgrSington.GetPlayerBySnId(snid)
if p == nil {
return nil
}
item := &Item{
ItemId: itemId,
}
f := func() {
itemX := srvdata.GameItemMgr.Get(p.Platform, itemId)
if itemX != nil {
item.Name = itemX.Name
//item.ShowLocation = itemX.ShowLocation
//item.Classify = itemX.Classify
//item.Type = itemX.Type
item.Effect0 = itemX.Effect
item.Effect = itemX.Effect
item.SaleType = itemX.SaleType
item.SaleGold = itemX.SaleGold
//item.Composition = itemX.Composition
//item.CompositionMax = itemX.CompositionMax
//item.Time = itemX.Time
//item.Location = itemX.Location
//item.Describe = itemX.Describe
}
}
switch itemId {
case common.ItemIDCoin:
item.ItemNum = p.Coin
f()
case common.ItemIDDiamond:
item.ItemNum = p.Diamond
f()
default:
if bagItem, ok := this.PlayerBag[snid]; ok {
if bagItem != nil {
item = bagItem.BagItem[itemId]
if item != nil {
f()
return item
}
}
}
}
return item
}
type AddItemParam struct {
Cost []*model.Item // 获得道具时消耗的道具数量
LogId string
RoomConfigId int32
}
func (this *BagMgr) AddItemsV2(args *model.AddItemParam) (*BagInfo, bag.OpResultCode, bool) {
p := PlayerMgrSington.GetPlayerBySnId(args.P.SnId)
var items []*Item
var costs []*model.Item
for _, v := range args.Change {
items = append(items, &Item{
ItemId: v.ItemId,
ItemNum: v.ItemNum,
})
}
for _, v := range args.Cost {
costs = append(costs, &model.Item{
ItemId: v.ItemId,
ItemNum: v.ItemNum,
})
}
return this.AddItems(p, items, args.Add, args.GainWay, args.Operator, args.Remark, args.GameId, args.GameFreeId, args.NoLog, AddItemParam{
Cost: costs,
LogId: args.LogId,
RoomConfigId: args.RoomConfigId,
})
}
// AddItems 给玩家背包添加道具
// add 加成数量
// gainWay 记录类型
// oper 操作人
// remark 备注
// gameId 游戏id
// gameFreeId 场次id
// NoLog 是否不记录日志
// Deprecated: use [ AddItemsV2 ] instead
func (this *BagMgr) AddItems(p *Player, addItems []*Item, add int64, gainWay int32, operator, remark string,
gameId, gameFreeId int64, noLog bool, params ...AddItemParam) (*BagInfo, bag.OpResultCode, bool) {
var cost []*model.Item
var id string
var roomConfigId int32
if len(params) > 0 {
cost = params[0].Cost
id = params[0].LogId
roomConfigId = params[0].RoomConfigId
}
var items []*Item
for _, v := range addItems {
if v == nil || v.ItemNum == 0 {
continue
}
item := srvdata.GameItemMgr.Get(p.Platform, v.ItemId)
if item == nil {
continue
}
switch item.Type {
case common.ItemTypeCoin:
//增加金币
if item.Id == common.ItemIDCoin {
p.AddCoin(v.ItemNum, add, gainWay, operator, remark)
}
case common.ItemTypeDiamond:
//增加钻石
if item.Id == common.ItemIDDiamond {
p.AddDiamond(v.ItemNum, add, gainWay, operator, remark)
}
case common.ItemTypeFishPower:
//增加炮台
p.ItemUnPlayerPowerListEx(v.ItemId)
case common.ItemTypeMoneyPond:
//增加个人金币池
if v.ItemId == common.ItemIDMoneyPond {
p.MoneyPond += v.ItemNum
}
case common.ItemTypeVipExp:
//增加玩家VIP经验
if v.ItemId == common.ItemIDVipExp {
p.AddMoneyPayTotal(v.ItemNum)
}
case common.ItemTypeShopScore:
if v.ItemId == common.ItemIDPhoneScore {
p.AddPhoneScore(v.ItemNum, 0, gainWay, operator, remark)
}
case common.ItemTypeExpireTime:
p.AddItemRecExpireTime(v.ItemId, v.ItemNum, 0, gainWay, operator, remark)
default:
// 道具变化
items = append(items, v)
}
}
// 添加道具到背包
var isSkin bool
var permitScore, long int64
var changeItems []int32
var newBagInfo *BagInfo
var logId string
if _, exist := this.PlayerBag[p.SnId]; !exist {
newBagInfo = &BagInfo{
SnId: p.SnId,
Platform: p.Platform,
BagItem: make(map[int32]*Item),
}
} else {
newBagInfo = this.PlayerBag[p.SnId]
}
if len(items) == 0 {
return newBagInfo, bag.OpResultCode_OPRC_Sucess, true
}
var code = bag.OpResultCode_OPRC_Sucess
//检查道具数量
for _, v := range items {
if v == nil || v.ItemNum == 0 {
continue
}
item := srvdata.GameItemMgr.Get(p.Platform, v.ItemId)
if item == nil {
code = bag.OpResultCode_OPRC_IdErr
return newBagInfo, code, false
}
if itm, exist := newBagInfo.BagItem[v.ItemId]; exist {
if v.ItemNum < 0 && itm.ItemNum < int64(math.Abs(float64(v.ItemNum))) {
code = bag.OpResultCode_OPRC_UseUp
return newBagInfo, code, false
}
}
}
for _, v := range items {
if v == nil || v.ItemNum == 0 {
continue
}
item := srvdata.GameItemMgr.Get(p.Platform, v.ItemId)
if item == nil {
code = bag.OpResultCode_OPRC_IdErr
continue
}
if !isSkin {
isSkin = item.GetType() == 21 && v.ItemNum > 0
}
if itm, exist := newBagInfo.BagItem[v.ItemId]; exist {
if itm.ItemNum+v.ItemNum < 0 {
code = bag.OpResultCode_OPRC_IdErr
continue
}
itm.ItemNum += v.ItemNum
} else {
if v.ItemNum < 0 {
code = bag.OpResultCode_OPRC_IdErr
continue
}
newBagInfo.BagItem[v.ItemId] = &Item{
ItemId: item.Id, // 物品id
ItemNum: v.ItemNum, // 数量
ObtainTime: time.Now().Unix(),
}
}
changeItems = append(changeItems, v.ItemId)
// 道具日志
if !noLog {
num := v.ItemNum
logType := ItemObtain
if v.ItemNum < 0 {
logType = ItemConsume
num = -v.ItemNum
}
log := model.NewItemLogEx(model.ItemParam{
Platform: p.Platform,
SnId: p.SnId,
LogType: int32(logType),
ItemId: v.ItemId,
ItemName: item.Name,
Count: num,
Remark: remark,
TypeId: gainWay,
GameId: gameId,
GameFreeId: gameFreeId,
Cost: cost,
LogId: id,
RoomConfigId: roomConfigId,
})
if log != nil {
LogChannelSingleton.WriteLog(log)
logId = log.LogId.Hex()
}
//获奖记录log
if logType == ItemObtain && v.ItemNum > 0 {
awardLogType := 0
if item.Type == common.ItemTypeChange {
//话费
awardLogType = 1
} else if item.Type == common.ItemTypeObjective {
//实物
awardLogType = 2
AwardLogMgr.UpdateAwardLog(p.Platform, item.Id, v.ItemNum)
}
if awardLogType != 0 {
data := model.AnnouncerLog{
Platform: p.Platform,
Snid: p.SnId,
Name: p.Name,
Phone: p.Tel,
ItemId: item.Id, //获得物品ID
TypeId: int32(awardLogType),
}
AwardLogMgr.UpdateAnnouncerLog(data)
}
}
}
if v.ItemId == common.ItemIDWeekScore && v.ItemNum > 0 {
TaskSubjectSingleton.Touch(common.TaskTypeActivityScore, &TaskData{
SnId: p.SnId,
Num: v.ItemNum,
})
}
if v.ItemId == common.ItemIDPetSkill && v.ItemNum > 0 {
PetMgrSington.CheckShowRed(p)
}
// 皮肤红点
if v.ItemNum > 0 && item.GetType() == common.ItemTypeSkinChip {
PetMgrSington.CheckSkinRed(p)
}
// 统计 v卡兑换消耗数量
if v.ItemId == common.ItemIDVCard && gainWay == common.GainWay_Exchange {
p.VCardCost += -v.ItemNum
if p.VCardCost < 0 {
p.VCardCost = 0
}
}
if v.ItemId == common.ItemIDPermit && v.ItemNum > 0 {
permitScore += v.ItemNum
}
if v.ItemId == common.ItemIDLong && v.ItemNum > 0 {
long += v.ItemNum
}
}
if len(changeItems) > 0 {
newBagInfo.dirty = true
newBagInfo.LogId = logId
p.dirty = true
this.PlayerBag[p.SnId] = newBagInfo
this.SyncBagData(p.SnId, changeItems...)
}
for _, v := range changeItems {
if v == common.ItemIDPermit {
item := this.GetItem(p.SnId, v)
startTs := PlatformMgrSingleton.GetConfig(p.Platform).PermitStartTs
if item != nil && item.ItemNum > 0 && startTs > 0 {
// 赛季积分排行榜
LogChannelSingleton.WriteLog(&model.PermitScore{
Platform: p.Platform,
SnId: p.SnId,
Name: p.Name,
Exp: item.ItemNum,
ModId: p.Roles.ModId,
StartTs: startTs,
Ts: time.Now().Unix(),
})
}
}
if v == common.ItemIDLong {
p.SendDiffData()
}
}
if permitScore > 0 || long > 0 {
LogChannelSingleton.WriteLog(&model.BackendPermitJoin{
Platform: p.Platform,
StartTs: PlatformMgrSingleton.GetConfig(p.Platform).PermitStartTs,
SnId: p.SnId,
Score: permitScore,
Long: long,
Ts: time.Now().Unix(),
})
}
// 自动解锁皮肤
if isSkin {
p.AutoSkinUnlock()
}
if code != bag.OpResultCode_OPRC_Sucess {
return newBagInfo, code, false
}
return newBagInfo, code, true
}
// Deprecated: use [ AddItemsV2 ] instead
func (this *BagMgr) AddItem(p *Player, itemId, itemNum int64, add int64, gainWay int32, operator, remark string,
gameId, gameFreeId int64, noLog bool, params ...AddItemParam) (*BagInfo, bag.OpResultCode, bool) {
return this.AddItems(p, []*Item{{ItemId: int32(itemId), ItemNum: itemNum}}, add, gainWay, operator, remark, gameId, gameFreeId, noLog, params...)
}
func (this *BagMgr) AddItemsOffline(platform string, snid int32, addItems []*model.Item, gainWay int32, operator, remark string,
gameId, gameFreeId int64, noLog bool, callback func(err error)) {
var findPlayer *model.PlayerBaseInfo
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
findPlayer = model.GetPlayerBaseInfo(platform, snid)
if findPlayer == nil {
return nil
}
newBagInfo := &model.BagInfo{
SnId: findPlayer.SnId,
Platform: findPlayer.Platform,
BagItem: make(map[int32]*model.Item),
GainWay: gainWay,
}
for _, v := range addItems {
if v == nil || v.ItemNum == 0 {
continue
}
newBagInfo.BagItem[v.ItemId] = &model.Item{ItemId: v.ItemId, ItemNum: v.ItemNum}
}
return model.SaveDBBagItem(newBagInfo)
}), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) {
logger.Logger.Tracef("AddItemsOffline failed: %v %+v", data, *findPlayer)
if data == nil && findPlayer != nil {
callback(nil)
if noLog {
return
}
for _, v := range addItems {
itemData := srvdata.GameItemMgr.Get(platform, v.ItemId)
if itemData == nil {
continue
}
num := v.ItemNum
logType := ItemObtain
if v.ItemNum < 0 {
logType = ItemConsume
num = -v.ItemNum
}
log := model.NewItemLogEx(model.ItemParam{
Platform: findPlayer.Platform,
SnId: findPlayer.SnId,
LogType: int32(logType),
ItemId: v.ItemId,
ItemName: itemData.Name,
Count: num,
Remark: remark,
TypeId: gainWay,
GameId: gameId,
GameFreeId: gameFreeId,
})
if log != nil {
LogChannelSingleton.WriteLog(log)
}
//获奖记录log
if logType == ItemObtain && v.ItemNum > 0 {
awardLogType := 0
if itemData.Type == common.ItemTypeChange {
//话费
awardLogType = 1
} else if itemData.Type == common.ItemTypeObjective {
//实物
awardLogType = 2
AwardLogMgr.UpdateAwardLog(findPlayer.Platform, itemData.Id, v.ItemNum)
}
if awardLogType > 0 {
logData := model.AnnouncerLog{
Platform: findPlayer.Platform,
Snid: findPlayer.SnId,
Name: findPlayer.Name,
Phone: findPlayer.Tel,
ItemId: itemData.Id, //获得物品ID
TypeId: int32(awardLogType),
}
AwardLogMgr.UpdateAnnouncerLog(logData)
}
}
}
} else {
callback(errors.New("AddItemsOffline failed"))
}
}), "AddItemsOffline").Start()
}
// AddMailByItem 赠送道具到邮件
// srcId 发送人 srcName发送人名字
// items[0]:道具id items[1]:道具数量 items[2]:道具id items[3]:道具数量
func (this *BagMgr) AddMailByItem(platform string, srcId int32, srcName string, snid int32, showId int64, items []int32) {
logger.Logger.Trace("AddMailByItem:", srcId, srcName, items)
var newMsg *model.Message
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
content := i18n.Tr("languages", "GiftMail", srcName, srcName, srcName, srcName)
title := i18n.Tr("languages", "GiftMailTitle")
newMsg = model.NewMessageByPlayer("", 1, srcId, srcName, snid, model.MSGTYPE_ITEM, title, content,
0, 0, model.MSGSTATE_UNREAD, time.Now().Unix(), 0, "", items, platform, showId)
return model.InsertMessage(platform, newMsg)
}), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) {
if data == nil {
p := PlayerMgrSington.GetPlayerBySnId(snid)
if p != nil {
p.AddMessage(newMsg)
}
}
}), "AddMailByItem").Start()
}
// VerifyUpJybInfo 兑换礼包
func (this *BagMgr) VerifyUpJybInfo(p *Player, args *model.VerifyUpJybInfoArgs) {
type VerifyInfo struct {
jyb *model.JybInfo
err error
}
pack := &playerproto.SCPlayerSetting{
OpRetCode: playerproto.OpResultCode_OPRC_Sucess,
}
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
jyb, err := model.VerifyUpJybInfo(args)
info := &VerifyInfo{
jyb: jyb,
err: err,
}
return info
}), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) {
if data != nil && data.(*VerifyInfo) != nil {
jyb := data.(*VerifyInfo).jyb
err := data.(*VerifyInfo).err
if jyb != nil && jyb.Award != nil { // 领取到礼包
pack.GainItem = &playerproto.JybInfoAward{}
if jyb.Award.Item != nil {
if len(jyb.Award.Item) > 0 {
items := make([]*Item, 0)
for _, v := range jyb.Award.Item {
items = append(items, &Item{
ItemId: v.ItemId, // 物品id
ItemNum: v.ItemNum, // 数量
ObtainTime: time.Now().Unix(),
})
}
if _, code, _ := this.AddItems(p, items, 0, common.GainWay_ActJybAward, "system", "礼包码兑换", 0, 0, false); code != bag.OpResultCode_OPRC_Sucess { //TODO 添加失败 要回退礼包
logger.Logger.Errorf("CSPlayerSettingHandler AddItems err", code)
pack.OpRetCode = playerproto.OpResultCode_OPRC_Error
proto.SetDefaults(pack)
p.SendToClient(int(playerproto.PlayerPacketID_PACKET_ALL_SETTING), pack)
}
p.dirty = true
}
}
jybLog := &model.JybLog{
Platform: p.Platform,
Id: jyb.JybId.Hex(),
Ts: time.Now().Unix(),
SnId: p.SnId,
Tp: jyb.CodeType,
Name: jyb.Name,
}
for _, v := range jyb.Award.Item {
//if _, code := BagMgrSingleton.UpBagInfo(p.SnId, p.Platform, v.ItemId, v.ItemNum); code == bag.OpResultCode_OPRC_Sucess { // 需修改
pack.GainItem.ItemId = append(pack.GainItem.ItemId, &playerproto.ItemInfo{
ItemId: v.ItemId,
ItemNum: v.ItemNum,
})
jybLog.Award = append(jybLog.Award, &model.JybItem{
Id: v.ItemId,
Num: int32(v.ItemNum),
})
}
if jyb.Award.Coin > 0 {
p.AddCoin(jyb.Award.Coin, 0, common.GainWay_ActJybAward, "system", "礼包码兑换")
if !p.IsRob {
LogChannelSingleton.WriteMQData(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, p.Channel, model.SystemFreeGive_GiveType_ActJybAward, model.SystemFreeGive_CoinType_Coin, int64(jyb.Award.Coin)))
}
jybLog.Award = append(jybLog.Award, &model.JybItem{
Id: common.ItemIDCoin,
Num: int32(jyb.Award.Coin),
})
}
if jyb.Award.Diamond > 0 {
p.AddDiamond(jyb.Award.Diamond, 0, common.GainWay_ActJybAward, "system", "礼包码兑换")
if !p.IsRob {
LogChannelSingleton.WriteMQData(model.GenerateSystemFreeGive(p.SnId, p.Name, p.Platform, p.Channel, model.SystemFreeGive_GiveType_ActJybAward, model.SystemFreeGive_CoinType_Diamond, int64(jyb.Award.Diamond)))
}
jybLog.Award = append(jybLog.Award, &model.JybItem{
Id: common.ItemIDDiamond,
Num: int32(jyb.Award.Coin),
})
}
// 领取日志
LogChannelSingleton.WriteLog(jybLog)
p.dirty = true
pack.GainItem.Coin = jyb.Award.Coin
pack.GainItem.Diamond = jyb.Award.Diamond
} else {
switch err.Error() {
case model.ErrJybISReceive.Error():
pack.OpRetCode = playerproto.OpResultCode_OPRC_Jyb_Receive
case model.ErrJYBPlCode.Error():
pack.OpRetCode = playerproto.OpResultCode_OPRC_Jyb_CodeExist
case model.ErrJybTsTimeErr.Error():
pack.OpRetCode = playerproto.OpResultCode_OPRC_Jyb_TimeErr
default:
pack.OpRetCode = playerproto.OpResultCode_OPRC_Jyb_CodeErr
}
}
} else {
proto.SetDefaults(pack)
p.SendToClient(int(playerproto.PlayerPacketID_PACKET_ALL_SETTING), pack)
}
proto.SetDefaults(pack)
p.SendToClient(int(playerproto.PlayerPacketID_PACKET_ALL_SETTING), pack)
}), "VerifyUpJybInfo").Start()
// 先检查玩家背包是否足够
}
// SyncBagData 通知玩家背包数据变化
func (this *BagMgr) SyncBagData(snid int32, changeItemIds ...int32) {
p := PlayerMgrSington.GetPlayerBySnId(snid)
if p == nil || p.IsRob {
return
}
var itemInfos []*bag.ItemInfo
for _, itemId := range changeItemIds {
itemInfo := this.GetItem(snid, itemId)
if itemInfo != nil {
itemInfos = append(itemInfos, &bag.ItemInfo{
ItemId: itemInfo.ItemId,
ItemNum: itemInfo.ItemNum,
//Name: itemInfo.Name,
//Classify: itemInfo.Classify,
//Type: itemInfo.Type,
//Effect0: itemInfo.Effect0,
//Effect: itemInfo.Effect,
//SaleType: itemInfo.SaleType,
//SaleGold: itemInfo.SaleGold,
//Composition: itemInfo.Composition,
//CompositionMax: itemInfo.CompositionMax,
//Time: itemInfo.Time,
//Location: itemInfo.Location,
//Describe: itemInfo.Describe,
ObtainTime: itemInfo.ObtainTime,
})
if itemInfo.ItemId == common.ItemIDVCard {
FriendMgrSington.UpdateInfo(p.Platform, p.SnId)
}
}
}
p.SyncBagData(itemInfos)
}
// 兑换话费卡
func (this *BagMgr) ItemExchangeCard(p *Player, itemId int32, money, cardType int32, logId string) bool {
// 兑换码奖品
var err error
var newMsg *model.Message
res := &webapiproto.SAGetMatchAwardCode{}
pack := &bag.SCItemExChangeRes{RetCode: bag.OpResultCode_OPRC_Sucess}
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
// 获取兑换码
pack := &webapiproto.ASGetMatchAwardCode{
Platform: p.Platform,
Snid: p.SnId,
ItemID: itemId,
Money: int64(money),
Tel: p.Tel,
CardType: cardType,
Remark: "背包内使用兑换",
}
logger.Logger.Trace("ItemChangeCode ", pack)
var buff []byte
buff, err = webapi.APIGetMatchAwardCode(common.GetAppId(), pack)
if err != nil {
return err
}
if err = proto.Unmarshal(buff, res); err != nil {
return err
}
if res.GetCode() == "" || res.GetTag() != webapiproto.TagCode_SUCCESS {
return nil
}
var params []string
for range []string{"zh", "vi", "en", "kh"} {
params = append(params, res.GetMoney(), res.GetCode()) // 金额,兑换码
}
// 发送邮件
title := i18n.Tr("languages", "MatchAwardTitle")
content := i18n.Tr("languages", "MatchAward", params)
newMsg = model.NewMessage("", 0, "", p.SnId, model.MSGTYPE_ITEM_CHANGE,
title, content, 0, 0, model.MSGSTATE_UNREAD, time.Now().Unix(), 0, "", nil, p.Platform, model.HallTienlen, nil)
err := model.InsertMessage(p.Platform, newMsg)
if err != nil {
logger.Logger.Errorf("发送邮件失败 snid:%v itemID:%v err:%v", p.SnId, itemId, err)
return err
}
return nil
}), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) {
if err != nil || res.GetCode() == "" || res.GetTag() != webapiproto.TagCode_SUCCESS {
//返回道具
items := make([]*model.Item, 0)
items = append(items, &model.Item{
ItemId: itemId, // 物品id
ItemNum: 1, // 数量
ObtainTime: time.Now().Unix(),
})
this.AddItemsV2(&model.AddItemParam{
P: p.PlayerData,
Change: items,
Add: 0,
GainWay: common.GainWayItemChange,
Operator: "system",
Remark: "背包内使用兑换失败",
GameId: 0,
GameFreeId: 0,
NoLog: false,
LogId: logId,
})
logger.Logger.Errorf("获取兑换码失败 snid:%v itemID:%v res:%v err:%v", p.SnId, itemId, res, err)
pack.RetCode = bag.OpResultCode_OPRC_Error
p.SendToClient(int(bag.SPacketID_PACKET_SC_ITEM_EXCHANGE_RES), pack)
// 标记兑换失败
task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
model.UpdateItemState(&model.UpdateParam{
Platform: p.Platform,
LogId: bson.ObjectIdHex(logId),
State: 1,
})
return nil
}), nil).Start()
return
}
p := PlayerMgrSington.GetPlayerBySnId(p.SnId)
if p != nil {
p.AddMessage(newMsg)
//已兑换log
itemData := srvdata.GameItemMgr.Get(p.Platform, itemId)
AwardLogMgr.UpdateAwardLog(p.Platform, itemData.Id, int64(1))
}
p.SendToClient(int(bag.SPacketID_PACKET_SC_ITEM_EXCHANGE_RES), pack)
}), fmt.Sprintf("ItemExChange%d", p.SnId)).Start()
return true
}
func (this *BagMgr) Update() {
}
func (this *BagMgr) Shutdown() {
module.UnregisteModule(this)
}
//========================implement IPlayerLoad ==============================
func (this *BagMgr) Load(platform string, snid int32, player any) *internal.PlayerLoadReplay {
data, err := model.GetBagInfo(snid, platform)
return &internal.PlayerLoadReplay{
Platform: platform,
Snid: snid,
Err: err,
Data: data,
}
}
func (this *BagMgr) Callback(player any, ret *internal.PlayerLoadReplay) {
if ret == nil || ret.Data == nil {
return
}
bagInfo, ok := ret.Data.(*model.BagInfo)
if !ok || bagInfo == nil {
return
}
//数据表 数据库数据相结合
newBagInfo := &BagInfo{
SnId: ret.Snid,
Platform: ret.Platform,
BagItem: make(map[int32]*Item),
}
for k, bi := range 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
}
func (this *BagMgr) LoadAfter(platform string, snid int32) *internal.PlayerLoadReplay {
// 查询最近游戏
gameID := model.GetRecentGame(platform, snid)
return &internal.PlayerLoadReplay{
Platform: platform,
Snid: snid,
Err: nil,
Data: gameID,
}
}
func (this *BagMgr) CallbackAfter(ret *internal.PlayerLoadReplay) {
if ret == nil {
return
}
if ret.Err != nil {
logger.Logger.Error("BagMgr LoadAfter err:", ret.Err)
return
}
p := PlayerMgrSington.GetPlayerBySnId(ret.Snid)
if p != nil {
p.GameID = ret.Data.([]int32)
p.AutoSkinUnlock()
}
}
func (this *BagMgr) Save(platform string, snid int32, isSync, force bool) {
bagInfo := this.PlayerBag[snid]
logger.Logger.Trace("SaveBagData:", bagInfo)
if bagInfo == nil || (!bagInfo.dirty && !force) {
return
}
type BagInfoMap struct {
SnId int32 //玩家账号直接在这里生成
Platform string //平台
BagItem []*Item //背包数据 key为itemId
}
// biMap 数据拷贝
var biMap = BagInfoMap{
SnId: bagInfo.SnId,
Platform: bagInfo.Platform,
}
for _, v := range bagInfo.BagItem {
biMap.BagItem = append(biMap.BagItem, &Item{ItemId: v.ItemId, ItemNum: v.ItemNum, ObtainTime: v.ObtainTime})
}
var err error
f := func() {
newBagInfo := &model.BagInfo{
SnId: biMap.SnId,
Platform: biMap.Platform,
BagItem: make(map[int32]*model.Item),
}
for _, v := range biMap.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 {
bagInfo.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()
}), "SaveBagData").StartByFixExecutor("SnId:" + strconv.Itoa(int(snid)))
}
func (this *BagMgr) Release(platform string, snid int32) {
delete(this.PlayerBag, snid)
}
func init() {
module.RegisteModule(BagMgrSingleton, time.Second, 0)
internal.RegisterPlayerLoad(BagMgrSingleton)
}