From ad60b215bf89cf19cfe977b1252ddace12170550 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Wed, 10 May 2023 06:40:56 +0300 Subject: [PATCH 11/11] Keep observes in sync with city investigation See osdn #46186 Signed-off-by: Marko Lindqvist --- client/packhand.c | 60 ++++++++++++++++++++++++++++------- common/networking/packets.def | 10 ++++++ fc_version | 2 +- server/diplomats.c | 17 ++++++++-- 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/client/packhand.c b/client/packhand.c index fc8164c376..c96b786f2d 100644 --- a/client/packhand.c +++ b/client/packhand.c @@ -973,12 +973,12 @@ static void city_packet_common(struct city *pcity, struct tile *pcenter, unit_list_destroy(pcity->client.info_units_present); pcity->client.info_units_present = - pcity->client.collecting_info_units_present; + pcity->client.collecting_info_units_present; pcity->client.collecting_info_units_present = NULL; unit_list_destroy(pcity->client.info_units_supported); pcity->client.info_units_supported = - pcity->client.collecting_info_units_supported; + pcity->client.collecting_info_units_supported; pcity->client.collecting_info_units_supported = NULL; } else { /* We didn't get any unit, let's clear the unit lists. */ @@ -1982,6 +1982,40 @@ static bool handle_unit_packet_common(struct unit *packet_unit) return ret; } +/**************************************************************************** + Receive an investigate_started packet + + Can't rely on generic packet_processing_started, as that works for + the requesting connection only, and not for observers. +****************************************************************************/ +void handle_investigate_started(int unit_id, int city_id) +{ + struct city *pcity = game_city_by_number(city_id); + + if (!pcity) { + log_error("Investigate city: unknown city id %d!", + city_id); + return; + } + + /* Start collecting supported and present units. */ + + /* Ensure we are not already in an investigate cycle. */ + fc_assert(pcity->client.collecting_info_units_supported == NULL); + fc_assert(pcity->client.collecting_info_units_present == NULL); + pcity->client.collecting_info_units_supported = + unit_list_new_full(unit_virtual_destroy); + pcity->client.collecting_info_units_present = + unit_list_new_full(unit_virtual_destroy); +} + +/**************************************************************************** + Receive an investigate_finished packet +****************************************************************************/ +void handle_investigate_finished(int unit_id, int city_id) +{ +} + /**************************************************************************** Receive a short_unit info packet. ****************************************************************************/ @@ -2005,21 +2039,23 @@ void handle_unit_short_info(const struct packet_unit_short_info *packet) return; } - /* New serial number: start collecting supported and present units. */ - if (last_serial_num - != client.conn.client.request_id_of_currently_handled_packet) { - last_serial_num = + if (!has_capability("obsinv", client.conn.capability)) { + /* New serial number: start collecting supported and present units. */ + if (last_serial_num + != client.conn.client.request_id_of_currently_handled_packet) { + last_serial_num = client.conn.client.request_id_of_currently_handled_packet; - /* Ensure we are not already in an investigate cycle. */ - fc_assert(pcity->client.collecting_info_units_supported == NULL); - fc_assert(pcity->client.collecting_info_units_present == NULL); - pcity->client.collecting_info_units_supported = + /* Ensure we are not already in an investigate cycle. */ + fc_assert(pcity->client.collecting_info_units_supported == NULL); + fc_assert(pcity->client.collecting_info_units_present == NULL); + pcity->client.collecting_info_units_supported = unit_list_new_full(unit_virtual_destroy); - pcity->client.collecting_info_units_present = + pcity->client.collecting_info_units_present = unit_list_new_full(unit_virtual_destroy); + } } - /* Okay, append a unit struct to the proper list. */ + /* Append a unit struct to the proper list. */ punit = unpackage_short_unit(packet); if (packet->packet_use == UNIT_INFO_CITY_SUPPORTED) { fc_assert(pcity->client.collecting_info_units_supported != NULL); diff --git a/common/networking/packets.def b/common/networking/packets.def index c076d6b3b6..018f4d4c65 100644 --- a/common/networking/packets.def +++ b/common/networking/packets.def @@ -361,6 +361,16 @@ end PACKET_PROCESSING_FINISHED = 1; sc end +PACKET_INVESTIGATE_STARTED = 21; sc, dsend + UNIT unit_id; + CITY city_id; +end + +PACKET_INVESTIGATE_FINISHED = 22; sc, dsend + UNIT unit_id; + CITY city_id; +end + /************** Login/pregame/endgame packets **********************/ # This packet is the first real (freeciv specific) packet send by the diff --git a/fc_version b/fc_version index c62b30f3ec..5615777877 100755 --- a/fc_version +++ b/fc_version @@ -70,7 +70,7 @@ DEFAULT_FOLLOW_TAG=stable # as long as possible. We want to maintain network compatibility with # the stable branch for as long as possible. NETWORK_CAPSTRING_MANDATORY="+Freeciv-3.0-network" -NETWORK_CAPSTRING_OPTIONAL="year32 plrculture32 pingfix researchclr cityculture32 rsdesc32" +NETWORK_CAPSTRING_OPTIONAL="year32 plrculture32 pingfix researchclr cityculture32 rsdesc32 obsinv" FREECIV_DISTRIBUTOR="" diff --git a/server/diplomats.c b/server/diplomats.c index 8117a11137..24e5b56771 100644 --- a/server/diplomats.c +++ b/server/diplomats.c @@ -19,6 +19,7 @@ /* utility */ #include "bitvector.h" +#include "capability.h" #include "fcintl.h" #include "log.h" #include "rand.h" @@ -200,13 +201,19 @@ bool diplomat_investigate(struct player *pplayer, struct unit *pdiplomat, log_debug("investigate: unit: %d", pdiplomat->id); + conn_list_iterate(pplayer->connections, pconn) { + if (has_capability("obsinv", pconn->capability)) { + dsend_packet_investigate_started(pconn, pdiplomat->id, pcity->id); + } + } conn_list_iterate_end; + /* Do It... */ update_dumb_city(pplayer, pcity); /* Special case for a diplomat/spy investigating a city: The investigator needs to know the supported and present units of a city, whether or not they are fogged. So, we send a list of them all before sending the city info. - As this is a special case we bypass send_unit_info. */ + As this is a special case we bypass send_unit_info(). */ unit_list_iterate(pcity->units_supported, punit) { package_short_unit(punit, &unit_packet, UNIT_INFO_CITY_SUPPORTED, pcity->id); @@ -241,7 +248,7 @@ bool diplomat_investigate(struct player *pplayer, struct unit *pdiplomat, pdiplomat->moves_left = 0; } - /* this may cause a diplomatic incident */ + /* This may cause a diplomatic incident */ action_consequence_success(paction, pplayer, cplayer, city_tile(pcity), city_link(pcity)); @@ -253,6 +260,12 @@ bool diplomat_investigate(struct player *pplayer, struct unit *pdiplomat, send_unit_info(NULL, pdiplomat); } + conn_list_iterate(pplayer->connections, pconn) { + if (has_capability("obsinv", pconn->capability)) { + dsend_packet_investigate_finished(pconn, pdiplomat->id, pcity->id); + } + } conn_list_iterate_end; + return TRUE; } -- 2.39.2