From 40988fe93da65d70d3f559a41bec42fed7637680 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Wed, 10 May 2023 06:43:56 +0300 Subject: [PATCH 10/10] Keep observes in sync with city investigation See osdn #46186 Signed-off-by: Marko Lindqvist --- client/packhand.c | 60 ++++++++++++++++++++++++++++++++++++---------- common/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 49942b5a2a..6157c5889e 100644 --- a/client/packhand.c +++ b/client/packhand.c @@ -939,12 +939,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. */ @@ -1883,6 +1883,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. ****************************************************************************/ @@ -1906,21 +1940,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/packets.def b/common/packets.def index 82ee232029..a94e2a42fc 100644 --- a/common/packets.def +++ b/common/packets.def @@ -343,6 +343,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 9f446a391e..d9f9483695 100755 --- a/fc_version +++ b/fc_version @@ -58,7 +58,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-2.6-network" -NETWORK_CAPSTRING_OPTIONAL="techloss_forgiveness year32" +NETWORK_CAPSTRING_OPTIONAL="techloss_forgiveness year32 obsinv" FREECIV_DISTRIBUTOR="" diff --git a/server/diplomats.c b/server/diplomats.c index e469e89ffd..9787a82d0e 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" @@ -176,13 +177,19 @@ void 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); @@ -210,7 +217,7 @@ void 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(ACTION_SPY_INVESTIGATE_CITY, pplayer, cplayer, city_tile(pcity), city_link(pcity)); @@ -1476,6 +1483,12 @@ static bool diplomat_infiltrate_tile(struct player *pplayer, } } unit_list_iterate_end; + 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