835 lines
22 KiB
Go
835 lines
22 KiB
Go
package main
|
||
|
||
import (
|
||
"math/rand"
|
||
"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"
|
||
"mongo.games.com/goserver/srvlib/action"
|
||
srvproto "mongo.games.com/goserver/srvlib/protocol"
|
||
|
||
"mongo.games.com/game/common"
|
||
"mongo.games.com/game/model"
|
||
"mongo.games.com/game/proto"
|
||
playerproto "mongo.games.com/game/protocol/player"
|
||
serverproto "mongo.games.com/game/protocol/server"
|
||
"mongo.games.com/game/worldsrv/internal"
|
||
)
|
||
|
||
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 {
|
||
common.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 { //删除旧的玩家
|
||
DbSaveInst.UnregisterDbSaveTask(oldp)
|
||
}
|
||
DbSaveInst.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.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{}
|
||
action.BroadcastMessage(common.GetSelfAreaId(), srvlib.GateServerType, packetid, rawpack, sc)
|
||
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 {
|
||
action.MulticastMessageToServer(gateSess, packetid, rawpack, v...)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func (this *PlayerMgr) BroadcastDataConfigToPlatform(platform string, tp int) {
|
||
packetId := int(playerproto.PlayerPacketID_PACKET_SCDataConfig)
|
||
pack := &playerproto.SCDataConfig{}
|
||
f, ok := DataConfigFuncMap[tp]
|
||
if ok {
|
||
d := f(platform, nil)
|
||
if d != nil {
|
||
pack.Cfg = append(pack.Cfg, d)
|
||
}
|
||
}
|
||
if len(pack.Cfg) > 0 {
|
||
this.BroadcastMessageToPlatform(platform, packetId, 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 {
|
||
action.MulticastMessageToServer(gateSess, packetid, rawpack, v...)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 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 {
|
||
action.MulticastMessageToServer(gateSess, packetid, rawpack, v...)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// BroadcastMessageToGroup 发送群组消息
|
||
func (this *PlayerMgr) BroadcastMessageToGroup(packetid int, rawpack interface{}, tags []string) bool {
|
||
pack := &serverproto.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(serverproto.SSPacketID_PACKET_SS_CUSTOMTAG_MULTICAST), pack, common.GetSelfAreaId(), srvlib.GateServerType)
|
||
return true
|
||
}
|
||
|
||
// BroadcastMessageToTarget 给某些玩家发消息
|
||
func (this *PlayerMgr) BroadcastMessageToTarget(target []int32, packetid int, rawpack interface{}) {
|
||
mgs := make(map[*netlib.Session][]*srvproto.MCSessionUnion)
|
||
for _, v := range target {
|
||
d := this.snidMap[v]
|
||
if d != nil && d.gateSess != nil && d.IsOnLine() {
|
||
mgs[d.gateSess] = append(mgs[d.gateSess], &srvproto.MCSessionUnion{
|
||
Mccs: &srvproto.MCClientSession{
|
||
SId: proto.Int64(d.sid),
|
||
},
|
||
})
|
||
}
|
||
}
|
||
|
||
for gateSess, v := range mgs {
|
||
if gateSess != nil && len(v) != 0 {
|
||
action.MulticastMessageToServer(gateSess, packetid, rawpack, v...)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 感兴趣所有clock event
|
||
func (this *PlayerMgr) InterestClockEvent() int {
|
||
return (1 << common.ClockEventMax) - 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)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 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 (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)
|
||
|
||
// 定时器
|
||
common.ClockMgrSingleton.RegisterSinker(PlayerMgrSington)
|
||
}
|