package main import ( "math/rand" "mongo.games.com/game/worldsrv/internal" "time" "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/core/utils" "mongo.games.com/goserver/srvlib" srvproto "mongo.games.com/goserver/srvlib/protocol" "mongo.games.com/game/common" "mongo.games.com/game/model" "mongo.games.com/game/proto" server_proto "mongo.games.com/game/protocol/server" ) var PlayerMgrSington = &PlayerMgr{ sidMap: make(map[int64]*Player), snidMap: make(map[int32]*Player), accountMap: make(map[string]*Player), tokenMap: make(map[string]*Player), players: make([]*Player, 0, 1024), playerOfPlatform: make(map[string]map[int32]*Player), loading: make(map[string]*PlayerPendingData), } type PlayerPendingData struct { sid int64 // 连接标识 ts int64 // 加载数据的开始时间 } type PlayerMgr struct { BaseClockSinker sidMap map[int64]*Player // sid snidMap map[int32]*Player // snid accountMap map[string]*Player // accountid tokenMap map[string]*Player // 客服token players []*Player // 只有真实玩家 playerOfPlatform map[string]map[int32]*Player // platform:snid;只有真实玩家 loading map[string]*PlayerPendingData // accountid,控制访问频率 } // PlayerStatics 在线统计 type PlayerStatics struct { PlayerCnt int // 真人数量 RobotCnt int // 机器人数量 PlayerGamingCnt int // 游戏中的真人数量 RobotGamingCnt int // 游戏中的机器人数量 GamingCnt map[int]int // gameid:玩家人数(包含机器人) } // GetOnlineCount 在线人数统计 func (this *PlayerMgr) GetOnlineCount() *PlayerStatics { ps := &PlayerStatics{ GamingCnt: make(map[int]int), } for _, player := range this.sidMap { if player != nil && player.IsOnLine() { if !player.IsRob { ps.PlayerCnt++ if player.scene != nil { ps.PlayerGamingCnt++ } } else { ps.RobotCnt++ if player.scene != nil { ps.RobotGamingCnt++ } } if player.scene != nil { ps.GamingCnt[player.scene.gameId] = ps.GamingCnt[player.scene.gameId] + 1 } } } return ps } // IsOnline 判断玩家是否在线 func (this *PlayerMgr) IsOnline(snId int32) bool { player, ok := this.snidMap[snId] if ok { return player.IsOnLine() } else { return false } } // AddPlayer 缓存玩家数据,并添加到持久化管理器中 func (this *PlayerMgr) AddPlayer(sid int64, playerInfo *model.PlayerData, s *netlib.Session) bool { player := NewPlayer(sid, playerInfo, s) if player == nil { return false } if sid == 0 { logger.Logger.Warnf("(this *PlayerMgr) AddPlayer player sid == 0:") return false } logger.Logger.Trace("(this *PlayerMgr) AddPlayer Set player ip:", player.Ip) this.sidMap[sid] = player var oldp *Player if p, exist := this.snidMap[player.SnId]; exist { oldp = p } this.snidMap[player.SnId] = player this.accountMap[player.AccountId] = player if player.customerToken != "" { this.tokenMap[player.customerToken] = player } if !player.IsRob { var found bool for i, p := range this.players { if p.SnId == player.SnId { found = true logger.Logger.Warnf("(this *PlayerMgr) AddPlayer [this.players] found player exist snid=%v", player.SnId) this.players[i] = player break } } if !found { this.players = append(this.players, player) } if player.HeadUrl == "" { player.HeadUrl = niceIdMgr.GetRobHeadUrl(player.Head) } //平台玩家管理器 if pp, exist := this.playerOfPlatform[player.Platform]; exist { pp[player.SnId] = player } else { pp = make(map[int32]*Player) pp[player.SnId] = player this.playerOfPlatform[player.Platform] = pp } logger.Logger.Tracef("###%v mount to DBSaver[AddPlayer]", player.Name) if oldp != nil { //删除旧的玩家 DbSaver_Inst.UnregisteDbSaveTask(oldp) } DbSaver_Inst.RegisterDbSaverTask(player) niceIdMgr.NiceIdCheck(player.SnId) } else { player.NiceId = niceIdMgr.PopNiceId(player.SnId) player.HeadUrl = niceIdMgr.GetRobHeadUrlIdx() } return true } // DelPlayer 清除玩家缓存数据 // 一般真人是数据持久化后删除或数据没有修改,机器人不用持久化(机器人数据没有主动删除) func (this *PlayerMgr) DelPlayer(snid int32) bool { player, ok := this.snidMap[snid] if !ok || player == nil { return false } if player.sid != 0 { delete(this.sidMap, player.sid) } delete(this.snidMap, player.SnId) delete(this.accountMap, player.AccountId) if player.customerToken != "" { delete(this.tokenMap, player.customerToken) } if player != nil && !player.IsRob { index := -1 for i, p := range this.players { if p.SnId == snid { index = i break } } if index != -1 { this.players = append(this.players[:index], this.players[index+1:]...) } //平台玩家管理器 if pp, exist := this.playerOfPlatform[player.Platform]; exist { delete(pp, player.SnId) } niceIdMgr.PushNiceId(player.NiceId) } for _, v := range internal.GetPlayerLoads() { v.Release(player.Platform, player.SnId) } player.OnLogouted() return true } // DroplinePlayer 玩家掉线或登出 // 1.玩家登出 // 2.玩家网络断开 // 3.被踢掉线 func (this *PlayerMgr) DroplinePlayer(p *Player) { delete(this.sidMap, p.sid) } // ReholdPlayer 玩家重连 // 1.登录获取玩家数据 func (this *PlayerMgr) ReholdPlayer(p *Player, newSid int64, newSess *netlib.Session) { if p.sid != 0 { delete(this.sidMap, p.sid) } if newSid == 0 { logger.Logger.Errorf("(this *PlayerMgr) ReholdPlayer(snid=%v, new=%v)", p.SnId, newSid) } p.sid = newSid p.gateSess = newSess p.SetOnline() this.sidMap[newSid] = p } // GetPlayer 获取玩家数据(玩家在线) func (this *PlayerMgr) GetPlayer(id int64) *Player { if pi, ok := this.sidMap[id]; ok { return pi } return nil } func (this *PlayerMgr) GetPlayerBySnId(id int32) *Player { if p, ok := this.snidMap[id]; ok { return p } return nil } func (this *PlayerMgr) GetPlatformPlayerBySnId(platform string, id int32) *Player { if players, exit := this.playerOfPlatform[platform]; exit { if p, ok := players[id]; ok { return p } } return nil } // GetPlayersBySnIds 批量取出玩家信息 func (this *PlayerMgr) GetPlayersBySnIds(ids []int32) []*Player { var retPlayers []*Player for _, v := range ids { if p, ok := this.snidMap[v]; ok { retPlayers = append(retPlayers, p) } } return retPlayers } func (this *PlayerMgr) GetPlayerByAccount(acc string) *Player { if p, ok := this.accountMap[acc]; ok { return p } return nil } func (this *PlayerMgr) GetPlayerByToken(token string) *Player { if p, ok := this.tokenMap[token]; ok { return p } return nil } func (this *PlayerMgr) UpdatePlayerToken(p *Player, newToken string) { oldToken := p.customerToken if oldToken != newToken { if oldToken != "" { if _, ok := this.tokenMap[oldToken]; ok { delete(this.tokenMap, oldToken) } } if newToken != "" { this.tokenMap[newToken] = p p.customerToken = newToken } } } // BroadcastMessage 给所有玩家发消息 func (this *PlayerMgr) BroadcastMessage(packetid int, rawpack interface{}) bool { sc := &srvproto.BCSessionUnion{ Bccs: &srvproto.BCClientSession{}, } pack, err := BroadcastMaker.CreateBroadcastPacket(sc, packetid, rawpack) if err == nil && pack != nil { srvlib.ServerSessionMgrSington.Broadcast(int(srvproto.SrvlibPacketID_PACKET_SS_BROADCAST), pack, common.GetSelfAreaId(), srvlib.GateServerType) return true } return false } // BroadcastMessageToPlatform 给某个平台所有玩家发消息 func (this *PlayerMgr) BroadcastMessageToPlatform(platform string, packetid int, rawpack interface{}) { if platform == "" { this.BroadcastMessage(packetid, rawpack) } else { players := this.playerOfPlatform[platform] mgs := make(map[*netlib.Session][]*srvproto.MCSessionUnion) for _, p := range players { if p != nil && p.gateSess != nil && p.IsOnLine() /*&& p.Platform == platform*/ { mgs[p.gateSess] = append(mgs[p.gateSess], &srvproto.MCSessionUnion{ Mccs: &srvproto.MCClientSession{ SId: proto.Int64(p.sid), }, }) } } for gateSess, v := range mgs { if gateSess != nil && len(v) != 0 { pack, err := MulticastMaker.CreateMulticastPacket(packetid, rawpack, v...) if err == nil { proto.SetDefaults(pack) gateSess.Send(int(srvproto.SrvlibPacketID_PACKET_SS_MULTICAST), pack) } } } } } func (this *PlayerMgr) BroadcastMessageToPlatformByFunc(platform string, packetid int, rawpack interface{}, f func(p *Player) bool) { if platform == "" { this.BroadcastMessage(packetid, rawpack) } else { players := this.playerOfPlatform[platform] mgs := make(map[*netlib.Session][]*srvproto.MCSessionUnion) for _, p := range players { if p != nil && p.gateSess != nil && p.IsOnLine() && f(p) { mgs[p.gateSess] = append(mgs[p.gateSess], &srvproto.MCSessionUnion{ Mccs: &srvproto.MCClientSession{ SId: proto.Int64(p.sid), }, }) } } for gateSess, v := range mgs { if gateSess != nil && len(v) != 0 { pack, err := MulticastMaker.CreateMulticastPacket(packetid, rawpack, v...) if err == nil { proto.SetDefaults(pack) gateSess.Send(int(srvproto.SrvlibPacketID_PACKET_SS_MULTICAST), pack) } } } } } // BroadcastMessageToPlatformWithHall 给某个平台所有在大厅中的玩家发消息 func (this *PlayerMgr) BroadcastMessageToPlatformWithHall(platform string, snid int32, packetid int, rawpack interface{}) { if platform == "" { this.BroadcastMessage(packetid, rawpack) } else { player := this.GetPlayerBySnId(snid) if player != nil { players := this.playerOfPlatform[platform] mgs := make(map[*netlib.Session][]*srvproto.MCSessionUnion) for _, p := range players { if p != nil && p.gateSess != nil && p.IsOnLine() && p.scene == nil { if FriendMgrSington.IsShield(p.Platform, p.SnId, snid) { continue } mgs[p.gateSess] = append(mgs[p.gateSess], &srvproto.MCSessionUnion{ Mccs: &srvproto.MCClientSession{ SId: proto.Int64(p.sid), }, }) } } for gateSess, v := range mgs { if gateSess != nil && len(v) != 0 { pack, err := MulticastMaker.CreateMulticastPacket(packetid, rawpack, v...) if err == nil { proto.SetDefaults(pack) gateSess.Send(int(srvproto.SrvlibPacketID_PACKET_SS_MULTICAST), pack) } } } } } } // BroadcastMessageToGroup 发送群组消息 func (this *PlayerMgr) BroadcastMessageToGroup(packetid int, rawpack interface{}, tags []string) bool { pack := &server_proto.SSCustomTagMulticast{ Tags: tags, } if byteData, ok := rawpack.([]byte); ok { pack.RawData = byteData } else { byteData, err := netlib.MarshalPacket(packetid, rawpack) if err == nil { pack.RawData = byteData } else { logger.Logger.Info("PlayerMgr.BroadcastMessageToGroup err:", err) return false } } srvlib.ServerSessionMgrSington.Broadcast(int(server_proto.SSPacketID_PACKET_SS_CUSTOMTAG_MULTICAST), pack, common.GetSelfAreaId(), srvlib.GateServerType) return true } // BroadcastMessageToTarget 给某些玩家发消息 func (this *PlayerMgr) BroadcastMessageToTarget(platform string, target []int32, packetid int, rawpack interface{}) { players := this.playerOfPlatform[platform] mgs := make(map[*netlib.Session][]*srvproto.MCSessionUnion) for _, p := range players { if p != nil && p.gateSess != nil && p.IsOnLine() /*&& p.Platform == platform*/ { if common.InSliceInt32(target, p.SnId) { mgs[p.gateSess] = append(mgs[p.gateSess], &srvproto.MCSessionUnion{ Mccs: &srvproto.MCClientSession{ SId: proto.Int64(p.sid), }, }) } } } for gateSess, v := range mgs { if gateSess != nil && len(v) != 0 { pack, err := MulticastMaker.CreateMulticastPacket(packetid, rawpack, v...) if err == nil { proto.SetDefaults(pack) gateSess.Send(int(srvproto.SrvlibPacketID_PACKET_SS_MULTICAST), pack) } } } } // 感兴趣所有clock event func (this *PlayerMgr) InterestClockEvent() int { return (1 << CLOCK_EVENT_MAX) - 1 } func (this *PlayerMgr) OnSecTimer() { for _, player := range this.players { utils.CatchPanic(func() { player.OnSecTimer() }) } } func (this *PlayerMgr) OnMiniTimer() { for _, player := range this.players { utils.CatchPanic(func() { player.OnMiniTimer() }) } } func (this *PlayerMgr) OnHourTimer() { for _, player := range this.players { utils.CatchPanic(func() { player.OnHourTimer() }) } } func (this *PlayerMgr) OnDayTimer() { for _, player := range this.players { utils.CatchPanic(func() { player.OnDayTimer(false, true, 1) }) } } func (this *PlayerMgr) OnMonthTimer() { for _, player := range this.players { utils.CatchPanic(func() { player.OnMonthTimer() }) } } func (this *PlayerMgr) OnWeekTimer() { for _, player := range this.players { utils.CatchPanic(func() { player.OnWeekTimer() }) } } func (this *PlayerMgr) OnShutdown() { this.SaveAll() } // SaveAll 保存所有数据,dirty=true func (this *PlayerMgr) SaveAll() { count := len(this.players) start := time.Now() saveCnt := 0 failCnt := 0 nochangeCnt := 0 logger.Logger.Info("===@PlayerMgr.SaveAll BEG@=== TotalCount:", count) for i, p := range this.players { idx := i + 1 if p.dirty { if model.SavePlayerData(p.PlayerData) { logger.Logger.Infof("===@SavePlayerData %v/%v snid:%v coin:%v safebox:%v coinpayts:%v safeboxts:%v gamets:%v save [ok] @=", idx, count, p.SnId, p.Coin, p.SafeBoxCoin, p.CoinPayTs, p.SafeBoxCoinTs, p.GameCoinTs) saveCnt++ } else { logger.Logger.Warnf("===@SavePlayerData %v/%v snid:%v coin:%v safebox:%v coinpayts:%v safeboxts:%v gamets:%v save [error]@=", idx, count, p.SnId, p.Coin, p.SafeBoxCoin, p.CoinPayTs, p.SafeBoxCoinTs, p.GameCoinTs) failCnt++ } } else { logger.Logger.Infof("nochange===@SavePlayerData %v/%v snid:%v coin:%v safebox:%v coinpayts:%v safeboxts:%v gamets:%v nochange [ok]@=", idx, count, p.SnId, p.Coin, p.SafeBoxCoin, p.CoinPayTs, p.SafeBoxCoinTs, p.GameCoinTs) nochangeCnt++ } for _, v := range internal.GetPlayerLoads() { v.Save(p.Platform, p.SnId, true, true) } } logger.Logger.Infof("===@PlayerMgr.SaveAll END@===, total:%v saveCnt:%v failCnt:%v nochangeCnt:%v take:%v", count, saveCnt, failCnt, nochangeCnt, time.Now().Sub(start)) } // 黑名单事件 //func (this *PlayerMgr) OnAddBlackInfo(blackinfo *BlackInfo) { // if blackinfo.Snid > 0 { // if p := this.GetPlayerBySnId(blackinfo.Snid); p != nil { // p.PlayerData.BlacklistType = int32(blackinfo.BlackType) // p.dirty = true // p.Time2Save() // } else { // task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { // model.UpdatePlayerBlacklistType(blackinfo.Platform, blackinfo.Snid, int32(blackinfo.BlackType)) // return nil // }), nil, "PlayerMgrOnAddBlackInfo").Start() // } // } //} //func (this *PlayerMgr) OnEditBlackInfo(blackinfo *BlackInfo) { // //nothing // //if blackinfo.Snid > 0 { // // if p := this.GetPlayerBySnId(blackinfo.Snid); p != nil { // // p.PlayerData.BlacklistType = int32(blackinfo.BlackType) // // p.dirty = true // // p.Time2Save() // // } else { // // task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { // // model.UpdatePlayerBlacklistType(blackinfo.Platform, blackinfo.Snid, int32(blackinfo.BlackType)) // // return nil // // }), nil, "PlayerMgrOnEditBlackInfo").Start() // // } // //} //} //func (this *PlayerMgr) OnRemoveBlackInfo(blackinfo *BlackInfo) { // //nothing // //if blackinfo.Snid > 0 { // // if p := this.GetPlayerBySnId(blackinfo.Snid); p != nil { // // p.PlayerData.BlacklistType = 0 // // p.dirty = true // // p.Time2Save() // // } else { // // task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { // // model.UpdatePlayerBlacklistType(blackinfo.Platform, blackinfo.Snid, int32(0)) // // return nil // // }), nil, "PlayerMgrOnRemoveBlackInfo").Start() // // } // //} //} func (this *PlayerMgr) KickoutByPlatform(name string) { for _, p := range this.players { if name == "" || p.Platform == name { p.Kickout(common.KickReason_Disconnection) } } } func (this *PlayerMgr) UpdateAllPlayerPackageTag(packageTag, platform, channel, promoter string, promoterTree, tagkey int32) int { var cnt int for _, p := range this.players { if p != nil && !p.IsRob { if p.PackageID == packageTag { p.Platform = platform p.Channel = channel p.BeUnderAgentCode = promoter p.PromoterTree = promoterTree //p.TagKey = tagkey p.dirty = true cnt++ } } } return cnt } // LoadRobots 预加载机器人数据 func (this *PlayerMgr) LoadRobots() { if model.GameParamData.PreLoadRobotCount > 0 { task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { tsBeg := time.Now() robots := model.GetRobotPlayers(model.GameParamData.PreLoadRobotCount) tsEnd := time.Now() logger.Logger.Tracef("GetRobotPlayers take:%v total:%v", tsEnd.Sub(tsBeg), len(robots)) return robots }), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) { if robots, ok := data.([]*model.PlayerData); ok { if robots != nil { for i := 0; i < len(robots); i++ { if this.GetPlayerBySnId(robots[i].SnId) == nil { player := NewPlayer(0, robots[i], nil) if player != nil { this.snidMap[player.SnId] = player this.accountMap[player.AccountId] = player if player.customerToken != "" { this.tokenMap[player.customerToken] = player } } } } } } }), "GetRobotPlayers").Start() } } func (this *PlayerMgr) StartLoading(accid string, sid int64) bool { ts := time.Now().Unix() if d, exist := this.loading[accid]; exist { d.sid = sid if ts-d.ts > 300 { d.ts = ts return false } return true } this.loading[accid] = &PlayerPendingData{sid: sid, ts: ts} return false } func (this *PlayerMgr) EndPlayerLoading(accid string) int64 { if d, exist := this.loading[accid]; exist { delete(this.loading, accid) return d.sid } return 0 } //func PlayerRankGe(p1, p2 *Player, n int) bool { // switch n { // case 0: // if p1.TotalCoin == p2.TotalCoin { // return p1.SnId < p2.SnId // } else { // return p1.TotalCoin > p2.TotalCoin // } // case 1: // if p1.CoinPayTotal == p2.CoinPayTotal { // return p1.SnId < p2.SnId // } else { // return p1.CoinPayTotal > p2.CoinPayTotal // } // case 2: // if p1.CoinExchangeTotal == p2.CoinExchangeTotal { // return p1.SnId < p2.SnId // } else { // return p1.CoinExchangeTotal > p2.CoinExchangeTotal // } // case 3: // a := p1.Coin + p1.SafeBoxCoin - p1.CoinPayTotal // b := p2.Coin + p2.SafeBoxCoin - p2.CoinPayTotal // if a == b { // return p1.SnId < p2.SnId // } else { // return a > b // } // // } // return false //} // func (this *PlayerMgr) GetRank() map[string][]*model.Rank { // ret := make(map[string][]*model.Rank) // ls := make(map[string]*list.List) // // platforms := PlatformMgrSingleton.Platforms // for p := range platforms { // ret[p] = make([]*model.Rank, 0) // ls[p] = list.New() // } // // for _, player := range this.players { // if player.IsRob { // continue // } // // p := player.PlayerData.Platform // if _, ok := platforms[p]; !ok { // continue // } // // l := ls[p] // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // if PlayerRankGe(player, np) { // l.InsertBefore(player, n) // goto CHECK // } // } // //else { // // logger.Logger.Warnf("PlayerMgr.GetRank n.Value.(*Player) fail") // // continue // //} // } // // l.PushBack(player) // CHECK: // if l.Len() > model.MAX_RANK_COUNT { // l.Remove(l.Back()) // } // } // // for p := range platforms { // l := ls[p] // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // ret[p] = append(ret[p], &model.Rank{ // SnId: np.PlayerData.SnId, // Name: np.PlayerData.Name, // Head: np.PlayerData.Head, // VIP: np.PlayerData.VIP, // TotalCoin: np.PlayerData.TotalCoin, // }) // } // } // } // // return ret // } //func (this *PlayerMgr) GetAssetRank(platform string) []*model.Rank { // ret := make([]*model.Rank, 0, model.MAX_RANK_COUNT) // l := list.New() // // for _, player := range this.players { // if player.IsRob { // continue // } // // if player.PlayerData.Platform != platform { // continue // } // // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // if PlayerRankGe(player, np, 0) { // l.InsertBefore(player, n) // goto CHECK // } // } // } // // l.PushBack(player) // CHECK: // if l.Len() > model.MAX_RANK_COUNT { // l.Remove(l.Back()) // } // } // // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // ret = append(ret, &model.Rank{ // SnId: np.PlayerData.SnId, // Name: np.PlayerData.Name, // Head: np.PlayerData.Head, // VIP: np.PlayerData.VIP, // TotalCoin: np.PlayerData.TotalCoin, // }) // } // } // // return ret //} //func (this *PlayerMgr) GetRechargeLists(platform string) []*model.Rank { // ret := make([]*model.Rank, 0, model.MAX_RANK_COUNT) // l := list.New() // // for _, player := range this.players { // if player.IsRob { // continue // } // // if player.PlayerData.Platform != platform { // continue // } // // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // if PlayerRankGe(player, np, 1) { // l.InsertBefore(player, n) // goto CHECK // } // } // } // // l.PushBack(player) // CHECK: // if l.Len() > model.MAX_RANK_COUNT { // l.Remove(l.Back()) // } // } // // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // ret = append(ret, &model.Rank{ // SnId: np.PlayerData.SnId, // Name: np.PlayerData.Name, // Head: np.PlayerData.Head, // VIP: np.PlayerData.VIP, // TotalCoin: np.PlayerData.CoinPayTotal, // }) // } // } // // return ret //} //func (this *PlayerMgr) GetExchangeLists(platform string) []*model.Rank { // ret := make([]*model.Rank, 0, model.MAX_RANK_COUNT) // l := list.New() // // for _, player := range this.players { // if player.IsRob { // continue // } // // if player.PlayerData.Platform != platform { // continue // } // // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // if PlayerRankGe(player, np, 2) { // l.InsertBefore(player, n) // goto CHECK // } // } // } // // l.PushBack(player) // CHECK: // if l.Len() > model.MAX_RANK_COUNT { // l.Remove(l.Back()) // } // } // // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // ret = append(ret, &model.Rank{ // SnId: np.PlayerData.SnId, // Name: np.PlayerData.Name, // Head: np.PlayerData.Head, // VIP: np.PlayerData.VIP, // TotalCoin: np.PlayerData.CoinExchangeTotal, // }) // } // } // // return ret //} //func (this *PlayerMgr) GetProfitLists(platform string) []*model.Rank { // ret := make([]*model.Rank, 0, model.MAX_RANK_COUNT) // l := list.New() // // for _, player := range this.players { // if player.IsRob { // continue // } // // if player.PlayerData.Platform != platform { // continue // } // // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // if PlayerRankGe(player, np, 3) { // l.InsertBefore(player, n) // goto CHECK // } // } // } // // l.PushBack(player) // CHECK: // if l.Len() > model.MAX_RANK_COUNT { // l.Remove(l.Back()) // } // } // // for n := l.Front(); n != nil; n = n.Next() { // if np, ok := n.Value.(*Player); ok { // ret = append(ret, &model.Rank{ // SnId: np.PlayerData.SnId, // Name: np.PlayerData.Name, // Head: np.PlayerData.Head, // VIP: np.PlayerData.VIP, // //TotalCoin: np.PlayerData.ProfitCoin, // }) // } // } // // return ret //} //func (this *PlayerMgr) DeletePlayerByPlatform(platform string) { // var dels []*Player // for _, p := range this.players { // if p != nil && p.Platform == platform { // p.Kickout(common.KickReason_Disconnection) // dels = append(dels, p) // } // } // // for _, p := range dels { // if p != nil { // p.isDelete = true // if p.scene == nil { // this.DelPlayer(p.SnId) // } // } // } //} func (this *PlayerMgr) StatsOnline() model.PlayerOLStats { stats := model.PlayerOLStats{ PlatformStats: make(map[string]*model.PlayerStats), RobotStats: model.PlayerStats{ InGameCnt: make(map[int32]map[int32]int32), }, } for _, p := range this.sidMap { if p != nil { if p.IsRob { pps := &stats.RobotStats if pps != nil { if p.scene == nil { pps.InHallCnt++ } else { if g, exist := pps.InGameCnt[int32(p.scene.gameId)]; exist { g[p.scene.dbGameFree.GetId()]++ } else { g := make(map[int32]int32) pps.InGameCnt[int32(p.scene.gameId)] = g g[p.scene.dbGameFree.GetId()]++ } } } } else { var pps *model.PlayerStats var exist bool if pps, exist = stats.PlatformStats[p.Platform]; !exist { pps = &model.PlayerStats{InGameCnt: make(map[int32]map[int32]int32)} stats.PlatformStats[p.Platform] = pps } if pps != nil { if p.scene == nil { pps.InHallCnt++ } else { if g, exist := pps.InGameCnt[int32(p.scene.gameId)]; exist { g[p.scene.dbGameFree.GetId()]++ } else { g := make(map[int32]int32) pps.InGameCnt[int32(p.scene.gameId)] = g g[p.scene.dbGameFree.GetId()]++ } } } } } } return stats } func (p *PlayerMgr) UpdateName(snId int32, name string) { player := p.GetPlayerBySnId(snId) if player == nil { return } player.setName(name) player.dirty = true } func (p *PlayerMgr) UpdateHead(snId, head int32) { player := p.GetPlayerBySnId(snId) if player == nil { return } player.Head = head //0:男 1:女 player.Sex = (player.Head%2 + 1) % 2 player.dirty = true player.changeIconTime = time.Now() } func (p *PlayerMgr) UpdateHeadOutline(snId, outline int32) { player := p.GetPlayerBySnId(snId) if player == nil { return } player.HeadOutLine = outline player.dirty = true } func (p *PlayerMgr) UpdateHeadUrl(snId int32, url string) { player := p.GetPlayerBySnId(snId) if player == nil { return } if player.HeadUrl != url { player.HeadUrl = url player.dirty = true } } //func (p *PlayerMgr) ModifyActSwitchToPlayer(platform string, modify bool) { // if modify { //活动开关修改了才去更新活动开关 // if players, ok := p.playerOfPlatform[platform]; ok { // for _, p := range players { // if p != nil && !p.IsRob { // p.ModifyActSwitch() // } // } // } // } //} /* 推荐好友规则 1.优先判断在线玩家人数N (1)N≥20;每次刷新,从在线玩家中随机6个 (2)N<20;则填充机器人,保证N=20,每次填充的机器人头像和昵称随机;然后从N中随机6个 2.刷新有CD(暂定20s),刷新过后进入cd */ type RecommendFriend struct { Snid int32 Name string Head int32 HeadUrl string RoleId int32 } // RecommendFriendRule 推荐好友 func (this *PlayerMgr) RecommendFriendRule(platform string, snid int32) []RecommendFriend { if platform == "" { return nil } else { rets := []RecommendFriend{} players := this.playerOfPlatform[platform] for _, player := range players { //优先真人 if player.SnId != snid && !FriendMgrSington.IsFriend(platform, snid, player.SnId) { roleId := common.DefaultRoleId if player.Roles != nil { roleId = int(player.Roles.ModId) } ret := RecommendFriend{ Snid: player.SnId, Name: player.Name, Head: player.Head, HeadUrl: player.HeadUrl, RoleId: int32(roleId), } rets = append(rets, ret) if len(rets) >= 20 { break } } } if len(rets) < 20 { for _, player := range this.snidMap { //其次机器人 if player.IsRob { roleId := common.DefaultRoleId if player.Roles != nil { roleId = int(player.Roles.ModId) } ret := RecommendFriend{ Snid: player.SnId, Name: player.Name, Head: player.Head, HeadUrl: player.HeadUrl, RoleId: int32(roleId), } rets = append(rets, ret) if len(rets) >= 20 { break } } } } needIdxs := []int{} if rets != nil { if len(rets) >= 6 { for { if len(needIdxs) >= 6 { break } randIdx := rand.Intn(len(rets)) if !common.InSliceInt(needIdxs, randIdx) { needIdxs = append(needIdxs, randIdx) } } } else { for i := 0; i < len(rets); i++ { needIdxs = append(needIdxs, i) } } } ret := []RecommendFriend{} for _, idx := range needIdxs { ret = append(ret, rets[idx]) } return ret } } func init() { //BlackListMgrSington.RegisterObserver(PlayerMgrSington) PlayerSubjectSign.AttachName(PlayerMgrSington) PlayerSubjectSign.AttachHead(PlayerMgrSington) PlayerSubjectSign.AttachHeadOutline(PlayerMgrSington) PlayerSubjectSign.AttachHeadUrl(PlayerMgrSington) PlayerSubjectSign.AttachName(FriendMgrSington) PlayerSubjectSign.AttachHead(FriendMgrSington) // 定时器 ClockMgrSington.RegisteSinker(PlayerMgrSington) }