820 lines
23 KiB
Go
820 lines
23 KiB
Go
package main
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"math"
|
||
webapiproto "mongo.games.com/game/protocol/webapi"
|
||
"mongo.games.com/game/webapi"
|
||
"mongo.games.com/game/worldsrv/internal"
|
||
"strconv"
|
||
"time"
|
||
|
||
"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"
|
||
"mongo.games.com/game/srvdata"
|
||
)
|
||
|
||
const (
|
||
BagItemMax int32 = 200
|
||
)
|
||
|
||
// 道具功能 Function
|
||
const (
|
||
ItemCanUse = iota //可以使用
|
||
ItemCanGive //可以赠送
|
||
ItemCanSell //可以出售
|
||
ItemCanExchange //可以兑换
|
||
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
|
||
}
|
||
|
||
// 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 ItemParam struct {
|
||
P *Player
|
||
Change []*Item // 道具变化数量
|
||
Cost []*model.ItemInfo // 获得道具时消耗的道具数量
|
||
Add int64 // 加成数量
|
||
GainWay int32 // 记录类型
|
||
Operator, Remark string // 操作人,备注
|
||
gameId, gameFreeId int64 // 游戏id,场次id
|
||
noLog bool // 是否不记录日志
|
||
}
|
||
|
||
type AddItemParam struct {
|
||
Cost []*model.ItemInfo // 获得道具时消耗的道具数量
|
||
}
|
||
|
||
func (this *BagMgr) AddItemsV2(args *ItemParam) (*BagInfo, bag.OpResultCode, bool) {
|
||
return this.AddItems(args.P, args.Change, args.Add, args.GainWay, args.Operator, args.Remark, args.gameId, args.gameFreeId, args.noLog, AddItemParam{
|
||
Cost: args.Cost,
|
||
})
|
||
}
|
||
|
||
// 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.ItemInfo
|
||
if len(params) > 0 {
|
||
cost = params[0].Cost
|
||
}
|
||
|
||
var items []*Item
|
||
for _, v := range addItems {
|
||
if v == nil || v.ItemNum == 0 {
|
||
continue
|
||
}
|
||
item := srvdata.GameItemMgr.Get(p.Platform, v.ItemId)
|
||
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
|
||
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,
|
||
})
|
||
if log != nil {
|
||
LogChannelSingleton.WriteLog(log)
|
||
}
|
||
}
|
||
|
||
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)
|
||
}
|
||
// 统计 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
|
||
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 []*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)
|
||
}
|
||
}
|
||
} 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
|
||
}
|
||
}
|
||
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,
|
||
})
|
||
}
|
||
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)))
|
||
}
|
||
}
|
||
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)))
|
||
}
|
||
}
|
||
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) 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([]*Item, 0)
|
||
items = append(items, &Item{
|
||
ItemId: itemId, // 物品id
|
||
ItemNum: 1, // 数量
|
||
ObtainTime: time.Now().Unix(),
|
||
})
|
||
this.AddItems(p, items, 0, common.GainWayItemChange, "system", "背包内使用兑换失败", 0, 0, false)
|
||
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)
|
||
return
|
||
}
|
||
p := PlayerMgrSington.GetPlayerBySnId(p.SnId)
|
||
if p != nil {
|
||
p.AddMessage(newMsg)
|
||
}
|
||
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)
|
||
}
|