cross_manager.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. package model
  2. import (
  3. "rocommon/util"
  4. "roserver/baseserver/model"
  5. "roserver/serverproto"
  6. "sort"
  7. "strconv"
  8. "time"
  9. )
  10. const (
  11. Expired_Time = 10 * 60 * 1000
  12. TrialRankExpired_Time = 1 * 60 * 1000
  13. )
  14. // //远航试炼缓存
  15. var NtfViewUidList = map[uint64]uint64{}
  16. func AddNtfUid(uid uint64) {
  17. NtfViewUidList[uid] = util.GetTimeMilliseconds()
  18. }
  19. func DelNtfUid(uid uint64) {
  20. delete(NtfViewUidList, uid)
  21. }
  22. func NtfMsg(msg interface{}) {
  23. nowTime := util.GetTimeMilliseconds()
  24. for uid, oldTime := range NtfViewUidList {
  25. role := RoleMag.GetRoleFromUUid(uid)
  26. if role == nil {
  27. delete(NtfViewUidList, uid)
  28. continue
  29. }
  30. role.ReplayGate(msg, true)
  31. if oldTime+Expired_Time <= nowTime {
  32. DelNtfUid(uid)
  33. }
  34. }
  35. }
  36. var cacheCrossYuanHangTrialViewList []*serverproto.YuanHangTrialData
  37. var refreshCacheTime uint64
  38. func SetYuanHangTrialViewList(viewList []*serverproto.YuanHangTrialData) {
  39. cacheCrossYuanHangTrialViewList = viewList
  40. refreshCacheTime = util.GetTimeMilliseconds()
  41. }
  42. func GetYuanHangTrialViewList() []*serverproto.YuanHangTrialData {
  43. //每30s重新获取一次可见列表
  44. nowTime := util.GetTimeMilliseconds()
  45. if refreshCacheTime+30*1000 < nowTime {
  46. return nil
  47. }
  48. return cacheCrossYuanHangTrialViewList
  49. }
  50. func UpdateTrialViewItem(viewDataList []*serverproto.YuanHangTrialData) {
  51. for idx := 0; idx < len(viewDataList); idx++ {
  52. bFind := false
  53. for k := 0; k < len(cacheCrossYuanHangTrialViewList); k++ {
  54. if cacheCrossYuanHangTrialViewList[k].Uid == viewDataList[idx].Uid {
  55. cacheCrossYuanHangTrialViewList[k] = viewDataList[idx]
  56. bFind = true
  57. break
  58. }
  59. }
  60. if !bFind {
  61. cacheCrossYuanHangTrialViewList = append(cacheCrossYuanHangTrialViewList, viewDataList[idx])
  62. }
  63. ntfRole := RoleMag.GetRoleFromUUid(viewDataList[idx].Uid)
  64. if ntfRole == nil {
  65. ntfRole = RoleMag.GetRoleFromOffline(viewDataList[idx].Uid)
  66. if ntfRole != nil {
  67. ntfRole.(*Role).GetRoleCross().UpdateTrialInfo(viewDataList[idx].BeChallengeNum)
  68. }
  69. }
  70. }
  71. }
  72. var cacheCrossYuanHangTrialRankList []*cacheTrialRank
  73. type cacheTrialRank struct {
  74. StartIdx int32
  75. RefreshTime uint64
  76. rankList []*serverproto.CommonRankInfo
  77. }
  78. func UpdateYuanHangTrialRankList(startIdx int32, rankList []*serverproto.CommonRankInfo) {
  79. bFind := false
  80. for idx := 0; idx < len(cacheCrossYuanHangTrialRankList); idx++ {
  81. if cacheCrossYuanHangTrialRankList[idx].StartIdx == startIdx {
  82. cacheCrossYuanHangTrialRankList[idx].rankList = rankList
  83. cacheCrossYuanHangTrialRankList[idx].RefreshTime = util.GetTimeMilliseconds()
  84. bFind = true
  85. break
  86. }
  87. }
  88. if !bFind {
  89. cacheCrossYuanHangTrialRankList = append(cacheCrossYuanHangTrialRankList,
  90. &cacheTrialRank{
  91. StartIdx: startIdx,
  92. rankList: rankList,
  93. RefreshTime: util.GetTimeMilliseconds(),
  94. })
  95. }
  96. }
  97. func GetYuanHangTrialRankList(startIdx int32) []*serverproto.CommonRankInfo {
  98. for idx := 0; idx < len(cacheCrossYuanHangTrialRankList); idx++ {
  99. if cacheCrossYuanHangTrialRankList[idx].StartIdx == startIdx {
  100. nowTime := util.GetTimeMilliseconds()
  101. if cacheCrossYuanHangTrialRankList[idx].RefreshTime+TrialRankExpired_Time <= nowTime {
  102. return nil
  103. }
  104. return cacheCrossYuanHangTrialRankList[idx].rankList
  105. }
  106. }
  107. return nil
  108. }
  109. // 全局跨服使用GCrossRouter
  110. // 服务器列表状态缓存
  111. type ServerStateCache struct {
  112. ServerType int32
  113. ServerState *serverproto.SCGCrossGetServerStateAck
  114. RefreshTime uint64
  115. }
  116. var ServerStateCacheList = map[int32]*ServerStateCache{}
  117. // force是否判断过期需要重新获取
  118. func GetServerStateListByType(serverType int32, force bool) *serverproto.SCGCrossGetServerStateAck {
  119. nowTime := util.GetTimeMilliseconds()
  120. if dataList, ok := ServerStateCacheList[serverType]; ok {
  121. if dataList.ServerState == nil || (force && dataList.RefreshTime < nowTime) {
  122. return nil
  123. }
  124. return dataList.ServerState
  125. } else {
  126. return nil
  127. }
  128. }
  129. func GetServerStateByTypeAndLine(serverType, lineNum int32) string {
  130. retSID := ""
  131. listData := GetServerStateListByType(serverType, false)
  132. if listData == nil {
  133. return retSID
  134. }
  135. for idx := 0; idx < len(listData.ServerList); idx++ {
  136. tmpNodeId := listData.ServerList[idx]
  137. beginLineNum := (tmpNodeId.Id-1)*tmpNodeId.MaxLineNum + 1
  138. endLineNum := tmpNodeId.Id * tmpNodeId.MaxLineNum
  139. if beginLineNum <= lineNum && lineNum <= endLineNum {
  140. retSID = tmpNodeId.Sid
  141. break
  142. }
  143. }
  144. return retSID
  145. }
  146. // 选择线路未满的房间(线路号从小达到)
  147. func GetServerStateByType(serverType int32) (string, int32) {
  148. retSID := ""
  149. listData := GetServerStateListByType(serverType, false)
  150. if listData == nil {
  151. return retSID, 0
  152. }
  153. var lineNum int32 = 0
  154. for idx := 0; idx < len(listData.ServerList); idx++ {
  155. tmpNodeId := listData.ServerList[idx]
  156. beginLineNum := (tmpNodeId.Id-1)*tmpNodeId.MaxLineNum + 1
  157. endLineNum := tmpNodeId.Id * tmpNodeId.MaxLineNum
  158. for lineIdx := beginLineNum; lineIdx <= endLineNum; lineIdx++ {
  159. bFull := false
  160. for k := 0; k < len(tmpNodeId.StateList); k++ {
  161. if tmpNodeId.StateList[k].Line == lineIdx {
  162. if tmpNodeId.StateList[k].CurNum >= tmpNodeId.MaxSpaceEntityNum {
  163. bFull = true
  164. }
  165. break
  166. }
  167. }
  168. if !bFull {
  169. retSID = tmpNodeId.Sid
  170. lineNum = lineIdx
  171. break
  172. }
  173. }
  174. }
  175. return retSID, lineNum
  176. }
  177. func UpdateServerStateListByType(serverType int32, serverStateData *serverproto.SSGetGServerStateAck) {
  178. if len(serverStateData.ServerList) <= 0 {
  179. return
  180. }
  181. nowTime := util.GetTimeMilliseconds()
  182. if dataList, ok := ServerStateCacheList[serverType]; ok {
  183. dataList.ServerState.ServerList = serverStateData.ServerList
  184. dataList.RefreshTime = nowTime + 5*1000
  185. } else {
  186. ServerStateCacheList[serverType] = &ServerStateCache{
  187. ServerType: serverType,
  188. RefreshTime: nowTime + 5*1000,
  189. ServerState: &serverproto.SCGCrossGetServerStateAck{
  190. ServerType: serverType,
  191. ServerList: serverStateData.ServerList,
  192. },
  193. }
  194. sort.Slice(ServerStateCacheList[serverType].ServerState.ServerList, func(i, j int) bool {
  195. return ServerStateCacheList[serverType].ServerState.ServerList[i].Id <
  196. ServerStateCacheList[serverType].ServerState.ServerList[j].Id
  197. })
  198. }
  199. //人数为0的线路初始化
  200. listData := ServerStateCacheList[serverType].ServerState
  201. for idx := 0; idx < len(listData.ServerList); idx++ {
  202. tmpNodeId := listData.ServerList[idx]
  203. if len(tmpNodeId.StateList) >= int(tmpNodeId.MaxLineNum) {
  204. continue
  205. }
  206. beginLineNum := (tmpNodeId.Id-1)*tmpNodeId.MaxLineNum + 1
  207. endLineNum := tmpNodeId.Id * tmpNodeId.MaxLineNum
  208. for lineIdx := beginLineNum; lineIdx <= endLineNum; lineIdx++ {
  209. bFind := false
  210. for k := 0; k < len(tmpNodeId.StateList); k++ {
  211. if tmpNodeId.StateList[k].Line == lineIdx {
  212. bFind = true
  213. break
  214. }
  215. }
  216. if !bFind {
  217. tmpNodeId.StateList = append(tmpNodeId.StateList, &serverproto.StateDetailDesc{Line: lineIdx})
  218. }
  219. }
  220. }
  221. }
  222. // 分发来自跨服的消息
  223. func SendMsgFromCrossRouter(msg interface{}, cliId model.ClientID) {
  224. if cliId.SessID > 0 {
  225. role := RoleMag.GetRole(cliId)
  226. if role == nil {
  227. return
  228. }
  229. util.DebugF("uid=%v receive SSGCrossMapEnterNtf ms=%v", role.GetUUid(), msg)
  230. role.ReplayGate(msg, true)
  231. } else if len(cliId.SessIdList) > 0 {
  232. var clientIdLIstMap = map[string][]uint64{}
  233. //只发送当前game相关的玩家
  234. for idx := 0; idx < len(cliId.SessIdList); idx++ {
  235. role := RoleMag.GetRoleFromUUid(cliId.SessIdList[idx])
  236. if role == nil {
  237. continue
  238. }
  239. serviceId := role.CliID().ServiceID
  240. clientIdLIstMap[serviceId] = append(clientIdLIstMap[serviceId], role.CliID().SessID)
  241. }
  242. for key, dataList := range clientIdLIstMap {
  243. ReplayGateList(msg, dataList, key, true)
  244. }
  245. }
  246. }
  247. type CrossManager struct {
  248. updateTimer util.ServerTimer //更新定时器
  249. initStartUp bool
  250. seasonStartTime, seasonEndTime time.Time
  251. refreshTime time.Time
  252. }
  253. func newCrossMag() *CrossManager {
  254. mag := &CrossManager{}
  255. mag.updateTimer = util.NewDurationTimer(util.GetCurrentTime(), 5000)
  256. return mag
  257. }
  258. func (this *CrossManager) init(ms uint64) {
  259. nowTime := util.GetTimeByUint64(ms)
  260. if nowTime.Before(this.refreshTime.AddDate(0, 0, 7)) {
  261. return
  262. }
  263. endTime := util.GetLatestWeek10HourTime(ms)
  264. if nowTime.After(endTime) {
  265. msg := &serverproto.SSCrossYuanHangTrialRankUpdateReq{}
  266. SendCrossService(msg)
  267. util.InfoF("cross rank refresh time:%v", nowTime)
  268. this.refreshTime = nowTime
  269. }
  270. }
  271. func (this *CrossManager) getSeasonTime(seasonId int32) (time.Time, time.Time) {
  272. resetTime := int64((model.ConvertArenaSeason.Reset + 1) * HourMs)
  273. diffDurationDay := model.ConvertArenaSeason.DiffDurationDay
  274. deltaTime := (diffDurationDay + resetTime) * int64(seasonId-1)
  275. loc := util.GetLoc()
  276. startTime := time.Unix(model.ConvertArenaSeason.StartTime.Unix()+deltaTime, 0).In(loc)
  277. endTime := time.Unix(model.ConvertArenaSeason.EndTime.Unix()+deltaTime, 0).In(loc)
  278. return startTime, endTime
  279. }
  280. func (this *CrossManager) Update(ms uint64) {
  281. this.init(ms)
  282. if this.initStartUp && this.updateTimer.IsStart() && this.updateTimer.IsExpired(ms) {
  283. if len(ServerStateCacheList) <= 0 {
  284. ssStateMsg := &serverproto.SSGetGServerStateReq{
  285. ServerType: model.SERVICE_NODE_TYPE_GLOBALCROSSMAP,
  286. }
  287. SendSocial(ssStateMsg)
  288. }
  289. }
  290. }
  291. // 获取对应赛季奖励
  292. func (this *CrossManager) GetSeasonReward(role uint64, selfRank, rewardSeasonId int32) {
  293. if selfRank <= 0 || role == 0 {
  294. return
  295. }
  296. //获取排名奖励,发送邮件
  297. for _, data := range model.ConvertCrossRankInfo.RewardInfo {
  298. if selfRank >= data.Left && selfRank <= data.Right {
  299. itemList := make([]*serverproto.KeyValueType, 0)
  300. for k, v := range data.RewardList {
  301. itemList = append(itemList, &serverproto.KeyValueType{
  302. Key: k,
  303. Value: v,
  304. })
  305. }
  306. //发送邮件,不在线的通过db那边清空分数
  307. AddMailOnlineAndOffline([]uint64{role}, model.GlobalMailyuanhangRankAward, int32(serverproto.MailType_MailType_GM),
  308. itemList, []int32{int32(util.GetTimeSeconds())}, "飞艇排行榜奖励", "恭喜您在遠航試煉中獲得了第"+strconv.FormatInt(int64(selfRank), 10)+"名")
  309. //在线的清空分数
  310. r := RoleMag.GetRoleFromUUid(role)
  311. if r != nil {
  312. r.SetYuanRankScore()
  313. }
  314. util.InfoF("send rank award uid:%v award:%v", role, itemList)
  315. break
  316. }
  317. }
  318. //
  319. //// 赛季第一名触发称号事件
  320. //var value int32 = 1
  321. //if selfRank != 1 {
  322. // value = role.roleTask.GetTypeCnt(int32(serverproto.TaskType_Eve_Arean_First)) * -1
  323. //} else {
  324. // TaskMagCheck(role, serverproto.TaskType_Eve_Arean_First_Cnt, 1)
  325. //}
  326. //role.roleTask.AddTypeCnt(serverproto.TaskType_Eve_Arean_First, value)
  327. //TaskMagCheck(role, serverproto.TaskType_Eve_Arean_First, rewardSeasonId)
  328. }
  329. // 赛季结算
  330. func (this *CrossManager) DoSeasonReward(seasonId int32) {
  331. ssMsg := &serverproto.SSArenaRankUpdateReq{
  332. LastSeasonId: seasonId,
  333. }
  334. sendNum := 0
  335. for _, chRole := range RoleMag.channelRoleList {
  336. if chRole.GetState() != ROLE_STATE_ONLINE {
  337. continue
  338. }
  339. //段位奖励
  340. //chRole.(*Role).GetRoleArena().ScoreLevelReward()
  341. //top排行奖励
  342. //if chRole.(*Role).GetRoleArena().arenaInfo.Score >= model.MinTopRankScore {
  343. if chRole.(*Role).GetRoleArena().arenaInfo.Score > 0 {
  344. ssMsg.RewardPlayerList = append(ssMsg.RewardPlayerList, chRole.GetUUid())
  345. sendNum++
  346. if sendNum >= 50 {
  347. SendRankService(ssMsg)
  348. sendNum = 0
  349. ssMsg.RewardPlayerList = ssMsg.RewardPlayerList[:0]
  350. }
  351. }
  352. }
  353. //rank处理结算数据
  354. SendRankService(ssMsg)
  355. }
  356. // 开启新赛季
  357. func (this *CrossManager) DoSeasonRefresh() {
  358. for _, chRole := range RoleMag.channelRoleList {
  359. if chRole.GetState() == ROLE_STATE_ONLINE ||
  360. chRole.GetState() == ROLE_STATE_OFFLINE {
  361. chRole.(*Role).GetRoleArena().DoSeasonRefresh()
  362. }
  363. }
  364. }