actor_base.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package mapAOI
  2. import (
  3. aoiTower "f1-game/internal/algorithm/aoi_tower"
  4. "f1-game/internal/enum"
  5. nameRemote "f1-game/internal/name/remote"
  6. mapCall "f1-game/nodes/map/internal/call"
  7. mapTypes "f1-game/nodes/map/internal/types"
  8. "time"
  9. clog "github.com/cherry-game/cherry/logger"
  10. cactor "github.com/cherry-game/cherry/net/actor"
  11. )
  12. // TODO 待重构:不要绑定死 actorBase 与 objectType
  13. // actorBase 实现为通用方法集合,在每一层 AOI 中做定制化调用
  14. // 每一层 AOI 各自做实现,这样可以灵活地把多种不同的对象放在一起,比如:行军对象和军团对象
  15. type actorBase struct {
  16. cactor.Base
  17. aoi *aoiTower.AOI
  18. aoiUpdateTime time.Duration
  19. objectType enum.ObjectType
  20. printLog bool
  21. }
  22. func newActorAOIBase(objectType enum.ObjectType, aoi *aoiTower.AOI, aoiUpdateTime time.Duration) actorBase {
  23. return actorBase{
  24. aoi: aoi,
  25. aoiUpdateTime: aoiUpdateTime,
  26. objectType: objectType,
  27. }
  28. }
  29. func (p *actorBase) OnInit() {
  30. p.Remote().Register(nameRemote.MapAOI_Enter, p.enter)
  31. p.Remote().Register(nameRemote.MapAOI_Move, p.move)
  32. p.Remote().Register(nameRemote.MapAOI_Leave, p.leave)
  33. p.Remote().Register(nameRemote.MapAOI_Update, p.update)
  34. p.Timer().Add(p.aoiUpdateTime, p.aoiUpdate)
  35. p.initAOIFuncs()
  36. }
  37. func (p *actorBase) setPrintLog(printLog bool) {
  38. p.printLog = printLog
  39. }
  40. // enter 玩家登录进入地图
  41. func (p *actorBase) enter(req *mapTypes.AOIRequest) {
  42. if req.IsMarker() && req.ObjectType != p.objectType {
  43. return
  44. }
  45. object := aoiTower.NewObject(req.ObjectID, req.ObjectType, req.X, req.Y, req.IsWatcher(), req.IsMarker(), req.OwnerID())
  46. p.aoi.Enter(object)
  47. if p.printLog {
  48. clog.Debugf("[enter %s] object = {%s}", enum.GetObjectTypeName(p.objectType), object.Info())
  49. }
  50. }
  51. // move 玩家拖动屏幕
  52. func (p *actorBase) move(req *mapTypes.AOIRequest) {
  53. if req.ObjectType != enum.ObjectType_Player && req.ObjectType != p.objectType {
  54. return
  55. }
  56. p.aoi.Move(req.ObjectID, req.X, req.Y, time.Now().Unix())
  57. if p.printLog {
  58. clog.Debugf("[move %s] req = {%v}", enum.GetObjectTypeName(p.objectType), req)
  59. }
  60. }
  61. // leave 玩家下线离开
  62. func (p *actorBase) leave(objectID int64) {
  63. // TODO 需要判断,待改进
  64. if p.aoi.GetObject(objectID) == nil {
  65. return
  66. }
  67. p.aoi.Leave(objectID)
  68. if p.printLog {
  69. clog.Debugf("[leave %s] object = %d", enum.GetObjectTypeName(p.objectType), objectID)
  70. }
  71. }
  72. func (p *actorBase) update(req *mapTypes.AOIRequest) {
  73. if req.ObjectType == enum.ObjectType_Player || req.ObjectType != p.objectType {
  74. return
  75. }
  76. object := p.aoi.GetObject(req.ObjectID)
  77. if object == nil {
  78. return
  79. }
  80. p.aoi.UpdateID(*object, req.UpdateID(), req.FuncName())
  81. if p.printLog {
  82. clog.Debugf("[update %s] object = %d", enum.GetObjectTypeName(p.objectType), req.ObjectID)
  83. }
  84. }
  85. func (p *actorBase) initAOIFuncs() {
  86. p.aoi.OnMarkerEnter = p.onMarkerEnter
  87. p.aoi.OnMarkerMove = p.onMarkerMove
  88. p.aoi.OnMarkerLeave = p.onMarkerLeave
  89. p.aoi.OnMarkerUpdateID = p.onMarkerUpdateID
  90. p.aoi.OnWatcherEnter = p.onWatcherEnter
  91. p.aoi.OnWatcherMove = p.onWatcherMove
  92. p.aoi.OnTowerExpire = p.onTowerExpire
  93. }
  94. func (p *actorBase) aoiUpdate() {
  95. p.aoi.Tick(time.Now().Unix())
  96. }
  97. // marker进入的时候通知灯塔内所有watcher
  98. func (p *actorBase) onMarkerEnter(marker *aoiTower.Object, tower *aoiTower.Tower) {
  99. clog.Debugf("[onMarkerEnter] marker = (%v %s) towerId:%d", marker.ObjectID, enum.GetObjectTypeName(marker.ObjectType), tower.GetID())
  100. if tower.GetWatchers().IsEmpty() {
  101. return
  102. }
  103. mapCall.Logic.AOIMarkerEnterView(mapTypes.NewAOIMarkerEnterView(marker, tower.GetWatchers()))
  104. }
  105. // marker移动
  106. func (p *actorBase) onMarkerMove(marker *aoiTower.Object, newTower *aoiTower.Tower, oldTower *aoiTower.Tower) {
  107. clog.Debugf("[onMarkerMove] marker = (%v %s) newTowerId = %d oldTowerId = %d", marker.ObjectID, enum.GetObjectTypeName(marker.ObjectType),
  108. newTower.GetID(), oldTower.GetID())
  109. enterWatchers := aoiTower.Objects{}
  110. newTower.GetWatchers().Range(func(watcher *aoiTower.Object) {
  111. if !oldTower.GetWatchers().Contains(watcher.ObjectID) {
  112. // 不在watcher的视野内,视为新加入的对象
  113. enterWatchers.Add(watcher)
  114. }
  115. })
  116. if !enterWatchers.IsEmpty() {
  117. mapCall.Logic.AOIMarkerEnterView(mapTypes.NewAOIMarkerEnterView(marker, enterWatchers))
  118. }
  119. leaveWatchers := aoiTower.Objects{}
  120. oldTower.GetWatchers().Range(func(watcher *aoiTower.Object) {
  121. if !newTower.GetWatchers().Contains(watcher.ObjectID) {
  122. // 移出了视野
  123. leaveWatchers.Add(watcher)
  124. }
  125. })
  126. if !leaveWatchers.IsEmpty() {
  127. mapCall.Logic.AOIMarkerLeaveView(mapTypes.NewAOIMarkerLeaveView(marker, leaveWatchers))
  128. }
  129. }
  130. // marker退出的时候通知灯塔内所有watcher
  131. func (p *actorBase) onMarkerLeave(marker *aoiTower.Object, tower *aoiTower.Tower) {
  132. clog.Debugf("[onMarkerLeave] marker = (%v %s) towerId = %d", marker.ObjectID, enum.GetObjectTypeName(marker.ObjectType), tower.GetID())
  133. mapCall.Logic.AOIMarkerDespawn(mapTypes.NewAOIMarkerDespawn(marker, tower.GetWatchers()))
  134. }
  135. // marker更新通知
  136. func (p *actorBase) onMarkerUpdateID(marker *aoiTower.Object, tower *aoiTower.Tower, updateID uint32, funcName string) {
  137. clog.Debugf("[onMarkerUpdateID] marker = (%v %s) towerId = %d updateID = %d funcName = %s", marker.ObjectID, enum.GetObjectTypeName(marker.ObjectType),
  138. tower.GetID(), updateID, funcName)
  139. mapCall.Logic.AOIUpdate(funcName, mapTypes.NewAOIMarkerUpdate(marker, tower.GetWatchers(), updateID))
  140. }
  141. // watcher进入的时候推送范围内所有marker
  142. func (p *actorBase) onWatcherEnter(watcher *aoiTower.Object, towers aoiTower.Towers) {
  143. towers.Range(func(tower *aoiTower.Tower) {
  144. if !tower.GetMarkers().IsEmpty() {
  145. mapCall.Logic.AOIMarkerEnterView(mapTypes.NewBatchAOMarkerEnterView(tower.GetMarkers(), p.objectType, watcher.OwnerID()))
  146. }
  147. })
  148. }
  149. // watcher移动时的新灯塔内对象全视为新加入对象,因为延迟删除所以不需要处理oldTowers
  150. func (p *actorBase) onWatcherMove(watcher *aoiTower.Object, newTowers aoiTower.Towers, oldTowers aoiTower.Towers) {
  151. newTowers.Range(func(tower *aoiTower.Tower) {
  152. if !tower.GetMarkers().IsEmpty() {
  153. mapCall.Logic.AOIMarkerEnterView(mapTypes.NewBatchAOMarkerEnterView(tower.GetMarkers(), p.objectType, watcher.OwnerID()))
  154. }
  155. })
  156. }
  157. // 灯塔过期
  158. func (p *actorBase) onTowerExpire(watcher *aoiTower.Object, tower *aoiTower.Tower) {
  159. clog.Debugf("[onTowerExpire] watcher = %v towerId = %d", watcher.ObjectID, tower.GetID())
  160. if tower.GetMarkers().IsEmpty() {
  161. return
  162. }
  163. // 移出了视野
  164. mapCall.Logic.AOIMarkerLeaveView(mapTypes.NewBatchAOIMarkerLeaveView(tower.GetMarkers(), p.objectType, watcher.OwnerID()))
  165. }