| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- package model
- import (
- "math/rand"
- "rocommon"
- "rocommon/service"
- "rocommon/util"
- "roserver/baseserver/model"
- "roserver/baseserver/set"
- "roserver/serverproto"
- )
- type RoleManager struct {
- rocommon.UpdateModule
- onlineNum int
- channelRoleList map[uint64]RoleOuter //[channelid,Role]
- uuidRoleList map[uint64]RoleOuter //[uuid,role]
- offlineRoleList map[uint64]RoleOuter //[uuid,role]
- openRoleList map[string]RoleOuter //[openid,rol]
- updateTimer util.ServerTimer //主循环定时器
- lastResetTime uint64
- playerFifoList set.Interface //最近在线玩家列表 FIFO
- noticeInfo *serverproto.SSWebGMNoticeNtf //走马灯公告
- tw *util.TimeWheel
- allGameOnlineNum int32 //所有game服务器当前在线的玩家数量
- }
- func NewRoleManager() *RoleManager {
- rm := &RoleManager{
- channelRoleList: make(map[uint64]RoleOuter),
- uuidRoleList: make(map[uint64]RoleOuter),
- offlineRoleList: make(map[uint64]RoleOuter),
- openRoleList: make(map[string]RoleOuter),
- lastResetTime: util.GetTimeMilliseconds(),
- }
- //rm.updateTimer = util.NewDurationTimer(util.GetCurrentTime(), 500)
- rm.updateTimer = util.NewDurationTimer(util.GetCurrentTime(), 2000)
- rm.playerFifoList = set.New(set.NonThreadSafe)
- rm.tw = util.NewTimeWheel(100, 32)
- rm.tw.Callback = rm.UpdateWithTimeTimeWheelTask
- return rm
- }
- var updateCount = 0
- var ResetCount = 0
- func (this *RoleManager) Update(ms uint64) {
- if !this.updateTimer.IsStart() || !this.updateTimer.IsExpired(ms) {
- return
- }
- //注意不能5点后停服,5点后启服(不会触发隔天重置)
- dailyResetHour5 := model.IsDailyResetHour5(this.lastResetTime)
- if dailyResetHour5 {
- rand.Seed(int64(ms))
- }
- //dailyReset := model.IsDailyReset(this.lastResetTime)
- //if dailyReset {
- // rand.Seed(int64(util.GetTimeMilliseconds()))
- //}
- //已经离线的玩家处理
- for key, offRole := range this.offlineRoleList {
- //offRole.Update(ms)
- if offRole.IsLogout(ms) {
- offRole.Logout()
- delete(this.offlineRoleList, key)
- delete(this.openRoleList, offRole.GetOpenId())
- util.DebugF("Role delete offline=%v uid=%v", key, offRole.GetUUid())
- }
- }
- this.onlineNum = 0
- ResetCount = 0
- for key, chRole := range this.channelRoleList {
- switch chRole.GetState() {
- case ROLE_STATE_OFFLINE:
- chRole.Update(ms)
- delete(this.channelRoleList, key)
- delete(this.uuidRoleList, chRole.GetUUid())
- //放到离线处理中
- this.addOfflineRole(chRole.GetUUid(), chRole)
- util.DebugF("Role delete ROLE_STATE_OFFLINE clid=%v uid=%v", key, chRole.GetUUid())
- case ROLE_STATE_ZOMBIE:
- //需要做删除操作
- delete(this.channelRoleList, key)
- delete(this.uuidRoleList, chRole.GetUUid())
- delete(this.offlineRoleList, chRole.GetUUid())
- delete(this.openRoleList, chRole.GetOpenId())
- chRole.Logout()
- util.DebugF("Role delete ROLE_STATE_ZOMBIE clid=%v uid=%v", key, chRole.GetUUid())
- case ROLE_STATE_ONLINE:
- chRole.Update(ms)
- this.onlineNum++
- //每日重置
- if dailyResetHour5 {
- //设置reset标记,在每个玩家自身的update中处理
- //chRole.DailyReset(true)
- chRole.SetUpdateDailyReset(ms, true)
- //ResetCount++
- }
- }
- }
- updateCount++
- //if updateCount > 50 {
- // updateCount = 0
- // //util.InfoF("RoleManager update onlineNum=%v offlineNum=%v", this.onlineNum, len(this.offlineRoleList))
- //}
- if ResetCount > 0 {
- util.InfoF("RoleManager dailyreset online=%v resetnum=%v", this.onlineNum, ResetCount)
- }
- //12表示1分钟(60表示5分钟)
- if this.onlineNum > 0 && updateCount >= 60 {
- updateCount = 0
- model.ElasticPutLogInfo(&model.ElasticLogST{
- LogType: "RoleOnlineNum",
- LogDesc: "RoleOnlineNum",
- Param1: this.onlineNum,
- })
- tmpNode := service.GetServiceConfig().Node
- //netease log
- nLog := &NeteaseLogOnlineRoleNum{
- Server: service.GetServiceConfig().Node.Zone*100 + service.GetServiceConfig().Node.Id,
- Online: this.onlineNum,
- OnLineTime: uint64(util.GetTimeSeconds()),
- }
- nLog.Log(nil)
- //添加到mysql log
- logData := &serverproto.SSRoleLogData{
- Type: int32(serverproto.MysqlLogType_LType_OnlineNum),
- ParamList: []int32{int32(tmpNode.Zone), int32(tmpNode.Id), int32(this.onlineNum)}, //zoneid,subid,onlinenum
- }
- mysqlOnlineNumNtf := &serverproto.SSRoleLogNtf{}
- mysqlOnlineNumNtf.LogList = append(mysqlOnlineNumNtf.LogList, logData)
- SendDb(mysqlOnlineNumNtf)
- }
- if dailyResetHour5 {
- this.lastResetTime = ms
- }
- }
- func (this *RoleManager) UpdateWithTimeWheel(ms uint64) {
- this.tw.Update(ms)
- }
- //task tick
- func (this *RoleManager) UpdateWithTimeTimeWheelTask(twTask *util.TWTask, ms uint64) {
- chRole, ok := this.uuidRoleList[twTask.Uid]
- if !ok {
- chRole, ok = this.offlineRoleList[twTask.Uid]
- if !ok {
- util.WarnF("uid=%v UpdateWithTimeTimeWheelTask save but role data not find", twTask.Uid)
- return
- }
- }
- chRole.Save()
- if chRole.GetState() == ROLE_STATE_ONLINE ||
- chRole.GetState() == ROLE_STATE_OFFLINE {
- chRole.Save()
- }
- }
- //bool表示给定的cid是否已经存在role, bool是否已经存在
- func (this *RoleManager) AddRole(cid model.ClientID, openId string, selectZone int32) (RoleOuter, bool, bool) {
- role, ok := this.channelRoleList[cid.SessID]
- if ok {
- util.WarnF("channel role exist id=", cid)
- return role, true, false
- }
- util.WarnF("AddRole openid=%v", openId)
- bHas := false
- role, ok = this.openRoleList[openId]
- if !ok {
- role = NewRole(cid)
- } else {
- bHas = true
- if role.GetSelectZone() != selectZone {
- delete(this.channelRoleList, role.CliID().SessID)
- delete(this.uuidRoleList, role.GetUUid())
- delete(this.openRoleList, openId)
- role.SwitchState(ROLE_STATE_ZOMBIE, nil)
- role = NewRole(cid)
- bHas = false
- }
- }
- this.channelRoleList[cid.SessID] = role
- this.openRoleList[openId] = role
- return role, false, bHas
- }
- func (this *RoleManager) AddRoleObj(role RoleOuter) bool {
- //if _, ok := this.channelRoleList[role.CliID().SessID]; ok {
- // return false
- //}
- //if _, ok := this.uuidRoleList[role.GetUUid()]; ok {
- // return false
- //}
- if role.GetUUid() == 0 {
- util.InfoF("AddRoleObj uid=0")
- }
- this.channelRoleList[role.CliID().SessID] = role
- this.uuidRoleList[role.GetUUid()] = role
- return true
- }
- func (this *RoleManager) RemoveRoleObj(role RoleOuter) bool {
- delete(this.channelRoleList, role.CliID().SessID)
- delete(this.uuidRoleList, role.GetUUid())
- return true
- }
- func (this *RoleManager) RemoveRoleObjByOpenId(openId string) {
- delete(this.openRoleList, openId)
- }
- //添加到uuid角色列表中
- func (this *RoleManager) Resolve(role *Role) {
- if role.GetUUid() == 0 {
- util.InfoF("AddRoleObj uid=0")
- }
- if _, ok := this.uuidRoleList[role.GetUUid()]; ok {
- //log.Println("channel role exist id:", role.GetUUid())
- return
- }
- this.uuidRoleList[role.GetUUid()] = role
- }
- func (this *RoleManager) GetRole(cid model.ClientID) RoleOuter {
- if role, ok := this.channelRoleList[cid.SessID]; ok {
- return role
- } else {
- if role, ok := this.uuidRoleList[cid.SessID]; ok {
- return role
- }
- }
- util.InfoF("role not found id=%v", cid)
- return nil
- }
- func (this *RoleManager) GetRoleOrKick(cid model.ClientID, ev rocommon.ProcEvent) RoleOuter {
- role := this.GetRole(cid)
- if role == nil {
- ev.Session().Send(&serverproto.SSUserKickNtf{
- Error: int32(serverproto.ErrorCode_ERROR_OK),
- ClientId: cid.SessID,
- })
- } else if ev.SeqId() > 0 {
- //序列号处理
- msgInfo := rocommon.MessageInfoByMsg(ev.Msg())
- role.ReqAckConfirm(uint32(msgInfo.ID), ev.SeqId())
- }
- return role
- }
- func (this *RoleManager) GetRoleFromChannel(id uint64) RoleOuter {
- if role, ok := this.channelRoleList[id]; ok {
- return role
- }
- return nil
- }
- func (this *RoleManager) RemoveRoleFromChannel(id uint64) bool {
- delete(this.channelRoleList, id)
- return true
- }
- func (this *RoleManager) RemoveOfflineRole(id uint64) bool {
- delete(this.offlineRoleList, id)
- return true
- }
- func (this *RoleManager) GetRoleFromUUid(id uint64) RoleOuter {
- if role, ok := this.uuidRoleList[id]; ok {
- return role
- }
- util.InfoF("role not found uid=%v", id)
- return nil
- }
- func (this *RoleManager) GetRoleByOpenId(openId string) RoleOuter {
- if role, ok := this.openRoleList[openId]; ok {
- return role
- }
- return nil
- }
- func (this *RoleManager) GetRoleUUIdList() map[uint64]RoleOuter {
- return this.uuidRoleList
- }
- func (this *RoleManager) GetRoleFromOffline(id uint64) RoleOuter {
- if role, ok := this.offlineRoleList[id]; ok {
- return role
- }
- return nil
- }
- func (this *RoleManager) GetRoleOfflineList() map[uint64]RoleOuter {
- return this.offlineRoleList
- }
- func (this *RoleManager) AddFIFOList(uid uint64) {
- if this.playerFifoList.Size() >= 200 {
- this.playerFifoList.Pop()
- }
- if !this.playerFifoList.Has(uid) {
- this.playerFifoList.Add(uid)
- }
- }
- func (this *RoleManager) GetFIFOList(idx, num int32, role *Role, exceptUidList map[uint64]struct{}) (bool, []uint64) {
- var retUidList []uint64
- if role == nil {
- return false, retUidList
- }
- if idx <= 0 {
- idx = 1
- }
- var retSetList = set.New(set.NonThreadSafe)
- var count int32 = 0
- for _, data := range this.playerFifoList.List() {
- count++
- tmpUid := data.(uint64)
- if tmpUid <= 0 {
- continue
- }
- if count >= idx && num > 0 {
- if role.GetRoleSocial().isInSubList(tmpUid) || tmpUid == role.GetUUid() {
- continue
- }
- if _, ok := exceptUidList[tmpUid]; ok {
- continue
- }
- num--
- retSetList.Add(data)
- retUidList = append(retUidList, tmpUid)
- if num <= 0 {
- break
- }
- }
- }
- if num > 0 {
- for _, data := range this.playerFifoList.List() {
- tmpUid := data.(uint64)
- if tmpUid <= 0 {
- continue
- }
- if role.GetRoleSocial().isInSubList(tmpUid) || tmpUid == role.GetUUid() {
- continue
- }
- if _, ok := exceptUidList[tmpUid]; ok {
- continue
- }
- //表示之前已经遍历过,不需要继续
- if retSetList.Has(data) {
- break
- }
- num--
- retUidList = append(retUidList, tmpUid)
- if num <= 0 {
- break
- }
- }
- return false, retUidList
- }
- return true, retUidList
- }
- //[sessionId]clientuse channelid
- //[serviceID] 所在的网关节点
- func (this *RoleManager) KickFromGate(sessionId uint64, serviceID string) {
- if tmpRole, ok := this.channelRoleList[sessionId]; ok {
- if tmpRole.CliID().SessID == sessionId && tmpRole.GetState() == ROLE_STATE_ONLINE {
- util.InfoF("uid=%v KickFromGate sessionId=%v", tmpRole.GetUUid(), sessionId)
- tmpRole.SwitchState(ROLE_STATE_OFFLINE, nil)
- }
- } else {
- //服务器重启,客户端没有关闭的情况下会有该错误
- //发送CSLoginReq请求到达比断开连接到达要快
- util.ErrorF("KickFromGate sessionId=%v err=not find", sessionId)
- }
- }
- func (this *RoleManager) addOfflineRole(uid uint64, role RoleOuter) bool {
- if _, ok := this.offlineRoleList[uid]; ok {
- return false
- }
- //清空玩家对应的gate相关信息
- role.(*Role).SetCliIDSessionID(0)
- this.offlineRoleList[uid] = role
- return true
- }
- func (this *RoleManager) SendMsg2OnlinePlayer(msg interface{}, fromUid uint64) {
- var clientIdLIstMap = map[string][]uint64{}
- //var clientIdList []uint64
- for _, data := range this.uuidRoleList {
- if data.GetState() != ROLE_STATE_ONLINE {
- continue
- }
- if fromUid != 0 && data.(*Role).GetRoleSocial().IsInBlackList(fromUid) {
- continue
- }
- serviceId := data.CliID().ServiceID
- clientIdLIstMap[serviceId] = append(clientIdLIstMap[serviceId], data.CliID().SessID)
- if len(clientIdLIstMap[serviceId]) > 20 {
- ReplayGateList(msg, clientIdLIstMap[serviceId], serviceId, true)
- clientIdLIstMap[serviceId] = clientIdLIstMap[serviceId][:0]
- }
- }
- for sid, val := range clientIdLIstMap {
- if len(val) > 0 {
- ReplayGateList(msg, val, sid, true)
- }
- }
- }
- func (this *RoleManager) SetGMNoticeInfo(info *serverproto.SSWebGMNoticeNtf) {
- this.noticeInfo = info
- this.noticeInfo.NoticeTime = uint64(util.GetTimeMilliseconds())
- scMsg := &serverproto.SCWebGMNoticeNtf{
- NoticeInfo: this.noticeInfo.NoticeInfo,
- }
- this.SendMsg2OnlinePlayer(scMsg, 0)
- }
- func (this *RoleManager) NoticeInfoNtf(role *Role) {
- if this.noticeInfo == nil {
- return
- }
- //持续一小时
- if this.noticeInfo.NoticeTime+uint64(60*60*1000) > util.GetTimeMilliseconds() {
- scMsg := &serverproto.SCWebGMNoticeNtf{
- NoticeInfo: this.noticeInfo.NoticeInfo,
- }
- role.ReplayGate(scMsg, true)
- }
- }
- func (this *RoleManager) ServerMaintain(state int32) {
- for _, data := range this.uuidRoleList {
- if data.GetState() != ROLE_STATE_ONLINE {
- continue
- }
- data.KickWithSave(int32(serverproto.ErrorCode_ERROR_SERVER_MAINTAIN))
- }
- }
- //gate端口后,game上对应role的处理
- func (this *RoleManager) GateCloseKickRole(serviceId string) {
- for _, chRole := range this.channelRoleList {
- if chRole.GetState() == ROLE_STATE_ONLINE && chRole.CliID().ServiceID == serviceId {
- chRole.SwitchState(ROLE_STATE_OFFLINE, nil)
- util.DebugF("GateCloseKickRole role=%v %v", chRole.GetUUid(), chRole.GetOpenId())
- }
- }
- }
- //social通知game当前在线的玩家数量
- func (this *RoleManager) PlayerOnlineNumFromSocial(onlineNum int32) {
- this.allGameOnlineNum = onlineNum
- }
- func (this *RoleManager) IsGameOnlineNumLimit() bool {
- if this.allGameOnlineNum >= 6000 {
- return true
- }
- return false
- }
- func (this *RoleManager) SendRushReward(rushType, rushRound int32) {
- for _, chRole := range this.channelRoleList {
- if chRole.GetState() != ROLE_STATE_ONLINE {
- continue
- }
- if rushType == model.Rush_Type_Tower {
- chRole.(*Role).GetRoleTower().GetFightCountMailReward(rushRound)
- } else if rushType == model.Rush_Type_Arena {
- chRole.(*Role).GetRoleArena().GetFightCountMailReward(rushRound)
- } else if rushType == model.Rush_Type_Map {
- chRole.(*Role).GetRoleBattle().GetFightCountMailReward(rushRound)
- } else if rushType == model.Rush_Type_Pet {
- chRole.(*Role).GetRolePet().GetFightCountMailReward(rushRound)
- } else if rushType == model.Rush_Type_Skill {
- chRole.(*Role).GetRoleRush().GetFightCountMailReward(rushRound)
- }
- }
- }
- func (this *RoleManager) GuildBattleBeginNtf(inBattle bool) {
- ntfMsg := &serverproto.SCGuildBattleStageNtf{
- InGuildBattle: inBattle,
- }
- for _, chRole := range this.channelRoleList {
- if chRole.GetState() != ROLE_STATE_ONLINE {
- continue
- }
- chRole.(*Role).ReplayGate(ntfMsg, true)
- }
- }
- //文件热加载通知操作(调用该方法时文件已经重新加载,转换部分需要这边重新处理)
- func (this *RoleManager) ServerReloadConfigNtf(cfgList []string) {
- //转换
- for _, cfgData := range cfgList {
- if cfgData == "CombinedServiceCfg" {
- model.ConvertCombinedServer()
- this.CombineServerNtf()
- }
- }
- }
- func (this *RoleManager) CombineServerNtf() {
- ntfMsg := &serverproto.SCCombineServerOnlineNtf{
- CombineTime: 0,
- }
- data, ok := model.ConvertCombineServerData[1]
- for _, chRole := range this.channelRoleList {
- if chRole.GetState() != ROLE_STATE_ONLINE {
- continue
- }
- if ok {
- zoneId := chRole.GetSelectZone()
- for _, server := range data.ServerList {
- if server.Key <= zoneId && zoneId <= server.Value {
- ntfMsg.CombineTime = data.CombineTime
- break
- }
- }
- }
- chRole.ReplayGate(ntfMsg, true)
- }
- }
|