actor_player.go 5.5 KB

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