1 /***********************************************************************
2  Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2, or (at your option)
6    any later version.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 ***********************************************************************/
13 
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17 
18 #include <string.h>
19 
20 /* utility */
21 #include "bitvector.h"
22 #include "capability.h"
23 #include "fcintl.h"
24 #include "log.h"
25 #include "mem.h"
26 #include "rand.h"
27 #include "string_vector.h"
28 #include "support.h"
29 
30 /* common */
31 #include "achievements.h"
32 #include "actions.h"
33 #include "capstr.h"
34 #include "citizens.h"
35 #include "events.h"
36 #include "extras.h"
37 #include "game.h"
38 #include "government.h"
39 #include "idex.h"
40 #include "map.h"
41 #include "name_translation.h"
42 #include "movement.h"
43 #include "multipliers.h"
44 #include "nation.h"
45 #include "packets.h"
46 #include "player.h"
47 #include "research.h"
48 #include "rgbcolor.h"
49 #include "road.h"
50 #include "spaceship.h"
51 #include "specialist.h"
52 #include "style.h"
53 #include "traderoutes.h"
54 #include "unit.h"
55 #include "unitlist.h"
56 #include "worklist.h"
57 
58 /* client/include */
59 #include "chatline_g.h"
60 #include "citydlg_g.h"
61 #include "cityrep_g.h"
62 #include "connectdlg_g.h"
63 #include "dialogs_g.h"
64 #include "editgui_g.h"
65 #include "gui_main_g.h"
66 #include "inteldlg_g.h"
67 #include "mapctrl_g.h"          /* popup_newcity_dialog() */
68 #include "mapview_g.h"
69 #include "menu_g.h"
70 #include "messagewin_g.h"
71 #include "pages_g.h"
72 #include "plrdlg_g.h"
73 #include "ratesdlg_g.h"
74 #include "repodlgs_g.h"
75 #include "spaceshipdlg_g.h"
76 #include "voteinfo_bar_g.h"
77 #include "wldlg_g.h"
78 
79 /* client */
80 #include "agents.h"
81 #include "attribute.h"
82 #include "audio.h"
83 #include "client_main.h"
84 #include "climap.h"
85 #include "climisc.h"
86 #include "connectdlg_common.h"
87 #include "control.h"
88 #include "editor.h"
89 #include "goto.h"               /* client_goto_init() */
90 #include "helpdata.h"           /* boot_help_texts() */
91 #include "mapview_common.h"
92 #include "music.h"
93 #include "options.h"
94 #include "overview_common.h"
95 #include "tilespec.h"
96 #include "update_queue.h"
97 #include "voteinfo.h"
98 
99 #include "packhand.h"
100 
101 /* Define this macro to get additional debug output about the transport
102  * status of the units. */
103 #undef DEBUG_TRANSPORT
104 
105 static void city_packet_common(struct city *pcity, struct tile *pcenter,
106                                struct player *powner,
107                                struct tile_list *worked_tiles,
108                                bool is_new, bool popup, bool investigate);
109 static bool handle_unit_packet_common(struct unit *packet_unit);
110 
111 
112 /* The dumbest of cities, placeholders for unknown and unseen cities. */
113 static struct {
114   struct city_list *cities;
115   struct player *placeholder;
116 } invisible = {
117   .cities = NULL,
118   .placeholder = NULL
119 };
120 
121 static struct {
122   int len;
123   enum event_type event;
124   char *caption;
125   char *headline;
126   char *lines;
127   int parts;
128 } page_msg_report = { .parts = 0 };
129 
130 extern const char forced_tileset_name[];
131 
132 static int last_turn = 0;
133 
134 /****************************************************************************
135   Called below, and by client/client_main.c client_game_free()
136 ****************************************************************************/
packhand_free(void)137 void packhand_free(void)
138 {
139   if (NULL != invisible.cities) {
140     city_list_iterate(invisible.cities, pcity) {
141       idex_unregister_city(pcity);
142       destroy_city_virtual(pcity);
143     } city_list_iterate_end;
144 
145     city_list_destroy(invisible.cities);
146     invisible.cities = NULL;
147   }
148 
149   if (NULL != invisible.placeholder) {
150     free(invisible.placeholder);
151     invisible.placeholder = NULL;
152   }
153 }
154 
155 /****************************************************************************
156   Called only by handle_map_info() below.
157 ****************************************************************************/
packhand_init(void)158 static void packhand_init(void)
159 {
160   packhand_free();
161 
162   invisible.cities = city_list_new();
163 
164   /* Can't use player_new() here, as it will register the player. */
165   invisible.placeholder = fc_calloc(1, sizeof(*invisible.placeholder));
166   memset(invisible.placeholder, 0, sizeof(*invisible.placeholder));
167   /* Set some values to prevent bugs ... */
168   sz_strlcpy(invisible.placeholder->name, ANON_PLAYER_NAME);
169   sz_strlcpy(invisible.placeholder->username, _(ANON_USER_NAME));
170   invisible.placeholder->unassigned_user = TRUE;
171   sz_strlcpy(invisible.placeholder->ranked_username, ANON_USER_NAME);
172   invisible.placeholder->unassigned_ranked = TRUE;
173 }
174 
175 /****************************************************************************
176   Unpackage the unit information into a newly allocated unit structure.
177 
178   Information for the client must also be processed in
179   handle_unit_packet_common()! Especially notice that unit structure filled
180   here is just temporary one. Values must be copied to real unit in
181   handle_unit_packet_common().
182 ****************************************************************************/
unpackage_unit(const struct packet_unit_info * packet)183 static struct unit *unpackage_unit(const struct packet_unit_info *packet)
184 {
185   struct unit *punit = unit_virtual_create(player_by_number(packet->owner),
186 					   NULL,
187 					   utype_by_number(packet->type),
188 					   packet->veteran);
189 
190   /* Owner, veteran, and type fields are already filled in by
191    * unit_virtual_create. */
192   punit->nationality = player_by_number(packet->nationality);
193   punit->id = packet->id;
194   unit_tile_set(punit, index_to_tile(packet->tile));
195   punit->facing = packet->facing;
196   punit->homecity = packet->homecity;
197   output_type_iterate(o) {
198     punit->upkeep[o] = packet->upkeep[o];
199   } output_type_iterate_end;
200   punit->moves_left = packet->movesleft;
201   punit->hp = packet->hp;
202   punit->activity = packet->activity;
203   punit->activity_count = packet->activity_count;
204 
205   if (packet->activity_tgt == EXTRA_NONE) {
206     punit->activity_target = NULL;
207   } else {
208     punit->activity_target = extra_by_number(packet->activity_tgt);
209   }
210 
211   punit->changed_from = packet->changed_from;
212   punit->changed_from_count = packet->changed_from_count;
213 
214  if (packet->changed_from_tgt == EXTRA_NONE) {
215     punit->changed_from_target = NULL;
216   } else {
217     punit->changed_from_target = extra_by_number(packet->changed_from_tgt);
218   }
219 
220   punit->ai_controlled = packet->ai;
221   punit->fuel = packet->fuel;
222   punit->goto_tile = index_to_tile(packet->goto_tile);
223   punit->paradropped = packet->paradropped;
224   punit->done_moving = packet->done_moving;
225 
226   /* Transporter / transporting information. */
227   punit->client.occupied = packet->occupied;
228   if (packet->transported) {
229     punit->client.transported_by = packet->transported_by;
230   } else {
231     punit->client.transported_by = -1;
232   }
233 
234   punit->battlegroup = packet->battlegroup;
235   punit->has_orders = packet->has_orders;
236   punit->orders.length = packet->orders_length;
237   punit->orders.index = packet->orders_index;
238   punit->orders.repeat = packet->orders_repeat;
239   punit->orders.vigilant = packet->orders_vigilant;
240   if (punit->has_orders) {
241     int i;
242 
243     punit->orders.list
244       = fc_malloc(punit->orders.length * sizeof(*punit->orders.list));
245     for (i = 0; i < punit->orders.length; i++) {
246       punit->orders.list[i].order = packet->orders[i];
247       punit->orders.list[i].dir = packet->orders_dirs[i];
248       punit->orders.list[i].activity = packet->orders_activities[i];
249       punit->orders.list[i].target = packet->orders_targets[i];
250     }
251   }
252 
253   punit->action_decision_want = packet->action_decision_want;
254   punit->action_decision_tile
255       = index_to_tile(packet->action_decision_tile);
256 
257   punit->client.asking_city_name = FALSE;
258 
259   return punit;
260 }
261 
262 /****************************************************************************
263   Unpackage a short_unit_info packet.  This extracts a limited amount of
264   information about the unit, and is sent for units we shouldn't know
265   everything about (like our enemies' units).
266 
267   Information for the client must also be processed in
268   handle_unit_packet_common()! Especially notice that unit structure filled
269   here is just temporary one. Values must be copied to real unit in
270   handle_unit_packet_common().
271 ****************************************************************************/
272 static struct unit *
unpackage_short_unit(const struct packet_unit_short_info * packet)273 unpackage_short_unit(const struct packet_unit_short_info *packet)
274 {
275   struct unit *punit = unit_virtual_create(player_by_number(packet->owner),
276 					   NULL,
277 					   utype_by_number(packet->type),
278 					   FALSE);
279 
280   /* Owner and type fields are already filled in by unit_virtual_create. */
281   punit->id = packet->id;
282   unit_tile_set(punit, index_to_tile(packet->tile));
283   punit->facing = packet->facing;
284   punit->nationality = NULL;
285   punit->veteran = packet->veteran;
286   punit->hp = packet->hp;
287   punit->activity = packet->activity;
288 
289   if (packet->activity_tgt == EXTRA_NONE) {
290     punit->activity_target = NULL;
291   } else {
292     punit->activity_target = extra_by_number(packet->activity_tgt);
293   }
294 
295   /* Transporter / transporting information. */
296   punit->client.occupied = packet->occupied;
297   if (packet->transported) {
298     punit->client.transported_by = packet->transported_by;
299   } else {
300     punit->client.transported_by = -1;
301   }
302 
303   return punit;
304 }
305 
306 /****************************************************************************
307   After we send a join packet to the server we receive a reply.  This
308   function handles the reply.
309 ****************************************************************************/
handle_server_join_reply(bool you_can_join,const char * message,const char * capability,const char * challenge_file,int conn_id)310 void handle_server_join_reply(bool you_can_join, const char *message,
311                               const char *capability,
312                               const char *challenge_file, int conn_id)
313 {
314   const char *s_capability = client.conn.capability;
315 
316   conn_set_capability(&client.conn, capability);
317   close_connection_dialog();
318 
319   if (you_can_join) {
320     struct packet_client_info client_info;
321 
322     log_verbose("join game accept:%s", message);
323     client.conn.established = TRUE;
324     client.conn.id = conn_id;
325 
326     agents_game_joined();
327     set_server_busy(FALSE);
328 
329     if (get_client_page() == PAGE_MAIN
330         || get_client_page() == PAGE_NETWORK) {
331       set_client_page(PAGE_START);
332     }
333 
334     client_info.gui = get_gui_type();
335     strncpy(client_info.distribution, FREECIV_DISTRIBUTOR,
336             sizeof(client_info.distribution));
337     send_packet_client_info(&client.conn, &client_info);
338 
339     /* we could always use hack, verify we're local */
340 #ifdef DEBUG
341     if (!hackless || is_server_running())
342 #endif
343     {
344       send_client_wants_hack(challenge_file);
345     }
346 
347     set_client_state(C_S_PREPARING);
348   } else {
349     output_window_printf(ftc_client,
350                          _("You were rejected from the game: %s"), message);
351     client.conn.id = -1; /* not in range of conn_info id */
352 
353     if (auto_connect) {
354       log_normal(_("You were rejected from the game: %s"), message);
355     }
356     server_connect();
357 
358     set_client_page(PAGE_MAIN);
359   }
360   if (strcmp(s_capability, our_capability) == 0) {
361     return;
362   }
363   output_window_printf(ftc_client, _("Client capability string: %s"),
364                        our_capability);
365   output_window_printf(ftc_client, _("Server capability string: %s"),
366                        s_capability);
367 }
368 
369 /****************************************************************************
370   Handles a remove-city packet, used by the server to tell us any time a
371   city is no longer there.
372 ****************************************************************************/
handle_city_remove(int city_id)373 void handle_city_remove(int city_id)
374 {
375   struct city *pcity = game_city_by_number(city_id);
376   bool need_menus_update;
377 
378   fc_assert_ret_msg(NULL != pcity, "Bad city %d.", city_id);
379 
380   need_menus_update = (NULL != get_focus_unit_on_tile(city_tile(pcity)));
381 
382   agents_city_remove(pcity);
383   editgui_notify_object_changed(OBJTYPE_CITY, pcity->id, TRUE);
384   client_remove_city(pcity);
385 
386   /* Update menus if the focus unit is on the tile. */
387   if (need_menus_update) {
388     menus_update();
389   }
390 }
391 
392 /**************************************************************************
393   Handle a remove-unit packet, sent by the server to tell us any time a
394   unit is no longer there.
395 **************************************************************************/
handle_unit_remove(int unit_id)396 void handle_unit_remove(int unit_id)
397 {
398   struct unit *punit = game_unit_by_number(unit_id);
399   struct unit_list *cargos;
400   struct player *powner;
401   bool need_economy_report_update;
402 
403   if (!punit) {
404     log_error("Server wants us to remove unit id %d, "
405               "but we don't know about this unit!",
406               unit_id);
407     return;
408   }
409 
410   /* Close the action selection dialog if the actor unit is lost. */
411   if (action_selection_actor_unit() == punit->id) {
412     action_selection_close();
413     /* Open another action selection dialog if there are other actors in the
414      * current selection that want a decision. */
415     action_selection_next_in_focus(unit_id);
416   }
417 
418   need_economy_report_update = (0 < punit->upkeep[O_GOLD]);
419   powner = unit_owner(punit);
420 
421   /* Unload cargo if this is a transporter. */
422   cargos = unit_transport_cargo(punit);
423   if (unit_list_size(cargos) > 0) {
424     unit_list_iterate(cargos, pcargo) {
425       unit_transport_unload(pcargo);
426     } unit_list_iterate_end;
427   }
428 
429   /* Unload unit if it is transported. */
430   if (unit_transport_get(punit)) {
431     unit_transport_unload(punit);
432   }
433   punit->client.transported_by = -1;
434 
435   agents_unit_remove(punit);
436   editgui_notify_object_changed(OBJTYPE_UNIT, punit->id, TRUE);
437   client_remove_unit(punit);
438 
439   if (!client_has_player() || powner == client_player()) {
440     if (need_economy_report_update) {
441       economy_report_dialog_update();
442     }
443     units_report_dialog_update();
444   }
445 }
446 
447 /****************************************************************************
448   The tile (x,y) has been nuked!
449 ****************************************************************************/
handle_nuke_tile_info(int tile)450 void handle_nuke_tile_info(int tile)
451 {
452   put_nuke_mushroom_pixmaps(index_to_tile(tile));
453 }
454 
455 /****************************************************************************
456   The name of team 'team_id'
457 ****************************************************************************/
handle_team_name_info(int team_id,const char * team_name)458 void handle_team_name_info(int team_id, const char *team_name)
459 {
460   struct team_slot *tslot = team_slot_by_number(team_id);
461 
462   fc_assert_ret(NULL != tslot);
463   team_slot_set_defined_name(tslot, team_name);
464   conn_list_dialog_update();
465 }
466 
467 /****************************************************************************
468   A combat packet.  The server tells us the attacker and defender as well
469   as both of their hitpoints after the combat is over (in most combat, one
470   unit always dies and their HP drops to zero).  If make_winner_veteran is
471   set then the surviving unit becomes veteran.
472 ****************************************************************************/
handle_unit_combat_info(int attacker_unit_id,int defender_unit_id,int attacker_hp,int defender_hp,bool make_winner_veteran)473 void handle_unit_combat_info(int attacker_unit_id, int defender_unit_id,
474 			     int attacker_hp, int defender_hp,
475 			     bool make_winner_veteran)
476 {
477   bool show_combat = FALSE;
478   struct unit *punit0 = game_unit_by_number(attacker_unit_id);
479   struct unit *punit1 = game_unit_by_number(defender_unit_id);
480 
481   if (punit0 && punit1) {
482     popup_combat_info(attacker_unit_id, defender_unit_id, attacker_hp,
483                       defender_hp, make_winner_veteran);
484     if (tile_visible_mapcanvas(unit_tile(punit0)) &&
485 	tile_visible_mapcanvas(unit_tile(punit1))) {
486       show_combat = TRUE;
487     } else if (gui_options.auto_center_on_combat) {
488       if (unit_owner(punit0) == client.conn.playing) {
489         center_tile_mapcanvas(unit_tile(punit0));
490       } else {
491         center_tile_mapcanvas(unit_tile(punit1));
492       }
493       show_combat = TRUE;
494     }
495 
496     if (show_combat) {
497       int hp0 = attacker_hp, hp1 = defender_hp;
498 
499       audio_play_sound(unit_type_get(punit0)->sound_fight,
500 		       unit_type_get(punit0)->sound_fight_alt);
501       audio_play_sound(unit_type_get(punit1)->sound_fight,
502 		       unit_type_get(punit1)->sound_fight_alt);
503 
504       if (gui_options.smooth_combat_step_msec > 0) {
505         decrease_unit_hp_smooth(punit0, hp0, punit1, hp1);
506       } else {
507 	punit0->hp = hp0;
508 	punit1->hp = hp1;
509 
510 	set_units_in_combat(NULL, NULL);
511 	refresh_unit_mapcanvas(punit0, unit_tile(punit0), TRUE, FALSE);
512 	refresh_unit_mapcanvas(punit1, unit_tile(punit1), TRUE, FALSE);
513       }
514     }
515     if (make_winner_veteran) {
516       struct unit *pwinner = (defender_hp == 0 ? punit0 : punit1);
517 
518       pwinner->veteran++;
519       refresh_unit_mapcanvas(pwinner, unit_tile(pwinner), TRUE, FALSE);
520     }
521   }
522 }
523 
524 /**************************************************************************
525   Updates a city's list of improvements from packet data.
526   "have_impr" specifies whether the improvement should be added (TRUE)
527   or removed (FALSE). Returns TRUE if the improvement has been actually
528   added or removed.
529 **************************************************************************/
update_improvement_from_packet(struct city * pcity,struct impr_type * pimprove,bool have_impr)530 static bool update_improvement_from_packet(struct city *pcity,
531                                            struct impr_type *pimprove,
532                                            bool have_impr)
533 {
534   if (have_impr) {
535     if (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) {
536       city_add_improvement(pcity, pimprove);
537       return TRUE;
538     }
539   } else {
540     if (pcity->built[improvement_index(pimprove)].turn > I_NEVER) {
541       city_remove_improvement(pcity, pimprove);
542       return TRUE;
543     }
544   }
545   return FALSE;
546 }
547 
548 /****************************************************************************
549   A city-info packet contains all information about a city.  If we receive
550   this packet then we know everything about the city internals.
551 ****************************************************************************/
handle_city_info(const struct packet_city_info * packet)552 void handle_city_info(const struct packet_city_info *packet)
553 {
554   struct universal product;
555   int i;
556   bool popup;
557   bool city_is_new = FALSE;
558   bool city_has_changed_owner = FALSE;
559   bool need_science_dialog_update = FALSE;
560   bool need_units_dialog_update = FALSE;
561   bool need_economy_dialog_update = FALSE;
562   bool name_changed = FALSE;
563   bool update_descriptions = FALSE;
564   bool shield_stock_changed = FALSE;
565   bool production_changed = FALSE;
566   bool trade_routes_changed = FALSE;
567   struct unit_list *pfocus_units = get_units_in_focus();
568   struct city *pcity = game_city_by_number(packet->id);
569   struct tile_list *worked_tiles = NULL;
570   struct tile *pcenter = index_to_tile(packet->tile);
571   struct tile *ptile = NULL;
572   struct player *powner = player_by_number(packet->owner);
573 
574   fc_assert_ret_msg(NULL != powner, "Bad player number %d.", packet->owner);
575   fc_assert_ret_msg(NULL != pcenter, "Invalid tile index %d.", packet->tile);
576 
577   if (!universals_n_is_valid(packet->production_kind)) {
578     log_error("handle_city_info() bad production_kind %d.",
579               packet->production_kind);
580     product.kind = VUT_NONE;
581   } else {
582     product = universal_by_number(packet->production_kind,
583                                   packet->production_value);
584     if (!universals_n_is_valid(product.kind)) {
585       log_error("handle_city_info() "
586                 "production_kind %d with bad production_value %d.",
587                 packet->production_kind, packet->production_value);
588       product.kind = VUT_NONE;
589     }
590   }
591 
592   if (NULL != pcity) {
593     ptile = city_tile(pcity);
594 
595     if (NULL == ptile) {
596       /* invisible worked city */
597       city_list_remove(invisible.cities, pcity);
598       city_is_new = TRUE;
599 
600       pcity->tile = pcenter;
601       ptile = pcenter;
602       pcity->owner = powner;
603       pcity->original = powner;
604     } else if (city_owner(pcity) != powner) {
605       /* Remember what were the worked tiles.  The server won't
606        * send to us again. */
607       city_tile_iterate_skip_free_worked(city_map_radius_sq_get(pcity),
608                                          ptile, pworked, _index, _x, _y) {
609         if (pcity == tile_worked(pworked)) {
610           if (NULL == worked_tiles) {
611             worked_tiles = tile_list_new();
612           }
613           tile_list_append(worked_tiles, pworked);
614         }
615       } city_tile_iterate_skip_free_worked_end;
616       client_remove_city(pcity);
617       pcity = NULL;
618       city_has_changed_owner = TRUE;
619     }
620   }
621 
622   if (NULL == pcity) {
623     city_is_new = TRUE;
624     pcity = create_city_virtual(powner, pcenter, packet->name);
625     pcity->id = packet->id;
626     idex_register_city(pcity);
627     update_descriptions = TRUE;
628   } else if (pcity->id != packet->id) {
629     log_error("handle_city_info() city id %d != id %d.",
630               pcity->id, packet->id);
631     return;
632   } else if (ptile != pcenter) {
633     log_error("handle_city_info() city tile (%d, %d) != (%d, %d).",
634               TILE_XY(ptile), TILE_XY(pcenter));
635     return;
636   } else {
637     name_changed = (0 != strncmp(packet->name, pcity->name,
638                                  sizeof(pcity->name)));
639     /* pcity->trade_value doesn't change the city description, neither the
640      * trade routes lines. */
641     trade_routes_changed = (gui_options.draw_city_trade_routes
642                             && 0 != memcmp(pcity->trade, packet->trade,
643                                            sizeof(pcity->trade)));
644 
645     /* Descriptions should probably be updated if the
646      * city name, production or time-to-grow changes.
647      * Note that if either the food stock or surplus
648      * have changed, the time-to-grow is likely to
649      * have changed as well. */
650     update_descriptions = (gui_options.draw_city_names && name_changed)
651       || (gui_options.draw_city_productions
652           && (!are_universals_equal(&pcity->production, &product)
653               || pcity->surplus[O_SHIELD] != packet->surplus[O_SHIELD]
654               || pcity->shield_stock != packet->shield_stock))
655       || (gui_options.draw_city_growth
656           && (pcity->food_stock != packet->food_stock
657               || pcity->surplus[O_FOOD] != packet->surplus[O_FOOD]))
658       || (gui_options.draw_city_trade_routes && trade_routes_changed);
659   }
660 
661   sz_strlcpy(pcity->name, packet->name);
662 
663   /* check data */
664   city_size_set(pcity, 0);
665   for (i = 0; i < FEELING_LAST; i++) {
666     pcity->feel[CITIZEN_HAPPY][i] = packet->ppl_happy[i];
667     pcity->feel[CITIZEN_CONTENT][i] = packet->ppl_content[i];
668     pcity->feel[CITIZEN_UNHAPPY][i] = packet->ppl_unhappy[i];
669     pcity->feel[CITIZEN_ANGRY][i] = packet->ppl_angry[i];
670   }
671   for (i = 0; i < CITIZEN_LAST; i++) {
672     city_size_add(pcity, pcity->feel[i][FEELING_FINAL]);
673   }
674   specialist_type_iterate(sp) {
675     pcity->specialists[sp] = packet->specialists[sp];
676     city_size_add(pcity, pcity->specialists[sp]);
677   } specialist_type_iterate_end;
678 
679   if (city_size_get(pcity) != packet->size) {
680     log_error("handle_city_info() "
681               "%d citizens not equal %d city size in \"%s\".",
682               city_size_get(pcity), packet->size, city_name_get(pcity));
683     city_size_set(pcity, packet->size);
684   }
685 
686   /* The nationality of the citizens. */
687   if (game.info.citizen_nationality) {
688     citizens_init(pcity);
689     for (i = 0; i < packet->nationalities_count; i++) {
690       citizens_nation_set(pcity, player_slot_by_number(packet->nation_id[i]),
691                           packet->nation_citizens[i]);
692     }
693     fc_assert(citizens_count(pcity) == city_size_get(pcity));
694   }
695 
696   pcity->history = packet->history;
697   pcity->client.culture = packet->culture;
698 
699   pcity->city_radius_sq = packet->city_radius_sq;
700 
701   pcity->city_options = packet->city_options;
702 
703   for (i = 0; i < MAX_TRADE_ROUTES; i++) {
704     pcity->trade[i] = packet->trade[i];
705     pcity->trade_value[i] = packet->trade_value[i];
706   }
707 
708   if (pcity->surplus[O_SCIENCE] != packet->surplus[O_SCIENCE]
709       || pcity->surplus[O_SCIENCE] != packet->surplus[O_SCIENCE]
710       || pcity->waste[O_SCIENCE] != packet->waste[O_SCIENCE]
711       || (pcity->unhappy_penalty[O_SCIENCE]
712           != packet->unhappy_penalty[O_SCIENCE])
713       || pcity->prod[O_SCIENCE] != packet->prod[O_SCIENCE]
714       || pcity->citizen_base[O_SCIENCE] != packet->citizen_base[O_SCIENCE]
715       || pcity->usage[O_SCIENCE] != packet->usage[O_SCIENCE]) {
716     need_science_dialog_update = TRUE;
717   }
718 
719   pcity->food_stock=packet->food_stock;
720   if (pcity->shield_stock != packet->shield_stock) {
721     shield_stock_changed = TRUE;
722     pcity->shield_stock = packet->shield_stock;
723   }
724   pcity->pollution = packet->pollution;
725   pcity->illness_trade = packet->illness_trade;
726 
727   if (!are_universals_equal(&pcity->production, &product)) {
728     production_changed = TRUE;
729   }
730   /* Need to consider shield stock/surplus for unit dialog as used build
731    * slots may change, affecting number of "in-progress" units. */
732   if ((city_is_new && VUT_UTYPE == product.kind)
733       || (production_changed && (VUT_UTYPE == pcity->production.kind
734                                  || VUT_UTYPE == product.kind))
735       || pcity->surplus[O_SHIELD] != packet->surplus[O_SHIELD]
736       || shield_stock_changed) {
737     need_units_dialog_update = TRUE;
738   }
739   pcity->production = product;
740 
741   output_type_iterate(o) {
742     pcity->surplus[o] = packet->surplus[o];
743     pcity->waste[o] = packet->waste[o];
744     pcity->unhappy_penalty[o] = packet->unhappy_penalty[o];
745     pcity->prod[o] = packet->prod[o];
746     pcity->citizen_base[o] = packet->citizen_base[o];
747     pcity->usage[o] = packet->usage[o];
748   } output_type_iterate_end;
749 
750 #ifdef DONE_BY_create_city_virtual
751   if (city_is_new) {
752     worklist_init(&pcity->worklist);
753 
754     for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
755       pcity->built[i].turn = I_NEVER;
756     }
757   }
758 #endif /* DONE_BY_create_city_virtual */
759 
760   worklist_copy(&pcity->worklist, &packet->worklist);
761 
762   pcity->airlift = packet->airlift;
763   pcity->did_buy=packet->did_buy;
764   pcity->did_sell=packet->did_sell;
765   pcity->was_happy=packet->was_happy;
766 
767   pcity->turn_founded = packet->turn_founded;
768   pcity->turn_last_built = packet->turn_last_built;
769 
770   if (!universals_n_is_valid(packet->changed_from_kind)) {
771     log_error("handle_city_info() bad changed_from_kind %d.",
772               packet->changed_from_kind);
773     product.kind = VUT_NONE;
774   } else {
775     product = universal_by_number(packet->changed_from_kind,
776                                      packet->changed_from_value);
777     if (!universals_n_is_valid(product.kind)) {
778       log_error("handle_city_info() bad changed_from_value %d.",
779                 packet->changed_from_value);
780       product.kind = VUT_NONE;
781     }
782   }
783   pcity->changed_from = product;
784 
785   pcity->before_change_shields=packet->before_change_shields;
786   pcity->disbanded_shields=packet->disbanded_shields;
787   pcity->caravan_shields=packet->caravan_shields;
788   pcity->last_turns_shield_surplus = packet->last_turns_shield_surplus;
789 
790   improvement_iterate(pimprove) {
791     bool have = BV_ISSET(packet->improvements, improvement_index(pimprove));
792 
793     if (have && !city_is_new
794         && pcity->built[improvement_index(pimprove)].turn <= I_NEVER) {
795       audio_play_sound(pimprove->soundtag, pimprove->soundtag_alt);
796     }
797     need_economy_dialog_update |=
798         update_improvement_from_packet(pcity, pimprove, have);
799   } improvement_iterate_end;
800 
801   /* We should be able to see units in the city.  But for a diplomat
802    * investigating an enemy city we can't.  In that case we don't update
803    * the occupied flag at all: it's already been set earlier and we'll
804    * get an update if it changes. */
805   if (can_player_see_units_in_city(client.conn.playing, pcity)) {
806     pcity->client.occupied
807       = (unit_list_size(pcity->tile->units) > 0);
808   }
809 
810   pcity->client.walls = packet->walls;
811   if (pcity->client.walls > NUM_WALL_TYPES) {
812     pcity->client.walls = NUM_WALL_TYPES;
813   }
814   pcity->style = packet->style;
815   pcity->client.city_image = packet->city_image;
816 
817   pcity->client.happy = city_happy(pcity);
818   pcity->client.unhappy = city_unhappy(pcity);
819 
820   popup = (city_is_new && can_client_change_view()
821            && powner == client.conn.playing
822            && gui_options.popup_new_cities)
823           || packet->diplomat_investigate;
824 
825   city_packet_common(pcity, pcenter, powner, worked_tiles,
826                      city_is_new, popup, packet->diplomat_investigate);
827 
828   if (city_is_new && !city_has_changed_owner) {
829     agents_city_new(pcity);
830   } else {
831     agents_city_changed(pcity);
832   }
833 
834   /* Update the description if necessary. */
835   if (update_descriptions) {
836     update_city_description(pcity);
837   }
838 
839   /* Update focus unit info label if necessary. */
840   if (name_changed) {
841     unit_list_iterate(pfocus_units, pfocus_unit) {
842       if (pfocus_unit->homecity == pcity->id) {
843 	update_unit_info_label(pfocus_units);
844 	break;
845       }
846     } unit_list_iterate_end;
847   }
848 
849   /* Update the science dialog if necessary. */
850   if (need_science_dialog_update) {
851     science_report_dialog_update();
852   }
853 
854   /* Update the units dialog if necessary. */
855   if (need_units_dialog_update) {
856     units_report_dialog_update();
857   }
858 
859   /* Update the economy dialog if necessary. */
860   if (need_economy_dialog_update) {
861     economy_report_dialog_update();
862   }
863 
864   /* Update the panel text (including civ population). */
865   update_info_label();
866 
867   /* update caravan dialog */
868   if ((production_changed || shield_stock_changed)
869       && action_selection_target_city() == pcity->id) {
870     dsend_packet_unit_get_actions(&client.conn,
871                                   action_selection_actor_unit(),
872                                   action_selection_target_unit(),
873                                   action_selection_target_city(),
874                                   city_tile(pcity)->index,
875                                   FALSE);
876   }
877 
878   if (gui_options.draw_city_trade_routes
879       && (trade_routes_changed
880           || (city_is_new && 0 < city_num_trade_routes(pcity)))) {
881     update_map_canvas_visible();
882   }
883 }
884 
885 /****************************************************************************
886   A helper function for handling city-info and city-short-info packets.
887   Naturally, both require many of the same operations to be done on the
888   data.
889 ****************************************************************************/
city_packet_common(struct city * pcity,struct tile * pcenter,struct player * powner,struct tile_list * worked_tiles,bool is_new,bool popup,bool investigate)890 static void city_packet_common(struct city *pcity, struct tile *pcenter,
891                                struct player *powner,
892                                struct tile_list *worked_tiles,
893                                bool is_new, bool popup, bool investigate)
894 {
895   if (NULL != worked_tiles) {
896     /* We need to transfer the worked infos because the server will assume
897      * those infos are kept in our side and won't send to us again. */
898     tile_list_iterate(worked_tiles, pwork) {
899       tile_set_worked(pwork, pcity);
900     } tile_list_iterate_end;
901     tile_list_destroy(worked_tiles);
902   }
903 
904   if (is_new) {
905     tile_set_worked(pcenter, pcity); /* is_free_worked() */
906     city_list_prepend(powner->cities, pcity);
907 
908     if (client_is_global_observer() || powner == client_player()) {
909       city_report_dialog_update();
910     }
911 
912     players_iterate(pp) {
913       unit_list_iterate(pp->units, punit)
914 	if(punit->homecity==pcity->id)
915 	  unit_list_prepend(pcity->units_supported, punit);
916       unit_list_iterate_end;
917     } players_iterate_end;
918 
919     pcity->client.first_citizen_index = fc_rand(MAX_NUM_CITIZEN_SPRITES);
920   } else {
921     if (client_is_global_observer() || powner == client_player()) {
922       city_report_dialog_update_city(pcity);
923     }
924   }
925 
926   if (can_client_change_view()) {
927     refresh_city_mapcanvas(pcity, pcenter, FALSE, FALSE);
928   }
929 
930   if (city_workers_display==pcity)  {
931     city_workers_display=NULL;
932   }
933 
934   if (investigate) {
935     /* Commit the collected supported and present units. */
936     if (pcity->client.collecting_info_units_supported != NULL) {
937       /* We got units, let's move the unit lists. */
938       fc_assert(pcity->client.collecting_info_units_present != NULL);
939 
940       unit_list_destroy(pcity->client.info_units_present);
941       pcity->client.info_units_present =
942           pcity->client.collecting_info_units_present;
943       pcity->client.collecting_info_units_present = NULL;
944 
945       unit_list_destroy(pcity->client.info_units_supported);
946       pcity->client.info_units_supported =
947           pcity->client.collecting_info_units_supported;
948       pcity->client.collecting_info_units_supported = NULL;
949     } else {
950       /* We didn't get any unit, let's clear the unit lists. */
951       fc_assert(pcity->client.collecting_info_units_present == NULL);
952 
953       unit_list_clear(pcity->client.info_units_supported);
954       unit_list_clear(pcity->client.info_units_present);
955     }
956   }
957 
958   if (popup
959       && NULL != client.conn.playing
960       && !client.conn.playing->ai_controlled
961       && can_client_issue_orders()) {
962     menus_update();
963     if (!city_dialog_is_open(pcity)) {
964       popup_city_dialog(pcity);
965     }
966   }
967 
968   if (!is_new
969       && (popup || can_player_see_city_internals(client.conn.playing, pcity))) {
970     refresh_city_dialog(pcity);
971   }
972 
973   /* update menus if the focus unit is on the tile. */
974   if (get_focus_unit_on_tile(pcenter)) {
975     menus_update();
976   }
977 
978   if (is_new) {
979     log_debug("(%d,%d) creating city %d, %s %s", TILE_XY(pcenter),
980               pcity->id, nation_rule_name(nation_of_city(pcity)),
981               city_name_get(pcity));
982   }
983 
984   editgui_notify_object_changed(OBJTYPE_CITY, pcity->id, FALSE);
985 }
986 
987 /****************************************************************************
988   A city-short-info packet is sent to tell us about any cities we can't see
989   the internals of.  Most of the time this includes any cities owned by
990   someone else.
991 ****************************************************************************/
handle_city_short_info(const struct packet_city_short_info * packet)992 void handle_city_short_info(const struct packet_city_short_info *packet)
993 {
994   bool city_has_changed_owner = FALSE;
995   bool city_is_new = FALSE;
996   bool name_changed = FALSE;
997   bool update_descriptions = FALSE;
998   struct city *pcity = game_city_by_number(packet->id);
999   struct tile *pcenter = index_to_tile(packet->tile);
1000   struct tile *ptile = NULL;
1001   struct tile_list *worked_tiles = NULL;
1002   struct player *powner = player_by_number(packet->owner);
1003   int radius_sq = game.info.init_city_radius_sq;
1004 
1005   fc_assert_ret_msg(NULL != powner, "Bad player number %d.", packet->owner);
1006   fc_assert_ret_msg(NULL != pcenter, "Invalid tile index %d.", packet->tile);
1007 
1008   if (NULL != pcity) {
1009     ptile = city_tile(pcity);
1010 
1011     if (NULL == ptile) {
1012       /* invisible worked city */
1013       city_list_remove(invisible.cities, pcity);
1014       city_is_new = TRUE;
1015 
1016       pcity->tile = pcenter;
1017       ptile = pcenter;
1018       pcity->owner = powner;
1019       pcity->original = powner;
1020 
1021       whole_map_iterate(wtile) {
1022         if (wtile->worked == pcity) {
1023           int dist_sq = sq_map_distance(pcenter, wtile);
1024 
1025           if (dist_sq > city_map_radius_sq_get(pcity)) {
1026             city_map_radius_sq_set(pcity, dist_sq);
1027           }
1028         }
1029       } whole_map_iterate_end;
1030     } else if (city_owner(pcity) != powner) {
1031       /* Remember what were the worked tiles.  The server won't
1032        * send to us again. */
1033       city_tile_iterate_skip_free_worked(city_map_radius_sq_get(pcity), ptile,
1034                                          pworked, _index, _x, _y) {
1035         if (pcity == tile_worked(pworked)) {
1036           if (NULL == worked_tiles) {
1037             worked_tiles = tile_list_new();
1038           }
1039           tile_list_append(worked_tiles, pworked);
1040         }
1041       } city_tile_iterate_skip_free_worked_end;
1042       radius_sq = city_map_radius_sq_get(pcity);
1043       client_remove_city(pcity);
1044       pcity = NULL;
1045       city_has_changed_owner = TRUE;
1046     }
1047   }
1048 
1049   if (NULL == pcity) {
1050     city_is_new = TRUE;
1051     pcity = create_city_virtual(powner, pcenter, packet->name);
1052     pcity->id = packet->id;
1053     city_map_radius_sq_set(pcity, radius_sq);
1054     idex_register_city(pcity);
1055   } else if (pcity->id != packet->id) {
1056     log_error("handle_city_short_info() city id %d != id %d.",
1057               pcity->id, packet->id);
1058     return;
1059   } else if (city_tile(pcity) != pcenter) {
1060     log_error("handle_city_short_info() city tile (%d, %d) != (%d, %d).",
1061               TILE_XY(city_tile(pcity)), TILE_XY(pcenter));
1062     return;
1063   } else {
1064     name_changed = (0 != strncmp(packet->name, pcity->name,
1065                                  sizeof(pcity->name)));
1066 
1067     /* Check if city descriptions should be updated */
1068     if (gui_options.draw_city_names && name_changed) {
1069       update_descriptions = TRUE;
1070     }
1071 
1072     sz_strlcpy(pcity->name, packet->name);
1073 
1074     memset(pcity->feel, 0, sizeof(pcity->feel));
1075     memset(pcity->specialists, 0, sizeof(pcity->specialists));
1076   }
1077 
1078   pcity->specialists[DEFAULT_SPECIALIST] = packet->size;
1079   city_size_set(pcity, packet->size);
1080 
1081   /* We can't actually see the internals of the city, but the server tells
1082    * us this much. */
1083   if (pcity->client.occupied != packet->occupied) {
1084     pcity->client.occupied = packet->occupied;
1085     if (gui_options.draw_full_citybar) {
1086       update_descriptions = TRUE;
1087     }
1088   }
1089   pcity->client.walls = packet->walls;
1090   pcity->style = packet->style;
1091   pcity->client.city_image = packet->city_image;
1092 
1093   pcity->client.happy = packet->happy;
1094   pcity->client.unhappy = packet->unhappy;
1095 
1096   improvement_iterate(pimprove) {
1097     /* Don't update the non-visible improvements, they could hide the
1098      * previously seen informations about the city (diplomat investigation).
1099      */
1100     if (is_improvement_visible(pimprove)) {
1101       bool have = BV_ISSET(packet->improvements,
1102                            improvement_index(pimprove));
1103       update_improvement_from_packet(pcity, pimprove, have);
1104     }
1105   } improvement_iterate_end;
1106 
1107   city_packet_common(pcity, pcenter, powner, worked_tiles,
1108                      city_is_new, FALSE, FALSE);
1109 
1110   if (city_is_new && !city_has_changed_owner) {
1111     agents_city_new(pcity);
1112   } else {
1113     agents_city_changed(pcity);
1114   }
1115 
1116   /* Update the description if necessary. */
1117   if (update_descriptions) {
1118     update_city_description(pcity);
1119   }
1120 }
1121 
1122 /**************************************************************************
1123   Handle worker task assigned to the city
1124 **************************************************************************/
handle_worker_task(const struct packet_worker_task * packet)1125 void handle_worker_task(const struct packet_worker_task *packet)
1126 {
1127   struct city *pcity = game_city_by_number(packet->city_id);
1128   struct worker_task *ptask = NULL;
1129 
1130   if (pcity == NULL
1131       || (pcity->owner != client.conn.playing && !client_is_global_observer())) {
1132     return;
1133   }
1134 
1135   worker_task_list_iterate(pcity->task_reqs, ptask_old) {
1136     if (tile_index(ptask_old->ptile) == packet->tile_id) {
1137       ptask = ptask_old;
1138       break;
1139     }
1140   } worker_task_list_iterate_end;
1141 
1142   if (ptask == NULL) {
1143     if (packet->activity == ACTIVITY_LAST) {
1144       return;
1145     } else {
1146       ptask = fc_malloc(sizeof(struct worker_task));
1147       worker_task_list_append(pcity->task_reqs, ptask);
1148     }
1149   } else {
1150     if (packet->activity == ACTIVITY_LAST) {
1151       worker_task_list_remove(pcity->task_reqs, ptask);
1152       free(ptask);
1153       ptask = NULL;
1154     }
1155   }
1156 
1157   if (ptask != NULL) {
1158     ptask->ptile = index_to_tile(packet->tile_id);
1159     ptask->act = packet->activity;
1160     if (packet->tgt >= 0) {
1161       ptask->tgt = extra_by_number(packet->tgt);
1162     } else {
1163       ptask->tgt = NULL;
1164     }
1165     ptask->want = packet->want;
1166   }
1167 
1168   if (ptask && !worker_task_is_sane(ptask)) {
1169     log_debug("Bad worker task");
1170     worker_task_list_remove(pcity->task_reqs, ptask);
1171     free(ptask);
1172     ptask = NULL;
1173     return;
1174   }
1175 
1176   refresh_city_dialog(pcity);
1177 }
1178 
1179 /**************************************************************************
1180   Handle turn and year advancement.
1181 **************************************************************************/
handle_new_year(int year16,int year32,int fragments,int turn)1182 void handle_new_year(int year16, int year32, int fragments, int turn)
1183 {
1184   if (has_capability("year32", client.conn.capability)) {
1185     game.info.year32 = year32;
1186     game.info.year16 = year32;
1187   } else {
1188     game.info.year32 = year16;
1189     game.info.year16 = year16;
1190   }
1191   game.info.fragment_count = fragments;
1192   /*
1193    * The turn was increased in handle_end_turn()
1194    */
1195   fc_assert(game.info.turn == turn);
1196   update_info_label();
1197 
1198   unit_focus_update();
1199   auto_center_on_focus_unit();
1200 
1201   update_unit_info_label(get_units_in_focus());
1202   menus_update();
1203 
1204   set_seconds_to_turndone(current_turn_timeout());
1205 
1206 #if 0
1207   /* This information shouldn't be needed, but if it is this is the only
1208    * way we can get it. */
1209   if (NULL != client.conn.playing) {
1210     turn_gold_difference =
1211       client.conn.playing->economic.gold - last_turn_gold_amount;
1212     last_turn_gold_amount = client.conn.playing->economic.gold;
1213   }
1214 #endif
1215 
1216   update_city_descriptions();
1217   link_marks_decrease_turn_counters();
1218 
1219   if (gui_options.sound_bell_at_new_turn) {
1220     create_event(NULL, E_TURN_BELL, ftc_client,
1221                  _("Start of turn %d"), game.info.turn);
1222   }
1223 
1224   agents_new_turn();
1225 
1226   if (last_turn != turn) {
1227     start_turn();
1228     last_turn = turn;
1229   }
1230 }
1231 
1232 /**************************************************************************
1233   Called by the network code when an end-phase packet is received.  This
1234   signifies the end of our phase (it's not sent for other player's
1235   phases).
1236 **************************************************************************/
handle_end_phase(void)1237 void handle_end_phase(void)
1238 {
1239   /* Messagewindow will contain events happened since our own phase ended,
1240    * so player of the first phase and last phase are in equal situation. */
1241   meswin_clear();
1242 }
1243 
1244 /**************************************************************************
1245   Called by the network code when an start-phase packet is received.  This
1246   may be the start of our phase or someone else's phase.
1247 **************************************************************************/
handle_start_phase(int phase)1248 void handle_start_phase(int phase)
1249 {
1250   if (!client_has_player() && !client_is_observer()) {
1251     /* We are on detached state, let ignore this packet. */
1252     return;
1253   }
1254 
1255   if (phase < 0
1256       || (game.info.phase_mode == PMT_PLAYERS_ALTERNATE
1257           && phase >= player_count())
1258       || (game.info.phase_mode == PMT_TEAMS_ALTERNATE
1259           && phase >= team_count())) {
1260     log_error("handle_start_phase() illegal phase %d.", phase);
1261     return;
1262   }
1263 
1264   set_client_state(C_S_RUNNING);
1265 
1266   game.info.phase = phase;
1267 
1268   /* Possibly replace wait cursor with something else */
1269   if (phase == 0) {
1270     /* TODO: Have server set as busy also if switching phase
1271      * is taking long in a alternating phases mode. */
1272     set_server_busy(FALSE);
1273   }
1274 
1275   if (NULL != client.conn.playing
1276       && is_player_phase(client.conn.playing, phase)) {
1277     agents_start_turn();
1278     non_ai_unit_focus = FALSE;
1279 
1280     update_turn_done_button_state();
1281 
1282     if (client.conn.playing->ai_controlled
1283         && !gui_options.ai_manual_turn_done) {
1284       user_ended_turn();
1285     }
1286 
1287     unit_focus_set_status(client.conn.playing);
1288 
1289     city_list_iterate(client.conn.playing->cities, pcity) {
1290       pcity->client.colored = FALSE;
1291     } city_list_iterate_end;
1292 
1293     unit_list_iterate(client.conn.playing->units, punit) {
1294       punit->client.colored = FALSE;
1295     } unit_list_iterate_end;
1296 
1297     update_map_canvas_visible();
1298   }
1299 
1300   update_info_label();
1301 }
1302 
1303 /**************************************************************************
1304   Called when begin-turn packet is received. Server has finished processing
1305   turn change.
1306 **************************************************************************/
handle_begin_turn(void)1307 void handle_begin_turn(void)
1308 {
1309   log_debug("handle_begin_turn()");
1310 
1311   /* Server is still considered busy until it handles also the beginning
1312    * of the first phase. */
1313 
1314   stop_turn_change_wait();
1315 }
1316 
1317 /**************************************************************************
1318   Called when end-turn packet is received. Server starts processing turn
1319   change.
1320 **************************************************************************/
handle_end_turn(void)1321 void handle_end_turn(void)
1322 {
1323   log_debug("handle_end_turn()");
1324 
1325   /* Make sure wait cursor is in use */
1326   set_server_busy(TRUE);
1327 
1328   start_turn_change_wait();
1329 
1330   /*
1331    * The local idea of the game.info.turn is increased here since the
1332    * client will get unit updates (reset of move points for example)
1333    * between handle_end_turn() and handle_new_year(). These
1334    * unit updates will look like they did take place in the old turn
1335    * which is incorrect. If we get the authoritative information about
1336    * the game.info.turn in handle_new_year() we will check it.
1337    */
1338   game.info.turn++;
1339 
1340   log_verbose(_("Beginning turn %d"), game.info.turn);
1341 
1342   agents_before_new_turn();
1343 }
1344 
1345 /**************************************************************************
1346   Plays sound associated with event
1347 **************************************************************************/
play_sound_for_event(enum event_type type)1348 void play_sound_for_event(enum event_type type)
1349 {
1350   const char *sound_tag = get_event_tag(type);
1351 
1352   if (sound_tag) {
1353     audio_play_sound(sound_tag, NULL);
1354   }
1355 }
1356 
1357 /**************************************************************************
1358   Handle a message packet.  This includes all messages - both
1359   in-game messages and chats from other players.
1360 **************************************************************************/
handle_chat_msg(const struct packet_chat_msg * packet)1361 void handle_chat_msg(const struct packet_chat_msg *packet)
1362 {
1363   handle_event(packet->message,
1364                index_to_tile(packet->tile),
1365                packet->event,
1366                packet->turn,
1367                packet->phase,
1368                packet->conn_id);
1369 }
1370 
1371 /**************************************************************************
1372   Handle an early message packet. Thease have format like other chat
1373   messages but server sends them only about events related to establishing
1374   the connection and other setup in the early phase. They are a separate
1375   packet just so that client knows thse to be already relevant when it's
1376   only setting itself up - other chat messages might be just something
1377   sent to all clients, and we might want to still consider ourselves
1378   "not connected" (not receivers of those messages) until we are fully
1379   in the game.
1380 **************************************************************************/
handle_early_chat_msg(const struct packet_early_chat_msg * packet)1381 void handle_early_chat_msg(const struct packet_early_chat_msg *packet)
1382 {
1383   handle_event(packet->message,
1384                index_to_tile(packet->tile),
1385                packet->event,
1386                packet->turn,
1387                packet->phase,
1388                packet->conn_id);
1389 }
1390 
1391 /**************************************************************************
1392   Handle a connect message packet. Server sends connect message to
1393   client immediately when client connects.
1394 **************************************************************************/
handle_connect_msg(const char * message)1395 void handle_connect_msg(const char *message)
1396 {
1397   popup_connect_msg(_("Welcome"), message);
1398 }
1399 
1400 /****************************************************************************
1401   Page_msg header handler.
1402 ****************************************************************************/
handle_page_msg(const char * caption,const char * headline,enum event_type event,int len,int parts)1403 void handle_page_msg(const char *caption, const char *headline,
1404                      enum event_type event, int len, int parts)
1405 {
1406   if (!client_has_player()
1407       || !client_player()->ai_controlled
1408       || event != E_BROADCAST_REPORT) {
1409     if (page_msg_report.parts > 0) {
1410       /* Previous one was never finished */
1411       free(page_msg_report.caption);
1412       free(page_msg_report.headline);
1413       free(page_msg_report.lines);
1414     }
1415     page_msg_report.len = len;
1416     page_msg_report.event = event;
1417     page_msg_report.caption = fc_strdup(caption);
1418     page_msg_report.headline = fc_strdup(headline);
1419     page_msg_report.parts = parts;
1420     page_msg_report.lines = fc_malloc(len + 1);
1421     page_msg_report.lines[0] = '\0';
1422 
1423     if (parts == 0) {
1424       /* Empty report - handle as if last part was just received. */
1425       page_msg_report.parts = 1;
1426       handle_page_msg_part("");
1427     }
1428   }
1429 }
1430 
1431 /****************************************************************************
1432   Page_msg part handler.
1433 ****************************************************************************/
handle_page_msg_part(const char * lines)1434 void handle_page_msg_part(const char *lines)
1435 {
1436   if (page_msg_report.lines != NULL) {
1437     /* We have already decided to show the message at the time we got
1438      * the header packet. */
1439     fc_strlcat(page_msg_report.lines, lines, page_msg_report.len + 1);
1440     page_msg_report.parts--;
1441 
1442     if (page_msg_report.parts == 0) {
1443       /* This is the final part */
1444       popup_notify_dialog(page_msg_report.caption,
1445                           page_msg_report.headline,
1446                           page_msg_report.lines);
1447       play_sound_for_event(page_msg_report.event);
1448 
1449       free(page_msg_report.caption);
1450       free(page_msg_report.headline);
1451       free(page_msg_report.lines);
1452       page_msg_report.lines = NULL;
1453     }
1454   }
1455 }
1456 
1457 /****************************************************************************
1458   Packet unit_info.
1459 ****************************************************************************/
handle_unit_info(const struct packet_unit_info * packet)1460 void handle_unit_info(const struct packet_unit_info *packet)
1461 {
1462   struct unit *punit;
1463 
1464   punit = unpackage_unit(packet);
1465   if (handle_unit_packet_common(punit)) {
1466     punit->client.transported_by = -1;
1467     unit_virtual_destroy(punit);
1468   }
1469 }
1470 
1471 /**************************************************************************
1472   Called to do basic handling for a unit_info or short_unit_info packet.
1473 
1474   Both owned and foreign units are handled; you may need to check unit
1475   owner, or if unit equals focus unit, depending on what you are doing.
1476 
1477   Note: Normally the server informs client about a new "activity" here.
1478   For owned units, the new activity can be a result of:
1479   - The player issued a command (a request) with the client.
1480   - The server side AI did something.
1481   - An enemy encounter caused a sentry to idle. (See "Wakeup Focus").
1482 
1483   Depending on what caused the change, different actions may be taken.
1484   Therefore, this function is a bit of a jungle, and it is advisable
1485   to read thoroughly before changing.
1486 **************************************************************************/
handle_unit_packet_common(struct unit * packet_unit)1487 static bool handle_unit_packet_common(struct unit *packet_unit)
1488 {
1489   struct city *pcity;
1490   struct unit *punit;
1491   bool need_menus_update = FALSE;
1492   bool need_economy_report_update = FALSE;
1493   bool need_units_report_update = FALSE;
1494   bool repaint_unit = FALSE;
1495   bool repaint_city = FALSE;	/* regards unit's homecity */
1496   struct tile *old_tile = NULL;
1497   bool check_focus = FALSE;     /* conservative focus change */
1498   bool moved = FALSE;
1499   bool ret = FALSE;
1500 
1501   punit = player_unit_by_number(unit_owner(packet_unit), packet_unit->id);
1502   if (!punit && game_unit_by_number(packet_unit->id)) {
1503     /* This means unit has changed owner. We deal with this here
1504      * by simply deleting the old one and creating a new one. */
1505     handle_unit_remove(packet_unit->id);
1506   }
1507 
1508   if (punit) {
1509     /* In some situations, the size of repaint units require can change;
1510      * in particular, city-builder units sometimes get a potential-city
1511      * outline, but to speed up redraws we don't repaint this whole area
1512      * unnecessarily. We need to ensure that when the footprint shrinks,
1513      * old bits aren't left behind on the canvas.
1514      * If the current (old) status of the unit is such that it gets a large
1515      * repaint, as a special case, queue a large repaint immediately, to
1516      * schedule the correct amount/location to be redrawn; but rely on the
1517      * repaint being deferred until the unit is updated, so that what's
1518      * drawn reflects the new status (e.g., no city outline). */
1519     if (unit_drawn_with_city_outline(punit, TRUE)) {
1520       refresh_unit_mapcanvas(punit, unit_tile(punit), TRUE, FALSE);
1521     }
1522 
1523     ret = TRUE;
1524     punit->activity_count = packet_unit->activity_count;
1525     unit_change_battlegroup(punit, packet_unit->battlegroup);
1526     if (punit->ai_controlled != packet_unit->ai_controlled) {
1527       punit->ai_controlled = packet_unit->ai_controlled;
1528       repaint_unit = TRUE;
1529       /* AI is set:     may change focus */
1530       /* AI is cleared: keep focus */
1531       if (packet_unit->ai_controlled && unit_is_in_focus(punit)) {
1532         check_focus = TRUE;
1533       }
1534     }
1535 
1536     if (punit->facing != packet_unit->facing) {
1537       punit->facing = packet_unit->facing;
1538       repaint_unit = TRUE;
1539     }
1540 
1541     if (punit->activity != packet_unit->activity
1542         || punit->activity_target == packet_unit->activity_target
1543         || punit->client.transported_by != packet_unit->client.transported_by
1544         || punit->client.occupied != packet_unit->client.occupied
1545 	|| punit->has_orders != packet_unit->has_orders
1546 	|| punit->orders.repeat != packet_unit->orders.repeat
1547 	|| punit->orders.vigilant != packet_unit->orders.vigilant
1548 	|| punit->orders.index != packet_unit->orders.index) {
1549 
1550       /*** Change in activity or activity's target. ***/
1551 
1552       /* May change focus if focus unit gets a new activity.
1553        * But if new activity is Idle, it means user specifically selected
1554        * the unit */
1555       if (unit_is_in_focus(punit)
1556 	  && (packet_unit->activity != ACTIVITY_IDLE
1557 	      || packet_unit->has_orders)) {
1558         check_focus = TRUE;
1559       }
1560 
1561       repaint_unit = TRUE;
1562 
1563       /* Wakeup Focus */
1564       if (gui_options.wakeup_focus
1565           && NULL != client.conn.playing
1566           && !client.conn.playing->ai_controlled
1567           && unit_owner(punit) == client.conn.playing
1568           && punit->activity == ACTIVITY_SENTRY
1569           && packet_unit->activity == ACTIVITY_IDLE
1570           && !unit_is_in_focus(punit)
1571           && is_player_phase(client.conn.playing, game.info.phase)) {
1572         /* many wakeup units per tile are handled */
1573         unit_focus_urgent(punit);
1574         check_focus = FALSE; /* and keep it */
1575       }
1576 
1577       punit->activity = packet_unit->activity;
1578       punit->activity_target = packet_unit->activity_target;
1579 
1580       if (punit->client.transported_by
1581           != packet_unit->client.transported_by) {
1582         if (packet_unit->client.transported_by == -1) {
1583           /* The unit was unloaded from its transport. The check for a new
1584            * transport is done below. */
1585           unit_transport_unload(punit);
1586         }
1587 
1588         punit->client.transported_by = packet_unit->client.transported_by;
1589       }
1590 
1591       if (punit->client.occupied != packet_unit->client.occupied) {
1592         if (get_focus_unit_on_tile(unit_tile(packet_unit))) {
1593           /* Special case: (un)loading a unit in a transporter on the same
1594            *tile as the focus unit may (dis)allow the focus unit to be
1595            * loaded.  Thus the orders->(un)load menu item needs updating. */
1596           need_menus_update = TRUE;
1597         }
1598         punit->client.occupied = packet_unit->client.occupied;
1599       }
1600 
1601       punit->has_orders = packet_unit->has_orders;
1602       punit->orders.length = packet_unit->orders.length;
1603       punit->orders.index = packet_unit->orders.index;
1604       punit->orders.repeat = packet_unit->orders.repeat;
1605       punit->orders.vigilant = packet_unit->orders.vigilant;
1606 
1607       /* We cheat by just stealing the packet unit's list. */
1608       if (punit->orders.list) {
1609 	free(punit->orders.list);
1610       }
1611       punit->orders.list = packet_unit->orders.list;
1612       packet_unit->orders.list = NULL;
1613 
1614       if (NULL == client.conn.playing
1615           || unit_owner(punit) == client.conn.playing) {
1616         refresh_unit_city_dialogs(punit);
1617       }
1618     } /*** End of Change in activity or activity's target. ***/
1619 
1620     /* These two lines force the menus to be updated as appropriate when
1621      * the focus unit changes. */
1622     if (unit_is_in_focus(punit)) {
1623       need_menus_update = TRUE;
1624     }
1625 
1626     if (punit->homecity != packet_unit->homecity) {
1627       /* change homecity */
1628       struct city *hcity;
1629 
1630       if ((hcity = game_city_by_number(punit->homecity))) {
1631 	unit_list_remove(hcity->units_supported, punit);
1632 	refresh_city_dialog(hcity);
1633       }
1634 
1635       punit->homecity = packet_unit->homecity;
1636       if ((hcity = game_city_by_number(punit->homecity))) {
1637 	unit_list_prepend(hcity->units_supported, punit);
1638 	repaint_city = TRUE;
1639       }
1640 
1641       /* This can change total upkeep figures */
1642       need_units_report_update = TRUE;
1643     }
1644 
1645     if (punit->hp != packet_unit->hp) {
1646       /* hp changed */
1647       punit->hp = packet_unit->hp;
1648       repaint_unit = TRUE;
1649     }
1650 
1651     if (punit->utype != unit_type_get(packet_unit)) {
1652       /* Unit type has changed (been upgraded) */
1653       struct city *ccity = tile_city(unit_tile(punit));
1654 
1655       punit->utype = unit_type_get(packet_unit);
1656       repaint_unit = TRUE;
1657       repaint_city = TRUE;
1658       if (ccity != NULL && (ccity->id != punit->homecity)) {
1659 	refresh_city_dialog(ccity);
1660       }
1661       if (unit_is_in_focus(punit)) {
1662         /* Update the orders menu -- the unit might have new abilities */
1663         need_menus_update = TRUE;
1664       }
1665       need_units_report_update = TRUE;
1666     }
1667 
1668     /* May change focus if an attempted move or attack exhausted unit */
1669     if (punit->moves_left != packet_unit->moves_left
1670         && unit_is_in_focus(punit)) {
1671       check_focus = TRUE;
1672     }
1673 
1674     if (!same_pos(unit_tile(punit), unit_tile(packet_unit))) {
1675       /*** Change position ***/
1676       struct city *ccity = tile_city(unit_tile(punit));
1677 
1678       old_tile = unit_tile(punit);
1679       moved = TRUE;
1680 
1681       /* Show where the unit is going. */
1682       do_move_unit(punit, packet_unit);
1683 
1684       if (ccity != NULL)  {
1685 	if (can_player_see_units_in_city(client.conn.playing, ccity)) {
1686 	  /* Unit moved out of a city - update the occupied status. */
1687 	  bool new_occupied =
1688 	    (unit_list_size(ccity->tile->units) > 0);
1689 
1690           if (ccity->client.occupied != new_occupied) {
1691             ccity->client.occupied = new_occupied;
1692             refresh_city_mapcanvas(ccity, ccity->tile, FALSE, FALSE);
1693             if (gui_options.draw_full_citybar) {
1694               update_city_description(ccity);
1695             }
1696           }
1697         }
1698 
1699         if (ccity->id == punit->homecity) {
1700           repaint_city = TRUE;
1701         } else {
1702           refresh_city_dialog(ccity);
1703         }
1704       }
1705 
1706       if ((ccity = tile_city(unit_tile(punit)))) {
1707         if (can_player_see_units_in_city(client.conn.playing, ccity)) {
1708           /* Unit moved into a city - obviously it's occupied. */
1709           if (!ccity->client.occupied) {
1710             ccity->client.occupied = TRUE;
1711             refresh_city_mapcanvas(ccity, ccity->tile, FALSE, FALSE);
1712             if (gui_options.draw_full_citybar) {
1713               update_city_description(ccity);
1714             }
1715           }
1716         }
1717 
1718         if (ccity->id == punit->homecity) {
1719           repaint_city = TRUE;
1720         } else {
1721           refresh_city_dialog(ccity);
1722         }
1723       }
1724 
1725     }  /*** End of Change position. ***/
1726 
1727     if (repaint_city || repaint_unit) {
1728       /* We repaint the city if the unit itself needs repainting or if
1729        * there is a special city-only redrawing to be done. */
1730       if ((pcity = game_city_by_number(punit->homecity))) {
1731 	refresh_city_dialog(pcity);
1732       }
1733       if (repaint_unit && tile_city(unit_tile(punit))
1734           && tile_city(unit_tile(punit)) != pcity) {
1735         /* Refresh the city we're occupying too. */
1736         refresh_city_dialog(tile_city(unit_tile(punit)));
1737       }
1738     }
1739 
1740     need_economy_report_update = (punit->upkeep[O_GOLD]
1741                                   != packet_unit->upkeep[O_GOLD]);
1742     /* unit upkeep information */
1743     output_type_iterate(o) {
1744       punit->upkeep[o] = packet_unit->upkeep[o];
1745     } output_type_iterate_end;
1746 
1747     punit->nationality = packet_unit->nationality;
1748     punit->veteran = packet_unit->veteran;
1749     punit->moves_left = packet_unit->moves_left;
1750     punit->fuel = packet_unit->fuel;
1751     punit->goto_tile = packet_unit->goto_tile;
1752     punit->paradropped = packet_unit->paradropped;
1753     if (punit->done_moving != packet_unit->done_moving) {
1754       punit->done_moving = packet_unit->done_moving;
1755       check_focus = TRUE;
1756     }
1757 
1758     /* This won't change punit; it enqueues the call for later handling. */
1759     agents_unit_changed(punit);
1760     editgui_notify_object_changed(OBJTYPE_UNIT, punit->id, FALSE);
1761 
1762     punit->action_decision_tile = packet_unit->action_decision_tile;
1763     if (punit->action_decision_want != packet_unit->action_decision_want
1764         && should_ask_server_for_actions(packet_unit)) {
1765       /* The unit wants the player to decide. */
1766       action_decision_request(punit);
1767       check_focus = TRUE;
1768     }
1769     punit->action_decision_want = packet_unit->action_decision_want;
1770   } else {
1771     /*** Create new unit ***/
1772     punit = packet_unit;
1773     idex_register_unit(punit);
1774 
1775     unit_list_prepend(unit_owner(punit)->units, punit);
1776     unit_list_prepend(unit_tile(punit)->units, punit);
1777 
1778     unit_register_battlegroup(punit);
1779 
1780     if ((pcity = game_city_by_number(punit->homecity))) {
1781       unit_list_prepend(pcity->units_supported, punit);
1782     }
1783 
1784     log_debug("New %s %s id %d (%d %d) hc %d %s",
1785               nation_rule_name(nation_of_unit(punit)),
1786               unit_rule_name(punit), TILE_XY(unit_tile(punit)),
1787               punit->id, punit->homecity,
1788               (pcity ? city_name_get(pcity) : "(unknown)"));
1789 
1790     repaint_unit = !unit_transported(punit);
1791     agents_unit_new(punit);
1792 
1793     /* Check if we should link cargo units.
1794      * (This might be necessary if the cargo info was sent to us before
1795      * this transporter.) */
1796     if (punit->client.occupied) {
1797       unit_list_iterate(unit_tile(punit)->units, aunit) {
1798         if (aunit->client.transported_by == punit->id) {
1799           fc_assert(aunit->transporter == NULL);
1800           unit_transport_load(aunit, punit, TRUE);
1801         }
1802       } unit_list_iterate_end;
1803     }
1804 
1805     if ((pcity = tile_city(unit_tile(punit)))) {
1806       /* The unit is in a city - obviously it's occupied. */
1807       pcity->client.occupied = TRUE;
1808     }
1809 
1810     if (should_ask_server_for_actions(punit)) {
1811       /* The unit wants the player to decide. */
1812       action_decision_request(punit);
1813       check_focus = TRUE;
1814     }
1815 
1816     need_units_report_update = TRUE;
1817   } /*** End of Create new unit ***/
1818 
1819   fc_assert_ret_val(punit != NULL, ret);
1820 
1821   /* Check if we have to load the unit on a transporter. */
1822   if (punit->client.transported_by != -1) {
1823     struct unit *ptrans
1824       = game_unit_by_number(packet_unit->client.transported_by);
1825 
1826     /* Load unit only if transporter is known by the client.
1827      * (If not, cargo will be loaded later when the transporter info is
1828      * sent to the client.) */
1829     if (ptrans && ptrans != unit_transport_get(punit)) {
1830       /* First, we have to unload the unit from its old transporter. */
1831       unit_transport_unload(punit);
1832       unit_transport_load(punit, ptrans, TRUE);
1833 #ifdef DEBUG_TRANSPORT
1834       log_debug("load %s (ID: %d) onto %s (ID: %d)",
1835                 unit_name_translation(punit), punit->id,
1836                 unit_name_translation(ptrans), ptrans->id);
1837     } else if (ptrans && ptrans == unit_transport_get(punit)) {
1838       log_debug("%s (ID: %d) is loaded onto %s (ID: %d)",
1839                 unit_name_translation(punit), punit->id,
1840                 unit_name_translation(ptrans), ptrans->id);
1841     } else {
1842       log_debug("%s (ID: %d) is not loaded", unit_name_translation(punit),
1843                 punit->id);
1844 #endif /* DEBUG_TRANSPORT */
1845     }
1846   }
1847 
1848   if (unit_is_in_focus(punit)
1849       || get_focus_unit_on_tile(unit_tile(punit))
1850       || (moved && get_focus_unit_on_tile(old_tile))) {
1851     update_unit_info_label(get_units_in_focus());
1852     /* Update (an possible active) unit select dialog. */
1853     unit_select_dialog_update();
1854   }
1855 
1856   if (repaint_unit) {
1857     refresh_unit_mapcanvas(punit, unit_tile(punit), TRUE, FALSE);
1858   }
1859 
1860   if ((check_focus || get_num_units_in_focus() == 0)
1861       && NULL != client.conn.playing
1862       && !client.conn.playing->ai_controlled
1863       && is_player_phase(client.conn.playing, game.info.phase)) {
1864     unit_focus_update();
1865   }
1866 
1867   if (need_menus_update) {
1868     menus_update();
1869   }
1870 
1871   if (!client_has_player() || unit_owner(punit) == client_player()) {
1872     if (need_economy_report_update) {
1873       economy_report_dialog_update();
1874     }
1875     if (need_units_report_update) {
1876       units_report_dialog_update();
1877     }
1878   }
1879 
1880   return ret;
1881 }
1882 
1883 /****************************************************************************
1884   Receive a short_unit info packet.
1885 ****************************************************************************/
handle_unit_short_info(const struct packet_unit_short_info * packet)1886 void handle_unit_short_info(const struct packet_unit_short_info *packet)
1887 {
1888   struct city *pcity;
1889   struct unit *punit;
1890 
1891   /* Special case for a diplomat/spy investigating a city: The investigator
1892    * needs to know the supported and present units of a city, whether or not
1893    * they are fogged. So, we send a list of them all before sending the city
1894    * info. */
1895   if (packet->packet_use == UNIT_INFO_CITY_SUPPORTED
1896       || packet->packet_use == UNIT_INFO_CITY_PRESENT) {
1897     static int last_serial_num = 0;
1898 
1899     pcity = game_city_by_number(packet->info_city_id);
1900     if (!pcity) {
1901       log_error("Investigate city: unknown city id %d!",
1902                 packet->info_city_id);
1903       return;
1904     }
1905 
1906     /* New serial number: start collecting supported and present units. */
1907     if (last_serial_num
1908         != client.conn.client.request_id_of_currently_handled_packet) {
1909       last_serial_num =
1910           client.conn.client.request_id_of_currently_handled_packet;
1911       /* Ensure we are not already in an investigate cycle. */
1912       fc_assert(pcity->client.collecting_info_units_supported == NULL);
1913       fc_assert(pcity->client.collecting_info_units_present == NULL);
1914       pcity->client.collecting_info_units_supported =
1915           unit_list_new_full(unit_virtual_destroy);
1916       pcity->client.collecting_info_units_present =
1917           unit_list_new_full(unit_virtual_destroy);
1918     }
1919 
1920     /* Okay, append a unit struct to the proper list. */
1921     punit = unpackage_short_unit(packet);
1922     if (packet->packet_use == UNIT_INFO_CITY_SUPPORTED) {
1923       fc_assert(pcity->client.collecting_info_units_supported != NULL);
1924       unit_list_append(pcity->client.collecting_info_units_supported, punit);
1925     } else {
1926       fc_assert(packet->packet_use == UNIT_INFO_CITY_PRESENT);
1927       fc_assert(pcity->client.collecting_info_units_present != NULL);
1928       unit_list_append(pcity->client.collecting_info_units_present, punit);
1929     }
1930 
1931     /* Done with special case. */
1932     return;
1933   }
1934 
1935   if (player_by_number(packet->owner) == client.conn.playing) {
1936     log_error("handle_unit_short_info() for own unit.");
1937   }
1938 
1939   punit = unpackage_short_unit(packet);
1940   if (handle_unit_packet_common(punit)) {
1941     punit->client.transported_by = -1;
1942     unit_virtual_destroy(punit);
1943   }
1944 }
1945 
1946 /****************************************************************************
1947   Server requested topology change.
1948 ****************************************************************************/
handle_set_topology(int topology_id)1949 void handle_set_topology(int topology_id)
1950 {
1951   game.map.topology_id = topology_id;
1952 
1953   if (forced_tileset_name[0] == '\0'
1954       && (tileset_map_topo_compatible(topology_id, tileset, NULL) != TOPO_COMPATIBLE
1955           || strcmp(tileset_basename(tileset), game.control.preferred_tileset))) {
1956     const char *ts_to_load;
1957 
1958     ts_to_load = tileset_name_for_topology(topology_id);
1959 
1960     if (ts_to_load != NULL && ts_to_load[0] != '\0') {
1961       tilespec_reread_frozen_refresh(ts_to_load);
1962     }
1963   }
1964 }
1965 
1966 /****************************************************************************
1967   Receive information about the map size and topology from the server.  We
1968   initialize some global variables at the same time.
1969 ****************************************************************************/
handle_map_info(int xsize,int ysize,int topology_id)1970 void handle_map_info(int xsize, int ysize, int topology_id)
1971 {
1972   int ts_topo;
1973 
1974   if (!map_is_empty()) {
1975     map_free();
1976   }
1977 
1978   game.map.xsize = xsize;
1979   game.map.ysize = ysize;
1980 
1981   if (tileset_map_topo_compatible(topology_id, tileset, &ts_topo) == TOPO_INCOMP_HARD) {
1982     tileset_error(LOG_NORMAL, _("Map topology (%s) and tileset (%s) incompatible."),
1983                   describe_topology(topology_id), describe_topology(ts_topo));
1984   }
1985 
1986   game.map.topology_id = topology_id;
1987 
1988   map_init_topology();
1989   map_allocate();
1990   client_player_maps_reset();
1991   init_client_goto();
1992   mapdeco_init();
1993 
1994   generate_citydlg_dimensions();
1995 
1996   calculate_overview_dimensions();
1997 
1998   packhand_init();
1999 }
2000 
2001 /****************************************************************************
2002   Packet game_info handler.
2003 ****************************************************************************/
handle_game_info(const struct packet_game_info * pinfo)2004 void handle_game_info(const struct packet_game_info *pinfo)
2005 {
2006   bool boot_help;
2007   bool update_aifill_button = FALSE, update_ai_skill_level = FALSE;
2008   int techloss_forgiveness = game.info.techloss_forgiveness;
2009 
2010   if (game.info.aifill != pinfo->aifill) {
2011     update_aifill_button = TRUE;
2012   }
2013   if (game.info.skill_level != pinfo->skill_level) {
2014     update_ai_skill_level = TRUE;
2015   }
2016 
2017   if (game.info.is_edit_mode != pinfo->is_edit_mode) {
2018     popdown_all_city_dialogs();
2019     /* Clears the current goto command. */
2020     set_hover_state(NULL, HOVER_NONE, ACTIVITY_LAST, NULL, ORDER_LAST);
2021 
2022     if (pinfo->is_edit_mode && game.scenario.handmade) {
2023       if (!handmade_scenario_warning()) {
2024         /* Gui didn't handle this */
2025         output_window_append(ftc_client,
2026                              _("This scenario may have manually set properties the editor "
2027                                "cannot handle."));
2028         output_window_append(ftc_client,
2029                              _("They won't be saved when scenario is saved from the editor."));
2030       }
2031     }
2032   }
2033 
2034   game.info = *pinfo;
2035 
2036   /* Backward compatibility hack: early 2.6 beta servers did not send
2037    * techloss_forgiveness in the GAME_INFO packet. Elsewhere we scrape
2038    * it out of a SERVER_SETTING_INT packet. Preserve that across GAME_INFO
2039    * packets. */
2040   if (!has_capability("techloss_forgiveness", client.conn.capability)) {
2041     game.info.techloss_forgiveness = techloss_forgiveness;
2042   }
2043 
2044   if (!has_capability("year32", client.conn.capability)) {
2045     game.info.year32 = game.info.year16;
2046   }
2047 
2048   /* check the values! */
2049 #define VALIDATE(_count, _maximum, _string)                                 \
2050   if (game.info._count > _maximum) {                                        \
2051     log_error("handle_game_info(): Too many " _string "; using %d of %d",   \
2052               _maximum, game.info._count);                                  \
2053     game.info._count = _maximum;                                            \
2054   }
2055 
2056   VALIDATE(granary_num_inis,	MAX_GRANARY_INIS,	"granary entries");
2057 #undef VALIDATE
2058 
2059   game.default_government =
2060     government_by_number(game.info.default_government_id);
2061   game.government_during_revolution =
2062     government_by_number(game.info.government_during_revolution_id);
2063 
2064   boot_help = (can_client_change_view()
2065 	       && game.info.victory_conditions != pinfo->victory_conditions);
2066   if (boot_help) {
2067     boot_help_texts(); /* reboot, after setting game.spacerace */
2068   }
2069   unit_focus_update();
2070   menus_update();
2071   players_dialog_update();
2072   if (update_aifill_button || update_ai_skill_level) {
2073     update_start_page();
2074   }
2075 
2076   if (can_client_change_view()) {
2077     update_info_label();
2078   }
2079 
2080   editgui_notify_object_changed(OBJTYPE_GAME, 1, FALSE);
2081 }
2082 
2083 /**************************************************************************
2084   Sets the remaining turn time.
2085 **************************************************************************/
handle_timeout_info(float seconds_to_phasedone,float last_turn_change_time)2086 void handle_timeout_info(float seconds_to_phasedone, float last_turn_change_time)
2087 {
2088   if (current_turn_timeout() != 0 && seconds_to_phasedone >= 0) {
2089     /* If this packet is received in the middle of a turn, this value
2090      * represents the number of seconds from now to the end of the turn
2091      * (not from the start of the turn). So we need to restart our
2092      * timer. */
2093     set_seconds_to_turndone(seconds_to_phasedone);
2094   }
2095 
2096   game.tinfo.last_turn_change_time = last_turn_change_time;
2097 }
2098 
2099 /**************************************************************************
2100   Sets the target government.  This will automatically start a revolution
2101   if the target government differs from the current one.
2102 **************************************************************************/
set_government_choice(struct government * government)2103 void set_government_choice(struct government *government)
2104 {
2105   if (NULL != client.conn.playing
2106       && can_client_issue_orders()
2107       && government != government_of_player(client.conn.playing)) {
2108     dsend_packet_player_change_government(&client.conn, government_number(government));
2109   }
2110 }
2111 
2112 /**************************************************************************
2113   Begin a revolution by telling the server to start it.  This also clears
2114   the current government choice.
2115 **************************************************************************/
start_revolution(void)2116 void start_revolution(void)
2117 {
2118   dsend_packet_player_change_government(&client.conn,
2119 				    game.info.government_during_revolution_id);
2120 }
2121 
2122 /**************************************************************************
2123   Handle a notification that the player slot identified by 'playerno' has
2124   become unused. If the slot is already unused, then just ignore. Otherwise
2125   update the total player count and the GUI.
2126 **************************************************************************/
handle_player_remove(int playerno)2127 void handle_player_remove(int playerno)
2128 {
2129   struct player_slot *pslot;
2130   struct player *pplayer;
2131   int plr_nbr;
2132 
2133   pslot = player_slot_by_number(playerno);
2134 
2135   if (NULL == pslot || !player_slot_is_used(pslot)) {
2136     /* Ok, just ignore. */
2137     return;
2138   }
2139 
2140   pplayer = player_slot_get_player(pslot);
2141 
2142   if (can_client_change_view()) {
2143     close_intel_dialog(pplayer);
2144   }
2145 
2146   /* Update the connection informations. */
2147   if (client_player() == pplayer) {
2148     client.conn.playing = NULL;
2149   }
2150   conn_list_iterate(pplayer->connections, pconn) {
2151     pconn->playing = NULL;
2152   } conn_list_iterate_end;
2153   conn_list_clear(pplayer->connections);
2154 
2155   /* Save player number before player is freed */
2156   plr_nbr = player_number(pplayer);
2157 
2158   player_destroy(pplayer);
2159 
2160   players_dialog_update();
2161   conn_list_dialog_update();
2162 
2163   editgui_refresh();
2164   editgui_notify_object_changed(OBJTYPE_PLAYER, plr_nbr, TRUE);
2165 }
2166 
2167 /****************************************************************************
2168   Handle information about a player. If the packet refers to a player slot
2169   that is not currently used, then this function will set that slot to
2170   used and update the total player count.
2171 ****************************************************************************/
handle_player_info(const struct packet_player_info * pinfo)2172 void handle_player_info(const struct packet_player_info *pinfo)
2173 {
2174   bool is_new_nation = FALSE;
2175   bool turn_done_changed = FALSE;
2176   bool new_player = FALSE;
2177   int i;
2178   struct player *pplayer, *my_player;
2179   struct nation_type *pnation;
2180   struct government *pgov, *ptarget_gov;
2181   struct player_slot *pslot;
2182   struct team_slot *tslot;
2183 
2184   /* Player. */
2185   pslot = player_slot_by_number(pinfo->playerno);
2186   fc_assert(NULL != pslot);
2187   new_player = !player_slot_is_used(pslot);
2188   pplayer = player_new(pslot);
2189 
2190   if ((pplayer->rgb == NULL) != !pinfo->color_valid
2191       || (pinfo->color_valid &&
2192           (pplayer->rgb->r != pinfo->color_red
2193            || pplayer->rgb->g != pinfo->color_green
2194            || pplayer->rgb->b != pinfo->color_blue))) {
2195     struct rgbcolor *prgbcolor;
2196 
2197     if (pinfo->color_valid) {
2198       prgbcolor = rgbcolor_new(pinfo->color_red,
2199                                pinfo->color_green,
2200                                pinfo->color_blue);
2201       fc_assert_ret(prgbcolor != NULL);
2202     } else {
2203       prgbcolor = NULL;
2204     }
2205 
2206     player_set_color(pplayer, prgbcolor);
2207     tileset_player_init(tileset, pplayer);
2208 
2209     rgbcolor_destroy(prgbcolor);
2210 
2211     /* Queue a map update -- may need to redraw borders, etc. */
2212     update_map_canvas_visible();
2213   }
2214   pplayer->client.color_changeable = pinfo->color_changeable;
2215 
2216   if (new_player) {
2217     /* Initialise client side player data (tile vision). At the moment
2218      * redundant as the values are initialised with 0 due to fc_calloc(). */
2219     client_player_init(pplayer);
2220   }
2221 
2222   /* Team. */
2223   tslot = team_slot_by_number(pinfo->team);
2224   fc_assert(NULL != tslot);
2225   team_add_player(pplayer, team_new(tslot));
2226 
2227   pnation = nation_by_number(pinfo->nation);
2228   pgov = government_by_number(pinfo->government);
2229   ptarget_gov = government_by_number(pinfo->target_government);
2230 
2231   /* Now update the player information. */
2232   sz_strlcpy(pplayer->name, pinfo->name);
2233   sz_strlcpy(pplayer->username, pinfo->username);
2234   pplayer->unassigned_user = pinfo->unassigned_user;
2235 
2236   is_new_nation = player_set_nation(pplayer, pnation);
2237   pplayer->is_male = pinfo->is_male;
2238   pplayer->score.game = pinfo->score;
2239   pplayer->was_created = pinfo->was_created;
2240 
2241   pplayer->economic.gold = pinfo->gold;
2242   pplayer->economic.tax = pinfo->tax;
2243   pplayer->economic.science = pinfo->science;
2244   pplayer->economic.luxury = pinfo->luxury;
2245   pplayer->client.tech_upkeep = pinfo->tech_upkeep;
2246   pplayer->government = pgov;
2247   pplayer->target_government = ptarget_gov;
2248   /* Don't use player_iterate here, because we ignore the real number
2249    * of players and we want to read all the datas. */
2250   BV_CLR_ALL(pplayer->real_embassy);
2251   fc_assert(8 * sizeof(pplayer->real_embassy)
2252             >= ARRAY_SIZE(pinfo->real_embassy));
2253   for (i = 0; i < ARRAY_SIZE(pinfo->real_embassy); i++) {
2254     if (pinfo->real_embassy[i]) {
2255       BV_SET(pplayer->real_embassy, i);
2256     }
2257   }
2258   pplayer->gives_shared_vision = pinfo->gives_shared_vision;
2259   pplayer->style = style_by_number(pinfo->style);
2260 
2261   if (pplayer == client.conn.playing) {
2262     bool music_change = FALSE;
2263 
2264     if (pplayer->music_style != pinfo->music_style) {
2265       pplayer->music_style = pinfo->music_style;
2266       music_change = TRUE;
2267     }
2268     if (pplayer->client.mood != pinfo->mood) {
2269       pplayer->client.mood = pinfo->mood;
2270       music_change = TRUE;
2271     }
2272 
2273     if (music_change) {
2274       start_style_music();
2275     }
2276   }
2277 
2278   pplayer->history = pinfo->history;
2279 
2280   /* Don't use player_iterate or player_slot_count here, because we ignore
2281    * the real number of players and we want to read all the datas. */
2282   fc_assert(ARRAY_SIZE(pplayer->ai_common.love) >= ARRAY_SIZE(pinfo->love));
2283   for (i = 0; i < ARRAY_SIZE(pinfo->love); i++) {
2284     pplayer->ai_common.love[i] = pinfo->love[i];
2285   }
2286 
2287   my_player = client_player();
2288 
2289   pplayer->is_connected = pinfo->is_connected;
2290 
2291   for (i = 0; i < B_LAST; i++) {
2292     pplayer->wonders[i] = pinfo->wonders[i];
2293   }
2294 
2295   /* Set AI.control. */
2296   if (pplayer->ai_controlled != pinfo->ai)  {
2297     pplayer->ai_controlled = pinfo->ai;
2298     if (pplayer == my_player)  {
2299       if (my_player->ai_controlled) {
2300         output_window_append(ftc_client, _("AI mode is now ON."));
2301         if (!gui_options.ai_manual_turn_done && !pplayer->phase_done) {
2302           /* End turn immediately */
2303           user_ended_turn();
2304         }
2305       } else {
2306         output_window_append(ftc_client, _("AI mode is now OFF."));
2307       }
2308     }
2309   }
2310 
2311   pplayer->ai_common.science_cost = pinfo->science_cost;
2312 
2313   turn_done_changed = (pplayer->phase_done != pinfo->phase_done
2314                        || pplayer->ai_controlled != pinfo->ai);
2315   pplayer->phase_done = pinfo->phase_done;
2316 
2317   pplayer->is_ready = pinfo->is_ready;
2318   pplayer->nturns_idle = pinfo->nturns_idle;
2319   pplayer->is_alive = pinfo->is_alive;
2320   pplayer->turns_alive = pinfo->turns_alive;
2321   pplayer->ai_common.barbarian_type = pinfo->barbarian_type;
2322   pplayer->revolution_finishes = pinfo->revolution_finishes;
2323   pplayer->ai_common.skill_level = pinfo->ai_skill_level;
2324 
2325   fc_assert(pinfo->multip_count == multiplier_count());
2326   game.control.num_multipliers = pinfo->multip_count;
2327   multipliers_iterate(pmul) {
2328     pplayer->multipliers[multiplier_index(pmul)] =
2329         pinfo->multiplier[multiplier_index(pmul)];
2330     pplayer->multipliers_target[multiplier_index(pmul)] =
2331         pinfo->multiplier_target[multiplier_index(pmul)];
2332   } multipliers_iterate_end;
2333 
2334   /* if the server requests that the client reset, then information about
2335    * connections to this player are lost. If this is the case, insert the
2336    * correct conn back into the player->connections list */
2337   if (conn_list_size(pplayer->connections) == 0) {
2338     conn_list_iterate(game.est_connections, pconn) {
2339       if (pplayer == pconn->playing) {
2340         /* insert the controller into first position */
2341         if (pconn->observer) {
2342           conn_list_append(pplayer->connections, pconn);
2343         } else {
2344           conn_list_prepend(pplayer->connections, pconn);
2345         }
2346       }
2347     } conn_list_iterate_end;
2348   }
2349 
2350 
2351   /* The player information is now fully set. Update the GUI. */
2352 
2353   if (pplayer == my_player && can_client_change_view()) {
2354     if (turn_done_changed) {
2355       update_turn_done_button_state();
2356     }
2357     science_report_dialog_update();
2358     economy_report_dialog_update();
2359     units_report_dialog_update();
2360     city_report_dialog_update();
2361     multipliers_dialog_update();
2362     update_info_label();
2363     menus_update();
2364   }
2365 
2366   upgrade_canvas_clipboard();
2367 
2368   players_dialog_update();
2369   update_start_page();
2370 
2371   if (is_new_nation) {
2372     races_toggles_set_sensitive();
2373 
2374     /* When changing nation during a running game, some refreshing is needed.
2375      * This may not be the only one! */
2376     update_map_canvas_visible();
2377   }
2378 
2379   if (can_client_change_view()) {
2380     /* Just about any changes above require an update to the intelligence
2381      * dialog. */
2382     update_intel_dialog(pplayer);
2383   }
2384 
2385   editgui_refresh();
2386   editgui_notify_object_changed(OBJTYPE_PLAYER, player_number(pplayer),
2387                                 FALSE);
2388 }
2389 
2390 /****************************************************************************
2391   Receive a research info packet.
2392 ****************************************************************************/
handle_research_info(const struct packet_research_info * packet)2393 void handle_research_info(const struct packet_research_info *packet)
2394 {
2395   struct research *presearch;
2396   bool tech_changed = FALSE;
2397   bool poptechup = FALSE;
2398   Tech_type_id gained_techs[advance_count()];
2399   int gained_techs_num = 0, i;
2400   enum tech_state newstate, oldstate;
2401 
2402 #ifdef DEBUG
2403   log_verbose("Research nb %d inventions: %s",
2404               packet->id,
2405               packet->inventions);
2406 #endif
2407   presearch = research_by_number(packet->id);
2408   fc_assert_ret(NULL != presearch);
2409 
2410   poptechup = (presearch->researching != packet->researching
2411                || presearch->tech_goal != packet->tech_goal);
2412   presearch->techs_researched = packet->techs_researched;
2413   if (presearch->future_tech == 0 && packet->future_tech > 0) {
2414     gained_techs[gained_techs_num++] = A_FUTURE;
2415   }
2416   presearch->future_tech = packet->future_tech;
2417   presearch->researching = packet->researching;
2418   presearch->client.researching_cost = packet->researching_cost;
2419   presearch->bulbs_researched = packet->bulbs_researched;
2420   presearch->tech_goal = packet->tech_goal;
2421   presearch->client.total_bulbs_prod = packet->total_bulbs_prod;
2422 
2423   advance_index_iterate(A_NONE, advi) {
2424     newstate = packet->inventions[advi] - '0';
2425     oldstate = research_invention_set(presearch, advi, newstate);
2426 
2427     if (newstate != oldstate) {
2428       if (TECH_KNOWN == newstate) {
2429         tech_changed = TRUE;
2430         if (A_NONE != advi) {
2431           gained_techs[gained_techs_num++] = advi;
2432         }
2433       } else if (TECH_KNOWN == oldstate) {
2434         tech_changed = TRUE;
2435       }
2436     }
2437   } advance_index_iterate_end;
2438 
2439   research_update(presearch);
2440 
2441   if (C_S_RUNNING == client_state()) {
2442     if (presearch == research_get(client_player())) {
2443       if (poptechup && !client_player()->ai_controlled) {
2444         science_report_dialog_popup(FALSE);
2445       }
2446       science_report_dialog_update();
2447       if (tech_changed) {
2448         /* Some ways a new or lost tech can affect menus:
2449          *  - If tech is needed for certain governments, the government
2450          *    switching menus need updating.
2451          *  - If we just learned/lost bridge building and focus is on a
2452          *    worker on a river, the road menu item needs updating. */
2453         menus_update();
2454         /* If we got a new tech the tech tree news an update. */
2455         science_report_dialog_redraw();
2456       }
2457       for (i = 0; i < gained_techs_num; i++) {
2458         show_tech_gained_dialog(gained_techs[i]);
2459       }
2460     }
2461     if (editor_is_active()) {
2462       editgui_refresh();
2463       research_players_iterate(presearch, pplayer) {
2464         editgui_notify_object_changed(OBJTYPE_PLAYER, player_number(pplayer),
2465                                       FALSE);
2466       } research_players_iterate_end;
2467     }
2468   }
2469 }
2470 
2471 /****************************************************************************
2472   Packet player_diplstate handler.
2473 ****************************************************************************/
handle_player_diplstate(const struct packet_player_diplstate * packet)2474 void handle_player_diplstate(const struct packet_player_diplstate *packet)
2475 {
2476   struct player *plr1 = player_by_number(packet->plr1);
2477   struct player *plr2 = player_by_number(packet->plr2);
2478   struct player *my_player = client_player();
2479   struct player_diplstate *ds = player_diplstate_get(plr1, plr2);
2480   bool need_players_dialog_update = FALSE;
2481 
2482   fc_assert_ret(ds != NULL);
2483 
2484   if (client_has_player() && my_player == plr2) {
2485     if (ds->type != packet->type) {
2486       need_players_dialog_update = TRUE;
2487     }
2488 
2489     /* Check if we detect change to armistice with us. If so,
2490      * ready all units for movement out of the territory in
2491      * question; otherwise they will be disbanded. */
2492     if (DS_ARMISTICE != player_diplstate_get(plr1, my_player)->type
2493         && DS_ARMISTICE == packet->type) {
2494       unit_list_iterate(my_player->units, punit) {
2495         if (!tile_owner(unit_tile(punit))
2496             || tile_owner(unit_tile(punit)) != plr1) {
2497           continue;
2498         }
2499         if (punit->client.focus_status == FOCUS_WAIT) {
2500           punit->client.focus_status = FOCUS_AVAIL;
2501         }
2502         if (punit->activity != ACTIVITY_IDLE) {
2503           request_new_unit_activity(punit, ACTIVITY_IDLE);
2504         }
2505       } unit_list_iterate_end;
2506     }
2507   }
2508 
2509   ds->type = packet->type;
2510   ds->turns_left = packet->turns_left;
2511   ds->has_reason_to_cancel = packet->has_reason_to_cancel;
2512   ds->contact_turns_left = packet->contact_turns_left;
2513 
2514   if (need_players_dialog_update) {
2515     players_dialog_update();
2516   }
2517 
2518   if (need_players_dialog_update
2519       && action_selection_actor_unit() != IDENTITY_NUMBER_ZERO) {
2520     /* An action selection dialog is open and our diplomatic state just
2521      * changed. Find out if the relationship that changed was to a
2522      * potential target. */
2523     struct tile *tgt_tile = NULL;
2524 
2525     /* Is a refresh needed because of a unit target? */
2526     if (action_selection_target_unit() != IDENTITY_NUMBER_ZERO) {
2527       struct unit *tgt_unit;
2528 
2529       tgt_unit = game_unit_by_number(action_selection_target_unit());
2530 
2531       if (tgt_unit != NULL && tgt_unit->owner == plr1) {
2532         /* An update is needed because of this unit target. */
2533         tgt_tile = unit_tile(tgt_unit);
2534         fc_assert(tgt_tile != NULL);
2535       }
2536     }
2537 
2538     /* Is a refresh needed because of a city target? */
2539     if (action_selection_target_city() != IDENTITY_NUMBER_ZERO) {
2540       struct city *tgt_city;
2541 
2542       tgt_city = game_city_by_number(action_selection_target_city());
2543 
2544       if (tgt_city != NULL && tgt_city->owner == plr1) {
2545         /* An update is needed because of this city target.
2546          * Overwrites any target tile from a unit. */
2547         tgt_tile = city_tile(tgt_city);
2548         fc_assert(tgt_tile != NULL);
2549       }
2550     }
2551 
2552     if (tgt_tile) {
2553       /* The diplomatic relationship to the target in an open action
2554        * selection dialog have changed. This probably changes
2555        * the set of available actions. */
2556       dsend_packet_unit_get_actions(&client.conn,
2557                                     action_selection_actor_unit(),
2558                                     action_selection_target_unit(),
2559                                     action_selection_target_city(),
2560                                     tgt_tile->index,
2561                                     FALSE);
2562     }
2563   }
2564 }
2565 
2566 /****************************************************************************
2567   Remove, add, or update dummy connection struct representing some
2568   connection to the server, with info from packet_conn_info.
2569   Updates player and game connection lists.
2570   Calls players_dialog_update() in case info for that has changed.
2571 ****************************************************************************/
handle_conn_info(const struct packet_conn_info * pinfo)2572 void handle_conn_info(const struct packet_conn_info *pinfo)
2573 {
2574   struct connection *pconn = conn_by_number(pinfo->id);
2575   bool preparing_client_state = FALSE;
2576 
2577   log_debug("conn_info id%d used%d est%d plr%d obs%d acc%d",
2578             pinfo->id, pinfo->used, pinfo->established, pinfo->player_num,
2579             pinfo->observer, (int) pinfo->access_level);
2580   log_debug("conn_info \"%s\" \"%s\" \"%s\"",
2581             pinfo->username, pinfo->addr, pinfo->capability);
2582 
2583   if (!pinfo->used) {
2584     /* Forget the connection */
2585     if (!pconn) {
2586       log_verbose("Server removed unknown connection %d", pinfo->id);
2587       return;
2588     }
2589     client_remove_cli_conn(pconn);
2590     pconn = NULL;
2591   } else {
2592     struct player_slot *pslot = player_slot_by_number(pinfo->player_num);
2593     struct player *pplayer = NULL;
2594 
2595     if (NULL != pslot) {
2596       pplayer = player_slot_get_player(pslot);
2597     }
2598 
2599     if (!pconn) {
2600       log_verbose("Server reports new connection %d %s",
2601                   pinfo->id, pinfo->username);
2602 
2603       pconn = fc_calloc(1, sizeof(struct connection));
2604       pconn->buffer = NULL;
2605       pconn->send_buffer = NULL;
2606       pconn->ping_time = -1.0;
2607       if (pplayer) {
2608         conn_list_append(pplayer->connections, pconn);
2609       }
2610       conn_list_append(game.all_connections, pconn);
2611       conn_list_append(game.est_connections, pconn);
2612     } else {
2613       log_packet("Server reports updated connection %d %s",
2614                  pinfo->id, pinfo->username);
2615       if (pplayer != pconn->playing) {
2616 	if (NULL != pconn->playing) {
2617 	  conn_list_remove(pconn->playing->connections, pconn);
2618 	}
2619 	if (pplayer) {
2620 	  conn_list_append(pplayer->connections, pconn);
2621 	}
2622       }
2623     }
2624 
2625     pconn->id = pinfo->id;
2626     pconn->established = pinfo->established;
2627     pconn->observer = pinfo->observer;
2628     pconn->access_level = pinfo->access_level;
2629     pconn->playing = pplayer;
2630 
2631     sz_strlcpy(pconn->username, pinfo->username);
2632     sz_strlcpy(pconn->addr, pinfo->addr);
2633     sz_strlcpy(pconn->capability, pinfo->capability);
2634 
2635     if (pinfo->id == client.conn.id) {
2636       /* NB: In this case, pconn is not a duplication of client.conn.
2637        *
2638        * pconn->addr is our address that the server knows whereas
2639        * client.conn.addr is the address to the server. Also,
2640        * pconn->capability stores our capabilites known at server side
2641        * whereas client.conn.capability represents the capabilities of the
2642        * server. */
2643       if (client.conn.playing != pplayer
2644           || client.conn.observer != pinfo->observer) {
2645         /* Our connection state changed, let prepare the changes and reset
2646          * the game. */
2647         preparing_client_state = TRUE;
2648       }
2649 
2650       /* Copy our current state into the static structure (our connection
2651        * to the server). */
2652       client.conn.established = pinfo->established;
2653       client.conn.observer = pinfo->observer;
2654       client.conn.access_level = pinfo->access_level;
2655       client.conn.playing = pplayer;
2656       sz_strlcpy(client.conn.username, pinfo->username);
2657     }
2658   }
2659 
2660   players_dialog_update();
2661   conn_list_dialog_update();
2662 
2663   if (pinfo->used && pinfo->id == client.conn.id) {
2664     /* For updating the sensitivity of the "Edit Mode" menu item,
2665      * among other things. */
2666     menus_update();
2667   }
2668 
2669   if (preparing_client_state) {
2670     set_client_state(C_S_PREPARING);
2671   }
2672 }
2673 
2674 /*************************************************************************
2675   Handles a conn_ping_info packet from the server.  This packet contains
2676   ping times for each connection.
2677 **************************************************************************/
handle_conn_ping_info(int connections,const int * conn_id,const float * ping_time)2678 void handle_conn_ping_info(int connections, const int *conn_id,
2679                            const float *ping_time)
2680 {
2681   int i;
2682 
2683   for (i = 0; i < connections; i++) {
2684     struct connection *pconn = conn_by_number(conn_id[i]);
2685 
2686     if (!pconn) {
2687       continue;
2688     }
2689 
2690     pconn->ping_time = ping_time[i];
2691     log_debug("conn-id=%d, ping=%fs", pconn->id, pconn->ping_time);
2692   }
2693   /* The old_ping_time data is ignored. */
2694 
2695   players_dialog_update();
2696 }
2697 
2698 /**************************************************************************
2699   Received package about gaining an achievement.
2700 **************************************************************************/
handle_achievement_info(int id,bool gained,bool first)2701 void handle_achievement_info(int id, bool gained, bool first)
2702 {
2703   struct achievement *pach;
2704 
2705   if (id < 0 || id >= game.control.num_achievement_types) {
2706     log_error("Received illegal achievement info %d", id);
2707     return;
2708   }
2709 
2710   pach = achievement_by_number(id);
2711 
2712   if (gained) {
2713     BV_SET(pach->achievers, player_index(client_player()));
2714   } else {
2715     BV_CLR(pach->achievers, player_index(client_player()));
2716   }
2717 
2718   if (first) {
2719     pach->first = client_player();
2720   }
2721 }
2722 
2723 /**************************************************************************
2724 Ideally the client should let the player choose which type of
2725 modules and components to build, and (possibly) where to extend
2726 structurals.  The protocol now makes this possible, but the
2727 client is not yet that good (would require GUI improvements)
2728 so currently the client choices stuff automatically if there
2729 is anything unplaced.
2730 
2731 This function makes a choice (sends spaceship_action) and
2732 returns 1 if we placed something, else 0.
2733 
2734 Do things one at a time; the server will send us an updated
2735 spaceship_info packet, and we'll be back here to do anything
2736 which is left.
2737 **************************************************************************/
spaceship_autoplace(struct player * pplayer,struct player_spaceship * ship)2738 static bool spaceship_autoplace(struct player *pplayer,
2739 			       struct player_spaceship *ship)
2740 {
2741   if (can_client_issue_orders()) {
2742     struct spaceship_component place;
2743 
2744     if (next_spaceship_component(pplayer, ship, &place)) {
2745       dsend_packet_spaceship_place(&client.conn, place.type, place.num);
2746 
2747       return TRUE;
2748     }
2749   }
2750 
2751   return FALSE;
2752 }
2753 
2754 /****************************************************************************
2755   Packet spaceship_info handler.
2756 ****************************************************************************/
handle_spaceship_info(const struct packet_spaceship_info * p)2757 void handle_spaceship_info(const struct packet_spaceship_info *p)
2758 {
2759   struct player_spaceship *ship;
2760   struct player *pplayer = player_by_number(p->player_num);
2761 
2762   fc_assert_ret_msg(NULL != pplayer, "Invalid player number %d.",
2763                     p->player_num);
2764 
2765   ship = &pplayer->spaceship;
2766   ship->state        = p->sship_state;
2767   ship->structurals  = p->structurals;
2768   ship->components   = p->components;
2769   ship->modules      = p->modules;
2770   ship->fuel         = p->fuel;
2771   ship->propulsion   = p->propulsion;
2772   ship->habitation   = p->habitation;
2773   ship->life_support = p->life_support;
2774   ship->solar_panels = p->solar_panels;
2775   if (has_capability("year32", client.conn.capability)) {
2776     ship->launch_year = p->launch_year32;
2777   } else {
2778     ship->launch_year = p->launch_year16;
2779   }
2780   ship->population   = p->population;
2781   ship->mass         = p->mass;
2782   ship->support_rate = p->support_rate;
2783   ship->energy_rate  = p->energy_rate;
2784   ship->success_rate = p->success_rate;
2785   ship->travel_time  = p->travel_time;
2786   ship->structure    = p->structure;
2787 
2788   if (pplayer != client_player()) {
2789     refresh_spaceship_dialog(pplayer);
2790     menus_update();
2791     return;
2792   }
2793 
2794   if (!spaceship_autoplace(pplayer, ship)) {
2795     /* We refresh the dialog when the packet did *not* cause placing
2796      * of new part. That's because those cases where part is placed, are
2797      * followed by exactly one case where there's no more parts to place -
2798      * we want to refresh the dialog only when that last packet comes. */
2799     refresh_spaceship_dialog(pplayer);
2800   }
2801 }
2802 
2803 /****************************************************************************
2804   Packet tile_info handler.
2805 ****************************************************************************/
handle_tile_info(const struct packet_tile_info * packet)2806 void handle_tile_info(const struct packet_tile_info *packet)
2807 {
2808   enum known_type new_known;
2809   enum known_type old_known;
2810   bool known_changed = FALSE;
2811   bool tile_changed = FALSE;
2812   struct player *powner = player_by_number(packet->owner);
2813   struct player *eowner = player_by_number(packet->extras_owner);
2814   struct resource *presource = resource_by_number(packet->resource);
2815   struct terrain *pterrain = terrain_by_number(packet->terrain);
2816   struct tile *ptile = index_to_tile(packet->tile);
2817 
2818   fc_assert_ret_msg(NULL != ptile, "Invalid tile index %d.", packet->tile);
2819   old_known = client_tile_get_known(ptile);
2820 
2821   if (NULL == tile_terrain(ptile) || pterrain != tile_terrain(ptile)) {
2822     tile_changed = TRUE;
2823     switch (old_known) {
2824     case TILE_UNKNOWN:
2825       tile_set_terrain(ptile, pterrain);
2826       break;
2827     case TILE_KNOWN_UNSEEN:
2828     case TILE_KNOWN_SEEN:
2829       if (NULL != pterrain || TILE_UNKNOWN == packet->known) {
2830         tile_set_terrain(ptile, pterrain);
2831       } else {
2832         tile_changed = FALSE;
2833         log_error("handle_tile_info() unknown terrain (%d, %d).",
2834                   TILE_XY(ptile));
2835       }
2836       break;
2837     };
2838   }
2839 
2840   if (!BV_ARE_EQUAL(ptile->extras, packet->extras)) {
2841     ptile->extras = packet->extras;
2842     tile_changed = TRUE;
2843   }
2844 
2845   tile_changed = tile_changed || (tile_resource(ptile) != presource);
2846 
2847   /* always called after setting terrain */
2848   tile_set_resource(ptile, presource);
2849 
2850   if (tile_owner(ptile) != powner) {
2851     tile_set_owner(ptile, powner, NULL);
2852     tile_changed = TRUE;
2853   }
2854   if (extra_owner(ptile) != eowner) {
2855     ptile->extras_owner = eowner;
2856     tile_changed = TRUE;
2857   }
2858 
2859   if (NULL == tile_worked(ptile)
2860    || tile_worked(ptile)->id != packet->worked) {
2861     if (IDENTITY_NUMBER_ZERO != packet->worked) {
2862       struct city *pwork = game_city_by_number(packet->worked);
2863 
2864       if (NULL == pwork) {
2865         char named[MAX_LEN_NAME];
2866 
2867         /* new unseen ("invisible") city, or before city_info */
2868         fc_snprintf(named, sizeof(named), "%06u", packet->worked);
2869 
2870         pwork = create_city_virtual(invisible.placeholder, NULL, named);
2871         pwork->id = packet->worked;
2872         idex_register_city(pwork);
2873 
2874         city_list_prepend(invisible.cities, pwork);
2875 
2876         log_debug("(%d,%d) invisible city %d, %s",
2877                   TILE_XY(ptile), pwork->id, city_name_get(pwork));
2878       } else if (NULL == city_tile(pwork)) {
2879         /* old unseen ("invisible") city, or before city_info */
2880         if (NULL != powner && city_owner(pwork) != powner) {
2881           /* update placeholder with current owner */
2882           pwork->owner = powner;
2883           pwork->original = powner;
2884         }
2885       } else {
2886         /* We have a real (not invisible) city record for this ID, but
2887          * perhaps our info about that city is out of date. */
2888         int dist_sq = sq_map_distance(city_tile(pwork), ptile);
2889 
2890         if (dist_sq > city_map_radius_sq_get(pwork)) {
2891           /* This is probably enemy city which has grown in diameter since we
2892            * last saw it. We need city_radius_sq to be at least big enough so
2893            * that all workers fit in, so set it so. */
2894           city_map_radius_sq_set(pwork, dist_sq);
2895         }
2896         /* This might be a known city that is open in a dialog.
2897          * (And this might be our only prompt to refresh the worked tiles
2898          * display in its city map, if a worker rearrangement does not
2899          * change anything else about the city such as output.) */
2900         {
2901           struct city *oldwork = tile_worked(ptile);
2902           if (oldwork && NULL != city_tile(oldwork)) {
2903             /* Refresh previous city too if it's real and different */
2904             refresh_city_dialog(oldwork);
2905           }
2906           /* Refresh new city working tile (which we already know is real) */
2907           refresh_city_dialog(pwork);
2908         }
2909       }
2910 
2911       /* This marks tile worked by (possibly invisible) city. Other
2912        * parts of the code have to handle invisible cities correctly
2913        * (ptile->worked->tile == NULL) */
2914       tile_set_worked(ptile, pwork);
2915     } else {
2916       /* Tile is no longer being worked by a city.
2917        * (Again, this might be our only prompt to refresh the worked tiles
2918        * display for the previous working city.) */
2919       if (tile_worked(ptile) && NULL != city_tile(tile_worked(ptile))) {
2920         refresh_city_dialog(tile_worked(ptile));
2921       }
2922       tile_set_worked(ptile, NULL);
2923     }
2924 
2925     tile_changed = TRUE;
2926   }
2927 
2928   if (old_known != packet->known) {
2929     known_changed = TRUE;
2930   }
2931 
2932   if (NULL != client.conn.playing) {
2933     dbv_clr(&client.conn.playing->tile_known, tile_index(ptile));
2934     vision_layer_iterate(v) {
2935       dbv_clr(&client.conn.playing->client.tile_vision[v], tile_index(ptile));
2936     } vision_layer_iterate_end;
2937 
2938     switch (packet->known) {
2939     case TILE_KNOWN_SEEN:
2940       dbv_set(&client.conn.playing->tile_known, tile_index(ptile));
2941       vision_layer_iterate(v) {
2942         dbv_set(&client.conn.playing->client.tile_vision[v], tile_index(ptile));
2943       } vision_layer_iterate_end;
2944       break;
2945     case TILE_KNOWN_UNSEEN:
2946       dbv_set(&client.conn.playing->tile_known, tile_index(ptile));
2947       break;
2948     case TILE_UNKNOWN:
2949       break;
2950     default:
2951       log_error("handle_tile_info() invalid known (%d).", packet->known);
2952       break;
2953     };
2954   }
2955   new_known = client_tile_get_known(ptile);
2956 
2957   if (packet->spec_sprite[0] != '\0') {
2958     if (!ptile->spec_sprite
2959 	|| strcmp(ptile->spec_sprite, packet->spec_sprite) != 0) {
2960       if (ptile->spec_sprite) {
2961 	free(ptile->spec_sprite);
2962       }
2963       ptile->spec_sprite = fc_strdup(packet->spec_sprite);
2964       tile_changed = TRUE;
2965     }
2966   } else {
2967     if (ptile->spec_sprite) {
2968       free(ptile->spec_sprite);
2969       ptile->spec_sprite = NULL;
2970       tile_changed = TRUE;
2971     }
2972   }
2973 
2974   if (TILE_KNOWN_SEEN == old_known && TILE_KNOWN_SEEN != new_known) {
2975     /* This is an error. So first we log the error,
2976      * then make an assertion. */
2977     unit_list_iterate(ptile->units, punit) {
2978       log_error("%p %d %s at (%d,%d) %s", punit, punit->id,
2979                 unit_rule_name(punit), TILE_XY(unit_tile(punit)),
2980                 player_name(unit_owner(punit)));
2981     } unit_list_iterate_end;
2982     fc_assert_msg(0 == unit_list_size(ptile->units), "Ghost units seen");
2983     /* Repairing... */
2984     unit_list_clear(ptile->units);
2985   }
2986 
2987   ptile->continent = packet->continent;
2988   game.map.num_continents = MAX(ptile->continent, game.map.num_continents);
2989 
2990   if (packet->label[0] == '\0') {
2991     if (ptile->label != NULL) {
2992       FC_FREE(ptile->label);
2993       ptile->label = NULL;
2994       tile_changed = TRUE;
2995     }
2996   } else if (ptile->label == NULL || strcmp(packet->label, ptile->label)) {
2997       tile_set_label(ptile, packet->label);
2998       tile_changed = TRUE;
2999   }
3000 
3001   if (known_changed || tile_changed) {
3002     /*
3003      * A tile can only change if it was known before and is still
3004      * known. In the other cases the tile is new or removed.
3005      */
3006     if (known_changed && TILE_KNOWN_SEEN == new_known) {
3007       agents_tile_new(ptile);
3008     } else if (known_changed && TILE_KNOWN_UNSEEN == new_known) {
3009       agents_tile_remove(ptile);
3010     } else {
3011       agents_tile_changed(ptile);
3012     }
3013     editgui_notify_object_changed(OBJTYPE_TILE, tile_index(ptile), FALSE);
3014   }
3015 
3016   /* refresh tiles */
3017   if (can_client_change_view()) {
3018     /* the tile itself (including the necessary parts of adjacent tiles) */
3019     if (tile_changed || old_known != new_known) {
3020       refresh_tile_mapcanvas(ptile, TRUE, FALSE);
3021     }
3022   }
3023 
3024   /* update menus if the focus unit is on the tile. */
3025   if (tile_changed) {
3026     if (get_focus_unit_on_tile(ptile)) {
3027       menus_update();
3028     }
3029   }
3030 
3031   /* FIXME: we really ought to call refresh_city_dialog() for any city
3032    * whose radii include this tile, to update the city map display.
3033    * But that would be expensive. We deal with the (common) special
3034    * case of changes in worked tiles above. */
3035 }
3036 
3037 /****************************************************************************
3038   Received packet containing info about current scenario
3039 ****************************************************************************/
handle_scenario_info(const struct packet_scenario_info * packet)3040 void handle_scenario_info(const struct packet_scenario_info *packet)
3041 {
3042   game.scenario.is_scenario = packet->is_scenario;
3043   sz_strlcpy(game.scenario.name, packet->name);
3044   sz_strlcpy(game.scenario.authors, packet->authors);
3045   game.scenario.players = packet->players;
3046   game.scenario.startpos_nations = packet->startpos_nations;
3047   game.scenario.prevent_new_cities = packet->prevent_new_cities;
3048   game.scenario.lake_flooding = packet->lake_flooding;
3049   game.scenario.have_resources = packet->have_resources;
3050   game.scenario.save_random = packet->save_random;
3051   game.scenario.handmade = packet->handmade;
3052   game.scenario.allow_ai_type_fallback = packet->allow_ai_type_fallback;
3053 
3054   editgui_notify_object_changed(OBJTYPE_GAME, 1, FALSE);
3055 }
3056 
3057 /****************************************************************************
3058   Received packet containing description of current scenario
3059 ****************************************************************************/
handle_scenario_description(const char * description)3060 void handle_scenario_description(const char *description)
3061 {
3062   sz_strlcpy(game.scenario_desc.description, description);
3063 
3064   editgui_notify_object_changed(OBJTYPE_GAME, 1, FALSE);
3065 }
3066 
3067 /****************************************************************************
3068   Take arrival of ruleset control packet to indicate that
3069   current allocated governments should be free'd, and new
3070   memory allocated for new size. The same for nations.
3071 ****************************************************************************/
handle_ruleset_control(const struct packet_ruleset_control * packet)3072 void handle_ruleset_control(const struct packet_ruleset_control *packet)
3073 {
3074   /* The ruleset is going to load new nations. So close
3075    * the nation selection dialog if it is open. */
3076   popdown_races_dialog();
3077 
3078   game.client.ruleset_init = FALSE;
3079   game.client.ruleset_ready = FALSE;
3080   game_ruleset_free();
3081   game_ruleset_init();
3082   game.client.ruleset_init = TRUE;
3083   game.control = *packet;
3084 
3085   /* check the values! */
3086 #define VALIDATE(_count, _maximum, _string)                                 \
3087   if (game.control._count > _maximum) {                                     \
3088     log_error("handle_ruleset_control(): Too many " _string                 \
3089               "; using %d of %d", _maximum, game.control._count);           \
3090     game.control._count = _maximum;                                         \
3091   }
3092 
3093   VALIDATE(num_unit_classes,	UCL_LAST,		"unit classes");
3094   VALIDATE(num_unit_types,	U_LAST,			"unit types");
3095   VALIDATE(num_impr_types,	B_LAST,			"improvements");
3096   VALIDATE(num_tech_types,      A_LAST,                 "advances");
3097   VALIDATE(num_base_types,	MAX_BASE_TYPES,		"bases");
3098   VALIDATE(num_road_types,      MAX_ROAD_TYPES,         "roads");
3099   VALIDATE(num_disaster_types,  MAX_DISASTER_TYPES,     "disasters");
3100   VALIDATE(num_achievement_types, MAX_ACHIEVEMENT_TYPES, "achievements");
3101 
3102   /* game.control.government_count, game.control.nation_count and
3103    * game.control.styles_count are allocated dynamically, and does
3104    * not need a size check.  See the allocation bellow. */
3105 
3106   VALIDATE(terrain_count,	MAX_NUM_TERRAINS,	"terrains");
3107   VALIDATE(resource_count,	MAX_NUM_RESOURCES,	"resources");
3108 
3109   VALIDATE(num_specialist_types, SP_MAX,		"specialists");
3110 #undef VALIDATE
3111 
3112   governments_alloc(game.control.government_count);
3113   nations_alloc(game.control.nation_count);
3114   styles_alloc(game.control.num_styles);
3115   city_styles_alloc(game.control.styles_count);
3116   music_styles_alloc(game.control.num_music_styles);
3117 
3118   if (game.control.desc_length > 0) {
3119     game.ruleset_description = fc_malloc(game.control.desc_length + 1);
3120     game.ruleset_description[0] = '\0';
3121   }
3122 
3123   if (packet->preferred_tileset[0] != '\0') {
3124     /* There is tileset suggestion */
3125     if (strcmp(packet->preferred_tileset, tileset_basename(tileset))) {
3126       /* It's not currently in use */
3127       if (gui_options.autoaccept_tileset_suggestion) {
3128         tilespec_reread(game.control.preferred_tileset, TRUE, 1.0f);
3129       } else {
3130         popup_tileset_suggestion_dialog();
3131       }
3132     }
3133   }
3134 
3135   if (packet->preferred_soundset[0] != '\0') {
3136     /* There is soundset suggestion */
3137     if (strcmp(packet->preferred_soundset, sound_set_name)) {
3138       /* It's not currently in use */
3139       if (gui_options.autoaccept_soundset_suggestion) {
3140         audio_restart(game.control.preferred_soundset, music_set_name);
3141       } else {
3142         popup_soundset_suggestion_dialog();
3143       }
3144     }
3145   }
3146 
3147   if (packet->preferred_musicset[0] != '\0') {
3148     /* There is musicset suggestion */
3149     if (strcmp(packet->preferred_musicset, music_set_name)) {
3150       /* It's not currently in use */
3151       if (gui_options.autoaccept_musicset_suggestion) {
3152         audio_restart(sound_set_name, game.control.preferred_musicset);
3153       } else {
3154         popup_musicset_suggestion_dialog();
3155       }
3156     }
3157   }
3158 
3159   tileset_ruleset_reset(tileset);
3160 }
3161 
3162 /****************************************************************************
3163   Ruleset summary.
3164 ****************************************************************************/
handle_ruleset_summary(const struct packet_ruleset_summary * packet)3165 void handle_ruleset_summary(const struct packet_ruleset_summary *packet)
3166 {
3167   int len;
3168 
3169   if (game.ruleset_summary != NULL) {
3170     free(game.ruleset_summary);
3171   }
3172 
3173   len = strlen(packet->text);
3174 
3175   game.ruleset_summary = fc_malloc(len + 1);
3176 
3177   fc_strlcpy(game.ruleset_summary, packet->text, len + 1);
3178 }
3179 
3180 /****************************************************************************
3181   Next part of ruleset description.
3182 ****************************************************************************/
handle_ruleset_description_part(const struct packet_ruleset_description_part * packet)3183 void handle_ruleset_description_part(
3184                         const struct packet_ruleset_description_part *packet)
3185 {
3186   fc_strlcat(game.ruleset_description, packet->text,
3187              game.control.desc_length + 1);
3188 }
3189 
3190 /****************************************************************************
3191   Received packet indicating that all rulesets have now been received.
3192 ****************************************************************************/
handle_rulesets_ready(void)3193 void handle_rulesets_ready(void)
3194 {
3195   /* Setup extra hiders caches */
3196   extra_type_iterate(pextra) {
3197     pextra->hiders = extra_type_list_new();
3198     extra_type_iterate(phider) {
3199       if (BV_ISSET(pextra->hidden_by, extra_index(phider))) {
3200         extra_type_list_append(pextra->hiders, phider);
3201       }
3202     } extra_type_iterate_end;
3203   } extra_type_iterate_end;
3204 
3205   unit_class_iterate(pclass) {
3206     set_unit_class_caches(pclass);
3207     set_unit_move_type(pclass);
3208   } unit_class_iterate_end;
3209 
3210   /* Setup improvement feature caches */
3211   improvement_feature_cache_init();
3212 
3213   /* Setup road integrators caches */
3214   road_integrators_cache_init();
3215 
3216   /* Setup unit unknown move cost caches */
3217   unit_type_iterate(ptype) {
3218     ptype->unknown_move_cost = utype_unknown_move_cost(ptype);
3219     set_unit_type_caches(ptype);
3220     unit_type_action_cache_set(ptype);
3221   } unit_type_iterate_end;
3222 
3223   /* Adjust editor for changed ruleset. */
3224   editor_ruleset_changed();
3225 
3226   /* We are not going to crop any more sprites from big sprites, free them. */
3227   finish_loading_sprites(tileset);
3228 
3229   game.client.ruleset_ready = TRUE;
3230 }
3231 
3232 /****************************************************************************
3233   Packet ruleset_unit_class handler.
3234 ****************************************************************************/
handle_ruleset_unit_class(const struct packet_ruleset_unit_class * p)3235 void handle_ruleset_unit_class(const struct packet_ruleset_unit_class *p)
3236 {
3237   struct unit_class *c = uclass_by_number(p->id);
3238 
3239   fc_assert_ret_msg(NULL != c, "Bad unit_class %d.", p->id);
3240 
3241   names_set(&c->name, NULL, p->name, p->rule_name);
3242   c->min_speed          = p->min_speed;
3243   c->hp_loss_pct        = p->hp_loss_pct;
3244   c->hut_behavior       = p->hut_behavior;
3245   c->non_native_def_pct = p->non_native_def_pct;
3246   c->flags              = p->flags;
3247 
3248   PACKET_STRVEC_EXTRACT(c->helptext, p->helptext);
3249 }
3250 
3251 /****************************************************************************
3252   Packet ruleset_unit handler.
3253 ****************************************************************************/
handle_ruleset_unit(const struct packet_ruleset_unit * p)3254 void handle_ruleset_unit(const struct packet_ruleset_unit *p)
3255 {
3256   int i;
3257   struct unit_type *u = utype_by_number(p->id);
3258 
3259   fc_assert_ret_msg(NULL != u, "Bad unit_type %d.", p->id);
3260 
3261   names_set(&u->name, NULL, p->name, p->rule_name);
3262   sz_strlcpy(u->graphic_str, p->graphic_str);
3263   sz_strlcpy(u->graphic_alt, p->graphic_alt);
3264   sz_strlcpy(u->sound_move, p->sound_move);
3265   sz_strlcpy(u->sound_move_alt, p->sound_move_alt);
3266   sz_strlcpy(u->sound_fight, p->sound_fight);
3267   sz_strlcpy(u->sound_fight_alt, p->sound_fight_alt);
3268 
3269   u->uclass             = uclass_by_number(p->unit_class_id);
3270   u->build_cost         = p->build_cost;
3271   u->pop_cost           = p->pop_cost;
3272   u->attack_strength    = p->attack_strength;
3273   u->defense_strength   = p->defense_strength;
3274   u->move_rate          = p->move_rate;
3275   u->require_advance    = advance_by_number(p->tech_requirement);
3276   u->need_improvement   = improvement_by_number(p->impr_requirement);
3277   u->need_government    = government_by_number(p->gov_requirement);
3278   u->vision_radius_sq = p->vision_radius_sq;
3279   u->transport_capacity = p->transport_capacity;
3280   u->hp                 = p->hp;
3281   u->firepower          = p->firepower;
3282   u->obsoleted_by       = utype_by_number(p->obsoleted_by);
3283   u->converted_to       = utype_by_number(p->converted_to);
3284   u->convert_time       = p->convert_time;
3285   u->fuel               = p->fuel;
3286   u->flags              = p->flags;
3287   u->roles              = p->roles;
3288   u->happy_cost         = p->happy_cost;
3289   output_type_iterate(o) {
3290     u->upkeep[o] = p->upkeep[o];
3291   } output_type_iterate_end;
3292   u->paratroopers_range = p->paratroopers_range;
3293   u->paratroopers_mr_req = p->paratroopers_mr_req;
3294   u->paratroopers_mr_sub = p->paratroopers_mr_sub;
3295   u->bombard_rate       = p->bombard_rate;
3296   u->city_size          = p->city_size;
3297   u->cargo              = p->cargo;
3298   u->targets            = p->targets;
3299   u->embarks            = p->embarks;
3300   u->disembarks         = p->disembarks;
3301 
3302   if (p->veteran_levels == 0) {
3303     u->veteran = NULL;
3304   } else {
3305     u->veteran = veteran_system_new(p->veteran_levels);
3306 
3307     for (i = 0; i < p->veteran_levels; i++) {
3308       veteran_system_definition(u->veteran, i, p->veteran_name[i],
3309                                 p->power_fact[i], p->move_bonus[i], 0, 0);
3310     }
3311   }
3312 
3313   PACKET_STRVEC_EXTRACT(u->helptext, p->helptext);
3314 
3315   tileset_setup_unit_type(tileset, u);
3316 }
3317 
3318 /****************************************************************************
3319   Packet ruleset_unit_bonus handler.
3320 ****************************************************************************/
handle_ruleset_unit_bonus(const struct packet_ruleset_unit_bonus * p)3321 void handle_ruleset_unit_bonus(const struct packet_ruleset_unit_bonus *p)
3322 {
3323   struct unit_type *u = utype_by_number(p->unit);
3324   struct combat_bonus *bonus;
3325 
3326   fc_assert_ret_msg(NULL != u, "Bad unit_type %d.", p->unit);
3327 
3328   bonus = malloc(sizeof(*bonus));
3329 
3330   bonus->flag  = p->flag;
3331   bonus->type  = p->type;
3332   bonus->value = p->value;
3333   bonus->quiet = p->quiet;
3334 
3335   combat_bonus_list_append(u->bonuses, bonus);
3336 }
3337 
3338 /****************************************************************************
3339   Packet ruleset_unit_flag handler.
3340 ****************************************************************************/
handle_ruleset_unit_flag(const struct packet_ruleset_unit_flag * p)3341 void handle_ruleset_unit_flag(const struct packet_ruleset_unit_flag *p)
3342 {
3343   const char *flagname;
3344   const char *helptxt;
3345 
3346   fc_assert_ret_msg(p->id >= UTYF_USER_FLAG_1 && p->id <= UTYF_LAST_USER_FLAG, "Bad user flag %d.", p->id);
3347 
3348   if (p->name[0] == '\0') {
3349     flagname = NULL;
3350   } else {
3351     flagname = p->name;
3352   }
3353 
3354   if (p->helptxt[0] == '\0') {
3355     helptxt = NULL;
3356   } else {
3357     helptxt = p->helptxt;
3358   }
3359 
3360   set_user_unit_type_flag_name(p->id, flagname, helptxt);
3361 }
3362 
3363 /****************************************************************************
3364   Packet ruleset_tech handler.
3365 ****************************************************************************/
handle_ruleset_tech(const struct packet_ruleset_tech * p)3366 void handle_ruleset_tech(const struct packet_ruleset_tech *p)
3367 {
3368   struct advance *a = advance_by_number(p->id);
3369 
3370   fc_assert_ret_msg(NULL != a, "Bad advance %d.", p->id);
3371 
3372   names_set(&a->name, NULL, p->name, p->rule_name);
3373   sz_strlcpy(a->graphic_str, p->graphic_str);
3374   sz_strlcpy(a->graphic_alt, p->graphic_alt);
3375   a->require[AR_ONE] = advance_by_number(p->req[AR_ONE]);
3376   a->require[AR_TWO] = advance_by_number(p->req[AR_TWO]);
3377   a->require[AR_ROOT] = advance_by_number(p->root_req);
3378   a->flags = p->flags;
3379   a->cost = p->cost;
3380   a->num_reqs = p->num_reqs;
3381   PACKET_STRVEC_EXTRACT(a->helptext, p->helptext);
3382 
3383   tileset_setup_tech_type(tileset, a);
3384 }
3385 
3386 /****************************************************************************
3387   Packet ruleset_tech_flag handler.
3388 ****************************************************************************/
handle_ruleset_tech_flag(const struct packet_ruleset_tech_flag * p)3389 void handle_ruleset_tech_flag(const struct packet_ruleset_tech_flag *p)
3390 {
3391   const char *flagname;
3392   const char *helptxt;
3393 
3394   fc_assert_ret_msg(p->id >= TECH_USER_1 && p->id <= TECH_USER_LAST, "Bad user flag %d.", p->id);
3395 
3396   if (p->name[0] == '\0') {
3397     flagname = NULL;
3398   } else {
3399     flagname = p->name;
3400   }
3401 
3402   if (p->helptxt[0] == '\0') {
3403     helptxt = NULL;
3404   } else {
3405     helptxt = p->helptxt;
3406   }
3407 
3408   set_user_tech_flag_name(p->id, flagname, helptxt);
3409 }
3410 
3411 /****************************************************************************
3412   Packet ruleset_building handler.
3413 ****************************************************************************/
handle_ruleset_building(const struct packet_ruleset_building * p)3414 void handle_ruleset_building(const struct packet_ruleset_building *p)
3415 {
3416   int i;
3417   struct impr_type *b = improvement_by_number(p->id);
3418 
3419   fc_assert_ret_msg(NULL != b, "Bad improvement %d.", p->id);
3420 
3421   b->genus = p->genus;
3422   names_set(&b->name, NULL, p->name, p->rule_name);
3423   sz_strlcpy(b->graphic_str, p->graphic_str);
3424   sz_strlcpy(b->graphic_alt, p->graphic_alt);
3425   for (i = 0; i < p->reqs_count; i++) {
3426     requirement_vector_append(&b->reqs, p->reqs[i]);
3427   }
3428   fc_assert(b->reqs.size == p->reqs_count);
3429   for (i = 0; i < p->obs_count; i++) {
3430     requirement_vector_append(&b->obsolete_by, p->obs_reqs[i]);
3431   }
3432   fc_assert(b->obsolete_by.size == p->obs_count);
3433   b->build_cost = p->build_cost;
3434   b->upkeep = p->upkeep;
3435   b->sabotage = p->sabotage;
3436   b->flags = p->flags;
3437   PACKET_STRVEC_EXTRACT(b->helptext, p->helptext);
3438   sz_strlcpy(b->soundtag, p->soundtag);
3439   sz_strlcpy(b->soundtag_alt, p->soundtag_alt);
3440 
3441 #ifdef DEBUG
3442   if (p->id == improvement_count() - 1) {
3443     improvement_iterate(bdbg) {
3444       log_debug("Improvement: %s...", improvement_rule_name(bdbg));
3445       log_debug("  build_cost %3d", bdbg->build_cost);
3446       log_debug("  upkeep      %2d", bdbg->upkeep);
3447       log_debug("  sabotage   %3d", bdbg->sabotage);
3448       if (NULL != bdbg->helptext) {
3449         strvec_iterate(bdbg->helptext, text) {
3450           log_debug("  helptext    %s", text);
3451         } strvec_iterate_end;
3452       }
3453     } improvement_iterate_end;
3454   }
3455 #endif /* DEBUG */
3456 
3457   tileset_setup_impr_type(tileset, b);
3458 }
3459 
3460 /****************************************************************************
3461   Packet ruleset_multiplier handler.
3462 ****************************************************************************/
handle_ruleset_multiplier(const struct packet_ruleset_multiplier * p)3463 void handle_ruleset_multiplier(const struct packet_ruleset_multiplier *p)
3464 {
3465   struct multiplier *pmul = multiplier_by_number(p->id);
3466 
3467   fc_assert_ret_msg(NULL != pmul, "Bad multiplier %d.", p->id);
3468 
3469   pmul->start  = p->start;
3470   pmul->stop   = p->stop;
3471   pmul->step   = p->step;
3472   pmul->def    = p->def;
3473   pmul->offset = p->offset;
3474   pmul->factor = p->factor;
3475 
3476   names_set(&pmul->name, NULL, p->name, p->rule_name);
3477 
3478   PACKET_STRVEC_EXTRACT(pmul->helptext, p->helptext);
3479 }
3480 
3481 /****************************************************************************
3482   Packet ruleset_government handler.
3483 ****************************************************************************/
handle_ruleset_government(const struct packet_ruleset_government * p)3484 void handle_ruleset_government(const struct packet_ruleset_government *p)
3485 {
3486   int j;
3487   struct government *gov = government_by_number(p->id);
3488 
3489   fc_assert_ret_msg(NULL != gov, "Bad government %d.", p->id);
3490 
3491   gov->item_number = p->id;
3492 
3493   for (j = 0; j < p->reqs_count; j++) {
3494     requirement_vector_append(&gov->reqs, p->reqs[j]);
3495   }
3496   fc_assert(gov->reqs.size == p->reqs_count);
3497 
3498   names_set(&gov->name, NULL, p->name, p->rule_name);
3499   sz_strlcpy(gov->graphic_str, p->graphic_str);
3500   sz_strlcpy(gov->graphic_alt, p->graphic_alt);
3501 
3502   PACKET_STRVEC_EXTRACT(gov->helptext, p->helptext);
3503 
3504   tileset_setup_government(tileset, gov);
3505 }
3506 
3507 /****************************************************************************
3508   Packet ruleset_government_ruler_title handler.
3509 ****************************************************************************/
handle_ruleset_government_ruler_title(const struct packet_ruleset_government_ruler_title * packet)3510 void handle_ruleset_government_ruler_title
3511     (const struct packet_ruleset_government_ruler_title *packet)
3512 {
3513   struct government *gov = government_by_number(packet->gov);
3514 
3515   fc_assert_ret_msg(NULL != gov, "Bad government %d.", packet->gov);
3516 
3517   (void) government_ruler_title_new(gov, nation_by_number(packet->nation),
3518                                     packet->male_title,
3519                                     packet->female_title);
3520 }
3521 
3522 /****************************************************************************
3523   Packet ruleset_terrain handler.
3524 ****************************************************************************/
handle_ruleset_terrain(const struct packet_ruleset_terrain * p)3525 void handle_ruleset_terrain(const struct packet_ruleset_terrain *p)
3526 {
3527   int j;
3528   struct terrain *pterrain = terrain_by_number(p->id);
3529 
3530   fc_assert_ret_msg(NULL != pterrain, "Bad terrain %d.", p->id);
3531 
3532   pterrain->tclass = p->tclass;
3533   pterrain->native_to = p->native_to;
3534   names_set(&pterrain->name, NULL, p->name, p->rule_name);
3535   sz_strlcpy(pterrain->graphic_str, p->graphic_str);
3536   sz_strlcpy(pterrain->graphic_alt, p->graphic_alt);
3537   pterrain->movement_cost = p->movement_cost;
3538   pterrain->defense_bonus = p->defense_bonus;
3539 
3540   output_type_iterate(o) {
3541     pterrain->output[o] = p->output[o];
3542   } output_type_iterate_end;
3543 
3544   if (pterrain->resources != NULL) {
3545     free(pterrain->resources);
3546   }
3547   pterrain->resources = fc_calloc(p->num_resources + 1,
3548 				  sizeof(*pterrain->resources));
3549   for (j = 0; j < p->num_resources; j++) {
3550     pterrain->resources[j] = resource_by_number(p->resources[j]);
3551     if (!pterrain->resources[j]) {
3552       log_error("handle_ruleset_terrain() "
3553                 "Mismatched resource %d for terrain \"%s\".",
3554                 p->resources[j], terrain_rule_name(pterrain));
3555     }
3556   }
3557   pterrain->resources[p->num_resources] = NULL;
3558 
3559   output_type_iterate(o) {
3560     pterrain->road_output_incr_pct[o] = p->road_output_incr_pct[o];
3561   } output_type_iterate_end;
3562 
3563   pterrain->base_time = p->base_time;
3564   pterrain->road_time = p->road_time;
3565   pterrain->irrigation_result = terrain_by_number(p->irrigation_result);
3566   pterrain->irrigation_food_incr = p->irrigation_food_incr;
3567   pterrain->irrigation_time = p->irrigation_time;
3568   pterrain->mining_result = terrain_by_number(p->mining_result);
3569   pterrain->mining_shield_incr = p->mining_shield_incr;
3570   pterrain->mining_time = p->mining_time;
3571   if (p->animal < 0) {
3572     pterrain->animal = NULL;
3573   } else {
3574     pterrain->animal = utype_by_number(p->animal);
3575   }
3576   pterrain->transform_result = terrain_by_number(p->transform_result);
3577   pterrain->transform_time = p->transform_time;
3578   pterrain->pillage_time = p->pillage_time;
3579   pterrain->clean_pollution_time = p->clean_pollution_time;
3580   pterrain->clean_fallout_time = p->clean_fallout_time;
3581 
3582   pterrain->flags = p->flags;
3583 
3584   fc_assert_ret(pterrain->rgb == NULL);
3585   pterrain->rgb = rgbcolor_new(p->color_red, p->color_green, p->color_blue);
3586 
3587   PACKET_STRVEC_EXTRACT(pterrain->helptext, p->helptext);
3588 
3589   tileset_setup_tile_type(tileset, pterrain);
3590 }
3591 
3592 /****************************************************************************
3593   Packet ruleset_terrain_flag handler.
3594 ****************************************************************************/
handle_ruleset_terrain_flag(const struct packet_ruleset_terrain_flag * p)3595 void handle_ruleset_terrain_flag(const struct packet_ruleset_terrain_flag *p)
3596 {
3597   const char *flagname;
3598   const char *helptxt;
3599 
3600   fc_assert_ret_msg(p->id >= TER_USER_1 && p->id <= TER_USER_LAST, "Bad user flag %d.", p->id);
3601 
3602   if (p->name[0] == '\0') {
3603     flagname = NULL;
3604   } else {
3605     flagname = p->name;
3606   }
3607 
3608   if (p->helptxt[0] == '\0') {
3609     helptxt = NULL;
3610   } else {
3611     helptxt = p->helptxt;
3612   }
3613 
3614   set_user_terrain_flag_name(p->id, flagname, helptxt);
3615 }
3616 
3617 /****************************************************************************
3618   Handle a packet about a particular terrain resource.
3619 ****************************************************************************/
handle_ruleset_resource(const struct packet_ruleset_resource * p)3620 void handle_ruleset_resource(const struct packet_ruleset_resource *p)
3621 {
3622   struct resource *presource = resource_by_number(p->id);
3623 
3624   fc_assert_ret_msg(NULL != presource, "Bad resource %d.", p->id);
3625 
3626   names_set(&presource->name, NULL, p->name, p->rule_name);
3627   sz_strlcpy(presource->graphic_str, p->graphic_str);
3628   sz_strlcpy(presource->graphic_alt, p->graphic_alt);
3629 
3630   output_type_iterate(o) {
3631     presource->output[o] = p->output[o];
3632   } output_type_iterate_end;
3633 
3634   tileset_setup_resource(tileset, presource);
3635 }
3636 
3637 /****************************************************************************
3638   Handle a packet about a particular extra type.
3639 ****************************************************************************/
handle_ruleset_extra(const struct packet_ruleset_extra * p)3640 void handle_ruleset_extra(const struct packet_ruleset_extra *p)
3641 {
3642   struct extra_type *pextra = extra_by_number(p->id);
3643   int i;
3644   bool cbase;
3645   bool croad;
3646 
3647   fc_assert_ret_msg(NULL != pextra, "Bad extra %d.", p->id);
3648 
3649   names_set(&pextra->name, NULL, p->name, p->rule_name);
3650 
3651   pextra->category = p->category;
3652   pextra->causes = p->causes;
3653   pextra->rmcauses = p->rmcauses;
3654 
3655   if (pextra->causes == 0) {
3656     extra_to_caused_by_list(pextra, EC_NONE);
3657   } else {
3658     for (i = 0; i < EC_COUNT; i++) {
3659       if (is_extra_caused_by(pextra, i)) {
3660         extra_to_caused_by_list(pextra, i);
3661       }
3662     }
3663   }
3664 
3665   cbase = is_extra_caused_by(pextra, EC_BASE);
3666   croad = is_extra_caused_by(pextra, EC_ROAD);
3667   if (cbase) {
3668     /* Index is one less than size of list when this base is already added. */
3669     base_type_init(pextra, extra_type_list_size(extra_type_list_by_cause(EC_BASE)) - 1);
3670   }
3671   if (croad) {
3672     /* Index is one less than size of list when this road is already added. */
3673     road_type_init(pextra, extra_type_list_size(extra_type_list_by_cause(EC_ROAD)) - 1);
3674   }
3675   if (!cbase && !croad) {
3676     pextra->data.special_idx = extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL));
3677     extra_to_caused_by_list(pextra, EC_SPECIAL);
3678   }
3679 
3680   for (i = 0; i < ERM_COUNT; i++) {
3681     if (is_extra_removed_by(pextra, i)) {
3682       extra_to_removed_by_list(pextra, i);
3683     }
3684   }
3685 
3686   sz_strlcpy(pextra->activity_gfx, p->activity_gfx);
3687   sz_strlcpy(pextra->act_gfx_alt, p->act_gfx_alt);
3688   sz_strlcpy(pextra->act_gfx_alt2, p->act_gfx_alt2);
3689   sz_strlcpy(pextra->rmact_gfx, p->rmact_gfx);
3690   sz_strlcpy(pextra->rmact_gfx_alt, p->rmact_gfx_alt);
3691   sz_strlcpy(pextra->graphic_str, p->graphic_str);
3692   sz_strlcpy(pextra->graphic_alt, p->graphic_alt);
3693 
3694   for (i = 0; i < p->reqs_count; i++) {
3695     requirement_vector_append(&pextra->reqs, p->reqs[i]);
3696   }
3697   fc_assert(pextra->reqs.size == p->reqs_count);
3698 
3699   for (i = 0; i < p->rmreqs_count; i++) {
3700     requirement_vector_append(&pextra->rmreqs, p->rmreqs[i]);
3701   }
3702   fc_assert(pextra->rmreqs.size == p->rmreqs_count);
3703 
3704   pextra->buildable = p->buildable;
3705   pextra->build_time = p->build_time;
3706   pextra->build_time_factor = p->build_time_factor;
3707   pextra->removal_time = p->removal_time;
3708   pextra->removal_time_factor = p->removal_time_factor;
3709   pextra->defense_bonus = p->defense_bonus;
3710 
3711   if (pextra->defense_bonus != 0) {
3712     if (extra_has_flag(pextra, EF_NATURAL_DEFENSE)) {
3713       extra_to_caused_by_list(pextra, EC_NATURAL_DEFENSIVE);
3714     } else {
3715       extra_to_caused_by_list(pextra, EC_DEFENSIVE);
3716     }
3717   }
3718 
3719   pextra->native_to = p->native_to;
3720 
3721   pextra->flags = p->flags;
3722   pextra->hidden_by = p->hidden_by;
3723   pextra->conflicts = p->conflicts;
3724 
3725   PACKET_STRVEC_EXTRACT(pextra->helptext, p->helptext);
3726 
3727   tileset_setup_extra(tileset, pextra);
3728 }
3729 
3730 /****************************************************************************
3731   Handle a packet about a particular base type.
3732 ****************************************************************************/
handle_ruleset_base(const struct packet_ruleset_base * p)3733 void handle_ruleset_base(const struct packet_ruleset_base *p)
3734 {
3735   struct base_type *pbase = base_by_number(p->id);
3736 
3737   fc_assert_ret_msg(NULL != pbase, "Bad base %d.", p->id);
3738 
3739   pbase->gui_type = p->gui_type;
3740   pbase->border_sq  = p->border_sq;
3741   pbase->vision_main_sq = p->vision_main_sq;
3742   pbase->vision_invis_sq = p->vision_invis_sq;
3743 
3744   pbase->flags = p->flags;
3745 }
3746 
3747 /****************************************************************************
3748   Handle a packet about a particular road type.
3749 ****************************************************************************/
handle_ruleset_road(const struct packet_ruleset_road * p)3750 void handle_ruleset_road(const struct packet_ruleset_road *p)
3751 {
3752   int i;
3753   struct road_type *proad = road_by_number(p->id);
3754 
3755   fc_assert_ret_msg(NULL != proad, "Bad road %d.", p->id);
3756 
3757   for (i = 0; i < p->first_reqs_count; i++) {
3758     requirement_vector_append(&proad->first_reqs, p->first_reqs[i]);
3759   }
3760   fc_assert(proad->first_reqs.size == p->first_reqs_count);
3761 
3762   proad->move_cost = p->move_cost;
3763   proad->move_mode = p->move_mode;
3764 
3765   output_type_iterate(o) {
3766     proad->tile_incr_const[o] = p->tile_incr_const[o];
3767     proad->tile_incr[o] = p->tile_incr[o];
3768     proad->tile_bonus[o] = p->tile_bonus[o];
3769   } output_type_iterate_end;
3770 
3771   proad->compat = p->compat;
3772   proad->integrates = p->integrates;
3773   proad->flags = p->flags;
3774 }
3775 
3776 /**************************************************************************
3777   Handle a packet about a particular action.
3778 **************************************************************************/
handle_ruleset_action(const struct packet_ruleset_action * p)3779 void handle_ruleset_action(const struct packet_ruleset_action *p)
3780 {
3781   struct action *act;
3782 
3783   /* Action id is currently hard coded in the gen_action enum. It is
3784    * therefore OK to use action_id_is_valid() */
3785   if (!action_id_is_valid(p->id)) {
3786     /* Action id out of range */
3787     log_error("handle_ruleset_action() the action id %d is out of range.",
3788               p->id);
3789 
3790     return;
3791   }
3792 
3793   act = action_by_number(p->id);
3794 
3795   sz_strlcpy(act->ui_name, p->ui_name);
3796   act->quiet = p->quiet;
3797 }
3798 
3799 /****************************************************************************
3800   Handle a packet about a particular action enabler.
3801 ****************************************************************************/
3802 void
handle_ruleset_action_enabler(const struct packet_ruleset_action_enabler * p)3803 handle_ruleset_action_enabler(const struct packet_ruleset_action_enabler *p)
3804 {
3805   struct action_enabler *enabler;
3806   int i;
3807 
3808   if (!action_id_is_valid(p->enabled_action)) {
3809     /* Non existing action */
3810     log_error("handle_ruleset_action_enabler() the action %d "
3811               "doesn't exist.",
3812               p->enabled_action);
3813 
3814     return;
3815   }
3816 
3817   enabler = action_enabler_new();
3818 
3819   enabler->action = p->enabled_action;
3820 
3821   for (i = 0; i < p->actor_reqs_count; i++) {
3822     requirement_vector_append(&enabler->actor_reqs, p->actor_reqs[i]);
3823   }
3824   fc_assert(enabler->actor_reqs.size == p->actor_reqs_count);
3825 
3826   for (i = 0; i < p->target_reqs_count; i++) {
3827     requirement_vector_append(&enabler->target_reqs, p->target_reqs[i]);
3828   }
3829   fc_assert(enabler->target_reqs.size == p->target_reqs_count);
3830 
3831   action_enabler_add(enabler);
3832 }
3833 
3834 /****************************************************************************
3835   Handle a packet about a particular disaster type.
3836 ****************************************************************************/
handle_ruleset_disaster(const struct packet_ruleset_disaster * p)3837 void handle_ruleset_disaster(const struct packet_ruleset_disaster *p)
3838 {
3839   struct disaster_type *pdis = disaster_by_number(p->id);
3840   int i;
3841 
3842   fc_assert_ret_msg(NULL != pdis, "Bad disaster %d.", p->id);
3843 
3844   names_set(&pdis->name, NULL, p->name, p->rule_name);
3845 
3846   for (i = 0; i < p->reqs_count; i++) {
3847     requirement_vector_append(&pdis->reqs, p->reqs[i]);
3848   }
3849   fc_assert(pdis->reqs.size == p->reqs_count);
3850 
3851   pdis->frequency = p->frequency;
3852 
3853   pdis->effects = p->effects;
3854 }
3855 
3856 /****************************************************************************
3857   Handle a packet about a particular achievement type.
3858 ****************************************************************************/
handle_ruleset_achievement(const struct packet_ruleset_achievement * p)3859 void handle_ruleset_achievement(const struct packet_ruleset_achievement *p)
3860 {
3861   struct achievement *pach = achievement_by_number(p->id);
3862 
3863   fc_assert_ret_msg(NULL != pach, "Bad achievement %d.", p->id);
3864 
3865   names_set(&pach->name, NULL, p->name, p->rule_name);
3866 
3867   pach->type = p->type;
3868   pach->unique = p->unique;
3869   pach->value = p->value;
3870 }
3871 
3872 /****************************************************************************
3873   Handle a packet about a particular trade route type.
3874 ****************************************************************************/
handle_ruleset_trade(const struct packet_ruleset_trade * p)3875 void handle_ruleset_trade(const struct packet_ruleset_trade *p)
3876 {
3877   struct trade_route_settings *pset = trade_route_settings_by_type(p->id);
3878 
3879   if (pset != NULL) {
3880     pset->trade_pct  = p->trade_pct;
3881     pset->cancelling = p->cancelling;
3882     pset->bonus_type = p->bonus_type;
3883   }
3884 }
3885 
3886 /****************************************************************************
3887   Handle the terrain control ruleset packet sent by the server.
3888 ****************************************************************************/
handle_ruleset_terrain_control(const struct packet_ruleset_terrain_control * p)3889 void handle_ruleset_terrain_control
3890     (const struct packet_ruleset_terrain_control *p)
3891 {
3892   /* Since terrain_control is the same as packet_ruleset_terrain_control
3893    * we can just copy the data directly. */
3894   terrain_control = *p;
3895   /* terrain_control.move_fragments likely changed */
3896   init_move_fragments();
3897 }
3898 
3899 /****************************************************************************
3900   Handle the list of nation sets, sent as part of the ruleset.
3901 ****************************************************************************/
handle_ruleset_nation_sets(const struct packet_ruleset_nation_sets * packet)3902 void handle_ruleset_nation_sets
3903     (const struct packet_ruleset_nation_sets *packet)
3904 {
3905   int i;
3906 
3907   for (i = 0; i < packet->nsets; i++) {
3908     struct nation_set *pset;
3909 
3910     pset = nation_set_new(packet->names[i], packet->rule_names[i],
3911                           packet->descriptions[i]);
3912     fc_assert(NULL != pset);
3913     fc_assert(i == nation_set_index(pset));
3914   }
3915 }
3916 
3917 /****************************************************************************
3918   Handle the list of nation groups, sent as part of the ruleset.
3919 ****************************************************************************/
handle_ruleset_nation_groups(const struct packet_ruleset_nation_groups * packet)3920 void handle_ruleset_nation_groups
3921     (const struct packet_ruleset_nation_groups *packet)
3922 {
3923   int i;
3924 
3925   for (i = 0; i < packet->ngroups; i++) {
3926     struct nation_group *pgroup;
3927 
3928     pgroup = nation_group_new(packet->groups[i]);
3929     fc_assert_action(NULL != pgroup, continue);
3930     fc_assert(i == nation_group_index(pgroup));
3931     pgroup->hidden = packet->hidden[i];
3932   }
3933 }
3934 
3935 /****************************************************************************
3936   Handle initial ruleset nation info.
3937 ****************************************************************************/
handle_ruleset_nation(const struct packet_ruleset_nation * packet)3938 void handle_ruleset_nation(const struct packet_ruleset_nation *packet)
3939 {
3940   struct nation_type *pnation = nation_by_number(packet->id);
3941   int i;
3942 
3943   fc_assert_ret_msg(NULL != pnation, "Bad nation %d.", packet->id);
3944 
3945   if (packet->translation_domain[0] != '\0') {
3946     size_t len = strlen(packet->translation_domain) + 1;
3947     pnation->translation_domain = fc_malloc(len);
3948     fc_strlcpy(pnation->translation_domain, packet->translation_domain, len);
3949   } else {
3950     pnation->translation_domain = NULL;
3951   }
3952   names_set(&pnation->adjective, pnation->translation_domain,
3953             packet->adjective, packet->rule_name);
3954   name_set(&pnation->noun_plural, pnation->translation_domain, packet->noun_plural);
3955   sz_strlcpy(pnation->flag_graphic_str, packet->graphic_str);
3956   sz_strlcpy(pnation->flag_graphic_alt, packet->graphic_alt);
3957   pnation->style = style_by_number(packet->style);
3958   for (i = 0; i < packet->leader_count; i++) {
3959     (void) nation_leader_new(pnation, packet->leader_name[i],
3960                              packet->leader_is_male[i]);
3961   }
3962 
3963   /* set later by PACKET_NATION_AVAILABILITY */
3964   pnation->client.is_pickable = FALSE;
3965   pnation->is_playable = packet->is_playable;
3966   pnation->barb_type = packet->barbarian_type;
3967 
3968   if ('\0' != packet->legend[0]) {
3969     pnation->legend = fc_strdup(nation_legend_translation(pnation, packet->legend));
3970   } else {
3971     pnation->legend = fc_strdup("");
3972   }
3973 
3974   for (i = 0; i < packet->nsets; i++) {
3975     struct nation_set *pset = nation_set_by_number(packet->sets[i]);
3976 
3977     if (NULL != pset) {
3978       nation_set_list_append(pnation->sets, pset);
3979     } else {
3980       log_error("handle_ruleset_nation() \"%s\" have unknown set %d.",
3981                 nation_rule_name(pnation), packet->sets[i]);
3982     }
3983   }
3984 
3985   for (i = 0; i < packet->ngroups; i++) {
3986     struct nation_group *pgroup = nation_group_by_number(packet->groups[i]);
3987 
3988     if (NULL != pgroup) {
3989       nation_group_list_append(pnation->groups, pgroup);
3990     } else {
3991       log_error("handle_ruleset_nation() \"%s\" have unknown group %d.",
3992                 nation_rule_name(pnation), packet->groups[i]);
3993     }
3994   }
3995 
3996   /* init_government may be NULL */
3997   pnation->init_government = government_by_number(packet->init_government_id);
3998   for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
3999     pnation->init_techs[i] = packet->init_techs[i];
4000   }
4001   for (i = 0; i < MAX_NUM_UNIT_LIST; i++) {
4002     pnation->init_units[i] = utype_by_number(packet->init_units[i]);
4003   }
4004   for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
4005     pnation->init_buildings[i] = packet->init_buildings[i];
4006   }
4007 
4008   tileset_setup_nation_flag(tileset, pnation);
4009 }
4010 
4011 /****************************************************************************
4012   Handle nation availability info.
4013   This can change during pregame so is separate from ruleset_nation.
4014 ****************************************************************************/
handle_nation_availability(int ncount,const bool * is_pickable,bool nationset_change)4015 void handle_nation_availability(int ncount, const bool *is_pickable,
4016                                 bool nationset_change)
4017 {
4018   int i;
4019 
4020   fc_assert_action(ncount == nation_count(),
4021                    ncount = MIN(ncount, nation_count()));
4022 
4023   for (i = 0; i < ncount; i++) {
4024     nation_by_number(i)->client.is_pickable = is_pickable[i];
4025   }
4026 
4027   races_update_pickable(nationset_change);
4028 }
4029 
4030 /****************************************************************************
4031   Handle a packet about a particular style.
4032 ****************************************************************************/
handle_ruleset_style(const struct packet_ruleset_style * p)4033 void handle_ruleset_style(const struct packet_ruleset_style *p)
4034 {
4035   struct nation_style *pstyle = style_by_number(p->id);
4036 
4037   fc_assert_ret_msg(NULL != pstyle, "Bad style %d.", p->id);
4038 
4039   names_set(&pstyle->name, NULL, p->name, p->rule_name);
4040 }
4041 
4042 /**************************************************************************
4043   Handle city style packet.
4044 **************************************************************************/
handle_ruleset_city(const struct packet_ruleset_city * packet)4045 void handle_ruleset_city(const struct packet_ruleset_city *packet)
4046 {
4047   int id, j;
4048   struct citystyle *cs;
4049 
4050   id = packet->style_id;
4051   fc_assert_ret_msg(0 <= id && game.control.styles_count > id,
4052                     "Bad citystyle %d.", id);
4053   cs = &city_styles[id];
4054 
4055   for (j = 0; j < packet->reqs_count; j++) {
4056     requirement_vector_append(&cs->reqs, packet->reqs[j]);
4057   }
4058   fc_assert(cs->reqs.size == packet->reqs_count);
4059 
4060   names_set(&cs->name, NULL, packet->name, packet->rule_name);
4061   sz_strlcpy(cs->graphic, packet->graphic);
4062   sz_strlcpy(cs->graphic_alt, packet->graphic_alt);
4063   sz_strlcpy(cs->citizens_graphic, packet->citizens_graphic);
4064   sz_strlcpy(cs->citizens_graphic_alt, packet->citizens_graphic_alt);
4065 
4066   tileset_setup_city_tiles(tileset, id);
4067 }
4068 
4069 /**************************************************************************
4070   Handle music style packet.
4071 **************************************************************************/
handle_ruleset_music(const struct packet_ruleset_music * packet)4072 void handle_ruleset_music(const struct packet_ruleset_music *packet)
4073 {
4074   int id, j;
4075   struct music_style *pmus;
4076 
4077   id = packet->id;
4078   fc_assert_ret_msg(0 <= id && game.control.num_music_styles > id,
4079                     "Bad music_style %d.", id);
4080 
4081   pmus = music_style_by_number(id);
4082 
4083   for (j = 0; j < packet->reqs_count; j++) {
4084     requirement_vector_append(&pmus->reqs, packet->reqs[j]);
4085   }
4086   fc_assert(pmus->reqs.size == packet->reqs_count);
4087 
4088   sz_strlcpy(pmus->music_peaceful, packet->music_peaceful);
4089   sz_strlcpy(pmus->music_combat, packet->music_combat);
4090 }
4091 
4092 /****************************************************************************
4093   Packet ruleset_game handler.
4094 ****************************************************************************/
handle_ruleset_game(const struct packet_ruleset_game * packet)4095 void handle_ruleset_game(const struct packet_ruleset_game *packet)
4096 {
4097   int i;
4098 
4099   /* Must set num_specialist_types before iterating over them. */
4100   DEFAULT_SPECIALIST = packet->default_specialist;
4101 
4102   fc_assert_ret(packet->veteran_levels > 0);
4103 
4104   game.veteran = veteran_system_new(packet->veteran_levels);
4105   game.veteran->levels = packet->veteran_levels;
4106 
4107   for (i = 0; i < MAX_NUM_TECH_LIST; i++) {
4108     game.rgame.global_init_techs[i] = packet->global_init_techs[i];
4109   }
4110   for (i = 0; i < MAX_NUM_BUILDING_LIST; i++) {
4111     game.rgame.global_init_buildings[i] = packet->global_init_buildings[i];
4112   }
4113 
4114   for (i = 0; i < packet->veteran_levels; i++) {
4115     veteran_system_definition(game.veteran, i, packet->veteran_name[i],
4116                               packet->power_fact[i], packet->move_bonus[i],
4117                               0, 0);
4118   }
4119 
4120   fc_assert(game.plr_bg_color == NULL);
4121   game.plr_bg_color = rgbcolor_new(packet->background_red,
4122                                    packet->background_green,
4123                                    packet->background_blue);
4124 
4125   tileset_background_init(tileset);
4126 }
4127 
4128 /****************************************************************************
4129   Handle info about a single specialist.
4130 ****************************************************************************/
handle_ruleset_specialist(const struct packet_ruleset_specialist * p)4131 void handle_ruleset_specialist(const struct packet_ruleset_specialist *p)
4132 {
4133   int j;
4134   struct specialist *s = specialist_by_number(p->id);
4135 
4136   fc_assert_ret_msg(NULL != s, "Bad specialist %d.", p->id);
4137 
4138   names_set(&s->name, NULL, p->plural_name, p->rule_name);
4139   name_set(&s->abbreviation, NULL, p->short_name);
4140 
4141   sz_strlcpy(s->graphic_alt, p->graphic_alt);
4142 
4143   for (j = 0; j < p->reqs_count; j++) {
4144     requirement_vector_append(&s->reqs, p->reqs[j]);
4145   }
4146   fc_assert(s->reqs.size == p->reqs_count);
4147 
4148   PACKET_STRVEC_EXTRACT(s->helptext, p->helptext);
4149 
4150   tileset_setup_specialist_type(tileset, p->id);
4151 }
4152 
4153 /**************************************************************************
4154   Handle reply to our city name request.
4155 **************************************************************************/
handle_city_name_suggestion_info(int unit_id,const char * name)4156 void handle_city_name_suggestion_info(int unit_id, const char *name)
4157 {
4158   struct unit *punit = player_unit_by_number(client_player(), unit_id);
4159 
4160   if (!can_client_issue_orders()) {
4161     return;
4162   }
4163 
4164   if (punit) {
4165     if (gui_options.ask_city_name) {
4166       bool other_asking = FALSE;
4167 
4168       unit_list_iterate(unit_tile(punit)->units, other) {
4169         if (other->client.asking_city_name) {
4170           other_asking = TRUE;
4171         }
4172       } unit_list_iterate_end;
4173       punit->client.asking_city_name = TRUE;
4174 
4175       if (!other_asking) {
4176         popup_newcity_dialog(punit, name);
4177       }
4178     } else {
4179       dsend_packet_unit_build_city(&client.conn, unit_id, name);
4180     }
4181   }
4182 }
4183 
4184 /**************************************************************************
4185   Handle the requested follow up question about an action
4186 
4187   The action can be a valid action or the special value ACTION_COUNT.
4188   ACTION_COUNT indicates that performing the action is impossible.
4189 **************************************************************************/
handle_unit_action_answer(int diplomat_id,int target_id,int cost,enum gen_action action_type)4190 void handle_unit_action_answer(int diplomat_id, int target_id, int cost,
4191                                enum gen_action action_type)
4192 {
4193   struct city *pcity = game_city_by_number(target_id);
4194   struct unit *punit = game_unit_by_number(target_id);
4195   struct unit *pdiplomat = player_unit_by_number(client_player(),
4196                                                  diplomat_id);
4197 
4198   if (ACTION_COUNT != action_type
4199       && !action_id_is_valid(action_type)) {
4200     /* Non existing action */
4201     log_error("handle_unit_action_answer() the action %d doesn't exist.",
4202               action_type);
4203 
4204     action_selection_no_longer_in_progress(diplomat_id);
4205     action_decision_clear_want(diplomat_id);
4206     action_selection_next_in_focus(diplomat_id);
4207     return;
4208   }
4209 
4210   if (!pdiplomat) {
4211     log_debug("Bad actor %d.", diplomat_id);
4212 
4213     action_selection_no_longer_in_progress(diplomat_id);
4214     action_selection_next_in_focus(diplomat_id);
4215     return;
4216   }
4217 
4218   switch (action_type) {
4219   case ACTION_SPY_BRIBE_UNIT:
4220     if (punit && client.conn.playing
4221         && !client.conn.playing->ai_controlled) {
4222       /* Focus on the unit so the player knows where it is */
4223       unit_focus_set(pdiplomat);
4224 
4225       popup_bribe_dialog(pdiplomat, punit, cost);
4226     } else {
4227       log_debug("Bad target %d.", target_id);
4228       action_selection_no_longer_in_progress(diplomat_id);
4229       action_decision_clear_want(diplomat_id);
4230       action_selection_next_in_focus(diplomat_id);
4231     }
4232     break;
4233   case ACTION_SPY_INCITE_CITY:
4234     if (pcity && client.conn.playing
4235         && !client.conn.playing->ai_controlled) {
4236       /* Focus on the unit so the player knows where it is */
4237       unit_focus_set(pdiplomat);
4238 
4239       popup_incite_dialog(pdiplomat, pcity, cost);
4240     } else {
4241       log_debug("Bad target %d.", target_id);
4242       action_selection_no_longer_in_progress(diplomat_id);
4243       action_decision_clear_want(diplomat_id);
4244       action_selection_next_in_focus(diplomat_id);
4245     }
4246     break;
4247   case ACTION_COUNT:
4248     log_debug("Server didn't respond to query.");
4249     action_selection_no_longer_in_progress(diplomat_id);
4250     action_decision_clear_want(diplomat_id);
4251     action_selection_next_in_focus(diplomat_id);
4252     break;
4253   default:
4254     log_error("handle_unit_action_answer() invalid action_type (%d).",
4255               action_type);
4256     action_selection_no_longer_in_progress(diplomat_id);
4257     action_decision_clear_want(diplomat_id);
4258     action_selection_next_in_focus(diplomat_id);
4259     break;
4260   };
4261 }
4262 
4263 /**************************************************************************
4264   Handle reply to possible actions.
4265 
4266   Note that a reply to a foreground request (a reply where disturb_player
4267   is true) must result in its clean up.
4268 **************************************************************************/
handle_unit_actions(const struct packet_unit_actions * packet)4269 void handle_unit_actions(const struct packet_unit_actions *packet)
4270 {
4271   struct unit *actor_unit = game_unit_by_number(packet->actor_unit_id);
4272 
4273   struct tile *target_tile = index_to_tile(packet->target_tile_id);
4274   struct city *target_city = game_city_by_number(packet->target_city_id);
4275   struct unit *target_unit = game_unit_by_number(packet->target_unit_id);
4276 
4277   const struct act_prob *act_probs = packet->action_probabilities;
4278 
4279   bool disturb_player = packet->disturb_player;
4280   bool valid = FALSE;
4281 
4282   /* The dead can't act */
4283   if (actor_unit && target_tile && (target_city || target_unit)) {
4284     /* At least one action must be possible */
4285     action_iterate(act) {
4286       if (action_prob_possible(act_probs[act])) {
4287         valid = TRUE;
4288         break;
4289       }
4290     } action_iterate_end;
4291   }
4292 
4293   if (valid && disturb_player) {
4294     /* The player can select an action and should be informed. */
4295 
4296     /* Show the client specific action dialog */
4297     popup_action_selection(actor_unit,
4298                            target_city, target_unit, target_tile,
4299                            act_probs);
4300   } else if (disturb_player) {
4301     /* Nothing to do. */
4302     action_selection_no_longer_in_progress(packet->actor_unit_id);
4303     action_decision_clear_want(packet->actor_unit_id);
4304     action_selection_next_in_focus(packet->actor_unit_id);
4305   } else {
4306     /* This was a background request. */
4307 
4308     if (action_selection_actor_unit() == actor_unit->id) {
4309       /* The situation may have changed. */
4310       action_selection_refresh(actor_unit,
4311                                target_city, target_unit, target_tile,
4312                                act_probs);
4313     }
4314   }
4315 }
4316 
4317 /**************************************************************************
4318   Handle list of potenttial buildings to sabotage.
4319 **************************************************************************/
handle_city_sabotage_list(int diplomat_id,int city_id,bv_imprs improvements)4320 void handle_city_sabotage_list(int diplomat_id, int city_id,
4321                                bv_imprs improvements)
4322 {
4323   struct city *pcity = game_city_by_number(city_id);
4324   struct unit *pdiplomat = player_unit_by_number(client_player(),
4325                                                  diplomat_id);
4326 
4327   if (!pdiplomat) {
4328     log_debug("Bad diplomat %d.", diplomat_id);
4329 
4330     action_selection_no_longer_in_progress(diplomat_id);
4331     action_selection_next_in_focus(diplomat_id);
4332     return;
4333   }
4334 
4335   if (!pcity) {
4336     log_debug("Bad city %d.", city_id);
4337 
4338     action_selection_no_longer_in_progress(diplomat_id);
4339     action_decision_clear_want(diplomat_id);
4340     action_selection_next_in_focus(diplomat_id);
4341     return;
4342   }
4343 
4344   if (can_client_issue_orders()) {
4345     improvement_iterate(pimprove) {
4346       update_improvement_from_packet(pcity, pimprove,
4347                                      BV_ISSET(improvements,
4348                                               improvement_index(pimprove)));
4349     } improvement_iterate_end;
4350 
4351     /* Focus on the unit so the player knows where it is */
4352     unit_focus_set(pdiplomat);
4353 
4354     popup_sabotage_dialog(pdiplomat, pcity);
4355   } else {
4356     log_debug("Can't issue orders");
4357     action_selection_no_longer_in_progress(diplomat_id);
4358     action_decision_clear_want(diplomat_id);
4359   }
4360 }
4361 
4362 /****************************************************************************
4363   Pass the header information about things be displayed in a gui-specific
4364   endgame dialog.
4365 ****************************************************************************/
handle_endgame_report(const struct packet_endgame_report * packet)4366 void handle_endgame_report(const struct packet_endgame_report *packet)
4367 {
4368   set_client_state(C_S_OVER);
4369   endgame_report_dialog_start(packet);
4370 }
4371 
4372 /****************************************************************************
4373   Pass endgame report about single player.
4374 ****************************************************************************/
handle_endgame_player(const struct packet_endgame_player * packet)4375 void handle_endgame_player(const struct packet_endgame_player *packet)
4376 {
4377   if (client_has_player()
4378       && packet->player_id == player_number(client_player())) {
4379     if (packet->winner) {
4380       start_menu_music("music_victory", NULL);
4381     } else {
4382       start_menu_music("music_defeat", NULL);
4383     }
4384   }
4385   endgame_report_dialog_player(packet);
4386 }
4387 
4388 /****************************************************************************
4389   Packet player_attribute_chunk handler.
4390 ****************************************************************************/
handle_player_attribute_chunk(const struct packet_player_attribute_chunk * packet)4391 void handle_player_attribute_chunk
4392     (const struct packet_player_attribute_chunk *packet)
4393 {
4394   if (!client_has_player()) {
4395     return;
4396   }
4397 
4398   generic_handle_player_attribute_chunk(client_player(), packet);
4399 
4400   if (packet->offset + packet->chunk_length == packet->total_length) {
4401     /* We successful received the last chunk. The attribute block is
4402        now complete. */
4403       attribute_restore();
4404   }
4405 }
4406 
4407 /**************************************************************************
4408   Handle request to start processing packet.
4409 **************************************************************************/
handle_processing_started(void)4410 void handle_processing_started(void)
4411 {
4412   agents_processing_started();
4413 
4414   fc_assert(client.conn.client.request_id_of_currently_handled_packet == 0);
4415   client.conn.client.request_id_of_currently_handled_packet =
4416       get_next_request_id(client.conn.
4417                           client.last_processed_request_id_seen);
4418   update_queue_processing_started(client.conn.client.
4419                                   request_id_of_currently_handled_packet);
4420 
4421   log_debug("start processing packet %d",
4422             client.conn.client.request_id_of_currently_handled_packet);
4423 }
4424 
4425 /**************************************************************************
4426   Handle request to stop processing packet.
4427 **************************************************************************/
handle_processing_finished(void)4428 void handle_processing_finished(void)
4429 {
4430   log_debug("finish processing packet %d",
4431             client.conn.client.request_id_of_currently_handled_packet);
4432 
4433   fc_assert(client.conn.client.request_id_of_currently_handled_packet != 0);
4434 
4435   client.conn.client.last_processed_request_id_seen =
4436       client.conn.client.request_id_of_currently_handled_packet;
4437   update_queue_processing_finished(client.conn.client.
4438                                    last_processed_request_id_seen);
4439 
4440   client.conn.client.request_id_of_currently_handled_packet = 0;
4441 
4442   agents_processing_finished();
4443 }
4444 
4445 /**************************************************************************
4446   Notify interested parties about incoming packet.
4447 **************************************************************************/
notify_about_incoming_packet(struct connection * pc,int packet_type,int size)4448 void notify_about_incoming_packet(struct connection *pc,
4449                                   int packet_type, int size)
4450 {
4451   fc_assert(pc == &client.conn);
4452   log_debug("incoming packet={type=%d, size=%d}", packet_type, size);
4453 }
4454 
4455 /**************************************************************************
4456   Notify interested parties about outgoing packet.
4457 **************************************************************************/
notify_about_outgoing_packet(struct connection * pc,int packet_type,int size,int request_id)4458 void notify_about_outgoing_packet(struct connection *pc,
4459                                   int packet_type, int size,
4460                                   int request_id)
4461 {
4462   fc_assert(pc == &client.conn);
4463   log_debug("outgoing packet={type=%d, size=%d, request_id=%d}",
4464             packet_type, size, request_id);
4465 
4466   fc_assert(request_id);
4467 }
4468 
4469 /**************************************************************************
4470   We have received PACKET_FREEZE_CLIENT.
4471 **************************************************************************/
handle_freeze_client(void)4472 void handle_freeze_client(void)
4473 {
4474   log_debug("handle_freeze_client");
4475 
4476   agents_freeze_hint();
4477 }
4478 
4479 /**************************************************************************
4480   We have received PACKET_THAW_CLIENT
4481 **************************************************************************/
handle_thaw_client(void)4482 void handle_thaw_client(void)
4483 {
4484   log_debug("handle_thaw_client");
4485 
4486   agents_thaw_hint();
4487   update_turn_done_button_state();
4488 }
4489 
4490 /**************************************************************************
4491   Reply to 'ping' packet with 'pong'
4492 **************************************************************************/
handle_conn_ping(void)4493 void handle_conn_ping(void)
4494 {
4495   send_packet_conn_pong(&client.conn);
4496 }
4497 
4498 /**************************************************************************
4499   Handle server shutdown.
4500 **************************************************************************/
handle_server_shutdown(void)4501 void handle_server_shutdown(void)
4502 {
4503   log_verbose("server shutdown");
4504 }
4505 
4506 /****************************************************************************
4507   Add effect data to ruleset cache.
4508 ****************************************************************************/
handle_ruleset_effect(const struct packet_ruleset_effect * packet)4509 void handle_ruleset_effect(const struct packet_ruleset_effect *packet)
4510 {
4511   recv_ruleset_effect(packet);
4512 }
4513 
4514 /**************************************************************************
4515   Handle a notification from the server that an object was successfully
4516   created. The 'tag' was previously sent to the server when the client
4517   requested the creation. The 'id' is the identifier of the newly created
4518   object.
4519 **************************************************************************/
handle_edit_object_created(int tag,int id)4520 void handle_edit_object_created(int tag, int id)
4521 {
4522   editgui_notify_object_created(tag, id);
4523 }
4524 
4525  /****************************************************************************
4526   Handle start position creation/removal.
4527 ****************************************************************************/
handle_edit_startpos(const struct packet_edit_startpos * packet)4528 void handle_edit_startpos(const struct packet_edit_startpos *packet)
4529 {
4530   struct tile *ptile = index_to_tile(packet->id);
4531   bool changed = FALSE;
4532 
4533   /* Check. */
4534   if (NULL == ptile) {
4535     log_error("%s(): invalid tile index %d.", __FUNCTION__, packet->id);
4536     return;
4537   }
4538 
4539   /* Handle. */
4540   if (packet->removal) {
4541     changed = map_startpos_remove(ptile);
4542   } else {
4543     if (NULL != map_startpos_get(ptile)) {
4544       changed = FALSE;
4545     } else {
4546       map_startpos_new(ptile);
4547       changed = TRUE;
4548     }
4549   }
4550 
4551   /* Notify. */
4552   if (changed && can_client_change_view()) {
4553     refresh_tile_mapcanvas(ptile, TRUE, FALSE);
4554     if (packet->removal) {
4555       editgui_notify_object_changed(OBJTYPE_STARTPOS,
4556                                     packet->id, TRUE);
4557     } else {
4558       editgui_notify_object_created(packet->tag, packet->id);
4559     }
4560   }
4561 }
4562 
4563 /****************************************************************************
4564   Handle start position internal information.
4565 ****************************************************************************/
handle_edit_startpos_full(const struct packet_edit_startpos_full * packet)4566 void handle_edit_startpos_full(const struct packet_edit_startpos_full *
4567                                packet)
4568 {
4569   struct tile *ptile = index_to_tile(packet->id);
4570   struct startpos *psp;
4571 
4572   /* Check. */
4573   if (NULL == ptile) {
4574     log_error("%s(): invalid tile index %d.", __FUNCTION__, packet->id);
4575     return;
4576   }
4577 
4578   psp = map_startpos_get(ptile);
4579   if (NULL == psp) {
4580     log_error("%s(): no start position at (%d, %d)",
4581               __FUNCTION__, TILE_XY(ptile));
4582     return;
4583   }
4584 
4585   /* Handle. */
4586   if (startpos_unpack(psp, packet) && can_client_change_view()) {
4587     /* Notify. */
4588     refresh_tile_mapcanvas(ptile, TRUE, FALSE);
4589     editgui_notify_object_changed(OBJTYPE_STARTPOS, startpos_number(psp),
4590                                   FALSE);
4591   }
4592 }
4593 
4594 /**************************************************************************
4595   A vote no longer exists. Remove from queue and update gui.
4596 **************************************************************************/
handle_vote_remove(int vote_no)4597 void handle_vote_remove(int vote_no)
4598 {
4599   voteinfo_queue_delayed_remove(vote_no);
4600   voteinfo_gui_update();
4601 }
4602 
4603 /**************************************************************************
4604   Find and update the corresponding vote and refresh the GUI.
4605 **************************************************************************/
handle_vote_update(int vote_no,int yes,int no,int abstain,int num_voters)4606 void handle_vote_update(int vote_no, int yes, int no, int abstain,
4607                         int num_voters)
4608 {
4609   struct voteinfo *vi;
4610 
4611   vi = voteinfo_queue_find(vote_no);
4612   fc_assert_ret_msg(NULL != vi,
4613                     "Got packet_vote_update for non-existant vote %d!",
4614                     vote_no);
4615 
4616   vi->yes = yes;
4617   vi->no = no;
4618   vi->abstain = abstain;
4619   vi->num_voters = num_voters;
4620 
4621   voteinfo_gui_update();
4622 }
4623 
4624 /****************************************************************************
4625   Create a new vote and add it to the queue. Refresh the GUI.
4626 ****************************************************************************/
handle_vote_new(const struct packet_vote_new * packet)4627 void handle_vote_new(const struct packet_vote_new *packet)
4628 {
4629   fc_assert_ret_msg(NULL == voteinfo_queue_find(packet->vote_no),
4630                     "Got a packet_vote_new for already existing "
4631                     "vote %d!", packet->vote_no);
4632 
4633   voteinfo_queue_add(packet->vote_no,
4634                      packet->user,
4635                      packet->desc,
4636                      packet->percent_required,
4637                      packet->flags);
4638   voteinfo_gui_update();
4639 }
4640 
4641 /**************************************************************************
4642   Update the vote's status and refresh the GUI.
4643 **************************************************************************/
handle_vote_resolve(int vote_no,bool passed)4644 void handle_vote_resolve(int vote_no, bool passed)
4645 {
4646   struct voteinfo *vi;
4647 
4648   vi = voteinfo_queue_find(vote_no);
4649   fc_assert_ret_msg(NULL != vi,
4650                     "Got packet_vote_resolve for non-existant vote %d!",
4651                     vote_no);
4652 
4653   vi->resolved = TRUE;
4654   vi->passed = passed;
4655 
4656   voteinfo_gui_update();
4657 }
4658 
4659 /**************************************************************************
4660   Play suitable music
4661 **************************************************************************/
handle_play_music(const char * tag)4662 void handle_play_music(const char *tag)
4663 {
4664   play_single_track(tag);
4665 }
4666