actor_aoi.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. package mapLogic
  2. import (
  3. "f1-game/internal/enum"
  4. "f1-game/internal/event"
  5. nameEvent "f1-game/internal/name/event"
  6. nameRemote "f1-game/internal/name/remote"
  7. nameRoute "f1-game/internal/name/route"
  8. "f1-game/internal/pb"
  9. "f1-game/internal/sessions"
  10. "f1-game/internal/types"
  11. "f1-game/nodes/map/internal/db"
  12. mapTypes "f1-game/nodes/map/internal/types"
  13. cfacade "github.com/cherry-game/cherry/facade"
  14. clog "github.com/cherry-game/cherry/logger"
  15. )
  16. func (p *actor) onInitAOI() {
  17. p.Remote().Register(nameRemote.MapLogic_AOIMarkerEnterView, p.aoiMarkerEnterView)
  18. p.Remote().Register(nameRemote.MapLogic_AOIMarkerLeaveView, p.aoiMarkerLeaveView)
  19. p.Remote().Register(nameRemote.MapLogic_AOIMarkerDespawn, p.aoiMarkerDespawn)
  20. p.Remote().Register(nameRemote.MapLogic_AOIMarkerUpdate, p.aoiMarkerUpdate)
  21. p.Remote().Register(nameRemote.MapLogic_AOIUpdateMarchState, p.aoiUpdateMarchState)
  22. p.Remote().Register(nameRemote.MapLogic_AOIUpdateBattle, p.aoiUpdateBattle)
  23. p.Event().Register(nameEvent.Map_WatcherSync, p.mapPlayerSync)
  24. p.Event().Register(nameEvent.Map_LeagueSync, p.mapLeagueSync)
  25. }
  26. // aoiMarkerEnterView aoi marker进入视野回调
  27. func (p *actor) aoiMarkerEnterView(req *mapTypes.AOIMarkerEnterView) {
  28. clog.Debugf("[aoiMarkerEnterView] ObjectType = %s, Marker size = %d, Watcher Size = %d",
  29. enum.GetObjectTypeName(req.ObjectType), req.Markers.Size(), req.Watchers.Size())
  30. if req.Watchers.Size() == 0 {
  31. return
  32. }
  33. watchers := req.Watchers.List()
  34. mapObjects := &pb.MapObjects{}
  35. mapObjects.ObjectList, mapObjects.LegionList = p.buildMapObjectAndLegion(req.ObjectType, req.Markers)
  36. // 先推送 marker 对应的玩家数据和联盟数据给 AOI 观察者
  37. p.playerAndLeaguePush(watchers, mapObjects.ObjectList)
  38. // 再推送 marker 对象
  39. sessions.PushPlayers(watchers, nameRoute.PushMapPusher_ObjectUpdate, mapObjects)
  40. }
  41. // aoiMarkerLeaveView aoi marker离开视野回调
  42. func (p *actor) aoiMarkerLeaveView(req *mapTypes.AOIMakerLeaveView) {
  43. clog.Debugf("[aoiMarkerLeaveView] ObjectType = %s, Marker size = %d, Watcher Size = %d", enum.GetObjectTypeName(req.ObjectType), req.Markers.Size(), req.Watchers.Size())
  44. if req.Watchers.Size() == 0 {
  45. return
  46. }
  47. proto := pb.I64List{
  48. List: req.Markers.List(),
  49. }
  50. sessions.PushPlayers(req.Watchers.List(), nameRoute.PushMapPusher_ObjectDel, &proto)
  51. }
  52. // aoiMarkerDespawn aoi marker移出aoi系统
  53. func (p *actor) aoiMarkerDespawn(req *mapTypes.AOIMakerDespawn) {
  54. clog.Debugf("[aoiMarkerDespawn] ObjectType = %s, Marker size = %d, Watcher Size = %d", enum.GetObjectTypeName(req.ObjectType), req.Markers.Size(), req.Watchers.Size())
  55. if req.Watchers.Size() == 0 {
  56. return
  57. }
  58. proto := pb.I64List{
  59. List: req.Markers.List(),
  60. }
  61. sessions.PushPlayers(req.Watchers.List(), nameRoute.PushMapPusher_ObjectDel, &proto)
  62. }
  63. // aoiMarkerUpdate aoi marker更新回调
  64. func (p *actor) aoiMarkerUpdate(req *mapTypes.AOIMarkerUpdate) {
  65. clog.Debugf("[aoiMarkerUpdate] ObjectType = %s, Marker size = %d, Watcher Size = %d",
  66. enum.GetObjectTypeName(req.ObjectType), req.Markers.Size(), req.Watchers.Size())
  67. if req.Watchers.Size() == 0 {
  68. return
  69. }
  70. watchers := req.Watchers.List()
  71. mapObjects := &pb.MapObjects{}
  72. mapObjects.ObjectList, mapObjects.LegionList = p.buildMapObjectAndLegion(req.ObjectType, req.Markers)
  73. // 先推送 marker 对应的玩家数据和联盟数据给 AOI 观察者
  74. p.playerAndLeaguePush(watchers, mapObjects.ObjectList)
  75. // 再推送 marker 对象
  76. sessions.PushPlayers(watchers, nameRoute.PushMapPusher_ObjectUpdate, mapObjects)
  77. }
  78. func (p *actor) buildMapObjectAndLegion(objectType enum.ObjectType, objectIDs types.Set[int64]) ([]*pb.MapObject, []*pb.MapLegion) {
  79. objectList := []*pb.MapObject{}
  80. legionList := []*pb.MapLegion{}
  81. switch objectType {
  82. case enum.ObjectType_Legion:
  83. for objectID := range objectIDs {
  84. legionTable, ok := p.LegionTables.Get(objectID)
  85. if !ok {
  86. continue
  87. }
  88. legionPB := legionTable.ToProto()
  89. for _, member := range legionTable.Members {
  90. marchTable, ok := p.MarchTables.Get(member.Key)
  91. if !ok {
  92. continue
  93. }
  94. legionPB.MarchList = append(legionPB.MarchList, marchTable.ToProto())
  95. }
  96. legionList = append(legionList, legionPB)
  97. }
  98. case enum.ObjectType_March:
  99. {
  100. for objectID := range objectIDs {
  101. marchTable, ok := p.MarchTables.Get(objectID)
  102. if !ok {
  103. continue
  104. }
  105. objectList = append(objectList, marchTable.ToProto())
  106. }
  107. }
  108. case enum.ObjectType_Build:
  109. {
  110. for objectID := range objectIDs {
  111. buildTable, ok := p.BuildTables.Get(objectID)
  112. if !ok {
  113. continue
  114. }
  115. siegeTable := p.SiegeTables.GetValue(objectID)
  116. objectList = append(objectList, buildTable.ToProto(siegeTable))
  117. }
  118. }
  119. case enum.ObjectType_Castle:
  120. {
  121. for objectID := range objectIDs {
  122. castleTable, ok := p.CastleTables.Get(objectID)
  123. if !ok {
  124. continue
  125. }
  126. siegeTable := p.SiegeTables.GetValue(objectID)
  127. proto := castleTable.ToProto(p.LogicTables, siegeTable)
  128. if castleTable.FirstOccupyLeague.LeagueID > 0 {
  129. if pbMapLeague, ok := pbMapLeagues.Get(castleTable.FirstOccupyLeague.LeagueID); ok {
  130. proto.Castle.FirstLeagueName = pbMapLeague.LeagueName
  131. proto.Castle.FirstLeagueAbbName = pbMapLeague.LeagueAbbName
  132. proto.Castle.FirstLeagueIcon = 0 // TODO: 联盟图标
  133. }
  134. }
  135. objectList = append(objectList, proto)
  136. }
  137. }
  138. case enum.ObjectType_Res:
  139. {
  140. for objectID := range objectIDs {
  141. resTable, ok := p.ResTables.Get(objectID)
  142. if !ok {
  143. continue
  144. }
  145. objectList = append(objectList, resTable.ToProto())
  146. }
  147. }
  148. case enum.ObjectType_Monster:
  149. {
  150. for objectID := range objectIDs {
  151. monsterTable, ok := p.MonsterTables.Get(objectID)
  152. if !ok {
  153. continue
  154. }
  155. objectList = append(objectList, monsterTable.ToProto())
  156. }
  157. }
  158. }
  159. return objectList, legionList
  160. }
  161. func (p *actor) playerAndLeaguePush(playerIDs []int64, objectList []*pb.MapObject) {
  162. players := types.Map[int64, *pb.MapPlayer]{}
  163. leagues := types.Map[int64, *pb.MapLeague]{}
  164. // 组装地图玩家对象数据
  165. for _, mapObject := range objectList {
  166. if mapObject.PlayerID != 0 && !players.Contains(mapObject.PlayerID) {
  167. if watcherTable, ok := p.WatcherTables.Get(mapObject.PlayerID); ok {
  168. players.Put(mapObject.PlayerID, watcherTable.ToMapPlayer())
  169. }
  170. }
  171. if mapObject.LeagueID != 0 && !leagues.Contains(mapObject.LeagueID) {
  172. if mapLeague, ok := pbMapLeagues.Get(mapObject.LeagueID); ok {
  173. leagues.Put(mapObject.LeagueID, mapLeague)
  174. }
  175. }
  176. }
  177. if players.Size() > 0 {
  178. proto := pb.MapPlayers{}
  179. for _, player := range players {
  180. proto.List = append(proto.List, player)
  181. }
  182. sessions.PushPlayers(playerIDs, nameRoute.PushMapPusher_PlayerUpdate, &proto)
  183. clog.Debugf("Player update push: watchers = (%v), proto = (%v)", playerIDs, &proto)
  184. }
  185. if leagues.Size() > 0 {
  186. proto := pb.MapLeagues{}
  187. for _, league := range leagues {
  188. proto.List = append(proto.List, league)
  189. }
  190. sessions.PushPlayers(playerIDs, nameRoute.PushMapPusher_LeagueUpdate, &proto)
  191. clog.Debugf("League update push: watchers = (%v), proto = (%v)", playerIDs, &proto)
  192. }
  193. }
  194. // aoiUpdateMarchState aoi 更新回调 行军状态
  195. func (p *actor) aoiUpdateMarchState(req *mapTypes.AOIMarkerUpdate) {
  196. clog.Debugf("[aoiUpdateMarchState] ObjectID = %v, ObjectType = %s, Watcher Size = %d",
  197. req.Markers, enum.GetObjectTypeName(req.ObjectType), req.Watchers.Size())
  198. if req.Watchers.Size() == 0 {
  199. return
  200. }
  201. ws := req.Watchers.List()
  202. for objectID := range req.Markers {
  203. marchTable, ok := p.MarchTables.Get(objectID)
  204. if !ok {
  205. clog.Warnf("[aoiUpdateMarchState] march not found. objectID = %d", objectID)
  206. continue
  207. }
  208. sessions.PushPlayers(ws, nameRoute.PushMapPusher_MarchState, marchTable.ToStatusProto())
  209. // 通知ui更新
  210. p.PushMapUIMarchState(marchTable.PlayerID, marchTable.ToStatusProto())
  211. }
  212. }
  213. // aoiUpdateBattle aoi 更新回调 战斗
  214. func (p *actor) aoiUpdateBattle(req *mapTypes.AOIMarkerUpdate) {
  215. clog.Debugf("[aoiUpdateBattle] Watcher Size = %d", req.Watchers.Size())
  216. if req.Watchers.Size() == 0 {
  217. return
  218. }
  219. push, ok := getAOIUpdateBattle(req.UpdateID)
  220. if !ok {
  221. return
  222. }
  223. sessions.PushPlayers(req.Watchers.List(), nameRoute.PushMapPusher_Battle, push)
  224. }
  225. func (p *actor) mapPlayerSync(eventData cfacade.IEventData) {
  226. clog.Debugf("[mapPlayerSync] event = %+v", eventData)
  227. mapWatcherSync, ok := eventData.(*event.MapWatcherSync)
  228. if !ok {
  229. return
  230. }
  231. data := mapWatcherSync.Data()
  232. watcherTable := p.WatcherTables.GetValue(data.PlayerID)
  233. if data.IsFacilitySync {
  234. watcherTable.SyncFacilityAttrs(data.FacilityAttrs)
  235. p.mapPlayerMainCitySync(watcherTable)
  236. } else {
  237. watcherTable.Update(data)
  238. }
  239. }
  240. // 处理城建给玩家个人主城的最大耐久加成值
  241. func (p *actor) mapPlayerMainCitySync(watcherTable *db.LogicWatcherTable) {
  242. if siegeTable, ok := p.SiegeTables.Get(watcherTable.MainCity); ok {
  243. oldDurability := siegeTable.FacilityDurability
  244. nowDurability := watcherTable.FacilityAttrs.GetI32(enum.AttrCityLife)
  245. if oldDurability != nowDurability {
  246. siegeTable.UpdateFacilityDurability(nowDurability)
  247. clog.Debugf("main city durability update. playerID = %d, oldDurability = %d, nowDurability = %d", watcherTable.PlayerID, oldDurability, nowDurability)
  248. // 推送玩家个人主城建筑耐久变化
  249. if buildTable, ok := p.BuildTables.Get(watcherTable.MainCity); ok && !buildTable.IsHide {
  250. p.UpdateObjectFull(buildTable.ObjectID, buildTable.Type)
  251. }
  252. }
  253. }
  254. }
  255. func (p *actor) mapLeagueSync(eventData cfacade.IEventData) {
  256. clog.Debugf("[mapLeagueSync] event = %+v", eventData)
  257. mapLeagueSync, ok := eventData.(*event.MapLeagueSync)
  258. if !ok {
  259. return
  260. }
  261. mapLeague := mapLeagueSync.MapLeague()
  262. pbMapLeagues.Put(mapLeague.LeagueID, mapLeague)
  263. }