package main import ( "errors" "fmt" "time" "github.com/globalsign/mgo/bson" "golang.org/x/exp/maps" "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/i18n" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/netlib" "mongo.games.com/goserver/core/task" "mongo.games.com/game/common" "mongo.games.com/game/model" "mongo.games.com/game/mq" "mongo.games.com/game/proto" "mongo.games.com/game/protocol/bag" playerproto "mongo.games.com/game/protocol/player" "mongo.games.com/game/protocol/server" 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 //可以分解 ItemCanCompound //可以合成 ItemMax ) func init() { internal.RegisterPlayerLoad(BagMgrSingleton) BagMgrSingleton.AddOnChangeFuncs(func(param *model.ChangeItemParam) { p := PlayerMgrSington.GetPlayerBySnId(param.SnId) if p == nil { return } itemData := srvdata.GameItemMgr.Get(p.Platform, param.ItemId) if itemData == nil { return } logType := ItemObtain if param.ItemNum < 0 { logType = ItemConsume } //获奖记录log if logType == ItemObtain && param.ItemNum > 0 { awardLogType := 0 if itemData.Type == common.ItemTypeChange { //话费 awardLogType = 1 } else if itemData.Type == common.ItemTypeObjective { //实物 awardLogType = 2 AwardLogMgr.UpdateAwardLog(p.Platform, itemData.Id, param.ItemNum) } if awardLogType != 0 { data := model.AnnouncerLog{ Platform: p.Platform, Snid: p.SnId, Name: p.Name, Phone: p.Tel, ItemId: param.ItemId, //获得物品ID TypeId: int32(awardLogType), } AwardLogMgr.UpdateAnnouncerLog(data) } } // 皮肤自动解锁 if p != nil && itemData.GetType() == 21 && param.ItemNum > 0 { p.AutoSkinUnlock() } if param.ItemNum > 0 { switch param.ItemId { case common.ItemIDWeekScore: TaskSubjectSingleton.Touch(common.TaskTypeActivityScore, &TaskData{ SnId: p.SnId, Num: param.ItemNum, }) case common.ItemIDPetSkill: ModelMgrSingleton.CheckShowRed(p) case common.ItemIDPermit, common.ItemIDLong: var permitScore, long int64 if param.ItemId == common.ItemIDLong { long = param.ItemNum } else { permitScore = param.ItemNum } mq.Write(&model.BackendPermitJoin{ Platform: p.Platform, StartTs: PlatformMgrSingleton.GetConfig(p.Platform).PermitStartTs, SnId: p.SnId, Score: permitScore, Long: long, Ts: time.Now().Unix(), }) } switch itemData.GetType() { case common.ItemTypeSkinChip: ModelMgrSingleton.CheckSkinRed(p) } } // 统计 v卡兑换消耗数量 if p != nil && param.ItemId == common.ItemIDVCard && param.GainWay == common.GainWay_Exchange { p.VCardCost += -param.ItemNum if p.VCardCost < 0 { p.VCardCost = 0 } } // 更新通行证赛季积分排行榜 if param.ItemId == common.ItemIDPermit { item := BagMgrSingleton.GetItem(p.SnId, param.ItemId) startTs := PlatformMgrSingleton.GetConfig(p.Platform).PermitStartTs if item != nil && item.ItemNum > 0 && startTs > 0 { // 赛季积分排行榜 mq.Write(&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 param.ItemId == common.ItemIDVCard { FriendMgrSington.UpdateInfo(p.Platform, p.SnId) } }) } type Item struct { ItemId int32 // 物品ID ItemNum int64 // 物品数量 ObtainTime int64 //获取的时间 //数据表数据 Name string // 名称 Effect0 []int32 // 竖版道具功能 ItemCanUse ... Effect []int32 // 横版道具功能 ItemCanUse ... SaleType int32 // 出售类型 SaleGold int32 // 出售金额 } type BagInfo struct { SnId int32 //玩家id Platform string //平台id BagItem map[int32]*Item //背包数据 key为itemId Ts int64 //更新时间戳 // 临时携带参数 dirty bool `bson:"-"` //是否需要更新数据库 LogId string `bson:"-"` //最后一次保存的日志id } func NewBagInfo(platform string, snid int32) *BagInfo { return &BagInfo{ SnId: snid, Platform: platform, BagItem: make(map[int32]*Item), Ts: time.Now().Unix(), dirty: true, LogId: "", } } // BagMgr 玩家背包 type BagMgr struct { PlayerBag map[int32]*BagInfo // snid:背包 // 道具变更监听,玩家离线时道具变更会在登录时根据道具日志执行一遍 onChangeFuncs []func(param *model.ChangeItemParam) } // BagMgrSingleton 背包管理器 var BagMgrSingleton = &BagMgr{ PlayerBag: make(map[int32]*BagInfo), } // ============================================================================ // 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: v.Count, 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...) } func (this *BagMgr) OnChangeFuncs(param *model.ChangeItemParam) { logger.Logger.Tracef("OnChangeFuncs %+v", *param) for _, v := range this.onChangeFuncs { v(param) } } // 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.Effect0 = itemX.Effect item.Effect = itemX.Effect item.SaleType = itemX.SaleType item.SaleGold = itemX.SaleGold } } 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 } // Range 遍历背包 func (this *BagMgr) Range(snid int32, fn func(item *Item) bool) { if v, exist := this.PlayerBag[snid]; exist { for k := range v.BagItem { e := this.GetItem(snid, k) if e == nil { continue } if !fn(e) { return } } } } // GetBagInfo 获取背包信息 // 是复制的一份数据 func (this *BagMgr) GetBagInfo(snid int32) *BagInfo { p := PlayerMgrSington.GetPlayerBySnId(snid) if p == nil { return nil } ret := NewBagInfo(p.Platform, p.SnId) if v, exist := this.PlayerBag[snid]; exist { ret.Ts = v.Ts ret.dirty = v.dirty ret.LogId = v.LogId for k := range v.BagItem { ret.BagItem[k] = this.GetItem(snid, k) } } else { this.PlayerBag[snid] = NewBagInfo(p.Platform, p.SnId) } return ret } // SyncBagData 通知玩家背包数据变化 func (this *BagMgr) SyncBagData(snid int32, changeItemIds ...int32) { if len(changeItemIds) == 0 { return } 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, ObtainTime: itemInfo.ObtainTime, }) } } pack := &bag.SCSyncBagData{ Infos: itemInfos, } p.SendToClient(int(bag.SPacketID_PACKET_SC_SYNCBAGDATA), pack) logger.Logger.Tracef("背包数据变更(%v): %v", p.SnId, pack) } // AddItemCheck 校验道具是否充足 // 返回道具变化,操作结果,是否成功 func (this *BagMgr) AddItemCheck(param *model.AddItemParam) ([]*model.Item, bag.OpResultCode, bool) { var items []*model.Item // 道具变化 p := PlayerMgrSington.GetPlayerBySnId(param.SnId) if p == nil { return items, bag.OpResultCode_OPRC_NotPlayer, false } // 获取背包 var newBagInfo *BagInfo if _, exist := this.PlayerBag[p.SnId]; !exist { newBagInfo = NewBagInfo(p.Platform, p.SnId) this.PlayerBag[p.SnId] = newBagInfo } else { newBagInfo = this.PlayerBag[p.SnId] } // 参数校验 for _, v := range param.Change { if v == nil || v.ItemNum == 0 { continue } item := srvdata.GameItemMgr.Get(p.Platform, v.ItemId) if item == nil { return items, bag.OpResultCode_OPRC_IdErr, false } if itm, exist := newBagInfo.BagItem[v.ItemId]; exist { if v.ItemNum < 0 && itm.ItemNum < -v.ItemNum { return items, bag.OpResultCode_OPRC_UseUp, false } } else { if v.ItemNum < 0 { return items, bag.OpResultCode_OPRC_UseUp, false } } items = append(items, &model.Item{ ItemId: v.ItemId, ItemNum: v.ItemNum, ObtainTime: v.ObtainTime, }) } return items, bag.OpResultCode_OPRC_Sucess, true } // AddItems 修改道具,玩家需在线 func (this *BagMgr) AddItems(param *model.AddItemParam) (*BagInfo, bag.OpResultCode, bool) { p := PlayerMgrSington.GetPlayerBySnId(param.SnId) if p == nil { return nil, bag.OpResultCode_OPRC_NotPlayer, false } // 非道具 var realItems []*model.Item for _, v := range param.Change { 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, param.Add, param.GainWay, param.Operator, param.Remark) } case common.ItemTypeDiamond: //增加钻石 if item.Id == common.ItemIDDiamond { p.AddDiamond(v.ItemNum, param.Add, param.GainWay, param.Operator, param.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, param.GainWay, param.Operator, param.Remark) } case common.ItemTypeExpireTime: p.AddItemRecExpireTime(v.ItemId, v.ItemNum, 0, param.GainWay, param.Operator, param.Remark) default: // 道具变化 realItems = append(realItems, v) } } param.Change = realItems if len(realItems) == 0 { return nil, bag.OpResultCode_OPRC_Sucess, true } // 非道具 items, code, ok := this.AddItemCheck(param) if !ok { return nil, code, ok } if len(items) == 0 { return nil, bag.OpResultCode_OPRC_Sucess, true } newBagInfo, ok := this.PlayerBag[param.SnId] if !ok { newBagInfo = NewBagInfo(p.Platform, p.SnId) this.PlayerBag[param.SnId] = newBagInfo } // 更新背包 var ts int64 // 最新日志纳秒时间戳 var itemInfos []int32 for _, v := range items { itemData := srvdata.GameItemMgr.Get(p.Platform, v.ItemId) if itemData == nil { continue } if itm, exist := newBagInfo.BagItem[v.ItemId]; exist { itm.ItemNum += v.ItemNum } else { newBagInfo.BagItem[v.ItemId] = &Item{ ItemId: v.ItemId, // 物品id ItemNum: v.ItemNum, // 数量 ObtainTime: time.Now().Unix(), } } 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: itemData.Name, Count: num, Remark: param.Remark, TypeId: param.GainWay, GameId: param.GameId, GameFreeId: param.GameFreeId, Cost: param.Cost, LogId: param.LogId, RoomConfigId: param.RoomConfigId, }) if log != nil { mq.Write(log) ts = log.Ts newBagInfo.LogId = log.LogId.Hex() } // 监听道具变化 this.OnChangeFuncs(&model.ChangeItemParam{ SnId: p.SnId, ItemId: v.ItemId, ItemNum: v.ItemNum, GainWay: param.GainWay, RoomConfigId: param.RoomConfigId, GameId: param.GameId, GameFreeId: param.GameFreeId, Cost: param.Cost, }) itemInfo := this.GetItem(p.SnId, v.ItemId) if itemInfo != nil { itemInfos = append(itemInfos, v.ItemId) } } // 同步游戏服务器 if p.scene != nil && !param.IsGame { b, err := netlib.Gob.Marshal(items) if err != nil { logger.Logger.Errorf("AddItems Marshal error(%v)", err) } else { p.SendToGame(int(server.SSPacketID_PACKET_PlayerChangeItems), &server.PlayerChangeItems{ Data: b, SnId: p.SnId, }) logger.Logger.Infof("AddItems SendToGame snid:%v gameId:%v %v", p.SnId, p.scene.GameFreeId, items) } } newBagInfo.dirty = true if ts > newBagInfo.Ts { newBagInfo.Ts = ts } this.PlayerBag[p.SnId] = newBagInfo p.SendDiffData() this.SyncBagData(p.SnId, itemInfos...) return newBagInfo, bag.OpResultCode_OPRC_Sucess, true } // AddItemsOffline 修改道具,玩家离线 func (this *BagMgr) AddItemsOffline(param *model.AddItemParam, callback func(err error)) { // 玩家在线时 p := PlayerMgrSington.GetPlayerBySnId(param.SnId) if p != nil { this.AddItems(param) if callback != nil { callback(nil) } return } // 玩家离线时 var findPlayer *model.PlayerBaseInfo task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { findPlayer = model.GetPlayerBaseInfo(param.Platform, param.SnId) if findPlayer == nil { return nil } newBagInfo := &model.BagInfo{ SnId: findPlayer.SnId, Platform: findPlayer.Platform, BagItem: make(map[int32]*model.Item), GainWay: param.GainWay, } for _, v := range param.Change { if v == nil || v.ItemNum == 0 { continue } itemData := srvdata.GameItemMgr.Get(param.Platform, v.ItemId) if itemData == nil { continue } newBagInfo.BagItem[v.ItemId] = &model.Item{ItemId: v.ItemId, ItemNum: v.ItemNum} } if err := model.SaveDBBagItem(newBagInfo); err != nil { logger.Logger.Errorf("离线保存道具变更错误 %v", err) return err } // 保存日志 if err := model.InsertItemLog(srvdata.GameItemMgr.GetItems(param.Platform), param, true); err != nil { logger.Logger.Errorf("离线保存道具变更日志错误 %v", err) return err } return nil }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { if data != nil || findPlayer == nil { logger.Logger.Errorf("AddItemsOffline Error %v", data) if callback != nil { callback(errors.New("AddItemsOffline failed")) } return } logger.Logger.Tracef("AddItemsOffline error(%v) Player:%+v", data, *findPlayer) if callback != nil { callback(nil) } })).StartByExecutor(fmt.Sprintf("Player%v", param.SnId)) } // 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([]*model.Item, 0) for _, v := range jyb.Award.Item { items = append(items, &model.Item{ ItemId: v.ItemId, // 物品id ItemNum: v.ItemNum, // 数量 ObtainTime: time.Now().Unix(), }) } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: p.Platform, SnId: p.SnId, Change: items, GainWay: common.GainWay_ActJybAward, Operator: "system", Remark: "礼包码兑换", }) 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 { mq.Write(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 { mq.Write(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), }) } // 领取日志 mq.Write(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() } // ItemExchangeCard 兑换话费卡 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.AddItems(&model.AddItemParam{ Platform: p.Platform, SnId: p.SnId, Change: items, Add: 0, GainWay: common.GainWayItemChange, Operator: "system", Remark: "背包内使用兑换失败", GameId: 0, GameFreeId: 0, 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 }