18
18
#include <assert.h>
19
19
#include <string.h>
21
22
#include "capability.h"
22
29
#include "capstr.h"
23
30
#include "events.h"
26
32
#include "government.h"
31
35
#include "nation.h"
32
36
#include "packets.h"
33
37
#include "player.h"
34
38
#include "spaceship.h"
35
39
#include "specialist.h"
38
41
#include "unitlist.h"
39
42
#include "worklist.h"
42
#include "attribute.h"
44
45
#include "chatline_g.h"
45
46
#include "citydlg_g.h"
46
47
#include "cityrep_g.h"
47
#include "civclient.h"
50
#include "clinet.h" /* aconnection */
51
#include "connectdlg_common.h"
52
48
#include "connectdlg_g.h"
54
49
#include "dialogs_g.h"
55
#include "ggzclient.h"
56
#include "goto.h" /* client_goto_init() */
57
#include "graphics_g.h"
50
#include "editgui_g.h"
58
51
#include "gui_main_g.h"
59
#include "helpdata.h" /* boot_help_texts() */
60
52
#include "inteldlg_g.h"
61
#include "mapctrl_g.h" /* popup_newcity_dialog() */
53
#include "mapctrl_g.h" /* popup_newcity_dialog() */
62
54
#include "mapview_g.h"
63
55
#include "menu_g.h"
64
56
#include "messagewin_g.h"
66
#include "overview_common.h"
67
57
#include "pages_g.h"
68
58
#include "plrdlg_g.h"
69
59
#include "repodlgs_g.h"
70
60
#include "spaceshipdlg_g.h"
61
#include "voteinfo_bar_g.h"
66
#include "attribute.h"
68
#include "client_main.h"
71
#include "connectdlg_common.h"
74
#include "ggzclient.h"
75
#include "goto.h" /* client_goto_init() */
76
#include "helpdata.h" /* boot_help_texts() */
77
#include "mapview_common.h"
79
#include "overview_common.h"
71
80
#include "tilespec.h"
72
81
#include "voteinfo.h"
75
83
#include "packhand.h"
77
static void handle_city_packet_common(struct city *pcity, bool is_new,
78
bool popup, bool investigate);
85
static void city_packet_common(struct city *pcity, struct tile *pcenter,
86
struct player *powner,
87
struct tile_list *worked_tiles,
88
bool is_new, bool popup, bool investigate);
79
89
static bool handle_unit_packet_common(struct unit *packet_unit);
80
92
static int *reports_thaw_requests = NULL;
81
93
static int reports_thaw_requests_size = 0;
95
/* The dumbest of cities, placeholders for unknown and unseen cities. */
96
static struct city_list *invisible_cities = NULL;
99
/****************************************************************************
100
Called below, and by client/civclient.c client_game_free()
101
****************************************************************************/
102
void packhand_free(void)
104
if (NULL != invisible_cities) {
105
city_list_iterate(invisible_cities, pcity) {
106
idex_unregister_city(pcity);
107
destroy_city_virtual(pcity);
108
} city_list_iterate_end;
110
city_list_free(invisible_cities);
111
invisible_cities = NULL;
115
/****************************************************************************
116
Called only by handle_map_info() below.
117
****************************************************************************/
118
static void packhand_init(void)
122
invisible_cities = city_list_new();
83
125
/**************************************************************************
84
126
Unpackage the unit information into a newly allocated unit structure.
128
Information for the client must also be processed in
129
handle_unit_packet_common()!
85
130
**************************************************************************/
86
131
static struct unit * unpackage_unit(struct packet_unit_info *packet)
88
struct unit *punit = create_unit_virtual(player_by_number(packet->owner), NULL,
133
struct unit *punit = create_unit_virtual(valid_player_by_number(packet->owner),
89
135
utype_by_number(packet->type),
174
226
char *capability, char *challenge_file,
177
char msg[MAX_LEN_MSG];
229
char *s_capability = client.conn.capability;
179
/* Never assume network data is valid and printable!
180
* Is there something that could be checked in message?
181
* In any case, check capability.
183
sz_strlcpy(aconnection.capability,
184
('\0' == capability[0] || is_ascii_name(capability))
231
sz_strlcpy(client.conn.capability, capability);
187
232
close_connection_dialog();
189
234
if (you_can_join) {
190
freelog(LOG_VERBOSE, "join game accept: %s", message);
191
aconnection.established = TRUE;
192
aconnection.id = conn_id;
235
struct packet_client_info client_info;
237
freelog(LOG_VERBOSE, "join game accept:%s", message);
238
client.conn.established = TRUE;
239
client.conn.id = conn_id;
193
241
agents_game_joined();
196
243
set_server_busy(FALSE);
198
switch (get_client_page()) {
245
if (get_client_page() == PAGE_MAIN
246
|| get_client_page() == PAGE_NETWORK
247
|| get_client_page() == PAGE_GGZ) {
202
248
set_client_page(PAGE_START);
251
client_info.gui = get_gui_type();
252
send_packet_client_info(&client.conn, &client_info);
209
254
/* we could always use hack, verify we're local */
210
255
send_client_wants_hack(challenge_file);
257
set_client_state(C_S_PREPARING);
212
append_output_window(_("You were rejected from the game...."));
213
/* ensure the network message doesn't have escapes */
214
my_snprintf(msg, sizeof(msg), "%s", Q_(message));
215
append_output_window(msg);
259
output_window_printf(ftc_client,
260
_("You were rejected from the game: %s"), message);
261
client.conn.id = -1; /* not in range of conn_info id */
217
263
if (auto_connect) {
218
freelog(LOG_NORMAL, _("You were rejected from the game...."));
219
freelog(LOG_NORMAL, "%s", msg);
264
freelog(LOG_NORMAL, _("You were rejected from the game: %s"), message);
221
266
gui_server_connect();
223
269
set_client_page(in_ggz ? PAGE_MAIN : PAGE_GGZ);
226
if (0 == strcmp(aconnection.capability, our_capability)) {
272
if (strcmp(s_capability, our_capability) == 0) {
229
my_snprintf(msg, sizeof(msg),
230
_("Client capability string: %s"), our_capability);
231
append_output_window(msg);
232
my_snprintf(msg, sizeof(msg),
233
_("Server capability string: %s"), aconnection.capability);
234
append_output_window(msg);
275
output_window_printf(ftc_client, _("Client capability string: %s"),
277
output_window_printf(ftc_client, _("Server capability string: %s"),
237
281
/****************************************************************************
352
399
/**************************************************************************
353
Updates a city's list of improvements from packet data. "impr" identifies
354
the improvement, and "have_impr" specifies whether the improvement should
400
Updates a city's list of improvements from packet data.
401
"have_impr" specifies whether the improvement should
355
402
be added (TRUE) or removed (FALSE).
356
403
**************************************************************************/
357
404
static void update_improvement_from_packet(struct city *pcity,
358
Impr_type_id impr, bool have_impr)
405
struct impr_type *pimprove,
361
if (pcity->improvements[impr] == I_NONE) {
362
city_add_improvement(pcity, impr);
409
if (pcity->built[improvement_index(pimprove)].turn <= I_NEVER) {
410
city_add_improvement(pcity, pimprove);
365
if (pcity->improvements[impr] != I_NONE) {
366
city_remove_improvement(pcity, impr);
371
/****************************************************************************
372
Handles a game-state packet from the server. The server sends these to
373
us regularly to inform the client of state changes.
374
****************************************************************************/
375
void handle_game_state(int value)
377
bool changed = (client_state() != value);
379
if (C_S_PREPARING == client_state()
380
&& C_S_RUNNING == value) {
381
popdown_races_dialog();
384
set_client_state(value);
386
if (C_S_RUNNING == client_state()) {
387
refresh_overview_canvas();
389
update_info_label(); /* get initial population right */
391
update_unit_info_label(get_units_in_focus());
393
/* Find something sensible to display instead of the intro gfx. */
394
center_on_something();
396
free_intro_radar_sprites();
400
if (C_S_OVER == client_state()) {
401
refresh_overview_canvas();
405
update_unit_info_label(NULL);
409
if (can_client_change_view()) {
410
update_map_canvas_visible();
413
/* If turn was going to change, that is now aborted. */
414
set_server_busy(FALSE);
413
if (pcity->built[improvement_index(pimprove)].turn > I_NEVER) {
414
city_remove_improvement(pcity, pimprove);
421
422
****************************************************************************/
422
423
void handle_city_info(struct packet_city_info *packet)
425
struct universal product;
424
426
int caravan_city_id;
426
429
bool city_is_new = FALSE;
427
430
bool city_has_changed_owner = FALSE;
428
431
bool need_units_dialog_update = FALSE;
429
bool popup, update_descriptions = FALSE, name_changed = FALSE;
432
bool name_changed = FALSE;
433
bool update_descriptions = FALSE;
430
434
bool shield_stock_changed = FALSE;
431
435
bool production_changed = FALSE;
432
bool traderoutes_changed = FALSE;
436
bool trade_routes_changed = FALSE;
433
437
struct unit_list *pfocus_units = get_units_in_focus();
434
438
struct city *pcity = game_find_city_by_number(packet->id);
436
if (pcity && (player_number(city_owner(pcity)) != packet->owner)) {
437
client_remove_city(pcity);
439
city_has_changed_owner = TRUE;
439
struct tile_list *worked_tiles = NULL;
440
struct tile *pcenter = map_pos_to_tile(packet->x, packet->y);
441
struct tile *ptile = NULL;
442
struct player *powner = valid_player_by_number(packet->owner);
444
if (NULL == powner) {
446
"handle_city_info() bad player number %d.",
451
if (NULL == pcenter) {
453
"handle_city_info() invalid tile (%d,%d).",
458
if (packet->production_kind < VUT_NONE || packet->production_kind >= VUT_LAST) {
459
freelog(LOG_ERROR, "handle_city_info()"
460
" bad production_kind %d.",
461
packet->production_kind);
462
product.kind = VUT_NONE;
464
product = universal_by_number(packet->production_kind,
465
packet->production_value);
466
if (product.kind < VUT_NONE || product.kind >= VUT_LAST) {
467
freelog(LOG_ERROR, "handle_city_info()"
468
" production_kind %d with bad production_value %d.",
469
packet->production_kind,
470
packet->production_value);
471
product.kind = VUT_NONE;
476
ptile = city_tile(pcity);
479
/* invisible worked city */
480
city_list_unlink(invisible_cities, pcity);
483
pcity->tile = pcenter;
485
pcity->owner = powner;
486
pcity->original = powner;
488
} else if (city_owner(pcity) != powner) {
489
/* Remember what were the worked tiles. The server won't
490
* send to us again. */
491
city_tile_iterate_skip_free_cxy(ptile, pworked, _x, _y) {
492
if (pcity == tile_worked(pworked)) {
493
if (NULL == worked_tiles) {
494
worked_tiles = tile_list_new();
496
tile_list_append(worked_tiles, pworked);
498
} city_tile_iterate_skip_free_cxy_end;
499
client_remove_city(pcity);
501
city_has_changed_owner = TRUE;
443
506
city_is_new = TRUE;
444
pcity = create_city_virtual(get_player(packet->owner),
445
map_pos_to_tile(packet->x, packet->y),
447
pcity->id=packet->id;
507
pcity = create_city_virtual(powner, pcenter, packet->name);
508
pcity->id = packet->id;
448
509
idex_register_city(pcity);
449
510
update_descriptions = TRUE;
511
} else if (pcity->id != packet->id) {
512
freelog(LOG_ERROR, "handle_city_info()"
513
" city id %d != id %d.",
517
} else if (ptile != pcenter) {
518
freelog(LOG_ERROR, "handle_city_info()"
519
" city tile (%d,%d) != (%d,%d).",
451
name_changed = (strcmp(city_name(pcity), packet->name) != 0);
524
name_changed = (0 != strncmp(packet->name, pcity->name,
525
sizeof(pcity->name)));
526
/* pcity->trade_value doesn't change the city description, neither the
527
* trade routes lines. */
528
trade_routes_changed = (draw_city_trade_routes
529
&& 0 != memcmp(pcity->trade, packet->trade,
530
sizeof(pcity->trade)));
453
532
/* Descriptions should probably be updated if the
454
533
* city name, production or time-to-grow changes.
522
594
pcity->shield_stock = packet->shield_stock;
524
596
pcity->pollution=packet->pollution;
597
pcity->illness = packet->illness;
527
|| pcity->production.is_unit != packet->production_is_unit
528
|| pcity->production.value != packet->production_value) {
600
|| !are_universals_equal(&pcity->production, &product)) {
529
601
need_units_dialog_update = TRUE;
531
if (pcity->production.is_unit != packet->production_is_unit
532
|| pcity->production.value != packet->production_value) {
603
if (!are_universals_equal(&pcity->production, &product)) {
533
604
production_changed = TRUE;
535
pcity->production.is_unit = packet->production_is_unit;
536
pcity->production.value = packet->production_value;
606
pcity->production = product;
608
#ifdef DONE_BY_create_city_virtual
537
609
if (city_is_new) {
538
610
worklist_init(&pcity->worklist);
540
for (i = 0; i < ARRAY_SIZE(pcity->improvements); i++) {
541
pcity->improvements[i] = I_NONE;
612
for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
613
pcity->built[i].turn = I_NEVER;
544
618
worklist_copy(&pcity->worklist, &packet->worklist);
620
pcity->airlift = packet->airlift;
545
621
pcity->did_buy=packet->did_buy;
546
622
pcity->did_sell=packet->did_sell;
547
623
pcity->was_happy=packet->was_happy;
548
pcity->airlift=packet->airlift;
550
pcity->turn_last_built=packet->turn_last_built;
551
625
pcity->turn_founded = packet->turn_founded;
552
pcity->changed_from.value = packet->changed_from_id;
553
pcity->changed_from.is_unit = packet->changed_from_is_unit;
626
pcity->turn_last_built = packet->turn_last_built;
628
if (packet->changed_from_kind < VUT_NONE || packet->changed_from_kind >= VUT_LAST) {
629
freelog(LOG_ERROR, "handle_city_info() bad changed_from_kind %d.",
630
packet->changed_from_kind);
631
product.kind = VUT_NONE;
633
product = universal_by_number(packet->changed_from_kind,
634
packet->changed_from_value);
635
if (product.kind < VUT_NONE || product.kind >= VUT_LAST) {
636
freelog(LOG_ERROR, "handle_city_info() bad changed_from_value %d.",
637
packet->changed_from_value);
638
product.kind = VUT_NONE;
641
pcity->changed_from = product;
554
643
pcity->before_change_shields=packet->before_change_shields;
555
644
pcity->disbanded_shields=packet->disbanded_shields;
556
645
pcity->caravan_shields=packet->caravan_shields;
557
646
pcity->last_turns_shield_surplus = packet->last_turns_shield_surplus;
559
for (i = 0; i < CITY_MAP_SIZE * CITY_MAP_SIZE; i++) {
560
const int x = i % CITY_MAP_SIZE, y = i / CITY_MAP_SIZE;
563
/* Need to pre-initialize before set_worker_city() -- dwp */
564
pcity->city_map[x][y] =
565
is_valid_city_coords(x, y) ? C_TILE_EMPTY : C_TILE_UNAVAILABLE;
567
if (is_valid_city_coords(x, y)) {
568
set_worker_city(pcity, x, y, packet->city_map[i]);
572
impr_type_iterate(i) {
573
if (pcity->improvements[i] == I_NONE
574
&& BV_ISSET(packet->improvements, i)
576
audio_play_sound(improvement_by_number(i)->soundtag,
577
improvement_by_number(i)->soundtag_alt);
579
update_improvement_from_packet(pcity, i,
580
BV_ISSET(packet->improvements, i));
581
} impr_type_iterate_end;
648
improvement_iterate(pimprove) {
649
bool have = BV_ISSET(packet->improvements, improvement_index(pimprove));
650
if (have && !city_is_new
651
&& pcity->built[improvement_index(pimprove)].turn <= I_NEVER) {
652
audio_play_sound(pimprove->soundtag, pimprove->soundtag_alt);
654
update_improvement_from_packet(pcity, pimprove, have);
655
} improvement_iterate_end;
583
657
/* We should be able to see units in the city. But for a diplomat
584
658
* investigating an enemy city we can't. In that case we don't update
585
659
* the occupied flag at all: it's already been set earlier and we'll
586
660
* get an update if it changes. */
587
if (can_player_see_units_in_city(game.player_ptr, pcity)) {
661
if (can_player_see_units_in_city(client.conn.playing, pcity)) {
588
662
pcity->client.occupied
589
663
= (unit_list_size(pcity->tile->units) > 0);
666
pcity->client.walls = packet->walls;
592
668
pcity->client.happy = city_happy(pcity);
593
669
pcity->client.unhappy = city_unhappy(pcity);
595
671
popup = (city_is_new && can_client_change_view()
596
&& city_owner(pcity) == game.player_ptr && popup_new_cities)
672
&& powner == client.conn.playing
597
674
|| packet->diplomat_investigate;
676
city_packet_common(pcity, pcenter, powner, worked_tiles,
677
city_is_new, popup, packet->diplomat_investigate);
599
679
if (city_is_new && !city_has_changed_owner) {
600
680
agents_city_new(pcity);
602
682
agents_city_changed(pcity);
605
pcity->client.walls = packet->walls;
607
handle_city_packet_common(pcity, city_is_new, popup,
608
packet->diplomat_investigate);
610
685
/* Update the description if necessary. */
611
686
if (update_descriptions) {
612
687
update_city_description(pcity);
647
724
Naturally, both require many of the same operations to be done on the
649
726
****************************************************************************/
650
static void handle_city_packet_common(struct city *pcity, bool is_new,
651
bool popup, bool investigate)
727
static void city_packet_common(struct city *pcity, struct tile *pcenter,
728
struct player *powner,
729
struct tile_list *worked_tiles,
730
bool is_new, bool popup, bool investigate)
732
if (NULL != worked_tiles) {
733
/* We need to transfer the worked infos because the server will assume
734
* those infos are kept in our side and won't send to us again. */
735
tile_list_iterate(worked_tiles, pwork) {
736
tile_set_worked(pwork, pcity);
737
} tile_list_iterate_end;
738
tile_list_free(worked_tiles);
656
742
pcity->units_supported = unit_list_new();
657
743
pcity->info_units_supported = unit_list_new();
658
744
pcity->info_units_present = unit_list_new();
660
tile_set_city(pcity->tile, pcity);
661
city_list_prepend(city_owner(pcity)->cities, pcity);
746
tile_set_worked(pcenter, pcity); /* is_free_worked() */
747
city_list_prepend(powner->cities, pcity);
663
if (city_owner(pcity) == game.player_ptr) {
749
if (powner == client.conn.playing) {
664
750
city_report_dialog_update();
667
for(i=0; i<game.info.nplayers; i++) {
668
unit_list_iterate(game.players[i].units, punit)
753
players_iterate(pp) {
754
unit_list_iterate(pp->units, punit)
669
755
if(punit->homecity==pcity->id)
670
756
unit_list_prepend(pcity->units_supported, punit);
671
757
unit_list_iterate_end;
758
} players_iterate_end;
674
if (city_owner(pcity) == game.player_ptr) {
760
if (powner == client.conn.playing) {
675
761
city_report_dialog_update_city(pcity);
679
765
if (can_client_change_view()) {
680
refresh_city_mapcanvas(pcity, pcity->tile, FALSE, FALSE);
766
refresh_city_mapcanvas(pcity, pcenter, FALSE, FALSE);
683
769
if (city_workers_display==pcity) {
721
811
bool city_has_changed_owner = FALSE;
722
812
bool city_is_new = FALSE;
813
bool name_changed = FALSE;
723
814
bool update_descriptions = FALSE;
724
815
struct city *pcity = game_find_city_by_number(packet->id);
726
if (pcity && (player_number(city_owner(pcity)) != packet->owner)) {
727
client_remove_city(pcity);
729
city_has_changed_owner = TRUE;
816
struct tile *pcenter = map_pos_to_tile(packet->x, packet->y);
817
struct tile *ptile = NULL;
818
struct tile_list *worked_tiles = NULL;
819
struct player *powner = valid_player_by_number(packet->owner);
821
if (NULL == powner) {
823
"handle_city_short_info() bad player number %d.",
828
if (NULL == pcenter) {
830
"handle_city_short_info() invalid tile (%d,%d).",
836
ptile = city_tile(pcity);
839
/* invisible worked city */
840
city_list_unlink(invisible_cities, pcity);
843
pcity->tile = pcenter;
845
pcity->owner = powner;
846
pcity->original = powner;
847
} else if (city_owner(pcity) != powner) {
848
/* Remember what were the worked tiles. The server won't
849
* send to us again. */
850
city_tile_iterate_skip_free_cxy(ptile, pworked, _x, _y) {
851
if (pcity == tile_worked(pworked)) {
852
if (NULL == worked_tiles) {
853
worked_tiles = tile_list_new();
855
tile_list_append(worked_tiles, pworked);
857
} city_tile_iterate_skip_free_cxy_end;
858
client_remove_city(pcity);
860
city_has_changed_owner = TRUE;
733
865
city_is_new = TRUE;
734
pcity = create_city_virtual(get_player(packet->owner),
735
map_pos_to_tile(packet->x, packet->y),
737
pcity->id=packet->id;
866
pcity = create_city_virtual(powner, pcenter, packet->name);
867
pcity->id = packet->id;
738
868
idex_register_city(pcity);
869
} else if (pcity->id != packet->id) {
870
freelog(LOG_ERROR, "handle_city_short_info()"
871
" city id %d != id %d.",
875
} else if (city_tile(pcity) != pcenter) {
876
freelog(LOG_ERROR, "handle_city_short_info()"
877
" city tile (%d,%d) != (%d,%d).",
878
TILE_XY(city_tile(pcity)),
882
name_changed = (0 != strncmp(packet->name, pcity->name,
883
sizeof(pcity->name)));
740
885
/* Check if city desciptions should be updated */
741
if (draw_city_names && strcmp(city_name(pcity), packet->name) != 0) {
886
if (draw_city_names && name_changed) {
742
887
update_descriptions = TRUE;
745
pcity->owner = player_by_number(packet->owner);
746
890
sz_strlcpy(pcity->name, packet->name);
748
assert(pcity->id == packet->id);
750
892
memset(pcity->feel, 0, sizeof(pcity->feel));
751
893
memset(pcity->specialists, 0, sizeof(pcity->specialists));
753
896
pcity->specialists[DEFAULT_SPECIALIST] =
754
897
pcity->size = packet->size;
764
907
update_descriptions = TRUE;
910
pcity->client.walls = packet->walls;
767
912
pcity->client.happy = packet->happy;
768
913
pcity->client.unhappy = packet->unhappy;
915
#ifdef DONE_BY_create_city_virtual
770
916
if (city_is_new) {
773
for (i = 0; i < ARRAY_SIZE(pcity->improvements); i++) {
774
pcity->improvements[i] = I_NONE;
919
for (i = 0; i < ARRAY_SIZE(pcity->built); i++) {
920
pcity->built[i].turn = I_NEVER;
778
impr_type_iterate(i) {
779
update_improvement_from_packet(pcity, i,
780
BV_ISSET(packet->improvements, i));
781
} impr_type_iterate_end;
925
improvement_iterate(pimprove) {
926
bool have = BV_ISSET(packet->improvements, improvement_index(pimprove));
927
update_improvement_from_packet(pcity, pimprove, have);
928
} improvement_iterate_end;
930
#ifdef DONE_BY_create_city_virtual
783
931
/* This sets dumb values for everything else. This is not really required,
784
932
but just want to be at the safe side. */
789
for (i = 0; i < NUM_TRADEROUTES; i++) {
937
for (i = 0; i < NUM_TRADE_ROUTES; i++) {
790
938
pcity->trade[i] = 0;
791
939
pcity->trade_value[i] = 0;
793
memset(pcity->surplus, 0, O_COUNT * sizeof(*pcity->surplus));
794
memset(pcity->waste, 0, O_COUNT * sizeof(*pcity->waste));
795
memset(pcity->prod, 0, O_COUNT * sizeof(*pcity->prod));
941
memset(pcity->surplus, 0, O_LAST * sizeof(*pcity->surplus));
942
memset(pcity->waste, 0, O_LAST * sizeof(*pcity->waste));
943
memset(pcity->prod, 0, O_LAST * sizeof(*pcity->prod));
796
944
pcity->food_stock = 0;
797
945
pcity->shield_stock = 0;
798
946
pcity->pollution = 0;
799
948
BV_CLR_ALL(pcity->city_options);
800
pcity->production.is_unit = FALSE;
801
pcity->production.value = 0;
949
pcity->production.kind = VUT_NONE;
950
pcity->production.value.building = NULL;
802
951
worklist_init(&pcity->worklist);
803
952
pcity->airlift = FALSE;
804
953
pcity->did_buy = FALSE;
805
954
pcity->did_sell = FALSE;
806
955
pcity->was_happy = FALSE;
808
for (y = 0; y < CITY_MAP_SIZE; y++) {
809
for (x = 0; x < CITY_MAP_SIZE; x++) {
810
pcity->city_map[x][y] = C_TILE_EMPTY;
813
956
} /* Dumb values */
959
city_packet_common(pcity, pcenter, powner, worked_tiles,
960
city_is_new, FALSE, FALSE);
815
962
if (city_is_new && !city_has_changed_owner) {
816
963
agents_city_new(pcity);
893
1038
**************************************************************************/
894
1039
void handle_start_phase(int phase)
897
if (phase < 0 || phase >= game.info.nplayers) {
899
freelog(LOG_ERROR, "Illegal phase %d received from server!", phase);
1041
if (!client_has_player() && !client_is_observer()) {
1042
/* We are on detached state, let ignore this packet. */
1047
|| (game.info.phase_mode == PMT_PLAYERS_ALTERNATE
1048
&& phase >= player_count())
1049
|| (game.info.phase_mode == PMT_TEAMS_ALTERNATE
1050
&& phase >= team_count())) {
1052
"handle_start_phase() illegal phase %d.",
1057
set_client_state(C_S_RUNNING);
903
1059
game.info.phase = phase;
905
if (game.player_ptr && is_player_phase(game.player_ptr, phase)) {
1061
if (NULL != client.conn.playing
1062
&& is_player_phase(client.conn.playing, phase)) {
906
1063
agents_start_turn();
907
1064
non_ai_unit_focus = FALSE;
909
turn_done_sent = FALSE;
910
1066
update_turn_done_button_state();
912
if(game.player_ptr->ai.control && !ai_manual_turn_done) {
1068
if (client.conn.playing->ai_data.control && !ai_manual_turn_done) {
913
1069
user_ended_turn();
916
player_set_unit_focus_status(game.player_ptr);
1072
player_set_unit_focus_status(client.conn.playing);
918
city_list_iterate(game.player_ptr->cities, pcity) {
1074
city_list_iterate(client.conn.playing->cities, pcity) {
919
1075
pcity->client.colored = FALSE;
920
1076
} city_list_iterate_end;
921
unit_list_iterate(game.player_ptr->units, punit) {
1078
unit_list_iterate(client.conn.playing->units, punit) {
922
1079
punit->client.colored = FALSE;
923
1080
} unit_list_iterate_end;
924
1082
update_map_canvas_visible();
1243
1413
refresh_city_dialog(pcity);
1245
1415
if (popup_caravan_arrival
1246
&& NULL != game.player_ptr
1247
&& !game.player_ptr->ai.control
1416
&& client_has_player()
1417
&& !client_player()->ai_data.control
1248
1418
&& can_client_issue_orders()
1249
1419
&& !unit_has_orders(punit)) {
1250
1420
if (punit->transported_by == -1
1251
&& game.player_ptr == unit_owner(punit)
1421
&& client_player() == unit_owner(punit)
1252
1422
&& (unit_can_help_build_wonder_here(punit)
1253
|| unit_can_est_traderoute_here(punit))) {
1423
|| unit_can_est_trade_route_here(punit))) {
1254
1424
process_caravan_arrival(punit);
1256
1426
/* Check for transported units. */
1257
unit_list_iterate(game.player_ptr->units, pcargo) {
1427
unit_list_iterate(client_player()->units, pcargo) {
1258
1428
if (pcargo->transported_by == punit->id
1259
&& game.player_ptr == unit_owner(pcargo)
1429
&& client_player() == unit_owner(pcargo)
1260
1430
&& !unit_has_orders(pcargo)
1261
1431
&& (unit_can_help_build_wonder_here(pcargo)
1262
|| unit_can_est_traderoute_here(pcargo))) {
1432
|| unit_can_est_trade_route_here(pcargo))) {
1263
1433
process_caravan_arrival(pcargo);
1265
1435
} unit_list_iterate_end;
1269
1439
} /*** End of Change position. ***/
1271
if (punit->unhappiness != packet_unit->unhappiness) {
1272
punit->unhappiness = packet_unit->unhappiness;
1273
repaint_city = TRUE;
1275
output_type_iterate(o) {
1276
if (punit->upkeep[o] != packet_unit->upkeep[o]) {
1277
punit->upkeep[o] = packet_unit->upkeep[o];
1278
repaint_city = TRUE;
1280
} output_type_iterate_end;
1281
1441
if (repaint_city || repaint_unit) {
1282
1442
/* We repaint the city if the unit itself needs repainting or if
1283
1443
* there is a special city-only redrawing to be done. */
1284
1444
if((pcity=game_find_city_by_number(punit->homecity))) {
1285
1445
refresh_city_dialog(pcity);
1287
if (repaint_unit && punit->tile->city && punit->tile->city != pcity) {
1447
if (repaint_unit && tile_city(punit->tile) && tile_city(punit->tile) != pcity) {
1288
1448
/* Refresh the city we're occupying too. */
1289
refresh_city_dialog(punit->tile->city);
1449
refresh_city_dialog(tile_city(punit->tile));
1453
/* unit upkeep information */
1454
output_type_iterate(o) {
1455
punit->upkeep[o] = packet_unit->upkeep[o];
1456
} output_type_iterate_end;
1293
1458
punit->veteran = packet_unit->veteran;
1294
1459
punit->moves_left = packet_unit->moves_left;
1295
1460
punit->fuel = packet_unit->fuel;
1464
1632
update_aifill_button = TRUE;
1635
if (game.info.is_edit_mode != pinfo->is_edit_mode) {
1636
popdown_all_city_dialogs();
1467
1639
game.info = *pinfo;
1469
game.government_when_anarchy
1470
= government_by_number(game.info.government_when_anarchy_id);
1471
game.player_ptr = player_by_number(game.info.player_idx);
1641
/* check the values! */
1642
#define VALIDATE(_count, _maximum, _string) \
1643
if (game.info._count > _maximum) { \
1644
freelog(LOG_ERROR, "handle_game_info():" \
1645
" Too many " _string "; using %d of %d", \
1646
_maximum, game.info._count); \
1647
game.info._count = _maximum; \
1650
VALIDATE(granary_num_inis, MAX_GRANARY_INIS, "granary entries");
1651
VALIDATE(num_teams, MAX_NUM_TEAMS, "teams");
1654
game.government_during_revolution =
1655
government_by_number(game.info.government_during_revolution_id);
1473
1657
boot_help = (can_client_change_view()
1474
1658
&& game.info.spacerace != pinfo->spacerace);
1531
1727
**************************************************************************/
1532
1728
void start_revolution(void)
1534
dsend_packet_player_change_government(&aconnection,
1535
game.info.government_when_anarchy_id);
1538
/**************************************************************************
1730
dsend_packet_player_change_government(&client.conn,
1731
game.info.government_during_revolution_id);
1734
/**************************************************************************
1735
Handle a notification that the player slot identified by 'playerno' has
1736
become unused. If the slot is already unused, then just ignore. Otherwise
1737
update the total player count and the GUI.
1738
**************************************************************************/
1739
void handle_player_remove(int playerno)
1741
struct player *pplayer;
1742
pplayer = player_slot_by_number(playerno);
1744
if (NULL == pplayer) {
1745
freelog(LOG_ERROR, "Invalid player slot number %d in "
1746
"handle_player_remove().", playerno);
1750
if (!player_slot_is_used(pplayer)) {
1751
/* Ok, just ignore. */
1755
game_remove_player(pplayer);
1756
player_init(pplayer);
1758
player_slot_set_used(pplayer, FALSE);
1759
set_player_count(player_count() - 1);
1761
update_players_dialog();
1762
update_conn_list_dialog();
1764
if (can_client_change_view()) {
1765
update_intel_dialog(pplayer);
1769
editgui_notify_object_changed(OBJTYPE_PLAYER, player_number(pplayer),
1773
/**************************************************************************
1774
Handle information about a player. If the packet refers to a player slot
1775
that is not currently used, then this function will set that slot to
1776
used and update the total player count.
1540
1777
**************************************************************************/
1541
1778
void handle_player_info(struct packet_player_info *pinfo)
1544
bool poptechup, new_tech = FALSE, phase_done_changed;
1545
char msg[MAX_LEN_MSG];
1546
struct player *pplayer = &game.players[pinfo->playerno];
1547
struct player_research* research;
1780
bool is_new_nation = FALSE;
1781
bool new_tech = FALSE;
1782
bool poptechup = FALSE;
1783
bool turn_done_changed = FALSE;
1785
struct player_research *research;
1786
struct player *pplayer, *my_player;
1787
struct nation_type *pnation;
1788
struct government *pgov, *ptarget_gov;
1791
/* First verify packet fields. */
1793
pplayer = player_slot_by_number(pinfo->playerno);
1795
if (NULL == pplayer) {
1796
freelog(LOG_ERROR, "Invalid player slot number %d in "
1797
"handle_player_info().", pinfo->playerno);
1801
pnation = nation_by_number(pinfo->nation);
1802
pgov = government_by_number(pinfo->government);
1803
ptarget_gov = government_by_number(pinfo->target_government);
1806
/* Now update the player information. */
1808
if (!player_slot_is_used(pplayer)) {
1809
player_slot_set_used(pplayer, TRUE);
1810
set_player_count(player_count() + 1);
1550
1813
sz_strlcpy(pplayer->name, pinfo->name);
1814
sz_strlcpy(pplayer->username, pinfo->username);
1552
is_new_nation = player_set_nation(pplayer, nation_by_number(pinfo->nation));
1553
pplayer->is_male=pinfo->is_male;
1554
team_add_player(pplayer, team_get_by_id(pinfo->team));
1816
is_new_nation = player_set_nation(pplayer, pnation);
1817
pplayer->is_male = pinfo->is_male;
1818
team_add_player(pplayer, team_by_number(pinfo->team));
1555
1819
pplayer->score.game = pinfo->score;
1556
if (has_capability("CreatedName", aconnection.capability)) {
1557
pplayer->was_created = pinfo->was_created;
1559
pplayer->was_created = FALSE;
1820
pplayer->was_created = pinfo->was_created;
1562
pplayer->economic.gold=pinfo->gold;
1563
pplayer->economic.tax=pinfo->tax;
1564
pplayer->economic.science=pinfo->science;
1565
pplayer->economic.luxury=pinfo->luxury;
1566
pplayer->government = government_by_number(pinfo->government);
1567
pplayer->target_government = government_by_number(pinfo->target_government);
1568
BV_CLR_ALL(pplayer->embassy);
1822
pplayer->economic.gold = pinfo->gold;
1823
pplayer->economic.tax = pinfo->tax;
1824
pplayer->economic.science = pinfo->science;
1825
pplayer->economic.luxury = pinfo->luxury;
1826
pplayer->government = pgov;
1827
pplayer->target_government = ptarget_gov;
1828
BV_CLR_ALL(pplayer->real_embassy);
1569
1829
players_iterate(pother) {
1570
if (pinfo->embassy[player_index(pother)]) {
1571
BV_SET(pplayer->embassy, player_index(pother));
1830
if (pinfo->real_embassy[player_index(pother)]) {
1831
BV_SET(pplayer->real_embassy, player_index(pother));
1573
1833
} players_iterate_end;
1574
1834
pplayer->gives_shared_vision = pinfo->gives_shared_vision;
1575
pplayer->city_style=pinfo->city_style;
1576
for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
1577
pplayer->ai.love[i] = pinfo->love[i];
1835
pplayer->city_style = pinfo->city_style;
1836
for (i = 0; i < player_slot_count(); i++) {
1837
pplayer->ai_data.love[i] = pinfo->love[i];
1840
my_id = client_player_number();
1841
my_player = client_player();
1580
1843
/* Check if we detect change to armistice with us. If so,
1581
1844
* ready all units for movement out of the territory in
1582
1845
* question; otherwise they will be disbanded. */
1584
&& pplayer->diplstates[player_index(game.player_ptr)].type
1586
&& pinfo->diplstates[player_index(game.player_ptr)].type
1588
unit_list_iterate(game.player_ptr->units, punit) {
1589
if (!tile_owner(punit->tile) || tile_owner(punit->tile) != pplayer) {
1846
if (client_has_player()
1847
&& DS_ARMISTICE != pplayer->diplstates[my_id].type
1848
&& DS_ARMISTICE == pinfo->diplstates[my_id].type) {
1849
unit_list_iterate(my_player->units, punit) {
1850
if (!tile_owner(unit_tile(punit))
1851
|| tile_owner(unit_tile(punit)) != pplayer) {
1592
1854
if (punit->focus_status == FOCUS_WAIT) {
1598
1860
} unit_list_iterate_end;
1601
for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
1602
pplayer->diplstates[i].type =
1603
pinfo->diplstates[i].type;
1604
pplayer->diplstates[i].turns_left =
1605
pinfo->diplstates[i].turns_left;
1606
pplayer->diplstates[i].contact_turns_left =
1607
pinfo->diplstates[i].contact_turns_left;
1608
pplayer->diplstates[i].has_reason_to_cancel =
1609
pinfo->diplstates[i].has_reason_to_cancel;
1863
for (i = 0; i < player_slot_count(); i++) {
1864
pplayer->diplstates[i].type = pinfo->diplstates[i].type;
1865
pplayer->diplstates[i].turns_left = pinfo->diplstates[i].turns_left;
1866
pplayer->diplstates[i].contact_turns_left
1867
= pinfo->diplstates[i].contact_turns_left;
1868
pplayer->diplstates[i].has_reason_to_cancel
1869
= pinfo->diplstates[i].has_reason_to_cancel;
1611
1871
pplayer->is_connected = pinfo->is_connected;
1613
for (i = 0; i < B_LAST/*game.control.num_impr_types*/; i++) {
1614
pplayer->small_wonders[i] = pinfo->small_wonders[i];
1873
for (i = 0; i < B_LAST; i++) {
1874
pplayer->wonders[i] = pinfo->wonders[i];
1617
1877
/* We need to set ai.control before read_player_info_techs */
1618
if(pplayer->ai.control!=pinfo->ai) {
1619
pplayer->ai.control=pinfo->ai;
1620
if(pplayer==game.player_ptr) {
1621
my_snprintf(msg, sizeof(msg), _("AI Mode is now %s."),
1622
game.player_ptr->ai.control?_("ON"):_("OFF"));
1623
append_output_window(msg);
1878
if (pplayer->ai_data.control != pinfo->ai) {
1879
pplayer->ai_data.control = pinfo->ai;
1880
if (pplayer == my_player) {
1881
if (my_player->ai_data.control) {
1882
output_window_append(ftc_client, _("AI mode is now ON."));
1884
output_window_append(ftc_client, _("AI mode is now OFF."));
1627
pplayer->ai.science_cost = pinfo->science_cost;
1889
pplayer->ai_data.science_cost = pinfo->science_cost;
1629
1891
/* If the server sends out player information at the wrong time, it is
1630
1892
* likely to give us inconsistent player tech information, causing a
1646
1908
/* check for bad values, complicated by discontinuous range */
1647
1909
if (NULL == advance_by_number(pinfo->researching)
1648
&& A_UNKNOWN != pinfo->researching
1649
&& A_FUTURE != pinfo->researching
1650
&& A_UNSET != pinfo->researching) {
1910
&& A_UNKNOWN != pinfo->researching
1911
&& A_FUTURE != pinfo->researching
1912
&& A_UNSET != pinfo->researching) {
1651
1913
research->researching = A_NONE; /* should never happen */
1653
1915
research->researching = pinfo->researching;
1655
1917
research->future_tech = pinfo->future_tech;
1656
research->tech_goal=pinfo->tech_goal;
1918
research->tech_goal = pinfo->tech_goal;
1658
if (can_client_change_view() && pplayer == game.player_ptr) {
1659
if (poptechup || new_tech) {
1660
science_dialog_update();
1663
if (game.player_ptr && !game.player_ptr->ai.control) {
1664
popup_science_dialog(FALSE);
1668
/* If we just learned bridge building and focus is on a settler
1669
on a river the road menu item will remain disabled unless we
1670
do this. (applys in other cases as well.) */
1671
if (get_num_units_in_focus() > 0) {
1675
economy_report_dialog_update();
1676
activeunits_report_dialog_update();
1677
city_report_dialog_update();
1920
turn_done_changed = (pplayer->phase_done != pinfo->phase_done
1921
|| pplayer->ai_data.control != pinfo->ai);
1922
pplayer->phase_done = pinfo->phase_done;
1680
1924
pplayer->is_ready = pinfo->is_ready;
1682
phase_done_changed = (pplayer->phase_done != pinfo->phase_done);
1683
pplayer->phase_done = pinfo->phase_done;
1685
pplayer->nturns_idle=pinfo->nturns_idle;
1686
pplayer->is_alive=pinfo->is_alive;
1688
pplayer->ai.barbarian_type = pinfo->barbarian_type;
1925
pplayer->nturns_idle = pinfo->nturns_idle;
1926
pplayer->is_alive = pinfo->is_alive;
1927
pplayer->ai_data.barbarian_type = pinfo->barbarian_type;
1689
1928
pplayer->revolution_finishes = pinfo->revolution_finishes;
1690
pplayer->ai.skill_level = pinfo->ai_skill_level;
1692
if (pplayer == game.player_ptr && phase_done_changed) {
1693
update_turn_done_button_state();
1695
update_players_dialog();
1696
update_worklist_report_dialog();
1697
upgrade_canvas_clipboard();
1699
if (pplayer == game.player_ptr && can_client_change_view()) {
1700
update_info_label();
1929
pplayer->ai_data.skill_level = pinfo->ai_skill_level;
1703
1931
/* if the server requests that the client reset, then information about
1704
1932
* connections to this player are lost. If this is the case, insert the
1705
1933
* correct conn back into the player->connections list */
1706
1934
if (conn_list_size(pplayer->connections) == 0) {
1707
1935
conn_list_iterate(game.est_connections, pconn) {
1708
if (pconn->player == pplayer) {
1936
if (pplayer == pconn->playing) {
1709
1937
/* insert the controller into first position */
1710
1938
if (pconn->observer) {
1711
1939
conn_list_append(pplayer->connections, pconn);
1716
1944
} conn_list_iterate_end;
1719
sz_strlcpy(pplayer->username, pinfo->username);
1948
/* The player information is now fully set. Update the GUI. */
1950
if (pplayer == my_player && can_client_change_view()) {
1951
if (poptechup || new_tech) {
1952
science_dialog_update();
1955
if (client_has_player() && !my_player->ai_data.control) {
1956
popup_science_dialog(FALSE);
1960
/* If we just learned bridge building and focus is on a settler
1961
on a river the road menu item will remain disabled unless we
1962
do this. (applys in other cases as well.) */
1963
if (get_num_units_in_focus() > 0) {
1967
if (turn_done_changed) {
1968
update_turn_done_button_state();
1970
economy_report_dialog_update();
1971
activeunits_report_dialog_update();
1972
city_report_dialog_update();
1973
update_info_label();
1976
upgrade_canvas_clipboard();
1978
update_players_dialog();
1979
update_conn_list_dialog();
1721
1981
if (is_new_nation) {
1722
1982
races_toggles_set_sensitive();
1984
/* When changing nation during a running game, some refreshing is needed.
1985
* This may not be the only one! */
1986
update_map_canvas_visible();
1724
1989
if (can_client_change_view()) {
1725
1990
/* Just about any changes above require an update to the intelligence
1727
1992
update_intel_dialog(pplayer);
1729
update_conn_list_dialog();
1996
editgui_notify_object_changed(OBJTYPE_PLAYER, player_number(pplayer),
1732
2000
/**************************************************************************
1754
2023
client_remove_cli_conn(pconn);
1757
/* Add or update the connection. Note the connection may refer to
1758
* a player we don't know about yet. */
1759
struct player *pplayer =
1760
((pinfo->player_num >= 0
1761
&& pinfo->player_num < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS)
1762
? player_by_number(pinfo->player_num) : NULL);
2026
struct player *pplayer = player_slot_by_number(pinfo->player_num);
1765
2029
freelog(LOG_VERBOSE, "Server reports new connection %d %s",
1766
pinfo->id, pinfo->username);
1768
pconn = fc_calloc(1, sizeof(struct connection));
1769
pconn->buffer = NULL;
1770
pconn->send_buffer = NULL;
1771
pconn->ping_time = -1.0;
2030
pinfo->id, pinfo->username);
2031
if (pinfo->id == client.conn.id) {
2032
/* Our connection. */
2033
pconn = &client.conn;
2035
pconn = fc_calloc(1, sizeof(struct connection));
2036
pconn->buffer = NULL;
2037
pconn->send_buffer = NULL;
2038
pconn->ping_time = -1.0;
1773
2041
conn_list_append(pplayer->connections, pconn);
1775
2043
conn_list_append(game.all_connections, pconn);
1776
2044
conn_list_append(game.est_connections, pconn);
1778
freelog(LOG_DEBUG, "Server reports updated connection %d %s",
2046
freelog(LOG_PACKET, "Server reports updated connection %d %s",
1779
2047
pinfo->id, pinfo->username);
1780
if (pplayer != pconn->player) {
1781
if (pconn->player) {
1782
conn_list_unlink(pconn->player->connections, pconn);
2048
if (pplayer != pconn->playing) {
2049
if (NULL != pconn->playing) {
2050
conn_list_unlink(pconn->playing->connections, pconn);
1785
2053
conn_list_append(pplayer->connections, pconn);
2058
if (pconn == &client.conn
2059
&& (pconn->playing != pplayer
2060
|| pconn->observer != pinfo->observer)) {
2061
/* Our connection state changed, let prepare the changes and reset
2063
preparing_client_state = TRUE;
1789
2066
pconn->id = pinfo->id;
1790
2067
pconn->established = pinfo->established;
1791
2068
pconn->observer = pinfo->observer;
1792
2069
pconn->access_level = pinfo->access_level;
1793
pconn->player = pplayer;
2070
pconn->playing = pplayer;
1794
2072
sz_strlcpy(pconn->username, pinfo->username);
1795
2073
sz_strlcpy(pconn->addr, pinfo->addr);
1796
2074
sz_strlcpy(pconn->capability, pinfo->capability);
1798
if (pinfo->id == aconnection.id) {
1799
aconnection.established = pconn->established;
1800
aconnection.observer = pconn->observer;
1801
aconnection.access_level = pconn->access_level;
1802
game.player_ptr = aconnection.player = pplayer;
1805
2077
update_players_dialog();
1806
2078
update_conn_list_dialog();
2080
if (pinfo->used && pconn == &client.conn) {
2081
/* For updating the sensitivity of the "Edit Mode" menu item,
2082
* among other things. */
2086
if (preparing_client_state) {
2087
set_client_state(C_S_PREPARING);
1809
2091
/*************************************************************************
2028
2317
**************************************************************************/
2029
2318
void handle_tile_info(struct packet_tile_info *packet)
2320
enum known_type new_known;
2321
enum known_type old_known;
2322
bool known_changed = FALSE;
2031
2323
bool tile_changed = FALSE;
2032
bool known_changed = FALSE;
2033
struct terrain *pterrain = terrain_by_number(packet->type);
2324
struct player *powner = valid_player_by_number(packet->owner);
2325
struct resource *presource = resource_by_number(packet->resource);
2326
struct terrain *pterrain = terrain_by_number(packet->terrain);
2034
2327
struct tile *ptile = map_pos_to_tile(packet->x, packet->y);
2035
enum known_type old_known = client_tile_get_known(ptile);
2037
if (!ptile->terrain || ptile->terrain->index != packet->type) {
2328
const struct nation_type *pnation;
2330
if (NULL == ptile) {
2332
"handle_tile_info() invalid tile (%d,%d).",
2336
old_known = client_tile_get_known(ptile);
2338
if (NULL == tile_terrain(ptile) || pterrain != tile_terrain(ptile)) {
2038
2339
tile_changed = TRUE;
2039
2340
switch (old_known) {
2040
2341
case TILE_UNKNOWN:
2041
ptile->terrain = pterrain;
2342
tile_set_terrain(ptile, pterrain);
2043
case TILE_KNOWN_FOGGED:
2045
if (pterrain || TILE_UNKNOWN == packet->known) {
2046
ptile->terrain = pterrain;
2344
case TILE_KNOWN_UNSEEN:
2345
case TILE_KNOWN_SEEN:
2346
if (NULL != pterrain || TILE_UNKNOWN == packet->known) {
2347
tile_set_terrain(ptile, pterrain);
2048
2349
tile_changed = FALSE;
2049
2350
freelog(LOG_ERROR,
2068
2370
} tile_special_type_iterate_end;
2070
if (NULL != ptile->resource) {
2071
tile_changed |= (ptile->resource->index != packet->resource);
2073
tile_changed |= (-1 != packet->resource);
2371
if (!BV_ARE_EQUAL(ptile->bases, packet->bases)) {
2372
ptile->bases = packet->bases;
2373
tile_changed = TRUE;
2376
tile_changed = tile_changed || (tile_resource(ptile) != presource);
2076
2378
/* always called after setting terrain */
2077
tile_set_resource(ptile, resource_by_number(packet->resource));
2079
if (packet->owner == MAP_TILE_OWNER_NULL) {
2080
if (tile_owner(ptile)) {
2081
tile_set_owner(ptile, NULL);
2082
tile_changed = TRUE;
2085
struct player *newowner = player_by_number(packet->owner);
2087
if (tile_owner(ptile) != newowner) {
2088
tile_set_owner(ptile, newowner);
2089
tile_changed = TRUE;
2379
tile_set_resource(ptile, presource);
2381
if (tile_owner(ptile) != powner) {
2382
tile_set_owner(ptile, powner, NULL);
2383
tile_changed = TRUE;
2386
if (NULL == tile_worked(ptile)
2387
|| tile_worked(ptile)->id != packet->worked) {
2388
if (IDENTITY_NUMBER_ZERO != packet->worked) {
2389
struct city *pwork = game_find_city_by_number(packet->worked);
2391
if (NULL == pwork) {
2392
char named[MAX_LEN_NAME];
2393
struct player *placeholder = powner;
2395
/* new unseen city, or before city_info */
2396
if (NULL == placeholder) {
2397
/* worker outside border allowed in earlier versions,
2398
* use non-player as placeholder.
2400
placeholder = player_by_number(MAX_NUM_PLAYERS);
2402
my_snprintf(named, sizeof(named), "%06u", packet->worked);
2404
pwork = create_city_virtual(placeholder, NULL, named);
2405
pwork->id = packet->worked;
2406
idex_register_city(pwork);
2408
city_list_prepend(invisible_cities, pwork);
2410
freelog(LOG_DEBUG, "(%d,%d) invisible city %d, %s",
2414
} else if (NULL == city_tile(pwork)) {
2415
/* old unseen city, or before city_info */
2416
if (NULL != powner && city_owner(pwork) != powner) {
2417
/* update placeholder with current owner */
2419
pwork->original = powner;
2423
/* This marks tile worked by invisible city. Other
2424
* parts of the code have to handle invisible cities correctly
2425
* (ptile->worked->tile == NULL) */
2426
tile_set_worked(ptile, pwork);
2428
tile_set_worked(ptile, NULL);
2431
tile_changed = TRUE;
2092
2434
if (old_known != packet->known) {
2093
2435
known_changed = TRUE;
2095
if (game.player_ptr) {
2096
BV_CLR(ptile->tile_known, game.info.player_idx);
2438
if (NULL != client.conn.playing) {
2439
BV_CLR(ptile->tile_known, player_index(client.conn.playing));
2097
2440
vision_layer_iterate(v) {
2098
BV_CLR(ptile->tile_seen[v], game.info.player_idx);
2441
BV_CLR(ptile->tile_seen[v], player_index(client.conn.playing));
2099
2442
} vision_layer_iterate_end;
2101
2444
switch (packet->known) {
2103
BV_SET(ptile->tile_known, game.info.player_idx);
2445
case TILE_KNOWN_SEEN:
2446
BV_SET(ptile->tile_known, player_index(client.conn.playing));
2104
2447
vision_layer_iterate(v) {
2105
BV_SET(ptile->tile_seen[v], game.info.player_idx);
2448
BV_SET(ptile->tile_seen[v], player_index(client.conn.playing));
2106
2449
} vision_layer_iterate_end;
2108
case TILE_KNOWN_FOGGED:
2109
BV_SET(ptile->tile_known, game.info.player_idx);
2451
case TILE_KNOWN_UNSEEN:
2452
BV_SET(ptile->tile_known, player_index(client.conn.playing));
2111
2454
case TILE_UNKNOWN:
2206
2566
**************************************************************************/
2207
2567
void handle_ruleset_control(struct packet_ruleset_control *packet)
2211
2569
/* The ruleset is going to load new nations. So close
2212
2570
* the nation selection dialog if it is open. */
2213
2571
popdown_races_dialog();
2215
ruleset_data_free();
2217
ruleset_cache_init();
2573
game_ruleset_free();
2574
game_ruleset_init();
2219
2575
game.control = *packet;
2220
governments_alloc(packet->government_count);
2221
nations_alloc(packet->nation_count);
2222
city_styles_alloc(packet->styles_count);
2577
/* check the values! */
2578
#define VALIDATE(_count, _maximum, _string) \
2579
if (game.control._count > _maximum) { \
2580
freelog(LOG_ERROR, "handle_ruleset_control():" \
2581
" Too many " _string "; using %d of %d", \
2582
_maximum, game.control._count); \
2583
game.control._count = _maximum; \
2586
VALIDATE(num_unit_classes, UCL_LAST, "unit classes");
2587
VALIDATE(num_unit_types, U_LAST, "unit types");
2588
VALIDATE(num_impr_types, B_LAST, "improvements");
2589
VALIDATE(num_tech_types, A_LAST_REAL, "advances");
2590
VALIDATE(num_base_types, MAX_BASE_TYPES, "bases");
2592
/* game.control.government_count, game.control.nation_count and
2593
* game.control.styles_count are allocated dynamically, and does
2594
* not need a size check. See the allocation bellow. */
2596
VALIDATE(terrain_count, MAX_NUM_TERRAINS, "terrains");
2597
VALIDATE(resource_count, MAX_NUM_RESOURCES, "resources");
2599
VALIDATE(num_specialist_types, SP_MAX, "specialists");
2602
governments_alloc(game.control.government_count);
2603
nations_alloc(game.control.nation_count);
2604
city_styles_alloc(game.control.styles_count);
2224
2606
/* After nation ruleset free/alloc, nation->player pointers are NULL.
2225
2607
* We have to initialize player->nation too, to keep state consistent.
2226
2608
* In case of /taking player, number of players has been reseted, so
2227
2609
* we can't use players_iterate() here, but have to go through all
2228
2610
* possible player slots instead. */
2229
for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
2230
game.players[i].nation = NULL;
2611
player_slots_iterate(pslot) {
2612
pslot->nation = NULL;
2613
} player_slots_iterate_end;
2233
2615
if (packet->prefered_tileset[0] != '\0') {
2234
2616
/* There is tileset suggestion */
2242
2624
/**************************************************************************
2244
2626
**************************************************************************/
2627
void handle_ruleset_unit_class(struct packet_ruleset_unit_class *p)
2629
struct unit_class *c = uclass_by_number(p->id);
2633
"handle_ruleset_unit_class() bad unit_class %d.",
2638
sz_strlcpy(c->name.vernacular, p->name);
2639
c->name.translated = NULL; /* unittype.c uclass_name_translation */
2640
c->move_type = p->move_type;
2641
c->min_speed = p->min_speed;
2642
c->hp_loss_pct = p->hp_loss_pct;
2643
c->hut_behavior = p->hut_behavior;
2644
c->flags = p->flags;
2648
/**************************************************************************
2650
**************************************************************************/
2245
2651
void handle_ruleset_unit(struct packet_ruleset_unit *p)
2247
struct unit_type *u;
2654
struct unit_type *u = utype_by_number(p->id);
2250
if(p->id < 0 || p->id >= game.control.num_unit_types || p->id >= U_LAST) {
2251
2657
freelog(LOG_ERROR,
2252
2658
"handle_ruleset_unit() bad unit_type %d.",
2256
u = utype_by_number(p->id);
2258
2663
sz_strlcpy(u->name.vernacular, p->name);
2259
2664
u->name.translated = NULL; /* unittype.c utype_name_translation */
2307
2714
**************************************************************************/
2308
2715
void handle_ruleset_tech(struct packet_ruleset_tech *p)
2717
struct advance *a = advance_by_number(p->id);
2312
if(p->id < 0 || p->id >= game.control.num_tech_types || p->id >= A_LAST) {
2313
2720
freelog(LOG_ERROR,
2314
2721
"handle_ruleset_tech() bad advance %d.",
2318
a = &advances[p->id];
2320
2726
sz_strlcpy(a->name.vernacular, p->name);
2321
2727
a->name.translated = NULL; /* tech.c advance_name_translation */
2322
2728
sz_strlcpy(a->graphic_str, p->graphic_str);
2323
2729
sz_strlcpy(a->graphic_alt, p->graphic_alt);
2324
a->req[0] = p->req[0];
2325
a->req[1] = p->req[1];
2326
a->root_req = p->root_req;
2730
a->require[AR_ONE] = advance_by_number(p->req[AR_ONE]);
2731
a->require[AR_TWO] = advance_by_number(p->req[AR_TWO]);
2732
a->require[AR_ROOT] = advance_by_number(p->root_req);
2327
2733
a->flags = p->flags;
2328
2734
a->preset_cost = p->preset_cost;
2329
2735
a->num_reqs = p->num_reqs;
2330
2736
a->helptext = mystrdup(p->helptext);
2332
tileset_setup_tech_type(tileset, p->id);
2738
tileset_setup_tech_type(tileset, a);
2335
2741
/**************************************************************************
2366
2773
sz_strlcpy(b->soundtag_alt, p->soundtag_alt);
2369
if(p->id == game.control.num_impr_types-1) {
2370
impr_type_iterate(id) {
2371
b = improvement_by_number(id);
2776
if(p->id == improvement_count()-1) {
2777
improvement_iterate(b) {
2372
2778
freelog(LOG_DEBUG, "Improvement: %s...",
2373
improvement_rule_name(id));
2374
if (tech_exists(b->obsolete_by)) {
2375
freelog(LOG_DEBUG, " obsolete_by %2d/%s",
2779
improvement_rule_name(b));
2780
if (A_NEVER != b->obsolete_by) {
2781
freelog(LOG_DEBUG, " obsolete_by %2d \"%s\"",
2782
advance_number(b->obsolete_by),
2377
2783
advance_rule_name(b->obsolete_by));
2379
freelog(LOG_DEBUG, " obsolete_by %2d/Never", b->obsolete_by);
2381
2785
freelog(LOG_DEBUG, " build_cost %3d", b->build_cost);
2382
2786
freelog(LOG_DEBUG, " upkeep %2d", b->upkeep);
2383
2787
freelog(LOG_DEBUG, " sabotage %3d", b->sabotage);
2384
2788
freelog(LOG_DEBUG, " helptext %s", b->helptext);
2385
} impr_type_iterate_end;
2789
} improvement_iterate_end;
2389
2793
b->allows_units = FALSE;
2390
2794
unit_type_iterate(ut) {
2391
if (ut->impr_requirement == p->id) {
2795
if (ut->need_improvement == b) {
2392
2796
b->allows_units = TRUE;
2395
2799
} unit_type_iterate_end;
2397
tileset_setup_impr_type(tileset, p->id);
2801
tileset_setup_impr_type(tileset, b);
2400
2804
/**************************************************************************
2561
2963
tileset_setup_resource(tileset, presource);
2966
/****************************************************************************
2967
Handle a packet about a particular base type.
2968
****************************************************************************/
2969
void handle_ruleset_base(struct packet_ruleset_base *p)
2972
struct base_type *pbase = base_by_number(p->id);
2976
"handle_ruleset_base() bad base %d.",
2981
sz_strlcpy(pbase->name.vernacular, p->name);
2982
pbase->name.translated = NULL; /* base.c base_name_translation */
2983
sz_strlcpy(pbase->graphic_str, p->graphic_str);
2984
sz_strlcpy(pbase->graphic_alt, p->graphic_alt);
2985
sz_strlcpy(pbase->activity_gfx, p->activity_gfx);
2986
pbase->buildable = p->buildable;
2987
pbase->pillageable = p->pillageable;
2989
for (i = 0; i < p->reqs_count; i++) {
2990
requirement_vector_append(&pbase->reqs, &p->reqs[i]);
2992
assert(pbase->reqs.size == p->reqs_count);
2994
pbase->native_to = p->native_to;
2996
pbase->gui_type = p->gui_type;
2998
pbase->build_time = p->build_time;
2999
pbase->border_sq = p->border_sq;
3001
pbase->flags = p->flags;
3003
tileset_setup_base(tileset, pbase);
2564
3006
/**************************************************************************
2565
3007
Handle the terrain control ruleset packet sent by the server.
2566
3008
**************************************************************************/