From 02816f16d97f23603d68a87aef08a09217ffafa3 Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Fri, 22 May 2026 05:04:07 +0300
Subject: [PATCH 43/43] Send access areas to the client

See RM #2038

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 client/packhand.c             | 35 +++++++++++++++++++++++++++++++++++
 common/accessarea.c           |  9 +++++++++
 common/accessarea.h           |  1 +
 common/networking/packets.def | 11 ++++++++++-
 server/aahand.c               | 14 +++++++++++++-
 5 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/client/packhand.c b/client/packhand.c
index fcda1d84aa..c6b9a7745c 100644
--- a/client/packhand.c
+++ b/client/packhand.c
@@ -28,6 +28,7 @@
 #include "support.h"
 
 /* common */
+#include "accessarea.h"
 #include "achievements.h"
 #include "actions.h"
 #include "capstr.h"
@@ -5804,3 +5805,37 @@ void handle_sync_serial_reply(int serial)
 {
   options_sync_reply(serial);
 }
+
+/**********************************************************************//**
+  Handle access area packet.
+**************************************************************************/
+void handle_access_area(const struct packet_access_area *packet)
+{
+  struct player *plr = player_by_number(packet->player);
+  struct aarea_list *alist;
+  struct access_area *aarea;
+
+  if (plr == nullptr) {
+    log_warn("handle_access_area() received illegal player");
+    return;
+  }
+
+  if (packet->index == 0) {
+    /* First access area packet. Clear old set. */
+    area_list_clear_plr(plr);
+
+    alist = aarea_list_new();
+    area_list_for_player_set(plr, alist);
+  } else {
+    alist = area_list_for_player(plr);
+  }
+
+  aarea = fc_malloc(sizeof(struct access_area));
+
+  aarea->cities = nullptr;
+  aarea->index = packet->index;
+  aarea->capital = packet->capital;
+  aarea->tiledefs = packet->tiledefs;
+
+  aarea_list_append(alist, aarea);
+}
diff --git a/common/accessarea.c b/common/accessarea.c
index b478121fb6..9c058b0f6d 100644
--- a/common/accessarea.c
+++ b/common/accessarea.c
@@ -96,6 +96,15 @@ void area_list_clear_plr(struct player *pplayer)
   area_list_clear(aalist[player_index(pplayer)]);
 }
 
+/*********************************************************************//**
+  Return current area list for player.
+  @param pplayer Whose list to return
+*************************************************************************/
+struct aarea_list *area_list_for_player(struct player *pplayer)
+{
+  return aalist[player_index(pplayer)];
+}
+
 /*********************************************************************//**
   Set access area list for player
   @param pplayer Whose list to set
diff --git a/common/accessarea.h b/common/accessarea.h
index 3541bbc786..39cd3e5404 100644
--- a/common/accessarea.h
+++ b/common/accessarea.h
@@ -36,6 +36,7 @@ const struct unit_type *access_info_access_unit(void);
 
 void area_list_clear(struct aarea_list *alist);
 void area_list_clear_plr(struct player *pplayer);
+struct aarea_list *area_list_for_player(struct player *pplayer);
 void area_list_for_player_set(struct player *pplayer, struct aarea_list *alist);
 
 #ifdef __cplusplus
diff --git a/common/networking/packets.def b/common/networking/packets.def
index e60676e640..3a961a7eb7 100644
--- a/common/networking/packets.def
+++ b/common/networking/packets.def
@@ -3,7 +3,7 @@
 Max used id:
 ============
 
-Max id: 520
+Max id: 521
 
 Packets are not ordered by their id, but by their category. New packet
 with higher id may get added to existing category, and not to the end of file.
@@ -301,6 +301,7 @@ type BV_UTYPE_FLAGS     = bitvector(bv_unit_type_flags)
 type BV_UTYPE_ROLES     = bitvector(bv_unit_type_roles)
 type BV_DISASTER_EFFECTS = bitvector(bv_disaster_effects)
 type BV_SPACESHIP_STRUCT = bitvector(bv_spaceship_structure)
+type BV_TILEDEFS         = bitvector(bv_tiledefs)
 
 # typedefs for IDs
 type EXTRA              = SINT8
@@ -2435,6 +2436,14 @@ PACKET_SYNC_SERIAL_REPLY = 518; sc, handle-via-fields, dsend
   UINT32 serial;
 end
 
+/************** Access areas **********************/
+PACKET_ACCESS_AREA = 521; sc, lsend
+  PLAYER player;
+  UINT16 index;
+  BOOL capital;
+  BV_TILEDEFS tiledefs;
+end
+
 /*************** Webclient specific packets ****************/
 /* Use range 256:511 for these                             */
 
diff --git a/server/aahand.c b/server/aahand.c
index c4a168a292..062ee15a16 100644
--- a/server/aahand.c
+++ b/server/aahand.c
@@ -38,6 +38,7 @@ void access_areas_refresh(struct civ_map *nmap, struct player *plr)
     struct unit *access_unit;
     struct aarea_list *alist;
     int index = 0;
+    struct packet_access_area packet;
 
     area_list_clear_plr(plr);
     alist = aarea_list_new();
@@ -51,6 +52,8 @@ void access_areas_refresh(struct civ_map *nmap, struct player *plr)
     access_unit = unit_virtual_create(plr, nullptr,
                                       access_utype, 0);
 
+    packet.player = player_number(plr);
+
     city_list_iterate(plr->cities, pcity) {
       if (pcity->server.aarea == nullptr) {
         struct access_area *aarea = fc_malloc(sizeof(struct access_area));
@@ -88,17 +91,26 @@ void access_areas_refresh(struct civ_map *nmap, struct player *plr)
         } city_list_iterate_end;
 
         BV_CLR_ALL(aarea->tiledefs);
+        BV_CLR_ALL(packet.tiledefs);
         pf_map_tiles_iterate(pfm, ptile, TRUE) {
           if (ptile != nullptr) {
             tiledef_iterate(td) {
               if (tile_matches_tiledef(td, ptile)) {
-                BV_SET(aarea->tiledefs, tiledef_number(td));
+                int tn = tiledef_number(td);
+
+                BV_SET(aarea->tiledefs, tn);
+                BV_SET(packet.tiledefs, tn);
               }
             } tiledef_iterate_end;
           }
         } pf_map_tiles_iterate_end;
 
         pf_map_destroy(pfm);
+
+        packet.index = aarea->index;
+        packet.capital = aarea->capital;
+
+        lsend_packet_access_area(plr->connections, &packet);
       }
     } city_list_iterate_end;
 
-- 
2.53.0

