actor_player.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package mapPlayer
  2. import (
  3. capp "f1-game/internal/cherry_app"
  4. "f1-game/internal/code"
  5. "f1-game/internal/component/rate"
  6. "f1-game/internal/enum"
  7. "f1-game/internal/event"
  8. nameLocal "f1-game/internal/name/local"
  9. nameRemote "f1-game/internal/name/remote"
  10. "f1-game/internal/pb"
  11. "f1-game/internal/types"
  12. mapCall "f1-game/nodes/map/internal/call"
  13. "f1-game/nodes/map/internal/db"
  14. ctime "github.com/cherry-game/cherry/extend/time"
  15. cfacade "github.com/cherry-game/cherry/facade"
  16. cherryActor "github.com/cherry-game/cherry/net/actor"
  17. )
  18. // actorPlayer 每个玩家一个PlayerActor
  19. type actorPlayer struct {
  20. capp.ActorLogger
  21. playerID int64 // 当前玩家id
  22. isOnline bool // 玩家是否在线
  23. now *ctime.CherryTime // 玩家当前时间
  24. funcLimiter rate.FuncLimiter // 函数访问限速
  25. funcErrCode int32 // 函数访问的错误码
  26. // 战斗处理器
  27. battleHandlers map[enum.TileBattleType]func(*pb.BattleReq, *pb.BattleRsp)
  28. }
  29. func newActorPlayer(playerID int64) actorPlayer {
  30. now := ctime.Now()
  31. return actorPlayer{
  32. ActorLogger: capp.NewLoggerPrefix("playerID", playerID),
  33. playerID: playerID,
  34. now: &now,
  35. funcLimiter: rate.NewFuncLimiter(30, 3, code.NodeRateLimiter),
  36. funcErrCode: code.NodeRateLimiter,
  37. }
  38. }
  39. func (p *actorPlayer) OnInit() {
  40. p.initRateLimits()
  41. p.initRemote()
  42. p.initPlayerLeague()
  43. p.initMap()
  44. p.initFacility()
  45. p.initPlayerTeam()
  46. p.initConscript()
  47. p.initQuest()
  48. p.initBattle()
  49. p.initAsset()
  50. p.initHero()
  51. p.initAssemble()
  52. p.initShop()
  53. p.initExchange()
  54. p.initShow()
  55. p.initPlayerStats()
  56. p.initSignIn()
  57. p.initSeason()
  58. p.initEvent()
  59. p.startTimer()
  60. }
  61. func (p *actorPlayer) initRemote() {
  62. p.Remote().Register(nameRemote.MapPlayer_OnSessionClosed, p.onSessionClosed)
  63. p.Remote().Register(nameRemote.MapPlayer_SyncData, p.syncData)
  64. p.Remote().Register(nameRemote.MapPlayer_SyncVip, p.syncVipAttrs)
  65. }
  66. func (p *actorPlayer) OnStop() {
  67. p.Info("[actorPlayer] OnStop() playerID = %d", p.playerID)
  68. p.Timer().RemoveAll()
  69. p.ActorLogger.Destory()
  70. }
  71. func (p *actorPlayer) OnLocalReceived(m *cfacade.Message) (bool, bool) {
  72. // 玩家未登录时,第一条消息必须是 map.player.login
  73. if !p.isOnline && m.FuncName != nameLocal.MapPlayer_Login {
  74. p.ResponseCode(m.Session, code.PlayerNotLogin)
  75. return false, false
  76. }
  77. p.funcErrCode = p.funcLimiter.Check(m.BuildTime, m.FuncName)
  78. if code.IsFail(p.funcErrCode) {
  79. p.ResponseCode(m.Session, p.funcErrCode)
  80. return false, false
  81. }
  82. return false, true
  83. }
  84. func (p *actorPlayer) OnRemoteReceived(m *cfacade.Message) (bool, bool) {
  85. if p.playerID == 0 {
  86. p.Warn("[OnRemoteReceive] player not found: Source = %s, Target = %s, FuncName = %s", m.Source, m.Target, m.FuncName)
  87. return false, false
  88. }
  89. // 如果找不到玩家表,直接返回错误
  90. if db.GetMapPlayerTable(p.playerID) == nil {
  91. p.Warn("[OnRemoteReceive] player not found: Source = %s, Target = %s, FuncName = %s", m.Source, m.Target, m.FuncName)
  92. return false, false
  93. }
  94. return false, true
  95. }
  96. func (p *actorPlayer) updateNowTime() {
  97. now := ctime.Now()
  98. p.now = &now
  99. }
  100. func (p *actorPlayer) initRateLimits() {
  101. p.funcLimiter.Add(nameLocal.MapPlayer_March, 1000, 10, code.OperationTooFast)
  102. p.funcLimiter.Add(nameLocal.MapPlayer_MarchStop, 1000, 10, code.OperationTooFast)
  103. p.funcLimiter.Add(nameLocal.MapPlayer_Retreat, 1000, 10, code.OperationTooFast)
  104. p.funcLimiter.Add(nameLocal.MapPlayer_Assemble, 1000, 10, code.OperationTooFast)
  105. p.funcLimiter.Add(nameLocal.MapPlayer_AssembleJoin, 1000, 10, code.OperationTooFast)
  106. p.funcLimiter.Add(nameLocal.MapPlayer_FindPath, 1000, 10, code.OperationTooFast)
  107. p.funcLimiter.Add(nameLocal.MapPlayer_MapObjectPosition, 1000, 10, code.OperationTooFast)
  108. }
  109. func (p *actorPlayer) EventRegister(name string, fn cherryActor.IEventFunc) {
  110. p.Event().Register(name, fn, p.playerID)
  111. }
  112. // 同步玩家数据
  113. func (p *actorPlayer) syncData(req *pb.SyncMapPlayerRequest) {
  114. p.Debug("sync player data: req = %+v", req)
  115. playerTable := db.GetMapPlayerTable(p.playerID)
  116. // 同步必要的数据
  117. playerTable.SyncData(req)
  118. // 抛事件
  119. p.PostEvent(event.NewMapWatcherSync(p.playerID, &event.MapWatcherData{
  120. PlayerID: p.playerID,
  121. PlayerName: req.PlayerName,
  122. IconID: req.IconID,
  123. FrameID: req.FrameID,
  124. }))
  125. }
  126. // 同步vip属性
  127. func (p *actorPlayer) syncVipAttrs(req *pb.SyncMapPlayerVip) {
  128. p.Debug("sync player vip attrs: req = %+v", req)
  129. playerTable := db.GetMapPlayerTable(p.playerID)
  130. vipAttrs := types.NewAttrs()
  131. for _, attr := range req.Attrs.List {
  132. vipAttrs.Set(attr.Key, attr.Value)
  133. }
  134. playerTable.SyncVip(req.Level, vipAttrs, req.ExpireTime)
  135. // 抛事件
  136. p.PostEvent(event.NewVipActive(p.playerID, vipAttrs, req.ExpireTime))
  137. }
  138. func (p *actorPlayer) onSessionClosed() {
  139. p.Info("[onLogout] playerID = %d", p.playerID)
  140. // 不在线则忽略
  141. if !p.isOnline {
  142. return
  143. }
  144. // 必需设置为 false,如果玩家被顶号,actor 不会被销毁,不设置会导致玩家无法登录
  145. p.isOnline = false
  146. //移除当前玩家所有定时器
  147. // p.Timer().RemoveAll()
  148. if playerTable := db.GetMapPlayerTable(p.playerID); playerTable != nil {
  149. if playerTable.ObjectID > 0 {
  150. mapCall.AOI.Leave(playerTable.ObjectID, enum.ObjectType_Player)
  151. }
  152. ServiceOnLogout(playerTable)
  153. playerTable.Save2Queue()
  154. }
  155. p.Info("[onLogout] finished! playerID = %d", p.playerID)
  156. }