actor_aoi.go 9.0 KB

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