actor_aoi.go 9.8 KB

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