package main import ( "bytes" "crypto/md5" "encoding/gob" "encoding/hex" "fmt" "io" "math" "math/rand" "slices" "strconv" "time" "github.com/globalsign/mgo/bson" "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/netlib" "mongo.games.com/goserver/core/task" "mongo.games.com/goserver/srvlib" srvlibproto "mongo.games.com/goserver/srvlib/protocol" "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" hallproto "mongo.games.com/game/protocol/gamehall" loginproto "mongo.games.com/game/protocol/login" msgproto "mongo.games.com/game/protocol/message" playerproto "mongo.games.com/game/protocol/player" "mongo.games.com/game/protocol/rankmatch" serverproto "mongo.games.com/game/protocol/server" "mongo.games.com/game/protocol/webapi" "mongo.games.com/game/protocol/welfare" "mongo.games.com/game/srvdata" "mongo.games.com/game/worldsrv/internal" ) // 对应到客户端的一个玩家对象. const ( PlayerStateCache = iota // 缓存(没有登录过,只查询过玩家数据) PlayerStateOnline // 在线 PlayerStateOffline // 离线(登录后掉线) ) const ( UpdateField_Coin int64 = 1 << iota UpdateField_SafeBoxCoin UpdateField_VIP UpdateField_CoinPayTotal UpdateField_TotalConvertibleFlow UpdateField_Ticket UpdateField_Grade UpdateField_Diamond UpdateField_VCoin UpdateField_ChessGrade UpdateField_RankScore UpdateField_PhoneScore UpdateField_InviteScore ) type Player struct { *model.PlayerData //po 持久化对象 diffData model.PlayerDiffData //差异数据 gateSess *netlib.Session //所在GateServer的session scene *Scene //当前所在个Scene thrscene int //是否在三方 sid int64 //对应客户端的sessionId state int //玩家状态 PlayerStateOnline PlayerStateOffline lastSaved time.Time //最后保存的时间 dirty bool //脏标记 pos int //位置 msgs map[string]*model.Message // beUnderAgent bool //是否隶属于代理 lastSceneId map[int32][]int32 //上一个房间id;gamefreeid:房间号 ollenSecs int32 //在线时长 currClubId int32 //当前所在的俱乐部id takeCoin int64 //携带金币 sceneCoin int64 //房间里当前的金币量 isNewbie bool //是否是新用户 applyPos int32 //申请的场景位置 flag int32 //Game服务器的用户状态 hallId int32 //所在游戏大厅 changeIconTime time.Time //上次修改头像时间 enterts time.Time //进入时间 lastChangeScene time.Time //上次换桌时间 dropTime time.Time // 掉线时间 isAudience bool //是否是观众 customerToken string //客服会话token isDelete bool //是否已删档用户 thridBalanceRefreshReqing bool //玩家请求刷新三方金额进行中 thridBalanceReqIsSucces bool //三方请求刷新成功 params *model.PlayerParams //客户端登陆游戏带上来的临时参数 exchangeState bool //订单操作状态 lastOnDayChange time.Time lastOnWeekChange time.Time lastOnMonthChange time.Time //例如["WWG平台"][true:已经刷新过不用再次刷新,false:未知需要刷新] //注意:该数据不会落地到mgo,游服第一次启动的时候会请求全部三方刷新余额,之后就会根据标记来进行刷新。 //确保thirdBalanceRefreshMark只在主协程里面操作 thirdBalanceRefreshMark map[string]bool EnterCoinSceneQueueTs int64 CoinSceneQueueRound int32 CoinSceneQueue *CoinScenePool EnterQueueTime time.Time //进入队列的时间 //比赛 cparams map[string]string //平台登陆数据 "name", "head", "geo-info", "lang", "ip" Iparams map[int]int64 //整形参数 sparams map[int]string //字符参数 //用户登录时获取 单用户活动开关控制 layered map[int]bool //true 为关 false为开 //用户分层ids layerlevels []int //缓存玩家身上所有分层数据 miniScene map[int32]*Scene //当前所在个Scene leavechan chan int // 比赛环境 matchCtx *PlayerMatchContext // 在线记录 onlineLog *model.OnlineLog // 数据埋点 DeviceName string // 设备名称 PackageName string // 包名 AppVersion string // app版本 BuildVersion string // app构建版本 AppChannel string // app渠道(玩家本次登录使用的包的渠道类型,换登录包,这个值也会变;玩家model.PlayerData存储的渠道是玩家第一次登录的渠道,不会修改) // 最后玩的游戏id LastGameId int GameID []int32 // 最近三天玩的游戏 ApplyList []int32 //玩家申请好友记录 TaskInviteList map[int32]int // 邀请好友私人桌对局 好友id:房间id LotteryCode *welfare.NotifyLotteryCode // 缓存一下,离开房间发送 } func NewPlayer(sid int64, pd *model.PlayerData, s *netlib.Session) *Player { // 玩家数据初始化 p := &Player{ PlayerData: pd, sid: sid, gateSess: s, msgs: make(map[string]*model.Message), cparams: make(map[string]string), Iparams: make(map[int]int64), sparams: make(map[int]string), pos: -1, beUnderAgent: pd.BeUnderAgentCode != "", thirdBalanceRefreshMark: make(map[string]bool), layered: make(map[int]bool), miniScene: make(map[int32]*Scene), TaskInviteList: make(map[int32]int), state: PlayerStateCache, } if p.IsRob { p.RobotRandName() } if p.init() { return p } return nil } // 玩家数据初始化 func (this *Player) init() bool { this.SetOnline() this.isNewbie = this.CreateTime == this.LastLoginTime if this.WelfData == nil { this.WelfData = model.NewWelfareData() } if this.VCardCost < 0 { this.VCardCost = 0 } if this.GuideData == nil { this.GuideData = make(map[int32]int32) } this.InitRolesAndPets() return true } func (this *Player) SyncBagData(itemInfo []*bag.ItemInfo) { pack := &bag.SCSyncBagData{ Infos: itemInfo, } this.SendToClient(int(bag.SPacketID_PACKET_SC_SYNCBAGDATA), pack) logger.Logger.Tracef("背包数据变更(%v): %v", this.SnId, pack) } // SendToClient 给客户端发消息,玩家需要在线 func (this *Player) SendToClient(packetid int, rawpack interface{}) bool { if this.IsOffline() { logger.Logger.Trace("Player if offline.") return false } return this.SendRawToClientIncOffLine(this.sid, this.gateSess, packetid, rawpack) } // SendRawToClientIncOffLine 给客户端发消息,不关心是否在线 func (this *Player) SendRawToClientIncOffLine(sid int64, gateSess *netlib.Session, packetid int, rawpack interface{}) bool { if gateSess == nil { logger.Logger.Tracef("[%v] sess == nil ", this.SnId, packetid) return false } if rawpack == nil { logger.Logger.Trace(" rawpack == nil ") return false } return common.SendToGate(sid, packetid, rawpack, gateSess) } func (this *Player) SendToGame(packetid int, rawpack interface{}) bool { if this.scene == nil || this.scene.gameSess == nil || this.scene.gameSess.Session == nil { logger.Logger.Tracef("[%v] sess == nil ", this.Name) return false } if rawpack == nil { logger.Logger.Trace(" rawpack == nil ") return false } return this.scene.SendToGame(packetid, rawpack) } // LoadAfter 玩家基础信息加载后加载其他数据 func (this *Player) LoadAfter() { var replays []*internal.PlayerLoadReplay task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { for _, v := range internal.GetPlayerLoads() { replays = append(replays, v.LoadAfter(this.Platform, this.SnId)) } return nil }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { if len(replays) != len(internal.GetPlayerLoads()) { return } for k, v := range internal.GetPlayerLoads() { if v == nil || replays[k] == nil { continue } v.CallbackAfter(replays[k]) } })).StartByExecutor(fmt.Sprintf("Player%v", this.SnId)) } func (this *Player) OnLogined() { logger.Logger.Tracef("(this *Player) OnLogined() %v", this.SnId) this.lastSaved = time.Now() isFirstLogin := false if this.CreateTime.Unix() > this.LastLogoutTime.Unix() { isFirstLogin = true } if !this.IsRob { this.ResetPermit() } // 跨天业务处理 tNow := time.Now() tLastLogout := this.PlayerData.LastLogoutTime this.PlayerData.LastLoginTime = tNow this.dirty = true if !common.InSameDay(tNow, tLastLogout) { //跨天 logger.Logger.Infof("(this *Player) OnLogined(%v) inSameDay LastLogoutTime(%v)", this.SnId, tLastLogout) isContinueDay := common.IsContinueDay(tNow, tLastLogout) // 计算跨了多少天 var t int t1 := tLastLogout t2 := tNow out := time.Date(t1.Year(), t1.Month(), t1.Day(), 0, 0, 0, 0, t1.Location()) in := time.Date(t2.Year(), t2.Month(), t2.Day(), 0, 0, 0, 0, t2.Location()) t = int(math.Floor(in.Sub(out).Hours() / 24)) this.OnDayTimer(true, isContinueDay, t) } // 跨月 inSameMoney := common.InSameMonth(tNow, tLastLogout) if !inSameMoney { this.OnMonthTimer() } // 跨周 inSameWeek := common.InSameWeek(tNow, tLastLogout) if !inSameWeek { this.OnWeekTimer() } this.SetOnline() //测试用 if this.IsRob { this.VIP = rand.Int31n(6) + 1 //机器人随机vip和头像 this.RobRandVip() } this.VipExtra = VipMgrSington.GetVipPointsExtra(this.Platform, this.VIP) // 头像决定性别 this.Sex = (this.Head%2 + 1) % 2 // 初始化差异数据 this.BackDiffData() this.BindGroupTag([]string{this.Platform}) this.RandRobotExData() if !this.IsRob { if isFirstLogin { cfg := PlatformMgrSingleton.GetConfig(this.Platform).GuideConfig var info *webapi.GuideInfo for _, v := range cfg.GetInfo() { if v.GetGuideId() == common.GuideIdNewPlayer { info = v break } } if info == nil || info.GetOn() != common.On { this.GuideStep = -1 } } this.SendJackPotInit() this.DealShopLog() PlayerOnlineSington.Check = true this.LoadMessage(tLastLogout.Unix(), isFirstLogin, !inSameWeek) //登录次数 this.LoginTimes++ //登录事件 this.ReportLoginEvent() //抽奖次数兼容老玩家 if !this.InitLotteryStatus && WelfareMgrSington.GetPhoneLotteryStatus(this.Platform) == model.WelfareOpen { this.addLotteryCount(20) this.InitLotteryStatus = true this.dirty = true mq.Write(model.GeneratePhoneLottery(this.SnId, this.Platform, "", 3, 20, 5, 0)) } //登录日志 logState := LoginStateMgrSington.GetLoginStateBySid(this.sid) var clog *model.ClientLoginInfo if logState != nil { clog = logState.clog } mq.Write(model.NewLoginLog(this.SnId, common.LoginLogTypeLogin, this.Tel, this.Ip, this.Platform, this.Channel, this.BeUnderAgentCode, this.PackageID, this.City, clog, this.GetTotalCoin(), 0, 0, this.DeviceName, this.PackageName, this.AppVersion, this.BuildVersion, this.AppChannel, this.ChannelId, this.ClientVer)) this.OnlineLogLogin() //红点检测 this.CheckShowRed() TaskSubjectSingleton.Touch(common.TaskTypeLogin, &TaskData{SnId: this.SnId, Num: 1}) // 登录游戏 this.LoadAfter() } } func (this *Player) OnRehold() { logger.Logger.Tracef("(this *Player) OnRehold() %v", this.SnId) this.SetOnline() var gameid int if this.scene != nil && this.scene.gameSess != nil { // 告诉游戏服务玩家重连 var gateSid int64 if this.gateSess != nil { if srvInfo, ok := this.gateSess.GetAttribute(srvlib.SessionAttributeServerInfo).(*srvlibproto.SSSrvRegiste); ok && srvInfo != nil { sessionId := srvlib.NewSessionIdEx(srvInfo.GetAreaId(), srvInfo.GetType(), srvInfo.GetId(), 0) gateSid = sessionId.Get() } } pack := &serverproto.WGPlayerRehold{ Id: proto.Int32(this.SnId), Sid: proto.Int64(this.sid), SceneId: proto.Int(this.scene.sceneId), GateSid: proto.Int64(gateSid), } proto.SetDefaults(pack) this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_PLAYERREHOLD), pack) logger.Logger.Tracef("WG PlayerRehold: %v", pack) //} gameid = this.scene.gameId } this.BindGroupTag([]string{this.Platform}) //登录事件 this.ReportLoginEvent() FriendMgrSingleton.ApplyList(this.Platform, this.SnId) FriendUnreadMgrSington.CheckSendFriendUnreadData(this.Platform, this.SnId) if !this.IsRob { TournamentMgr.Quit(this.Platform, this.SnId) // 比赛没有开始,退赛 this.SendJackPotInit() PlayerOnlineSington.Check = true this.DealShopLog() this.CheckShowRed() // 记录重连日志 logState := LoginStateMgrSington.GetLoginStateBySid(this.sid) var clog *model.ClientLoginInfo if logState != nil { clog = logState.clog } mq.Write(model.NewLoginLog(this.SnId, common.LoginLogTypeRehold, this.Tel, this.Ip, this.Platform, this.Channel, this.BeUnderAgentCode, this.PackageID, this.City, clog, this.GetTotalCoin(), gameid, 0, this.DeviceName, this.PackageName, this.AppVersion, this.BuildVersion, this.AppChannel, this.ChannelId, this.ClientVer)) this.OnlineLogRehold() } } func (this *Player) CheckShowRed() { // 邮件红点 this.MessageShowRed() //商城红点 ShopMgrSington.ShopCheckShowRed(this) //数据依赖于背包数据 放入加载背包数据之后执行 ModelMgrSingleton.CheckShowRed(this) // 皮肤红点 ModelMgrSingleton.CheckSkinRed(this) //福利红点 WelfareMgrSington.WelfareShowRed(this) // 排行赛红点 RankMgrSingleton.CheckShowRed(this.SnId) } // 为了worldsrv和gamesrv上机器人信息一致 func (this *Player) RandRobotExData() { if !this.IsRob { return } // 角色 datas := srvdata.PBDB_Game_IntroductionMgr.Datas.GetArr() if datas != nil { //随机 //var roles = []int32{} //for _, data := range datas { // if data.Type == 1 { //角色 // roles = append(roles, data.Id) // } //} //if roles != nil && len(roles) > 0 { // randId := common.RandInt32Slice(roles) // this.Roles = new(model.ModInfo) // this.Roles.ModUnlock = make(map[int32]int32) // this.Roles.ModUnlock[randId] = 1 // this.Roles.ModId = randId //} //女8男2 rand := common.RandInt(100) randId := int32(2000001) if rand < 20 { randId = 2000002 } this.Roles = new(model.ModInfo) this.Roles.ModUnlock = make(map[int32]int32) this.Roles.ModUnlock[randId] = 1 this.Roles.ModId = randId } // 宠物 // datas := srvdata.PBDB_Game_IntroductionMgr.Datas.GetArr() // if datas != nil { // var pets = []int32{} // for _, data := range datas { // if data.Type == 2 { //宠物 // pets = append(pets, data.Id) // } // } // if pets != nil && len(pets) > 0 { // randId := common.RandInt32Slice(pets) // this.Pets = new(model.ModInfo) // this.Pets.ModUnlock = make(map[int32]int32) // this.Pets.ModUnlock[randId] = 1 // this.Pets.ModId = randId // } // } } // SendGameConfig 玩家断线重连时,获取玩家所有游戏的配置信息 func (this *Player) SendGameConfig(gameId int32, plf, chl string) { pack := &hallproto.SCGetGameConfig{ GameId: gameId, } gps := PlatformMgrSingleton.GetGameFrees(this.Platform) for _, v := range gps { if v.Status && PlatformMgrSingleton.GetGlobalConfig().GameStatus[v.DbGameFree.Id] { if v.DbGameFree.GetGameRule() != 0 && v.DbGameFree.GetGameId() == gameId { // 场次配置 lgc := &hallproto.GameConfig1{ LogicId: proto.Int32(v.DbGameFree.Id), LimitCoin: proto.Int64(v.DbGameFree.GetLimitCoin()), MaxCoinLimit: proto.Int64(v.DbGameFree.GetMaxCoinLimit()), BaseScore: proto.Int32(v.DbGameFree.GetBaseScore()), BetScore: proto.Int32(v.DbGameFree.GetBetLimit()), OtherIntParams: v.DbGameFree.GetOtherIntParams(), MaxBetCoin: v.DbGameFree.GetMaxBetCoin(), MatchMode: proto.Int32(v.DbGameFree.GetMatchMode()), Status: v.Status, SceneType: v.DbGameFree.GetSceneType(), ChessGradeLimit: v.DbGameFree.GetChessGradeLimit(), RankType: v.DbGameFree.GetRankType(), SceneAdd: v.DbGameFree.GetSceneAdd(), } // 排位场参数 if v.DbGameFree.GetRankType() > 0 { lgc.RankType = v.DbGameFree.GetRankType() lgc.SceneAdd = v.DbGameFree.GetSceneAdd() } pack.GameCfg = append(pack.GameCfg, lgc) } } } // 游戏配置 if srvdata.GameFreeMgr.IsGameDif(gameId, common.GameDifChess) { cfg := ChessRankMgrSington.GetChessRankConfig(this.GetPlatform().Name, gameId) for _, v := range cfg.GetDatas() { pack.ChessRanks = append(pack.ChessRanks, &hallproto.ChessRankInfo{ Score: v.Score, Name: v.Name, }) } } this.SendToClient(int(hallproto.GameHallPacketID_PACKET_SC_GETGAMECONFIG), pack) logger.Logger.Tracef("SendGameConfig:%v", pack) } func (this *Player) LoadMessage(lastLogoutTime int64, isFirstLogin, isSkipWeek bool) { task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { //msgs, err := model.GetMessageByNotState(this.SnId, model.MSGSTATE_REMOVEED) //if err == nil { // return msgs //} else { // logger.Logger.Warnf("[%v] LoadMessage err:%v", this.Name, err) //} msgs, err := model.GetMessage(this.Platform, this.SnId) // model.GetNotDelMessage(this.Platform, this.SnId) if err == nil { return msgs } else { logger.Logger.Warnf("[%v] LoadMessage err:%v", this.Name, err) } return nil }), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) { if data != nil { if msgs, ok := data.([]model.Message); ok { for i := 0; i < len(msgs); i++ { this.msgs[msgs[i].Id.Hex()] = &msgs[i] } } //跨周 邮件>0 if isSkipWeek && len(this.msgs) > 0 { //过期邮件处理 for key, msg := range this.msgs { if msg.AttachState == model.MSGATTACHSTATE_DEFAULT && msg.Ticket > 0 { this.TicketTotalDel += msg.Ticket this.DelMessage(key, 1) } } this.dirty = true } var dbMsgs []*model.Message //第一次登录需要屏蔽订阅的邮件 if !isFirstLogin { msgs := MsgMgrSington.GetSubscribeMsgs(this.Platform, lastLogoutTime) for _, msg := range msgs { bHasAddToPlayer := false for _, pMsg := range this.msgs { if pMsg.Pid == msg.Id.Hex() { bHasAddToPlayer = true break } } if bHasAddToPlayer == false { newMsg := model.NewMessage(msg.Id.Hex(), msg.SrcId, "", this.SnId, msg.MType, msg.Title, msg.Content, msg.Coin, msg.Diamond, model.MSGSTATE_UNREAD, msg.CreatTs, msg.AttachState, msg.GiftId, msg.Params, msg.Platform, msg.ShowId, msg.Channel) dbMsgs = append(dbMsgs, newMsg) } } } if len(dbMsgs) != 0 { task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { return model.InsertMessage(this.Platform, dbMsgs...) }), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) { if data == nil { for _, msg := range dbMsgs { bHasAddToPlayer := false for _, pMsg := range this.msgs { if pMsg.Pid == msg.Id.Hex() { bHasAddToPlayer = true break } } if bHasAddToPlayer == false { this.AddMessage(msg) } } // 邮件由客户端拉取 //this.SendMessage() } }), "InsertMessage").StartByFixExecutor("logic_message") } else { // this.SendMessage() } if len(this.msgs) > model.MSG_MAX_COUNT { maxTs := int64(0) for _, m := range this.msgs { if m.CreatTs > maxTs { maxTs = m.CreatTs } } this.verifyMessage(maxTs) } this.MessageShowRed() } }), "GetMessage").StartByFixExecutor("logic_message") } func (this *Player) SendMessage(showId int64) { pack := &msgproto.SCMessageList{} if len(this.msgs) != 0 { for _, msg := range this.msgs { if msg.State != model.MSGSTATE_REMOVEED && (msg.ShowId == model.HallAll || msg.ShowId&showId != 0) { if len(msg.Channel) > 0 && !common.InSliceString(msg.Channel, this.LastChannel) { continue } giftState := int32(0) //if len(msg.GiftId) > 0 { // gift := GiftMgrSington.GetFromRecvGift(this.SnId, msg.GiftId) // if gift != nil { // giftState = gift.State // } else { // logger.Logger.Error("player: ", this.SnId, " not find gift : ", msg.GiftId) // } //} pack.Msgs = append(pack.Msgs, &msgproto.MessageData{ Id: proto.String(msg.Id.Hex()), Title: proto.String(msg.Title), Content: proto.String(msg.Content), MType: proto.Int32(msg.MType), SrcId: proto.Int32(msg.SrcId), SrcName: proto.String(msg.SrcName), Coin: proto.Int64(msg.Coin), Diamond: proto.Int64(msg.Diamond), Ticket: proto.Int64(msg.Ticket), Grade: proto.Int64(msg.Grade), State: proto.Int32(msg.State), Ts: proto.Int32(int32(msg.CreatTs)), Params: common.CopySliceInt64ToInt32(msg.Params), //todo 修改协议 AttachState: proto.Int32(msg.AttachState), GiftId: proto.String(msg.GiftId), GiftState: proto.Int32(giftState), }) } } proto.SetDefaults(pack) } //nil的msg需要发给前端便于覆盖前一个玩家的信息 this.SendToClient(int(msgproto.MSGPacketID_PACKET_SC_MESSAGELIST), pack) } func (this *Player) ReadMessage(id string) { if msg, exist := this.msgs[id]; exist { if msg.State == model.MSGSTATE_UNREAD { msg.State = model.MSGSTATE_READED task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { return model.ReadMessage(msg.Id, msg.Platform) }), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) { if data == nil { pack := &msgproto.SCMessageRead{ Id: proto.String(id), } proto.SetDefaults(pack) this.SendToClient(int(msgproto.MSGPacketID_PACKET_SC_MESSAGEREAD), pack) } }), "ReadMessage").StartByFixExecutor("logic_message") } } } func (this *Player) WebDelMessage(id string) { if msg, exist := this.msgs[id]; exist { if msg.State != model.MSGSTATE_REMOVEED { // 未删除状态通知客户端 pack := &msgproto.SCMessageDel{ Id: id, } proto.SetDefaults(pack) this.SendToClient(int(msgproto.MSGPacketID_PACKET_SC_MESSAGEDEL), pack) } //删除此邮件 delete(this.msgs, id) } } func (this *Player) DelMessage(id string, del int32) bool { if msg, exist := this.msgs[id]; exist { if msg.State != model.MSGSTATE_REMOVEED { task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { args := &model.DelMsgArgs{ Platform: msg.Platform, Id: msg.Id, Del: del, } return model.DelMessage(args) }), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) { if data == nil { pack := &msgproto.SCMessageDel{ Id: id, } proto.SetDefaults(pack) this.SendToClient(int(msgproto.MSGPacketID_PACKET_SC_MESSAGEDEL), pack) msg.State = model.MSGSTATE_REMOVEED //删除此邮件 delete(this.msgs, id) } }), "DelMessage").StartByFixExecutor("logic_message") return true } } return false } func (this *Player) MessageShowRed() { msgMap := make(map[int64]int) for _, msg := range this.msgs { if msg.State == model.MSGSTATE_UNREAD || (msg.State == model.MSGSTATE_READED && msg.AttachState == model.MSGATTACHSTATE_DEFAULT && (msg.Coin > 0 || msg.Diamond > 0 || len(msg.Params) > 0)) { if len(msg.Channel) > 0 && !common.InSliceString(msg.Channel, this.LastChannel) { continue } if msg.ShowId == model.HallAll { msgMap[model.HallMain] = 1 msgMap[model.HallTienlen] = 1 msgMap[model.HallFish] = 1 } else { msgMap[msg.ShowId] = 1 } } } for showId := range msgMap { this.SendShowRed(hallproto.ShowRedCode_Mail, int32(showId), 1) } } func (this *Player) AddMessage(msg *model.Message) { if msg == nil { return } if len(msg.Channel) > 0 && !common.InSliceString(msg.Channel, this.LastChannel) { return } if _, exist := this.msgs[msg.Id.Hex()]; !exist { this.msgs[msg.Id.Hex()] = msg //giftState := int32(0) //if len(msg.GiftId) > 0 { // gift := GiftMgrSington.GetFromRecvGift(this.SnId, msg.GiftId) // if gift != nil { // giftState = gift.State // } else { // logger.Logger.Error("player: ", this.SnId, " not find gift : ", msg.GiftId) // } //} //pack := &msg_proto.SCMessageAdd{ // Msg: &msg_proto.MessageData{ // Id: proto.String(msg.Id.Hex()), // Title: proto.String(msg.Title), // Content: proto.String(msg.Content), // MType: proto.Int32(msg.MType), // SrcId: proto.Int32(msg.SrcId), // SrcName: proto.String(msg.SrcName), // Coin: proto.Int64(msg.Coin), // Ticket: proto.Int64(msg.Ticket), // Grade: proto.Int64(msg.Grade), // State: proto.Int32(msg.State), // Ts: proto.Int32(int32(msg.CreatTs)), // Params: msg.Params, // AttachState: proto.Int32(msg.AttachState), // GiftId: proto.String(msg.GiftId), // GiftState: proto.Int32(giftState), // }, //} // //proto.SetDefaults(pack) //this.SendToClient(int(msg_proto.MSGPacketID_PACKET_SC_MESSAGEADD), pack) //if len(this.msgs) > model.MSG_MAX_COUNT { //如果邮件达到上限,删除最旧的一封邮件,调整一下,如果有附件没有领取,就不删除 // OldestKeyId := msg.Id.Hex() this.verifyoneMessage(msg) // 最新的一封时间最大 //} msgMap := make(map[int64]int) if msg.ShowId == model.HallAll { msgMap[model.HallMain] = 1 msgMap[model.HallTienlen] = 1 msgMap[model.HallFish] = 1 } else { msgMap[msg.ShowId] = 1 } for showId := range msgMap { this.SendShowRed(hallproto.ShowRedCode_Mail, int32(showId), 1) } } } func (this *Player) verifyoneMessage(msg *model.Message) { var len int for _, m := range this.msgs { if m.ShowId == model.HallAll || m.ShowId&msg.ShowId != 0 { len++ } } OldestKeyId := msg.Id.Hex() OldestCreatTs := msg.CreatTs if len > model.MSG_MAX_COUNT { for id, m := range this.msgs { if m.ShowId == model.HallAll || m.ShowId&msg.ShowId != 0 { if m.CreatTs < OldestCreatTs { OldestCreatTs = m.CreatTs OldestKeyId = id } } } this.DelMessage(OldestKeyId, 1) } } func (this *Player) verifyMessage(maxCreatTs int64) { var OldmainKeyId, OldsunKeyId []string var mainnum, sunnum int for id, m := range this.msgs { if m.CreatTs < maxCreatTs { if m.ShowId == model.HallAll || m.ShowId&model.HallMain != 0 { mainnum++ } else { sunnum++ } if mainnum > model.MSG_MAX_COUNT { // 主大厅 OldmainKeyId = append(OldmainKeyId, id) } else if sunnum > model.MSG_MAX_COUNT { // 子大厅 OldsunKeyId = append(OldsunKeyId, id) } /*if (m.Coin <= 0 && m.Ticket <= 0 && m.Grade <= 0) || m.AttachState == model.MSGATTACHSTATE_GOT { OldestCreatTs = m.CreatTs }*/ } } for _, id := range OldmainKeyId { this.DelMessage(id, 1) } for _, id := range OldsunKeyId { this.DelMessage(id, 1) } } func (this *Player) TestMail() { var newMsg *model.Message task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { var otherParams []int64 otherParams = append(otherParams, 10001, 3) otherParams = append(otherParams, 20001, 3) otherParams = append(otherParams, 20002, 3) newMsg = model.NewMessage("", 0, "", this.SnId, model.MSGTYPE_ITEM, "系统通知道具test", "测试", 100000, 100, model.MSGSTATE_UNREAD, time.Now().Unix(), 0, "", otherParams, this.Platform, 0, nil) return model.InsertMessage(this.Platform, newMsg) }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { if data == nil { this.AddMessage(newMsg) } }), "TestSendMessage").Start() } func (this *Player) TestSubMail() { var newMsg *model.Message task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { var otherParams []int64 otherParams = append(otherParams, 10001, 3) otherParams = append(otherParams, 20001, 3) otherParams = append(otherParams, 20002, 3) newMsg = model.NewMessage("", 0, "", 0, model.MSGTYPE_ITEM, "系统", "测试", 100000, 100, model.MSGSTATE_UNREAD, time.Now().Unix(), 0, "", otherParams, this.Platform, model.HallTienlen, nil) return model.InsertMessage(this.Platform, newMsg) }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { if data == nil { MsgMgrSington.AddMsg(newMsg) } }), "TestSubSendMessage").Start() } func (this *Player) GetMessageAttach(id string) { if msg, exist := this.msgs[id]; exist { if msg.AttachState == model.MSGATTACHSTATE_DEFAULT && (msg.Coin > 0 || msg.Ticket > 0 || msg.Grade > 0 || len(msg.Params) > 0 || msg.Diamond > 0) { task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { gift, err := model.GetMessageById(msg.Id.Hex(), msg.Platform) if err != nil || gift == nil { return nil } if gift.AttachState == model.MSGATTACHSTATE_GOT { return nil } err = model.GetMessageAttach(msg.Id, msg.Platform) if err != nil { return nil } return gift }), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) { attachMsg, ok := data.(*model.Message) if ok && attachMsg != nil { msg.AttachState = model.MSGATTACHSTATE_GOT var remark string var gainWay int32 = common.GainWay_MessageAttach // 领取道具 addItem := func() { items := make([]*model.Item, 0) if num := len(msg.Params); num > 0 && num%2 == 0 { for i := 0; i < num; i += 2 { items = append(items, &model.Item{ ItemId: int32(msg.Params[i]), // 物品id ItemNum: msg.Params[i+1], // 数量 ObtainTime: time.Now().Unix(), }) tp := int32(-1) switch msg.Params[i] { case common.ItemIDCoin: tp = model.SystemFreeGive_CoinType_Coin case common.ItemIDDiamond: tp = model.SystemFreeGive_CoinType_Diamond default: tp = model.SystemFreeGive_CoinType_Tiem } if tp != -1 { giveType := int32(-1) switch gainWay { case common.GainWayItemPermitRank: giveType = model.SystemFreeGive_GiveType_TaskPermitRank case common.GainWayClientUpgrade: giveType = model.SystemFreeGive_ClientUpgrade } if giveType != -1 && msg.Oper == 0 && !this.IsRob { mq.Write(model.GenerateSystemFreeGive(this.SnId, this.Name, this.Platform, this.Channel, giveType, tp, msg.Params[i+1])) } } } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: items, GainWay: gainWay, Operator: "mail", Remark: remark, }) this.dirty = true } } switch msg.MType { case model.MSGTYPE_ITEM: remark = "领取道具" gainWay = common.GainWay_MAIL_MTEM addItem() case model.MSGTYPE_IOSINSTALLSTABLE: remark = "IOS下载稳定版本" gainWay = common.GainWay_IOSINSTALLSTABLE case model.MSGTYPE_GIFT: remark = "礼物" case model.MSGTYPE_GOLDCOMERANK: remark = "财神降临奖励" gainWay = common.GainWay_GoldCome case model.MSGTYPE_RANDCOIN: remark = "红包雨" gainWay = common.GainWay_OnlineRandCoin case model.MSGTYPE_REBATE: remark = "流水返利" gainWay = common.GainWay_RebateTask //邮件领取 添加日志 task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { return model.InsertRebateLog(this.Platform, &model.Rebate{ SnId: this.SnId, RebateCoin: msg.Coin, ReceiveType: 1, CodeCoin: 0, }) }), nil, "InsertRebateLog").StartByFixExecutor("ReceiveCodeCoin") case model.MSGTYPE_ClubGet: //if len(msg.Params) != 0 { // //如果俱乐部解散 就存msg.Params[0] // remark = fmt.Sprintf("%v", msg.Params[0]) //} //gainWay = common.GainWay_ClubGetCoin //dirtyCoin = msg.Coin case model.MSGTYPE_ClubPump: //if len(msg.Params) != 0 { // remark = fmt.Sprintf("%v", msg.Params[0]) //} //gainWay = common.GainWay_ClubPumpCoin //notifyClient = false //dirtyCoin = msg.Coin case model.MSGTYPE_MATCH_SIGNUPFEE: gainWay = common.GainWay_MatchBreakBack case model.MSGTYPE_MATCH_TICKETREWARD: gainWay = common.GainWay_MatchSystemSupply this.TicketTotal += msg.Ticket case model.MSGTYPE_MATCH_SHOPEXCHANGE: remark = "积分商城兑换" gainWay = common.GainWay_Exchange case model.MSGTYPE_MATCH_SHOPERETURN: remark = "撤单返还" gainWay = common.GainWay_GradeShopReturn case model.MSGTYPE_RANK_REWARD: remark = "排位赛段位奖励" gainWay = common.GainWay_RankMatch addItem() case model.MSGTYPE_RANK_PermitReward: remark = "通行证排行奖励" gainWay = common.GainWayItemPermitRank addItem() case model.MSGTYPE_ClientUpgrade: remark = "客户端升级奖励" gainWay = common.GainWayClientUpgrade addItem() case model.MSGTYPE_Lottery: remark = "竞技管抽奖" gainWay = common.GainWayLottery addItem() } if msg.Coin > 0 { this.AddCoin(msg.Coin, 0, gainWay, msg.Id.Hex(), remark) this.AddPayCoinLog(msg.Coin, model.PayCoinLogType_Coin, "mail") if msg.Oper == 0 { //系统赠送 if !this.IsRob { mq.Write(model.GenerateSystemFreeGive(this.SnId, this.Name, this.Platform, this.Channel, model.SystemFreeGive_GiveType_MailSystemGive, model.SystemFreeGive_CoinType_Coin, int64(msg.Coin))) } } } if msg.Ticket > 0 { //增加报名券 this.AddTicket(msg.Ticket, gainWay, msg.Id.Hex(), remark) } if msg.Grade > 0 { //增加积分 this.AddGrade(msg.Grade, gainWay, msg.Id.Hex(), remark) } if msg.Diamond > 0 { this.AddDiamond(msg.Diamond, 0, gainWay, msg.Id.Hex(), remark) if msg.Oper == 0 { //系统赠送 if !this.IsRob { mq.Write(model.GenerateSystemFreeGive(this.SnId, this.Name, this.Platform, this.Channel, model.SystemFreeGive_GiveType_MailSystemGive, model.SystemFreeGive_CoinType_Diamond, int64(msg.Diamond))) } } } pack := &msgproto.SCGetMessageAttach{ Id: proto.String(id), } proto.SetDefaults(pack) this.SendToClient(int(msgproto.MSGPacketID_PACKET_SC_GETMESSAGEATTACH), pack) } }), "GetMessageAttach").StartByFixExecutor("logic_message") } } } func (this *Player) GetMessageByGiftId(id string) *model.Message { for _, msg := range this.msgs { if msg.GiftId == id && msg.State != model.MSGSTATE_REMOVEED { return msg } } return nil } func (this *Player) IsOnLine() bool { return this.state == PlayerStateOnline } func (this *Player) SetOnline() { this.state = PlayerStateOnline } func (this *Player) IsOffline() bool { return this.state != PlayerStateOnline } func (this *Player) SetOffline() { this.state = PlayerStateOffline this.UpdateLastLogoutTime() } func (this *Player) IsCacheState() bool { return this.state == PlayerStateCache } func (this *Player) UpdateLastLogoutTime() { this.PlayerData.LastLogoutTime = time.Now() } // Kick 踢掉线 func (this *Player) Kick(reason int32) { if this.IsOnLine() { logger.Logger.Trace("(this *Player) Kick()", this.SnId) scDisconnect := &loginproto.SSDisconnect{ SessionId: proto.Int64(this.sid), Type: proto.Int32(reason), } this.SendToClient(int(loginproto.GatePacketID_PACKET_SS_DICONNECT), scDisconnect) LoginStateMgrSington.LogoutBySid(this.sid) this.DropLine() internal.FirePlayerDropLine[*Player, *Scene](this) } TournamentMgr.ForceQuit(this.Platform, this.SnId) } // DropLine 掉线 // 1.玩家登出 // 2.玩家网络断开 // 3.被踢掉线 func (this *Player) DropLine() { logger.Logger.Tracef("(this *Player) DropLine() %v", this.SnId) if !this.IsRob { TournamentMgr.Quit(this.Platform, this.SnId) // 记录掉线日志 logState := LoginStateMgrSington.GetLoginStateBySid(this.sid) var clog *model.ClientLoginInfo if logState != nil { clog = logState.clog } var gameid int if this.scene != nil && this.scene.gameSess != nil { gameid = this.scene.gameId } mq.Write(model.NewLoginLog(this.SnId, common.LoginLogTypeDrop, this.Tel, this.Ip, this.Platform, this.Channel, this.BeUnderAgentCode, this.PackageID, this.City, clog, this.GetTotalCoin(), gameid, this.LastGameId, this.DeviceName, this.PackageName, this.AppVersion, this.BuildVersion, this.AppChannel, this.ChannelId, this.ClientVer)) this.SendPlayerCoin() this.OnlineLogDrop() PlayerOnlineSington.Check = true } if this.scene != nil && this.scene.gameSess != nil { pack := &serverproto.WGPlayerDropLine{ Id: proto.Int32(this.SnId), SceneId: proto.Int(this.scene.sceneId), } proto.SetDefaults(pack) this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_PLAYERDROPLINE), pack) } FriendMgrSingleton.UpdateLogoutTime(this.Platform, this.SnId) PlayerMgrSington.DropPlayer(this) } // Logout 主动登出 func (this *Player) Logout() { logger.Logger.Tracef("(this *Player) Logout() %v", this.SnId) scLogout := &loginproto.SCLogout{ OpRetCode: loginproto.OpResultCode_OPRC_Sucess, } this.SendToClient(int(loginproto.LoginPacketID_PACKET_SC_LOGOUT), scLogout) FriendMgrSingleton.UpdateLogoutTime(this.Platform, this.SnId) PlayerMgrSington.DropPlayer(this) } // OnLogoutFinish 玩家登出完成 func (this *Player) OnLogoutFinish() { logger.Logger.Tracef("(this *Player) OnLogoutFinish() %v", this.SnId) if !this.IsRobot() { FriendUnreadMgrSington.SaveFriendUnreadData(this.Platform, this.SnId) PlayerOnlineSington.Check = true //登录日志 logState := LoginStateMgrSington.GetLoginStateBySid(this.sid) var clog *model.ClientLoginInfo if logState != nil { clog = logState.clog } mq.Write(model.NewLoginLog(this.SnId, common.LoginLogTypeLogout, this.Tel, this.Ip, this.Platform, this.Channel, this.BeUnderAgentCode, this.PackageID, this.City, clog, this.GetTotalCoin(), 0, 0, this.DeviceName, this.PackageName, this.AppVersion, this.BuildVersion, this.AppChannel, this.ChannelId, this.ClientVer)) this.OnlineLogLogout() } } func (this *Player) MarshalData() (d []byte, e error) { data := &model.WGPlayerInfo{ PlayerData: this.PlayerData, } info := PlayerInfoMgrSingle.Players[this.SnId] if info != nil { data.GameData = info.GameData } d, e = netlib.Gob.Marshal(data) return } // UnmarshalData 更新玩家数据 // 例如游戏服数据同步 func (this *Player) UnmarshalData(data []byte, scene *Scene) { pd := &model.WGPlayerInfo{} if err := netlib.Gob.Unmarshal(data, pd); err != nil { logger.Logger.Warn("Player.SyncData err:", err) return } // GDatas 同步 for _, v := range []string{ strconv.Itoa(int(scene.dbGameFree.GetId())), strconv.Itoa(int(scene.dbGameFree.GetGameId())), common.GetKeyNoviceGameId(int(scene.dbGameFree.GetGameId())), common.GetKeyGameType(int(scene.dbGameFree.GetGameType())), } { if d, ok := pd.GDatas[v]; ok { this.GDatas[v] = d } } // PlayerInfo 同步 info := PlayerInfoMgrSingle.Players[this.SnId] if info == nil { info = &PlayerInfo{} PlayerInfoMgrSingle.Players[this.SnId] = info } info.GameData = pd.GameData this.LastRechargeWinCoin = pd.LastRechargeWinCoin oldRecharge := int64(0) oldExchange := int64(0) if this.PlayerData.TodayGameData != nil { oldRecharge = this.PlayerData.TodayGameData.RechargeCoin oldExchange = this.PlayerData.TodayGameData.ExchangeCoin } this.PlayerData.TodayGameData = pd.TodayGameData if this.PlayerData.TodayGameData != nil { this.PlayerData.TodayGameData.RechargeCoin = oldRecharge this.PlayerData.TodayGameData.ExchangeCoin = oldExchange } this.PlayerData.YesterdayGameData = pd.YesterdayGameData this.PlayerData.IsFoolPlayer = pd.IsFoolPlayer //this.PlayerData.TotalGameData = pd.TotalGameData this.PlayerData.WinTimes = pd.WinTimes this.PlayerData.FailTimes = pd.FailTimes this.PlayerData.DrawTimes = pd.DrawTimes this.PlayerData.WinCoin = pd.WinCoin this.PlayerData.FailCoin = pd.FailCoin this.PlayerData.TotalIn = pd.TotalIn this.PlayerData.TotalOut = pd.TotalOut this.PlayerData.ChessGrade = pd.ChessGrade this.PlayerData.MoneyPond = pd.MoneyPond this.PlayerData.Level = pd.Level this.PlayerData.Exp = pd.Exp this.PlayerData.UnMaxPower = pd.UnMaxPower this.PlayerData.PowerList = pd.PowerList this.PlayerData.PlayerTax = pd.PlayerTax this.PlayerData.TotalFlow = pd.TotalFlow if this.WelfData != nil && this.WelfData.PigBank != nil && pd.WelfData != nil && pd.WelfData.PigBank != nil { this.WelfData.PigBank.BankCoin = pd.WelfData.PigBank.BankCoin this.WelfData.PigBank.TakeTimes = pd.WelfData.PigBank.TakeTimes this.WelfData.PigBank.DayBuyTimes = pd.WelfData.PigBank.DayBuyTimes } this.ItemRecExpireTime = pd.ItemRecExpireTime this.IsTakeExpireItem = pd.IsTakeExpireItem this.dirty = true } func (this *Player) MarshalIParam() []*serverproto.PlayerIParam { var params []*serverproto.PlayerIParam for i, v := range this.Iparams { params = append(params, &serverproto.PlayerIParam{ ParamId: proto.Int(i), IntVal: proto.Int64(v), }) } return params } func (this *Player) UnmarshalIParam(params []*serverproto.PlayerIParam) { for _, p := range params { this.Iparams[int(p.GetParamId())] = p.GetIntVal() } } func (this *Player) MarshalSParam() []*serverproto.PlayerSParam { var params []*serverproto.PlayerSParam for i, v := range this.sparams { params = append(params, &serverproto.PlayerSParam{ ParamId: proto.Int(i), StrVal: proto.String(v), }) } return params } func (this *Player) UnmarshalSParam(params []*serverproto.PlayerSParam) { for _, p := range params { this.sparams[int(p.GetParamId())] = p.GetStrVal() } } func (this *Player) MarshalCParam() []*serverproto.PlayerCParam { var params []*serverproto.PlayerCParam for k, v := range this.cparams { params = append(params, &serverproto.PlayerCParam{ StrKey: proto.String(k), StrVal: proto.String(v), }) } return params } func (this *Player) Time2Save() { if this == nil { return } PlayerMgrSington.SavePlayer(this, true, false) if this.isDelete || (!this.IsOnLine() && !this.dirty && time.Now().Sub(this.lastSaved) > time.Minute*5 && this.scene == nil) { PlayerMgrSington.DelPlayer(this.SnId) } } func (this *Player) GetCoin() int64 { return this.Coin } // AddDiamond 添加钻石 // num 总数 // add num总数中有多少是加成获得 func (this *Player) AddDiamond(num, add int64, gainWay int32, oper, remark string) { if num == 0 { return } logger.Logger.Tracef("snid(%v) AddDiamond(%v)", this.SnId, num) this.dirty = true if num > 0 { this.Diamond += num } else { if -num > this.Diamond { logger.Logger.Errorf("Player.AddCoin exception!!! num(%v) oper(%v)", num, oper) num = -this.Diamond this.Diamond = 0 } else { this.Diamond += num } switch gainWay { case common.GainWay_MatchSignup: // 排除的 default: TaskSubjectSingleton.Touch(common.TaskTypeCostDiamond, &TaskData{ SnId: this.SnId, Num: -num, }) } } this.SendDiffData() if !this.IsRob { log := model.NewCoinLogEx(&model.CoinLogParam{ Platform: this.Platform, SnID: this.SnId, UserName: this.Username, Channel: this.Channel, ChangeType: common.BillTypeDiamond, ChangeNum: num, RemainNum: this.Diamond, Add: add, LogType: gainWay, GameID: 0, GameFreeID: 0, BaseCoin: 0, Operator: oper, Remark: remark, }) if log != nil { mq.Write(log) } } } // AddCoin 添加钻石 // num 总数 // add num总数中有多少是加成获得 func (this *Player) AddCoin(num, add int64, gainWay int32, oper, remark string, param ...string) { if num == 0 { return } logger.Logger.Tracef("snid(%v) AddCoin(%v)", this.SnId, num) //this.TotalData(num, gainWay) async := false if num > 0 && this.scene != nil && !this.scene.IsTestScene() && !this.scene.IsMatchScene() && !this.scene.IsCustom() && this.scene.sceneMode != common.SceneModeThr { //游戏场中加币,需要同步到gamesrv上 if StartAsyncAddCoinTransact(this, num, gainWay, oper, remark, true, 0, true) { async = true } } if num != 0 && !async { this.dirty = true if num > 0 { this.Coin += num } else { if -num > this.Coin { logger.Logger.Errorf("Player.AddCoin exception!!! num(%v) oper(%v)", num, oper) num = -this.Coin this.Coin = 0 } else { this.Coin += num } } this.SendDiffData() if !this.IsRob { var transferID string if len(param) > 0 { transferID = param[0] } log := model.NewCoinLogEx(&model.CoinLogParam{ Platform: this.Platform, SnID: this.SnId, UserName: this.Username, Channel: this.Channel, ChangeType: common.BillTypeCoin, ChangeNum: num, RemainNum: this.Coin, Add: add, LogType: gainWay, GameID: 0, GameFreeID: 0, BaseCoin: 0, Operator: oper, Remark: remark, TransferID: transferID, }) if log != nil { mq.Write(log) } } } } func (this *Player) AddCoinAsync(num, add int64, gainWay int32, oper, remark string, broadcast bool, retryCnt int, writeLog bool) bool { if num == 0 { return false } //if retryCnt == 0 { // this.TotalData(num, gainWay) //} //玩家可能正在换房间 async := false if num > 0 && retryCnt < 3 && this.scene != nil && !this.scene.IsTestScene() && this.scene.sceneMode != common.SceneModeThr { //游戏场中加币,需要同步到gamesrv上 if StartAsyncAddCoinTransact(this, num, gainWay, oper, remark, broadcast, retryCnt, writeLog) { async = true } } if num != 0 && !async { this.dirty = true if num > 0 { this.Coin += num } else { if -num > this.Coin { logger.Logger.Errorf("Player.AddCoin exception!!! num(%v) oper(%v)", num, oper) num = -this.Coin this.Coin = 0 } else { this.Coin += num } } this.SendDiffData() if !this.IsRob && writeLog { log := model.NewCoinLogEx(&model.CoinLogParam{ Platform: this.Platform, SnID: this.SnId, UserName: this.Username, Channel: this.Channel, ChangeType: common.BillTypeCoin, ChangeNum: num, RemainNum: this.Coin, Add: add, LogType: gainWay, GameID: 0, GameFreeID: 0, BaseCoin: 0, Operator: oper, Remark: remark, }) if log != nil { mq.Write(log) } } } return async } func (this *Player) AddTicket(num int64, gainWay int32, oper, remark string) { if num == 0 { return } if num > 0 { this.Ticket += num } else { if -num > this.Ticket { logger.Logger.Errorf("Player.AddTicket exception!!! num(%v) oper(%v)", num, oper) num = -this.Ticket this.Ticket = 0 } else { this.Ticket += num } } if num != 0 { this.dirty = true this.diffData.Ticket = -1 this.SendDiffData() //restCnt := this.Ticket //log := model.NewTicketLogEx(this.SnId, num, restCnt, this.Ver, gainWay, oper, remark, this.Platform, this.Channel, this.BeUnderAgentCode, this.PackageID, this.InviterId) //if log != nil { // TicketLogChannelSington.Write(log) //} } } func (this *Player) AddGrade(num int64, gainWay int32, oper, remark string) { if num == 0 { return } if num > 0 { this.Grade += num } else { if -num > this.Grade { logger.Logger.Errorf("Player.AddGrade exception!!! num(%v) oper(%v)", num, oper) num = -this.Grade this.Grade = 0 } else { this.Grade += num } } if num != 0 { this.dirty = true this.diffData.Grade = -1 this.SendDiffData() //restCnt := this.Grade //log := model.NewGradeLogEx(this.SnId, num, restCnt, this.Ver, gainWay, oper, remark, this.Platform, this.Channel, this.BeUnderAgentCode, this.PackageID, this.InviterId) //if log != nil { // GradeLogChannelSington.Write(log) //} } } func (this *Player) AddChessScore(num int64) { if num == 0 { return } if num > 0 { this.ChessGrade += num } else { if -num > this.ChessGrade { logger.Logger.Errorf("Player.AddChessGrade exception!!! num(%v) oper(%v)", num) num = -this.ChessGrade this.ChessGrade = 0 } else { this.ChessGrade += num } } if num != 0 { this.dirty = true this.diffData.ChessGrade = -1 this.SendDiffData() //restCnt := this.Grade //log := model.NewGradeLogEx(this.SnId, num, restCnt, this.Ver, gainWay, oper, remark, this.Platform, this.Channel, this.BeUnderAgentCode, this.PackageID, this.InviterId) //if log != nil { // GradeLogChannelSington.Write(log) //} } } func (this *Player) OnSecTimer() { //BagMgrSingleton.AddMailByItem(this.Platform, this.SnId, this.Name, this.SnId, 1, []int32{60001, 12}) } func (this *Player) OnMiniTimer() { if this.IsOnLine() { TaskSubjectSingleton.Touch(common.TaskTypeOnlineTs, &TaskData{ SnId: this.SnId, Num: 60, }) } // 长时间掉线又没有删除缓存 if this.IsOffline() && time.Now().Sub(this.LastLogoutTime) > time.Hour*2 { logger.Logger.Warnf("清除缓存异常 snid:%v dirty:%v lastLogoutTime:%v lastGameId:%v", this.SnId, this.dirty, this.LastLogoutTime, this.LastGameId) } } func (this *Player) OnHourTimer() { } func (this *Player) OnDayTimer(login, continuous bool, t int) { // 校验,跨天操作一天之内只执行一次 if common.InSameDayNoZero(time.Now().Local(), this.lastOnDayChange) { return } this.lastOnDayChange = time.Now().Local() logger.Logger.Infof("(this *Player) (%v) OnDayTimer(%v,%v) ", this.SnId, login, continuous) this.dirty = true if login || this.scene == nil { //跨天登录 数据给昨天,今天置为空 this.YesterdayGameData = this.TodayGameData this.TodayGameData = model.NewPlayerGameCtrlData() /* for k, v := range this.YesterdayGameData.CtrlData { t := &model.PlayerGameStatics{} t.AvgBetCoin = v.AvgBetCoin this.TodayGameData.CtrlData[k] = t } */ } //this.OnTimeDayTotal(continuous, t) //商城数据更新 this.ShopTotal = make(map[int32]*model.ShopTotal) this.ShopLastLookTime = make(map[int32]int64) // 福利活动更新 WelfareMgrSington.OnDayChanged(this) this.VipMatchTimes = 0 //VIP商城数据更新 this.UpdateVipShopData() // 重置每日任务 if this.WelfData != nil { if this.WelfData.Task != nil { for _, v := range srvdata.TaskMgr.GetActivityType(common.TaskActivityTypeEveryDay) { this.WelfData.Task[v.GetId()] = &model.TaskData{} } for _, v := range srvdata.TaskMgr.GetActivityType(common.TaskActivityTypePermitEveryDay) { this.WelfData.Task[v.GetId()] = &model.TaskData{} } } } //周卡数据更新 this.WeekCardAward = make(map[int32]bool) //周卡领取奖励 now := time.Now().Unix() for id, endTime := range this.WeekCardTime { if endTime < now { this.WeekCardTime[id] = 0 continue } if this.WeekCardTime[id] == 0 { continue } if now > this.WeekCardTime[id] { logger.Logger.Trace("周卡已过期,不能领取!") continue } if !this.WeekCardAward[id] { this.GetWeekCardAwary(id) } } // 赛季通行证活动 this.ResetPermit() TaskSubjectSingleton.Touch(common.TaskTypeFirstLogin, &TaskData{SnId: this.SnId, Num: 1}) // 首次登录游戏 TaskSubjectSingleton.Touch(common.TaskTypeLogin, &TaskData{SnId: this.SnId, Num: 1}) // 登录游戏 } func (this *Player) ResetPermit() { permitStartTs := PlatformMgrSingleton.GetConfig(this.Platform).PermitStartTs if (this.PermitStartTs == 0 || this.PermitStartTs < permitStartTs) && permitStartTs > 0 { this.PermitStartTs = permitStartTs this.Permit = time.Time{} if this.WelfData == nil { this.WelfData = model.NewWelfareData() } this.WelfData.PermitAward = make(map[int32]int64) this.WelfData.PermitExchange = make(map[int32][]int64) if this.WelfData.Task != nil { for _, v := range srvdata.TaskMgr.GetActivityType(common.TaskActivityTypePermit) { this.WelfData.Task[v.GetId()] = &model.TaskData{} } } this.dirty = true // 清理数据 bag := BagMgrSingleton.GetBagInfo(this.SnId) if bag != nil { if bag.BagItem[common.ItemIDPermit] != nil { BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: []*model.Item{ { ItemId: common.ItemIDPermit, ItemNum: -bag.BagItem[common.ItemIDPermit].ItemNum, }, }, GainWay: common.GainWayPermitReset, Operator: "system", Remark: "赛季积分清理", }) } if model.GameParamData.PermitInitScore > 0 { bagInfo := BagMgrSingleton.GetBagInfo(this.SnId) if bagInfo != nil { bagInfo.BagItem[common.ItemIDPermit] = &Item{ ItemId: common.ItemIDPermit, ItemNum: model.GameParamData.PermitInitScore, ObtainTime: time.Now().Unix(), } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: []*model.Item{ { ItemId: common.ItemIDPermit, ItemNum: model.GameParamData.PermitInitScore, }, }, GainWay: common.GainWayPermitReset, Operator: "system", Remark: "初始赛季积分", }) this.Permit = time.Now() } } } } } //func (this *Player) OnTimeDayTotal(continuous bool, t int) { // for k, tgd := range this.TotalGameData { // for i := 0; i < t; i++ { // tgd = append(tgd, new(model.PlayerGameTotal)) // } // if len(tgd) > 30 { // tgd = tgd[len(tgd)-30:] // } // this.TotalGameData[k] = tgd // } //} func (this *Player) OnMonthTimer() { //判断是否一天即可过滤0点多次切换 if common.InSameDayNoZero(time.Now().Local(), this.lastOnMonthChange) { return } this.lastOnMonthChange = time.Now().Local() } func (this *Player) OnWeekTimer() { logger.Logger.Tracef("OnWeekTimer %v", time.Now()) //判断是否一天即可过滤0点多次切换 if common.InSameDayNoZero(time.Now().Local(), this.lastOnWeekChange) { return } this.lastOnWeekChange = time.Now().Local() //清理比赛券 ticket := this.Ticket if ticket > 0 { this.AddTicket(-ticket, common.GainWay_Expire, "system", "过期清理") this.TicketTotalDel += ticket this.dirty = true } if len(this.msgs) > 0 { //自然过渡执行 //过期邮件处理 var keysId []string for key, msg := range this.msgs { if msg.AttachState == model.MSGATTACHSTATE_DEFAULT && msg.Ticket > 0 { this.TicketTotalDel += msg.Ticket keysId = append(keysId, key) } } this.dirty = true for _, v := range keysId { this.DelMessage(v, 1) } } // 重置周任务 if this.WelfData != nil { if this.WelfData.Task != nil { for _, v := range srvdata.TaskMgr.GetActivityType(common.TaskActivityTypeWeek) { this.WelfData.Task[v.GetId()] = &model.TaskData{} } } } // 重置周任务 // 重置邀请积分 CheckNewWeek(this.Platform, this.SnId) } func (this *Player) GetName() string { return this.Name } func (this *Player) setName(newName string) string { this.Name = newName return this.Name } func (this *Player) GetIP() string { return this.Ip } func (this *Player) ReturnScene(isLoaded bool) *Scene { logger.Logger.Tracef("(this *Player) ReturnScene %v", this.SnId) if this.scene == nil { logger.Logger.Warnf("(this *Player) ReturnScene this.scene == nil snid:%d", this.SnId) return nil } if !this.scene.HasPlayer(this) && !this.scene.HasAudience(this) { logger.Logger.Warnf("(this *Player) ReturnScene !this.scene.HasPlayer(this) && !this.scene.HasAudience(this) snid:%d", this.SnId) return nil } pack := &serverproto.WGPlayerReturn{ PlayerId: proto.Int32(this.SnId), IsLoaded: proto.Bool(isLoaded), RoomId: proto.Int(this.scene.sceneId), } ctx := this.scene.GetPlayerGameCtx(this.SnId) if ctx != nil { pack.EnterTs = proto.Int64(ctx.enterTs) } proto.SetDefaults(pack) if this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_PLAYERRETURN), pack) { //比赛场返场检查 //MatchMgrSington.OnPlayerReturnScene(this.scene, this) return this.scene } //不应该这这里处理,因为 miniGame中小游戏玩家 player.Scene是不存在的。 //FirePlayerReturnScene(this) return nil } func (this *Player) BackDiffData() { this.diffData.Coin = this.Coin this.diffData.SafeBoxCoin = this.SafeBoxCoin } func (this *Player) AddMoneyPayTotal(amount int64) { if amount > 0 { this.MoneyPayTotal += amount this.GetVIPLevel() } } func (this *Player) SendDiffData() { var dirty bool pack := &playerproto.SCPlayerDataUpdate{} pack.UpdateField = 0 //金币 if this.diffData.Coin != this.Coin { dirty = true pack.Coin = proto.Int64(this.Coin) this.diffData.Coin = this.Coin pack.UpdateField += UpdateField_Coin } //钻石 if this.diffData.Diamond != this.Diamond { dirty = true pack.Diamond = proto.Int64(this.Diamond) this.diffData.Diamond = this.Diamond pack.UpdateField += UpdateField_Diamond } //保险箱金币 if this.diffData.SafeBoxCoin != this.SafeBoxCoin { dirty = true pack.SafeBoxCoin = proto.Int64(this.SafeBoxCoin) this.diffData.SafeBoxCoin = this.SafeBoxCoin pack.UpdateField += UpdateField_SafeBoxCoin } //VIP等级 if this.diffData.VIP != this.VIP { dirty = true pack.Vip = proto.Int32(this.VIP) this.diffData.VIP = this.VIP pack.UpdateField += UpdateField_VIP } //手机积分 if this.diffData.PhoneScore != this.PhoneScore { dirty = true pack.PhoneScore = this.PhoneScore this.diffData.PhoneScore = this.PhoneScore pack.UpdateField += UpdateField_PhoneScore } // 邀请积分 if this.diffData.InviteScore != this.IScore { dirty = true pack.InviteScore = this.IScore this.diffData.InviteScore = this.IScore pack.UpdateField += UpdateField_InviteScore } //总充值金额 if this.diffData.CoinPayTotal != this.CoinPayTotal { dirty = true pack.CoinPayTotal = proto.Int64(this.CoinPayTotal) this.diffData.CoinPayTotal = this.CoinPayTotal pack.UpdateField += UpdateField_CoinPayTotal } //流水差异 if this.diffData.TotalConvertibleFlow != this.TotalConvertibleFlow { dirty = true pack.TotalConvertibleFlow = proto.Int64(this.TotalConvertibleFlow) this.diffData.TotalConvertibleFlow = this.TotalConvertibleFlow pack.UpdateField += UpdateField_TotalConvertibleFlow } //比赛报名券 if this.diffData.Ticket != this.Ticket { dirty = true pack.Ticket = proto.Int64(this.Ticket) this.diffData.Ticket = this.Ticket pack.UpdateField += UpdateField_Ticket } //积分 if this.diffData.Grade != this.Grade { dirty = true pack.Grade = proto.Int64(this.Grade) this.diffData.Grade = this.Grade pack.UpdateField += UpdateField_Grade } //象棋积分 if this.diffData.ChessGrade != this.ChessGrade { dirty = true pack.ChessGrade = proto.Int64(this.ChessGrade) this.diffData.ChessGrade = this.ChessGrade pack.UpdateField += UpdateField_ChessGrade } // 排位积分 if this.diffData.RankScore == nil { this.diffData.RankScore = make(map[int32]int64) } if p := RankMgrSingleton.GetPlayerSeason(this.SnId); p != nil { for k := range p.RankType { if this.diffData.RankScore[k] != p.RankType[k].Score { dirty = true if pack.RankScore == nil { pack.RankScore = make(map[int32]int64) } pack.RankScore[k] = proto.Int64(p.RankType[k].Score) this.diffData.RankScore[k] = p.RankType[k].Score pack.UpdateField += UpdateField_RankScore } } } if len(pack.RankScore) == 0 { pack.RankScore = nil } if dirty { FriendMgrSingleton.UpdateInfo(this.Platform, this.SnId) this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_PLAYERDATAUPDATE), pack) logger.Logger.Trace("(this *Player) SendDiffData() ", pack) } } func GetExchangeFlow(pd *model.PlayerData) int32 { if pd == nil { return 0 } platform := PlatformMgrSingleton.GetPlatform(pd.Platform) if platform != nil { if (platform.ExchangeFlag & ExchangeFlag_Flow) != 0 { key, err := GetPromoterKey(pd.PromoterTree, pd.BeUnderAgentCode, pd.Channel) if err == nil { cfg := PromoterMgrSington.GetConfig(key) if cfg != nil { if (cfg.ExchangeFlag & ExchangeFlag_Flow) != 0 { return cfg.ExchangeFlow } } } return platform.ExchangeFlow } } return 0 } func GetExchangeGiveFlow(pd *model.PlayerData) int32 { if pd == nil { return 0 } platform := PlatformMgrSingleton.GetPlatform(pd.Platform) if platform != nil { if (platform.ExchangeFlag & ExchangeFlag_Flow) != 0 { key, err := GetPromoterKey(pd.PromoterTree, pd.BeUnderAgentCode, pd.Channel) if err == nil { cfg := PromoterMgrSington.GetConfig(key) if cfg != nil { if (cfg.ExchangeFlag & ExchangeFlag_Flow) != 0 { return cfg.ExchangeGiveFlow } } } return platform.ExchangeGiveFlow } } return 0 } func GetExchangeForceTax(pd *model.PlayerData) int32 { if pd == nil { return 0 } platform := PlatformMgrSingleton.GetPlatform(pd.Platform) if platform != nil { if (platform.ExchangeFlag & ExchangeFlag_Force) != 0 { key, err := GetPromoterKey(pd.PromoterTree, pd.BeUnderAgentCode, pd.Channel) if err == nil { cfg := PromoterMgrSington.GetConfig(key) if cfg != nil { if (cfg.ExchangeFlag & ExchangeFlag_Force) != 0 { return cfg.ExchangeForceTax } } } return platform.ExchangeForceTax } } return 0 } func GetExchangeTax(pd *model.PlayerData) int32 { if pd == nil { return 0 } platform := PlatformMgrSingleton.GetPlatform(pd.Platform) if platform != nil { if (platform.ExchangeFlag & ExchangeFlag_Tax) != 0 { key, err := GetPromoterKey(pd.PromoterTree, pd.BeUnderAgentCode, pd.Channel) if err == nil { cfg := PromoterMgrSington.GetConfig(key) if cfg != nil { if (cfg.ExchangeFlag & ExchangeFlag_Tax) != 0 { return cfg.ExchangeTax } } } return platform.ExchangeTax } } return 0 } func GetExchangeFlag(pd *model.PlayerData) int32 { if pd == nil { return 0 } platform := PlatformMgrSingleton.GetPlatform(pd.Platform) if platform != nil { if (platform.ExchangeFlag & ExchangeFlag_Flow) != 0 { key, err := GetPromoterKey(pd.PromoterTree, pd.BeUnderAgentCode, pd.Channel) if err == nil { cfg := PromoterMgrSington.GetConfig(key) if cfg != nil { if (cfg.ExchangeFlag & ExchangeFlag_Flow) != 0 { return 2 } } } return 1 } } return 0 } func (this *Player) GetRegisterPrize() int32 { platform := this.GetPlatform() key, err := this.GetPromoterKey() var cfg *PromoterConfig if err == nil { cfg = PromoterMgrSington.GetConfig(key) } return GGetRegisterPrize(platform, cfg) } func GGetRegisterPrize(platform *Platform, cfg *PromoterConfig) int32 { if platform != nil { if cfg != nil { if (cfg.ExchangeFlag & ExchangeFlag_UpAcc) != 0 { return cfg.NewAccountGiveCoin } } return platform.NewAccountGiveCoin } return 0 } func (this *Player) GetUpdateAccPrize() int32 { platform := this.GetPlatform() key, err := this.GetPromoterKey() var cfg *PromoterConfig if err == nil { cfg = PromoterMgrSington.GetConfig(key) } return GGetUpdateAccPrize(platform, cfg) } func GGetUpdateAccPrize(platform *Platform, cfg *PromoterConfig) int32 { if platform != nil { if cfg != nil { if (cfg.ExchangeFlag & ExchangeFlag_UpAcc) != 0 { return cfg.UpgradeAccountGiveCoin } } return platform.UpgradeAccountGiveCoin } return 0 } func (this *Player) GetPromoterKey() (string, error) { return GetPromoterKey(this.PromoterTree, this.BeUnderAgentCode, this.Channel) } func (this *Player) SendPlayerInfo() { scPlayerData := &playerproto.SCPlayerData{ OpRetCode: playerproto.OpResultCode_OPRC_Sucess, Data: &playerproto.PlayerData{ AccId: proto.String(this.AccountId), //账号ID Platform: proto.String(this.Platform), //平台 Channel: proto.String(this.Channel), //渠道 ChannelID: this.ChannelId, // 渠道id Promoter: proto.String(this.BeUnderAgentCode), //推广员 Name: proto.String(this.Name), //名字 SnId: proto.Int32(this.SnId), //数字账号 Head: proto.Int32(this.Head), //头像 Sex: proto.Int32(this.Sex), //性别 GMLevel: proto.Int32(this.GMLevel), //GM等级 Coin: proto.Int64(this.Coin), //金币 SpecailFlag: proto.Int32(int32(this.Flags)), //特殊标记 Tel: proto.String(this.Tel), //手机号码 InviterId: proto.Int32(this.InviterId), //邀请人ID SafeBoxCoin: proto.Int64(this.SafeBoxCoin), //保险箱金币 VIP: proto.Int32(this.VIP), //VIP帐号 AlipayAccount: proto.String(this.AlipayAccount), //支付宝账号 AlipayAccName: proto.String(this.AlipayAccName), //支付宝实名 Bank: proto.String(this.Bank), //银行 BankAccount: proto.String(this.BankAccount), //银行帐号 BankAccName: proto.String(this.BankAccName), //银行开户名 HeadOutLine: proto.Int32(this.HeadOutLine), //头像框 CoinPayTotal: proto.Int64(this.CoinPayTotal), //总充值金额 CreateTs: proto.Int64(this.CreateTime.Unix()), //角色创建时间 //ClubCoin: proto.Int64(this.ClubCoin), //俱乐部金币 Ticket: proto.Int64(this.Ticket), //比赛入场券 Grade: proto.Int64(this.Grade), //积分 Diamond: proto.Int64(this.Diamond), //钻石 HeadUrl: proto.String(this.HeadUrl), //VipExp: proto.Int64(this.GetCurrentVIPExp()), ChessGrade: proto.Int64(this.ChessGrade), RankScore: make(map[int32]int64), UnMaxPower: proto.Int64(this.UnMaxPower), PowerList: this.PowerList, Level: proto.Int64(this.Level), Exp: proto.Int64(this.Exp), VipShopRefreshCount: proto.Int32(this.VipShopRefreshCount), Signature: this.Signature, Age: this.Age, GuideStep: this.GuideStep, GuideData: this.GuideData, }, } if this.Roles != nil { scPlayerData.Data.UseRoleId = this.Roles.ModId } if this.Pets != nil { scPlayerData.Data.UsePetId = this.Pets.ModId } if this.Skin != nil { scPlayerData.Data.UseSkinId = this.Skin.ModId } if this.WelfData != nil { scPlayerData.Data.ReliefFundTimes = this.WelfData.ReliefFundTimes } if item := BagMgrSingleton.GetItem(this.SnId, common.ItemIDVCard); item != nil { scPlayerData.Data.VCoin = item.ItemNum //V卡 } // 排位积分 scPlayerData.Data.RankScore = RankMgrSingleton.GetPlayerRankScore(this.SnId) raw := fmt.Sprintf("%v%v", model.DEFAULT_PLAYER_SAFEBOX_PWD, common.GetAppId()) h := md5.New() io.WriteString(h, raw) pwd := hex.EncodeToString(h.Sum(nil)) if this.SafeBoxPassword != pwd { scPlayerData.Data.SafeBoxIsExist = proto.Int32(1) } else { scPlayerData.Data.SafeBoxIsExist = proto.Int32(0) } if this.scene != nil { scPlayerData.RoomId = proto.Int(this.scene.sceneId) scPlayerData.GameId = proto.Int(this.scene.gameId) //增加gameFreeId scPlayerData.LogicId = this.scene.dbGameFree.Id } platform := PlatformMgrSingleton.GetPlatform(this.Platform) if platform != nil { scPlayerData.BindOption = proto.Int32(platform.BindOption) } else { scPlayerData.BindOption = proto.Int32(7) } //周卡数据 for id, endTime := range this.WeekCardTime { if endTime == 0 { continue } weekInfo := playerproto.WeekInfo{ Id: id, WeekCardTime: endTime, WeekCardAward: this.WeekCardAward[id], } scPlayerData.Data.WeekCard = append(scPlayerData.Data.WeekCard, &weekInfo) } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_PLAYERDATA), scPlayerData) logger.Logger.Tracef("Send SCPlayerData %v", scPlayerData) if !this.IsRob { this.SyncPlayerDataToGateSrv(this.PlayerData) } // 判断玩家是否在游戏内 if this.scene != nil && this.thrscene == 0 { this.SendGameConfig(int32(this.scene.gameId), this.Platform, this.Channel) } //this.SendJackpotInfo() // 更新vip this.GetVIPLevel() // 后台道具配置 this.SCItems() // 引导配置 this.SCGuide() // 其它配置 this.SCDataConfig(common.DataConfigAll) } func (this *Player) IsGM() bool { if this.GMLevel > 0 { return true } return false } func (this *Player) IsAgentor() bool { return false } func (this *Player) IsPlayer() bool { return true } func (this *Player) HasAuthority(role int) bool { switch role { case common.ClientRole_Agentor: return this.IsAgentor() case common.ClientRole_GM: return this.IsGM() case common.ClientRole_Player: return true } return false } func (this *Player) RobRandVip() { if this.IsRob { dbvip := srvdata.PBDB_VIPMgr.GetData(this.VIP) if dbvip != nil { outlines := dbvip.GetRewardOutlineID() n := len(outlines) this.HeadOutLine = outlines[rand.Intn(n)] logger.Logger.Tracef("(this *Player) RobRandVip() %d HeadOutLine=%d", this.SnId, this.HeadOutLine) this.dirty = true } this.Head = rand.Int31n(common.HeadRange) //0:男 1:女 this.Sex = (this.Head%2 + 1) % 2 // 随机皮肤 skinFunc := func(i int) { total := 0 for _, v := range common.SkinRandom[:i] { total += common.SkinWeightMap[v] } r := common.RandInt(total) n := common.SkinWeightMap[common.SkinRandom[0]] for k, v := range common.SkinRandom[:i] { if r < n { this.Skin.ModId = v if this.Skin.ModUnlock[v] == 0 { this.Skin.ModUnlock[v] = 1 if this.Skin.Mod[v] == nil { this.Skin.Mod[v] = &model.ModEx{} } this.Skin.Mod[v].Ts = time.Now().Unix() } break } if k+1 < len(common.SkinRandom) { n += common.SkinWeightMap[common.SkinRandom[k+1]] } } } switch { case this.VIP >= 1: skinFunc(5) case this.VIP >= 2: skinFunc(6) case this.VIP >= 5: skinFunc(7) default: skinFunc(4) } } } func (this *Player) ReportLoginEvent() { //用户登录 if !this.IsRob { isBindPhone := int32(0) if this.Tel != "" { isBindPhone = 1 if this.UpgradeTime.IsZero() { this.UpgradeTime = this.CreateTime } } mq.Write(model.GenerateLogin(model.CreatePlayerLoginEvent(this.SnId, this.Channel, this.BeUnderAgentCode, this.Platform, this.City, this.DeviceOS, this.Ip, this.CreateTime, this.UpgradeTime, isBindPhone, this.TelephonePromoter, this.DeviceId, this.ChannelId, this.AppChannel, this.ClientVer))) //登录通知 //ActMonitorMgrSington.SendActMonitorEvent(ActState_Login, this.SnId, this.Name, this.Platform, // 0, 0, "", 0) } } func (this *Player) ReportBindAlipayEvent() { //绑定支付宝事件 //if !this.IsRob { // d, e := model.MarshalPlayerBindAlipayEvent(2, this.SnId, this.Channel, this.BeUnderAgentCode, // this.Platform, this.City, this.DeviceOS, this.TelephonePromoter) // if e == nil { // rmd := model.NewInfluxDBData("hj.player_bind_alipay", d) // if rmd != nil { // InfluxDBDataChannelSington.Write(rmd) // } // } //} } func (this *Player) GetPlatform() *Platform { platform := PlatformMgrSingleton.GetPlatform(this.Platform) if platform != nil && platform.Isolated { return platform } return PlatformMgrSingleton.GetPlatform(DefaultPlatform) } func (this *Player) RobotRandName() { if this.IsRob { //if rand.Int31n(100) < 60 { pool := srvdata.PBDB_NameMgr.Datas.GetArr() cnt := int32(len(pool)) if cnt > 0 { this.Name = pool[rand.Int31n(cnt)].GetName() } //} else { // this.Name = "Guest" //} } return } // 这个冲账记录不可随便写,需要加该日志时,请找lyk确认,暂定依据是金币直接加到身上,不依赖其他数据状态的可以写该日志 // 业务准则:先更新标记,再写冲账记录 func (this *Player) AddPayCoinLog(coin int64, coinType int32, oper string) { ts := time.Now().UnixNano() billNo := ts log := model.NewPayCoinLog(billNo, this.SnId, coin, 0, oper, coinType, 0) if log != nil { ts = log.TimeStamp task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { err := model.InsertPayCoinLog(this.Platform, log) if err != nil { logger.Logger.Errorf("InsertPayCoinLog err:%v log:%v", err, log) return err } return err }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { switch coinType { case model.PayCoinLogType_Coin: if this.CoinPayTs < ts { this.CoinPayTs = ts this.dirty = true } case model.PayCoinLogType_SafeBoxCoin: if this.SafeBoxCoinTs < ts { this.SafeBoxCoinTs = ts this.dirty = true } } }), "InsertPayCoinLog").StartByFixExecutor("InsertPayCoinLog") } } // SyncPlayerDataToGateSrv 玩家信息同步到网关 func (this *Player) SyncPlayerDataToGateSrv(pd *model.PlayerData) { var buf bytes.Buffer enc := gob.NewEncoder(&buf) err := enc.Encode(pd) if err != nil { logger.Logger.Info("(this *Player) UpdateToGateSrv gob.Marshal error", err) } else { pack := &serverproto.WRPlayerData{ Sid: this.sid, PlayerData: buf.Bytes(), } proto.SetDefaults(pack) this.gateSess.Send(int(serverproto.SSPacketID_PACKET_WR_PlayerData), pack) } } func (this *Player) BindGroupTag(tags []string) { if this.gateSess == nil { return } pack := &serverproto.SGBindGroupTag{ Sid: proto.Int64(this.sid), Code: serverproto.SGBindGroupTag_OpCode_Add, Tags: tags, } proto.SetDefaults(pack) this.gateSess.Send(int(serverproto.SSPacketID_PACKET_SG_BINDGROUPTAG), pack) } func (this *Player) UnBindGroupTag(tags []string) { if this.gateSess == nil { return } pack := &serverproto.SGBindGroupTag{ Sid: proto.Int64(this.sid), Code: serverproto.SGBindGroupTag_OpCode_Del, Tags: tags, } proto.SetDefaults(pack) this.gateSess.Send(int(serverproto.SSPacketID_PACKET_SG_BINDGROUPTAG), pack) } func (this *Player) TryRetrieveLostGameCoin(sceneid int) { //发送一个探针,等待ack后同步金币 logProbe := model.NewCoinLog() logProbe.SnId = this.SnId logProbe.Count = 0 //必须是0,探针标识 logProbe.RestCount = 0 //this.Coin logProbe.SeqNo = this.GameCoinTs logProbe.RoomId = int32(sceneid) mq.Write(logProbe) this.SendDiffData() } func (this *Player) SyncGameCoin(sceneid int, enterts int64) { //游服金币冲账 endts := time.Now().UnixNano() var err error var gamecoinlogs []model.CoinWAL task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { gamecoinlogs, err = model.GetCoinWALBySnidAndInGameAndGreaterTs(this.Platform, this.SnId, int32(sceneid), enterts) return err }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { if err == nil && len(gamecoinlogs) != 0 { oldCoin := this.Coin var cnt int64 for i := 0; i < len(gamecoinlogs); i++ { ts := gamecoinlogs[i].Ts if ts >= enterts && ts <= endts { cnt = gamecoinlogs[i].Count this.Coin += cnt if ts > this.GameCoinTs { this.GameCoinTs = ts } } } newCoin := this.Coin newTs := this.GameCoinTs logger.Logger.Warnf("PlayerData(%v) SyncGameCoin before:enterts=%v before:Coin=%v after:GameCoinTs=%v after:Coin=%v", this.SnId, enterts, oldCoin, newTs, newCoin) } this.SendDiffData() }), "GetCoinWALBySnidAndInGameAndGreaterTs").Start() } func (this *Player) SendShowRed(showType hallproto.ShowRedCode, showChild, isShow int32) { pack := &hallproto.SCShowRed{ ShowRed: &hallproto.ShowRed{ ShowType: showType, ShowChild: proto.Int32(showChild), IsShow: proto.Int32(isShow), }, } proto.SetDefaults(pack) logger.Logger.Trace("SCShowRed:", pack) this.SendToClient(int(hallproto.HallPacketID_PACKET_SC_SHOWRED), pack) } func (this *Player) SCVIPInfo() { if this.IsRob { return } pack := &playerproto.SCVIPInfo{ OpRetCode: playerproto.OpResultCode_OPRC_Error, } vips := VipMgrSington.GetVIPcfg(this.Platform) if vips != nil { pack.MoneyRatio = int32(vips.MoneyRatio) for _, cfg := range vips.List { data := &playerproto.VIPcfg{ VipId: cfg.VipId, VipEx: cfg.VipEx, Price: cfg.Price, Privilege2: cfg.Privilege2, Privilege3: cfg.Privilege3, Privilege4: cfg.Privilege4, Privilege5: cfg.Privilege5, Privilege6: cfg.Privilege6, Privilege7Price: cfg.Privilege7Price, Privilege8: cfg.Privilege8, LineId: cfg.RewardOutlineID, ShopId2: cfg.ShopId2, ShopId7: cfg.ShopId7, MatchFreeTimes: cfg.MatchFreeTimes, Privilege9: cfg.Privilege9, } d := srvdata.PBDB_VIPMgr.GetData(cfg.VipId) if d != nil { data.PrivilegeShow = d.GetPrivilegeShow() } data.Privilege1 = make(map[int64]int64) for k, v := range cfg.Privilege1 { if k == common.ItemIDCoin { // 皮肤技能加成 add := this.GetSkillAdd(common.SkillIdVipGift) if add > 0 { //v += int64((float64(v) * float64(add)) / 100.00) } } data.Privilege1[k] = v } for itemId, itemNum := range cfg.Award { data.Item = append(data.Item, &playerproto.ItemInfo{ ItemId: int32(itemId), ItemNum: itemNum, }) } for itemId, itemNum := range cfg.Privilege7 { data.Privilege7 = append(data.Privilege7, &playerproto.ItemInfo{ ItemId: int32(itemId), ItemNum: itemNum, }) } data.BagStatus = make([]int32, 4) data.BagStatus[0] = 0 //每日礼包 0可领取 1不可领取 只能领取当前VIP等级的 data.BagStatus[1] = 0 //每日金币礼包 0可领取 1不可领取 只能领取当前VIP等级的 data.BagStatus[2] = this.GetPlayerVipBagStatus(cfg.ShopId7, cfg.VipId) //固定VIP礼包 0可领取 1不可领取 可以领取所有VIP等级的奖励 data.BagStatus[3] = this.GetPlayerVipBagStatus(1, cfg.VipId) // 等级礼包 0可领取 1不可领取 if cfg.VipId != this.VIP { data.BagStatus[0] = 1 //每日礼包 0可领取 1不可领取 只能领取当前VIP等级的 data.BagStatus[1] = 1 //每日金币礼包 0可领取 1不可领取 只能领取当前VIP等级的 } else { data.BagStatus[0] = this.GetPlayerVipBagStatus(0, cfg.VipId) data.BagStatus[1] = this.GetPlayerVipBagStatus(cfg.ShopId2, cfg.VipId) } pack.List = append(pack.List, data) } pack.TolVipExp, pack.Money = this.GetCurrentVIPExp() pack.Vip = this.VIP pack.OpRetCode = playerproto.OpResultCode_OPRC_Sucess } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_VIPINFO), pack) logger.Logger.Tracef("send vipinfo to client:%v", pack) } func (this *Player) GetVIPExpByPay(payTotal int64) int64 { vips := VipMgrSington.GetVIPcfg(this.Platform) return payTotal * int64(vips.MoneyRatio) } func (this *Player) VIPDraw(id, vip int32) { pack := &playerproto.SCVIPDraw{ Id: id, OpRetCode: playerproto.OpResultCode_OPRC_Error, Award: make(map[int64]int64), } send := func() { pack.Vip = vip this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_DRAWVIPGIFT), pack) logger.Logger.Tracef("send vipdraw to client:%v", pack) return } if this.WelfData.VIPBag == nil { this.WelfData.VIPBag = make(map[int32]map[int32]int32) } switch id { case 0: // 每日礼包只能领当前VIP等级的 vip = this.VIP if innerMap, ok := this.WelfData.VIPBag[vip]; ok { if _, ok := innerMap[id]; ok { logger.Logger.Trace("VIPDraw VIP is repeat id%v ", id) send() return } } case 1: // VIP等级礼包 if this.GetPlayerVipBagStatus(1, vip) == 1 { send() return } default: send() return } if this.WelfData.VIPBag[vip] == nil { this.WelfData.VIPBag[vip] = make(map[int32]int32) } data := VipMgrSington.GetVipCfg(this.Platform, vip) if data != nil { pack.OpRetCode = playerproto.OpResultCode_OPRC_Sucess this.WelfData.VIPBag[vip][id] = 1 switch id { case 0: var money, addVipExp int64 for k, v := range data.Privilege1 { switch k { case common.ItemIDCoin: money = v // 皮肤技能加成 add := this.GetSkillAdd(common.SkillIdVipGift) if add > 0 { money += int64((float64(money) * float64(add)) / 100.00) } this.AddCoin(money, 0, common.GainWay_VIPGift, "sys", "VIP每日礼包") pack.Award[common.ItemIDCoin] = money case common.ItemIDVipExp: vips := VipMgrSington.GetVIPcfg(this.Platform) addVipExp = int64(float64(v) / vips.MoneyRatio) this.AddMoneyPayTotal(addVipExp) pack.Award[common.ItemIDVipExp] = addVipExp default: BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: []*model.Item{ { ItemId: int32(k), ItemNum: v, }, }, GainWay: common.GainWay_VIPGift, Operator: "system", Remark: "VIP每日礼包", }) pack.Award[k] += v } } logger.Logger.Tracef("玩家领取VIP每日礼包成功!snid = %v,Vip = %v,金币数量 = %v,addVipEx = %v", this.SnId, this.VIP, money, addVipExp) //VIP礼包统计数据 var item []model.ItemInfo item = append(item, model.ItemInfo{ItemId: 1, ItemNum: money}) log := model.NewDbVip(this.Platform, this.SnId, this.VIP, 0, 0, 0, item, 0, "Vip每日礼包") mq.Write(log) case 1: var items []*model.Item var itemInfo []model.ItemInfo for k, v := range data.Privilege9 { items = append(items, &model.Item{ ItemId: int32(k), ItemNum: v, }) itemInfo = append(itemInfo, model.ItemInfo{ItemId: int32(k), ItemNum: v}) pack.Award[k] = v } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: items, GainWay: common.GainWayVipGift9, Operator: "system", Remark: "VIP等级礼包", }) logger.Logger.Tracef("玩家领取VIP等级礼包成功!snid = %v,Vip = %v,items %#v", this.SnId, this.VIP, items) //VIP礼包统计数据 log := model.NewDbVip(this.Platform, this.SnId, this.VIP, 9, 0, 0, itemInfo, 0, "Vip等级礼包") mq.Write(log) } } send() } // GetCurrentVIPExp 更新vip等级 // 返回当前经验和升级需要经验 func (this *Player) GetCurrentVIPExp() (exp int64, money int64) { vips := VipMgrSington.GetVIPcfg(this.Platform) exp = int64(float64(this.MoneyPayTotal) * vips.MoneyRatio) tolexp := int32(0) oldVipLevel := this.VIP if this.MoneyPayTotal != 0 { allExp := int64(float64(this.MoneyPayTotal) * vips.MoneyRatio) for _, v := range vips.List { tolexp = v.VipEx if allExp >= int64(v.VipEx) { this.VIP = v.VipId this.VipExtra = v.Privilege4 } else { break } } } money = int64(tolexp) - exp if money < 0 { money = 0 } if oldVipLevel != this.VIP { this.GetVIPLevel() } return // 默认 } // GetVIPLevel 更新vip等级,返回vip等级 func (this *Player) GetVIPLevel() int32 { if this.IsRob { return 0 } vips := VipMgrSington.GetVIPcfg(this.Platform) vip := int32(0) if vips != nil && this.MoneyPayTotal != 0 { allExp := this.MoneyPayTotal * int64(vips.MoneyRatio) for _, v := range vips.List { if allExp >= int64(v.VipEx) { vip = v.VipId this.VipExtra = v.Privilege4 } else { break } } } var b bool if vip != this.VIP { this.dirty = true b = true logger.Logger.Trace("VIP升级!") } this.VIP = vip //玩家VIP升级 this.SCVIPInfo() if b { ModelMgrSingleton.CheckSkinRed(this) } return this.VIP } func (this *Player) GetMaxVIPLevel() int32 { vips := VipMgrSington.GetVIPcfg(this.Platform) if vips != nil && len(vips.List) > 0 { vn := len(vips.List) - 1 return vips.List[vn].VipId } return 0 } // GetMatchFreeTimes 比赛场免费次数 func (this *Player) GetMatchFreeTimes() int32 { cfg := VipMgrSington.GetVIPLevelCfg(this.Platform, this.VIP) if cfg != nil { return cfg.GetMatchFreeTimes() } return 0 } // DoShopInfo 订单完成处理逻辑 // isLogin 是否登录 func (this *Player) DoShopInfo(info *model.DbShop, isLogin bool) { if info == nil { return } op := "Callback" if isLogin { op = "CallbackLogin" } switch info.PageId { case ShopPageBackend: logger.Logger.Tracef("GetPayGoodsInfo ShopPageBackend %+v", *info) default: if len(info.Amount) > 0 { this.AddCoin(int64(info.Amount[0]), 0, info.GainWay, op, info.Remark) this.AddDiamond(int64(info.Amount[1]), 0, info.GainWay, op, info.Remark) } this.AddMoneyPayTotal(int64(info.ConsumeNum)) this.MoneyTotal += int64(info.ConsumeTypeNum) info.Amount[2] = int32(this.GetVIPExpByPay(int64(info.ConsumeNum))) this.dirty = true this.SendDiffData() var itemInfo []*playerproto.PayItem var items []*model.Item if info.ItemInfo != nil { for _, v := range info.ItemInfo { items = append(items, &model.Item{ItemId: v.ItemId, ItemNum: v.ItemNum}) itemInfo = append(itemInfo, &playerproto.PayItem{ ItemId: v.ItemId, ItemNum: v.ItemNum, }) } } if len(items) > 0 { BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: items, GainWay: info.GainWay, Operator: info.Operator, Remark: info.Remark, }) } //钻石存储罐 if info.PageId == ShopPageDiamondBank { WelfareMgrSington.DiamondBankTakeCoin(this) } // 通行证 if info.PageId == ShopPagePermit { this.Permit = info.CreateTs.Local() mq.Write(&model.BackendPermitJoin{ Platform: this.Platform, StartTs: PlatformMgrSingleton.GetConfig(this.Platform).PermitStartTs, SnId: this.SnId, Ts: time.Now().Unix(), }) TaskSubjectSingleton.Touch(common.TaskTypeBuyPermit, &TaskData{ SnId: this.SnId, Num: 1, }) } switch info.Remark { case "BlindBox": if len(info.OtherParams) > 0 { this.WelfData.BlindBoxId = info.OtherParams[0] } else { logger.Logger.Errorf("GetPayGoodsInfo BlindBox OtherParams is nil") } case "FirstRecharge": if len(info.OtherParams) > 0 { this.WelfData.FirstPayDay = info.OtherParams[0] this.WelfData.FirstPayTickets = info.Ts } else { logger.Logger.Errorf("GetPayGoodsInfo FirstRecharge OtherParams is nil") } case "ContinuousPay": if len(info.OtherParams) > 0 { this.WelfData.ContinuousPayDay = info.OtherParams[0] this.WelfData.ContinuousPayTickets = info.Ts } else { logger.Logger.Errorf("GetPayGoodsInfo ContinuousPay OtherParams is nil") } } this.UpdatePlayerVipBag(info.ShopId) this.UpdateShopID(info.ShopId) PayGoodsInfo := &playerproto.SCPayGoodsInfo{ Gold: info.Amount, Item: itemInfo, ShopId: info.ShopId, Money: int64(info.ConsumeTypeNum), Name: info.Remark, } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_PAYGOODSINFO), PayGoodsInfo) } // 充值任务 if info.ConsumeNum > 0 { TaskSubjectSingleton.Touch(common.TaskTypePay, &TaskData{ SnId: this.SnId, Num: int64(info.ConsumeNum), }) } } // DealShopLog 处理订单 func (this *Player) DealShopLog() { task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { info := model.GetDbShopLogsByState(this.Platform, this.SnId) if info != nil { for _, shop := range info { err := model.UpdateDbShopState(shop.Platform, shop.LogId.Hex(), 1) if err != nil { logger.Logger.Error("Player CallbackPayment UpdateDbShopState err:", err) return nil } } } return info }), task.CompleteNotifyWrapper(func(i interface{}, t task.Task) { if i == nil { return } shops, ok := i.([]*model.DbShop) if !ok { return } for _, info := range shops { this.DoShopInfo(info, true) } })).StartByExecutor(fmt.Sprintf("Player%v", this.SnId)) } // 奖池信息 func (this *Player) SendJackPotInit() { var pack = &hallproto.SCHundredSceneGetGameJackpot{} gameFreeIds := []int32{ 3010001, 3010002, 3010003, 3010004, 3020001, 3020002, 3020003, 3020004, 3030001, 3030002, 3030003, 3030004, 3040001, 3040002, 3040003, 3050001, 3050002, 3050003} for _, id := range gameFreeIds { data := srvdata.PBDB_GameFreeMgr.GetData(id) if data != nil && len(data.Jackpot) > 0 { jpfi := &hallproto.GameJackpotFundInfo{ GameFreeId: proto.Int32(data.Id), JackPotFund: proto.Int64(int64(data.BaseScore * data.Jackpot[0])), } pack.GameJackpotFund = append(pack.GameJackpotFund, jpfi) } } if len(pack.GameJackpotFund) > 0 { this.SendToClient(int(hallproto.HundredScenePacketID_PACKET_SC_GAMEJACKPOT), pack) } } func (this *Player) OnlineLogLogin() { if this.IsRob { return } if this.onlineLog == nil { this.onlineLog = model.NewOnlineLog(bson.NewObjectId(), this.SnId, common.LoginLogTypeLogin, this.Platform) mq.Write(*this.onlineLog) } } func (this *Player) OnlineLogRehold() { if this.IsRob { return } if this.onlineLog == nil { this.onlineLog = model.NewOnlineLog(bson.NewObjectId(), this.SnId, common.LoginLogTypeRehold, this.Platform) mq.Write(*this.onlineLog) } } func (this *Player) OnlineLogDrop() { if this.IsRob { return } if this.onlineLog != nil && this.onlineLog.OfflineTs == 0 { this.onlineLog.OfflineType = common.LoginLogTypeDrop this.onlineLog.OfflineTs = time.Now().Unix() mq.Write(*this.onlineLog) this.onlineLog = nil } } func (this *Player) OnlineLogLogout() { if this.IsRob { return } if this.onlineLog != nil && this.onlineLog.OfflineTs == 0 { this.onlineLog.OfflineType = common.LoginLogTypeLogout this.onlineLog.OfflineTs = time.Now().Unix() mq.Write(*this.onlineLog) this.onlineLog = nil } } func (this *Player) AddDiamondToCoin(n int64) { if n > 0 { this.dirty = true this.DiamondToCoin += n } } // SendRankSeason 通知客户端赛季信息 func (this *Player) SendRankSeason() { pack := &rankmatch.SCRMSeasonInfo{} cfg := RankMgrSingleton.GetSeasonConfig(this.Platform) if cfg == nil { this.SendToClient(int(rankmatch.RankMatch_PACKET_RM_SCRMSeasonInfo), pack) return } pack = &rankmatch.SCRMSeasonInfo{ Id: cfg.SeasonId, TimeStamp: []int64{cfg.StartTs, cfg.EndTs}, } rank := RankMgrSingleton.GetPlayerSeason(this.SnId) if rank != nil && rank.PlayerRankSeason != nil && rank.RankType != nil { for k, v := range rank.RankType { if v == nil { continue } info := &rankmatch.SeasonInfo{Id: k} info.Lv, info.Score = RankMgrSingleton.GetPlayerRankLV(k, this.SnId) info.LastLv, info.LastScore = RankMgrSingleton.GetPlayerLastRankLV(k, this.SnId) se := RankMgrSingleton.GetPlayerSeason(this.SnId) if se != nil && se.RankType[k] != nil { if se.RankType[k].LastScore < se.RankType[k].Score { oldLv := srvdata.RankLevelMgr.GetRankLevel(k, se.RankType[k].LastScore) if info.Lv > oldLv { var awards *rankmatch.AwardItem var maxLv int32 = -1 for _, item := range RankMgrSingleton.GetRankAwardList(k) { // 1 可领取 2已领取 if info.Lv >= item.Lv { has := false // 是否已领取 for _, vv := range v.Awards { if vv.Id == item.Id { if vv.Ts > 0 { has = true } break } } if !has { if item.Lv > maxLv { awards = item maxLv = item.Lv } } } } if awards != nil { info.Award = awards } } se.RankType[k].LastScore = se.RankType[k].Score } } pack.Seasons = append(pack.Seasons, info) } } this.SendToClient(int(rankmatch.RankMatch_PACKET_RM_SCRMSeasonInfo), pack) logger.Logger.Trace("SCTMSeasonInfo:", pack) } // 金币排行榜数据 func (this *Player) SendPlayerCoin() { mq.Write(&model.RankPlayerCoin{ Platform: this.Platform, SnId: this.SnId, Name: this.Name, Sex: this.Sex, HeadUrl: this.HeadUrl, Coin: this.GetTotalCoin(), ModId: this.GetRoleId(), }) } // 解锁炮倍 func (this *Player) UnPlayerPowerEx(power int64) { logger.Logger.Tracef("解锁炮倍 当前最大解锁炮倍:%v,要解锁的炮倍:%v", this.UnMaxPower, power) if this.UnPlayerPower(power) { pack := &playerproto.SCPlayerUnPower{ UnMaxpower: power, } this.UnMaxPower = power this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_PlayerUnPower), pack) logger.Logger.Tracef("通知客户端解锁最大炮倍,snid = %v,power = %v", this.SnId, power) } } // 道具解锁炮台 func (this *Player) ItemUnPlayerPowerListEx(itemId int32) { if itemId == 0 { return } //判断炮台存不存在 var powerId int32 = 0 for _, data := range srvdata.PBDB_ArtillerySkinMgr.Datas.GetArr() { if data.CannonId == itemId { powerId = data.Id break } } if powerId == 0 { return } if this.UnPlayerPowerList(powerId) { //通知客户端解锁炮台 pack := &playerproto.SCPlayerUnPowerList{ UnPowerList: powerId, } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_PlayerUnPowerList), pack) logger.Logger.Trace("通知客户端解锁炮台 snid = %v,解锁的炮台:%v,当前已有的炮台 = %v", this.SnId, powerId, this.PowerList) } } // powerId 解锁炮台 func (this *Player) UnPlayerPowerListEx(powerId int32) { data := srvdata.PBDB_ArtillerySkinMgr.GetData(powerId) if data == nil { return } if this.UnPlayerPowerList(powerId) { //通知客户端解锁炮台 pack := &playerproto.SCPlayerUnPowerList{ UnPowerList: powerId, } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_PlayerUnPowerList), pack) logger.Logger.Trace("通知客户端解锁炮台 snid = %v,解锁的炮台:%v,当前已有的炮台 = %v", this.SnId, powerId, this.PowerList) } } func (this *Player) UpdatePlayerVipBag(shopId int32) { //判断是否是vip商品 更新数据 shopInfo := ShopMgrSington.GetShopInfo(shopId, this) if shopInfo != nil { if shopInfo.Page == ShopPagePrivilege { if this.WelfData.VIPBag == nil { this.WelfData.VIPBag = make(map[int32]map[int32]int32) } if _, ok := this.WelfData.VIPBag[shopInfo.VipLevel]; !ok { this.WelfData.VIPBag[shopInfo.VipLevel] = make(map[int32]int32) } this.WelfData.VIPBag[shopInfo.VipLevel][shopInfo.Id] = shopInfo.Type logger.Logger.Tracef("玩家购买VIP商品成功,更新购买状态!snid = %v shopId = %v,VIP = %v", this.SnId, shopInfo.Id, shopInfo.VipLevel) pack := &playerproto.SCVIPDraw{ Id: shopInfo.Type, Vip: shopInfo.VipLevel, OpRetCode: playerproto.OpResultCode_OPRC_Sucess, } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_DRAWVIPGIFT), pack) //VIP金币礼包&VIP固定礼包统计数据 var item []model.ItemInfo item = append(item, model.ItemInfo{ItemId: shopInfo.Type, ItemNum: shopInfo.Amount}) log := model.NewDbVip(this.Platform, this.SnId, shopInfo.VipLevel, shopInfo.Type, shopInfo.ConstType, int64(shopInfo.CostArea[0]), item, shopInfo.Id, shopInfo.Name) mq.Write(log) } //判断是否是礼包周卡 if shopInfo.Page == ShopPageGift { this.UpdateWeekCardData(shopId) } } } // 判断vip特权某个礼包是否领取过 返回值:0可领取 1 不可领取 func (this *Player) GetPlayerVipBagStatus(shopId, vipLevel int32) int32 { if vipLevel > this.VIP || vipLevel < 0 { return 1 } if this.WelfData == nil || this.WelfData.VIPBag == nil { return 0 } if _, ok := this.WelfData.VIPBag[vipLevel]; !ok { return 0 } if _, ok := this.WelfData.VIPBag[vipLevel][shopId]; !ok { return 0 } return 1 } func (this *Player) UpdateVipShopData() { this.VipShopData = nil this.VipShopRefreshCount = 0 //每日礼包 和每日金币礼包需要初始化 if this.WelfData != nil && this.WelfData.VIPBag != nil { var delKeyList []int32 for _, data := range this.WelfData.VIPBag { for shopId, shopType := range data { switch shopId { case 0: // 每日礼包 delKeyList = append(delKeyList, shopId) logger.Logger.Trace("初始化VIP每日礼包!!!!!!!") case 1: // 等级礼包,不需要重置 default: if shopType == 1 { delKeyList = append(delKeyList, shopId) logger.Logger.Trace("初始化VIP每日固定礼包!!!!!!!!!!") } } } } for _, delKey := range delKeyList { for _, data := range this.WelfData.VIPBag { delete(data, delKey) } } this.SCVIPInfo() } } func (this *Player) RandRobotVip(scene *Scene) { if !this.IsRobot() || scene == nil || scene.dbGameFree == nil { return } // vip config := srvdata.PBDB_PotOddMgr.GetData(scene.dbGameFree.GetId()) if config == nil || len(config.VipOdd) == 0 { return } var all int32 for _, v := range config.VipOdd { all += v } n := rand.Int31n(all) vip := 0 var sum int32 for k, v := range config.VipOdd { sum += v if n < sum { vip = k break } } this.VIP = int32(vip) } func (this *Player) RandRobotPetSkillLevel() { //随机机器人宠物技能等级 this.Pets.SkillInfo = make(map[int32]map[int32]int32) for petId, _ := range this.Pets.ModUnlock { skillLevel := int32(0) if this.VIP < 1 { skillLevel = rand.Int31n(2) } else if this.VIP >= 1 && this.VIP <= 3 { skillLevel = rand.Int31n(3) + 1 } else if this.VIP >= 4 && this.VIP <= 6 { skillLevel = rand.Int31n(4) + 2 } else if this.VIP >= 7 && this.VIP <= 9 { skillLevel = rand.Int31n(4) + 3 } else if this.VIP >= 10 && this.VIP <= 12 { skillLevel = rand.Int31n(5) + 4 } else if this.VIP >= 13 && this.VIP <= 16 { skillLevel = rand.Int31n(6) + 5 } this.Pets.SkillInfo[petId] = make(map[int32]int32) this.Pets.SkillInfo[petId][10001] = skillLevel } } // BindTelReward 发送绑定手机号奖励 func (this *Player) BindTelReward() { // todo 奖励限额;ip日期最多赠送多少奖励 // 发送奖励 plt := PlatformMgrSingleton.GetPlatform(this.Platform) if plt != nil { var items []*model.Item for k, v := range plt.BindTelReward { switch k { case 1: items = append(items, &model.Item{ ItemId: common.ItemIDCoin, ItemNum: v, }) case 2: items = append(items, &model.Item{ ItemId: common.ItemIDDiamond, ItemNum: v, }) default: items = append(items, &model.Item{ ItemId: k, ItemNum: v, }) } } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: items, Add: 0, GainWay: common.GainWay_BindTel, Operator: "system", Remark: "绑定手机号奖励", GameId: 0, GameFreeId: 0, }) } } func (this *Player) UpdateShopID(shopId int32) { var shopInfo = ShopMgrSington.ConfigMgr.GetShopInfo(this.Platform, shopId) if shopInfo != nil && shopInfo.FirstSwitch { if !slices.Contains(this.ShopID, int(shopInfo.Id)) { this.ShopID = append(this.ShopID, int(shopInfo.Id)) } } } // 增加抽奖次数 func (this *Player) addLotteryCount(count int32) { if WelfareMgrSington.GetPhoneLotteryStatus(this.Platform) == model.WelfareClose { return } this.LotteryCount += count if this.LotteryCount < 0 { this.LotteryCount = 0 } if this.LotteryCount >= math.MaxInt32 { this.LotteryCount = math.MaxInt32 } //通知客户端 pack := &playerproto.SCPhoneLotteryCount{ Count: this.LotteryCount, } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SC_PhoneLotteryCount), pack) } // AddPhoneScore 增加手机积分 func (this *Player) AddPhoneScore(num, add int64, gainWay int32, oper, remark string) { if num == 0 { return } if WelfareMgrSington.GetPhoneLotteryStatus(this.Platform) == model.WelfareClose { return } logger.Logger.Tracef("snid(%v) AddPhoneScore(%v)", this.SnId, num) this.dirty = true if num > 0 { this.PhoneScore += num } else { if -num > this.PhoneScore { logger.Logger.Errorf("Player.AddPhoneScore exception!!! num(%v) oper(%v)", num, oper) num = -this.PhoneScore this.PhoneScore = 0 } else { this.PhoneScore += num } } this.SendDiffData() } // 抽奖任务 func (this *Player) PhoneLotteryTask(taskId int32, num int64) { if WelfareMgrSington.GetPhoneLotteryStatus(this.Platform) == model.WelfareClose { if this.WelfData != nil && this.WelfData.PhoneLotteryTask != nil { this.WelfData.PhoneLotteryTask = make(map[int32]*model.TaskData) } return } if this.WelfData == nil { this.WelfData = model.NewWelfareData() } if this.WelfData.PhoneLotteryTask == nil { this.WelfData.PhoneLotteryTask = make(map[int32]*model.TaskData) } if this.WelfData.PhoneLotteryTask[taskId] == nil { this.WelfData.PhoneLotteryTask[taskId] = &model.TaskData{N: 0} // 初始化任务数据 } switch taskId { case common.TaskTypePay: this.WelfData.PhoneLotteryTask[taskId].N += num if this.WelfData.PhoneLotteryTask[taskId].N/20 > 0 { count := this.WelfData.PhoneLotteryTask[taskId].N / 20 this.addLotteryCount(int32(count)) this.WelfData.PhoneLotteryTask[taskId].N = this.WelfData.PhoneLotteryTask[taskId].N % 20 mq.Write(model.GeneratePhoneLottery(this.SnId, this.Platform, "", 3, int(count), 4, 0)) } case common.TaskTypeWinOrLose: this.WelfData.PhoneLotteryTask[taskId].N += num if this.WelfData.PhoneLotteryTask[taskId].N/200000000 > 0 { count := this.WelfData.PhoneLotteryTask[taskId].N / 200000000 this.addLotteryCount(int32(count)) this.WelfData.PhoneLotteryTask[taskId].N = this.WelfData.PhoneLotteryTask[taskId].N % 200000000 mq.Write(model.GeneratePhoneLottery(this.SnId, this.Platform, "", 3, int(count), 3, 0)) } case common.TaskTypeTienlenCount: this.WelfData.PhoneLotteryTask[taskId].N += num if this.WelfData.PhoneLotteryTask[taskId].N/20 > 0 { count := this.WelfData.PhoneLotteryTask[taskId].N / 20 this.addLotteryCount(int32(count)) this.WelfData.PhoneLotteryTask[taskId].N = this.WelfData.PhoneLotteryTask[taskId].N % 20 mq.Write(model.GeneratePhoneLottery(this.SnId, this.Platform, "", 3, int(count), 2, 0)) } case common.TaskTypeFirstLogin: this.addLotteryCount(5) mq.Write(model.GeneratePhoneLottery(this.SnId, this.Platform, "", 3, 5, 1, 0)) default: logger.Logger.Errorf("手机抽奖任务未找到对应的任务ID: %d", taskId) return } } func InviteTask(platform string, psnid, snid, scoreType int32, n int64) { if snid <= 0 { return } cfg := PlatformMgrSingleton.GetConfig(platform).ActInviteConfig switch scoreType { case common.InviteScoreTypeBind: case common.InviteScoreTypePay: score, ok := cfg.GetPayScore()[n] if ok { SaveInviteScore(&model.InviteScore{ Platform: platform, SnId: snid, InviteSnId: psnid, Tp: scoreType, Score: score, Ts: time.Now().Unix(), Money: n, }) } else { SaveInviteScore(&model.InviteScore{ Platform: platform, SnId: snid, InviteSnId: psnid, Tp: common.InviteScoreTypeRecharge, Score: cfg.GetRechargeScore(), Ts: time.Now().Unix(), Money: n, }) } } } func (this *Player) ResetTaskN(tp int32) { if this.WelfData == nil || this.WelfData.Task == nil { return } for _, v := range srvdata.TaskMgr.GetTaskType(tp) { data := this.WelfData.Task[v.GetId()] if data != nil { data.N = 0 } } } func (this *Player) ResetTask(tp int32) { if this.WelfData == nil || this.WelfData.Task == nil { return } for _, v := range srvdata.TaskMgr.GetActivityType(tp) { this.WelfData.Task[v.GetId()] = &model.TaskData{} } } func (this *Player) CollectTask(taskId int32, num int64) { state := WelfareMgrSington.GetCollectSwitch(this.Platform) if state != model.WelfareOpen { return } // 每日登录游戏赠送一个 // 每日转盘抽奖赠送一个 switch taskId { case common.TaskTypeTurnplate, common.TaskTypeFirstLogin: BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: []*model.Item{ { ItemId: common.ItemIDCollectBox, ItemNum: num, ObtainTime: time.Now().Unix(), }, }, GainWay: common.GainWayItemCollectLogin, Operator: "system", Remark: fmt.Sprintf("集卡活动%v", taskId), }) default: } } // 购买周卡检查 func (this *Player) CheckWeekCard(shopId int32) bool { id := int32(-1) for _, card := range srvdata.PBDB_GiftCardMgr.Datas.GetArr() { if card.ShopID == shopId { id = card.Id break } } if id == -1 { return false } logger.Logger.Trace("玩家请求购买周卡!") //获取当前时间 now := time.Now().Unix() //计算时间差 timeDiff := int32(this.WeekCardTime[id]-now) / 86400 if timeDiff > 3 { logger.Logger.Trace("当前剩余时间大于3天,无法购买周卡!") return false } return true } // 购买周卡 func (this *Player) UpdateWeekCardData(shopId int32) bool { id := int32(-1) cardTime := 0 for _, card := range srvdata.PBDB_GiftCardMgr.Datas.GetArr() { if card.ShopID == shopId { id = card.Id cardTime = int(card.Time) break } } if id == -1 { return false } if this.WeekCardTime == nil { this.WeekCardTime = make(map[int32]int64) } logger.Logger.Trace("玩家请求购买周卡!") //获取当前时间 now := time.Now().Unix() //计算时间差 timeDiff := int32(this.WeekCardTime[id]-now) / 86400 if timeDiff > 3 { logger.Logger.Trace("当前剩余时间大于3天,无法购买周卡!") return false } //计算剩余时间 addTime := 0 if timeDiff > 0 { addTime = int(timeDiff) } //计算7天后0点时间 sevenDaysLater := time.Now().AddDate(0, 0, cardTime+addTime+1) zeroTime := time.Date(sevenDaysLater.Year(), sevenDaysLater.Month(), sevenDaysLater.Day(), 0, 0, 0, 0, sevenDaysLater.Location()) logger.Logger.Trace("购买周卡后,时间变为:", zeroTime.Unix()) this.WeekCardTime[id] = zeroTime.Unix() this.GetWeekCardAwary(id) //周卡统计 mq.Write(model.GenerateActivityLog(this.SnId, this.Platform, model.ActivityLog_WeekCard, 1)) return true } // 领取周卡奖励 func (this *Player) GetWeekCardAwary(id int32) { logger.Logger.Trace("玩家请求领取周卡奖励!") data := srvdata.PBDB_GiftCardMgr.GetData(id) if this.WeekCardAward == nil { this.WeekCardAward = make(map[int32]bool) } now := time.Now().Unix() if this.WeekCardTime[id] != 0 && now > this.WeekCardTime[id] { logger.Logger.Trace("周卡已过期,不能领取!") return } ret := &playerproto.SCGetWeekCardAwary{} if !this.WeekCardAward[id] { //获取周卡奖励 items := data.GetDayRewards() var addItem []*model.Item for itemId, itemNum := range items { item := &model.Item{ItemId: int32(itemId), ItemNum: itemNum, ObtainTime: time.Now().Unix()} addItem = append(addItem, item) itemInfo := &playerproto.PayItem{} itemInfo.ItemId = int32(itemId) itemInfo.ItemNum = itemNum ret.Items = append(ret.Items, itemInfo) } BagMgrSingleton.AddItems(&model.AddItemParam{ Platform: this.Platform, SnId: this.SnId, Change: addItem, GainWay: common.GainWay_WeekCardAward, Operator: "system", Remark: "周卡每日奖励", }) //返回消息 this.WeekCardAward[id] = true ret.WeekCardAward = this.WeekCardAward[id] } info := &playerproto.WeekInfo{ Id: id, WeekCardTime: this.WeekCardTime[id], WeekCardAward: this.WeekCardAward[id], } ret.WeekCard = info this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SCGetWeekCardAwary), ret) mq.Write(model.GenerateActivityLog(this.SnId, this.Platform, model.ActivityLog_WeekCard, 2)) return } // 获取周卡权益 // typeId : 1-破产救济金领取翻倍 2-排位赛积分提升5% func (this *Player) GetWeekCardPrivilege(typeId int32) bool { logger.Logger.Trace("玩家请求获取周卡权益!") now := time.Now().Unix() for id, endTime := range this.WeekCardTime { if endTime > now { data := srvdata.PBDB_GiftCardMgr.GetData(id) for _, equity := range data.GetEquity() { if equity == typeId { return true } } } } return false } // 增加记牌器道具时限 func (this *Player) AddItemRecExpireTime(itemId int32, num, add int64, gainWay int32, oper, remark string) { if num <= 0 { return } logger.Logger.Tracef("snid(%v) AddItemRecExpireTime, itemId:(%v), num:(%v)", this.SnId, itemId, num) this.dirty = true itemData := srvdata.GameItemMgr.Get(this.Platform, itemId) if itemData == nil { return } if this.ItemRecExpireTime == 0 { this.ItemRecExpireTime = time.Now().Unix() + int64(itemData.Time)*3600*num } else { if this.ItemRecExpireTime >= time.Now().Unix() { this.ItemRecExpireTime += int64(itemData.Time) * 3600 * num } else { this.ItemRecExpireTime = time.Now().Unix() + int64(itemData.Time)*3600*num } } if this.scene != nil && this.scene.gameSess != nil { msg := &serverproto.WGBuyRecTimeItem{ SnId: this.SnId, ExpireTime: this.ItemRecExpireTime, Diamond: this.Diamond, } this.SendToGame(int(serverproto.SSPacketID_PACKET_WG_BUYRECTIMEITEM), msg) } } func (this *Player) GetIsPermit() bool { startTs := PlatformMgrSingleton.GetConfig(this.Platform).PermitStartTs if startTs == 0 { return false } endTs := PlatformMgrSingleton.GetConfig(this.Platform).PermitEndTs if this.Permit.Unix() >= startTs && this.Permit.Unix() < endTs { return true } return false } func (this *Player) SCItems() { cfg := PlatformMgrSingleton.GetConfig(this.Platform).ItemConfig if cfg == nil { return } var items []*serverproto.DB_GameItem for _, v := range cfg.GetItems() { items = append(items, &serverproto.DB_GameItem{ Id: v.GetId(), Name: v.GetName(), ShowLocation: v.GetShowLocation(), Classify: v.GetClassify(), Type: v.GetType(), Effect0: v.GetEffect0(), Effect: v.GetEffect(), SaleType: v.GetSaleType(), SaleGold: v.GetSaleGold(), Composition: v.GetComposition(), CompositionMax: v.GetCompositionMax(), Time: v.GetTime(), Location: v.GetLocation(), Describe: v.GetDescribe(), Num: v.GetNum(), Value: v.GetValue(), Entity: v.GetEntity(), Icon: v.GetIcon(), }) } pack := &playerproto.SCItem{ Items: items, } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SCItem), pack) logger.Logger.Tracef("SCItem: %v", pack) } // AutoSkinUnlock 自动解锁皮肤 func (this *Player) AutoSkinUnlock() { for _, v := range PlatformMgrSingleton.GetConfig(this.Platform).SkinConfig.GetItems() { if v.GetUnlockType() != common.SkinGetAuto { continue } SkinUnLock(this, v.GetId()) } } // GetSkillAdd 获取技能加成 // id 技能id func (this *Player) GetSkillAdd(id int32) int32 { return this.GetSkillAdd2(id, PlatformMgrSingleton.ConfigMgr) } func (this *Player) SCGuide() { cfg := PlatformMgrSingleton.GetConfig(this.Platform).GuideConfig pack := &playerproto.SCGuideConfig{} for _, data := range cfg.GetInfo() { var awards []*playerproto.ItemInfo for _, award := range data.Awards { item := &playerproto.ItemInfo{ ItemId: award.GetItemId(), ItemNum: award.GetItemNum(), } awards = append(awards, item) } info := &playerproto.GuideInfo{ On: data.GetOn(), Skip: data.GetSkip(), GuideId: data.GetGuideId(), Awards: awards, MaxStep: data.MaxStep, AwardStep: data.AwardStep, Url: data.Url, } pack.Info = append(pack.Info, info) } this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SCGuideConfig), pack) logger.Logger.Tracef("SCGuideConfig: %v", pack) } // DataConfigFuncMap 配置查询方法 var DataConfigFuncMap = map[int]func(platform string, p *Player) *playerproto.Config{ common.DataConfigSprite: func(platform string, p *Player) *playerproto.Config { cfg := PlatformMgrSingleton.GetConfig(platform).SpiritConfig if cfg == nil { return nil } return &playerproto.Config{ Tp: common.DataConfigSprite, On: cfg.On == 1, Value: cfg.Url, } }, common.DataConfigMatchAudience: func(platform string, p *Player) *playerproto.Config { if p == nil { return nil } cfg := PlatformMgrSingleton.GetConfig(platform).MatchAudience if cfg == nil { return nil } d, ok := cfg[p.GetSnId()] if !ok || d == nil { return &playerproto.Config{ Tp: common.DataConfigMatchAudience, On: false, } } return &playerproto.Config{ Tp: common.DataConfigMatchAudience, On: true, } }, } // SCDataConfig 通知配置 // tp 类型 0所有 1小精灵 2比赛观众开关 func (this *Player) SCDataConfig(tp int) { if this == nil { return } pack := &playerproto.SCDataConfig{} if tp == common.DataConfigAll { for _, f := range DataConfigFuncMap { d := f(this.Platform, this) if d != nil { pack.Cfg = append(pack.Cfg, d) } } } else { f, ok := DataConfigFuncMap[tp] if ok { d := f(this.Platform, this) if d != nil { pack.Cfg = append(pack.Cfg, d) } } } if len(pack.Cfg) > 0 { this.SendToClient(int(playerproto.PlayerPacketID_PACKET_SCDataConfig), pack) logger.Logger.Tracef("SCDataConfig: %v", pack) } } func init() { internal.RegisterPlayerListenerFunc(&internal.PlayerListenerFunc[*Player, *Scene]{ ClockFunc: common.ClockFunc{}, OnPlayerLoginedFunc: nil, OnPlayerLogoutedFunc: nil, OnPlayerDropLineFunc: func(p *Player) { p.dropTime = time.Now() }, OnPlayerReholdFunc: nil, OnPlayerEnterSceneBeforeFunc: nil, OnPlayerEnterSceneAfterFunc: nil, OnPlayerLeaveSceneBeforeFunc: nil, OnPlayerLeaveSceneAfterFunc: nil, OnPlayerReturnSceneBeforeFunc: nil, OnPlayerReturnSceneAfterFunc: nil, }) }