~ubuntu-branches/debian/sid/freeciv/sid

« back to all changes in this revision

Viewing changes to client/packhand.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2010-02-23 22:09:02 UTC
  • mfrom: (7.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100223220902-s3spqi1x4e190y0t
[ Karl Goetz ]
* Remove civserver files in /etc/ggzd/ (Closes: 523772, 517787)
* Adding ${misc:Depends} to all binary packages (lintian warnings)

[ Clint Adams ]
* New upstream version.
  - Drop data_dsc_use_bindir.diff (binary pathnames have changed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
#include <assert.h>
19
19
#include <string.h>
20
20
 
 
21
/* utility */
21
22
#include "capability.h"
 
23
#include "fcintl.h"
 
24
#include "log.h"
 
25
#include "mem.h"
 
26
#include "support.h"
 
27
 
 
28
/* common */
22
29
#include "capstr.h"
23
30
#include "events.h"
24
 
#include "fcintl.h"
25
31
#include "game.h"
26
32
#include "government.h"
27
33
#include "idex.h"
28
 
#include "log.h"
29
34
#include "map.h"
30
 
#include "mem.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"
36
 
#include "support.h"
37
40
#include "unit.h"
38
41
#include "unitlist.h"
39
42
#include "worklist.h"
40
43
 
41
 
#include "agents.h"
42
 
#include "attribute.h"
43
 
#include "audio.h"
 
44
/* include */
44
45
#include "chatline_g.h"
45
46
#include "citydlg_g.h"
46
47
#include "cityrep_g.h"
47
 
#include "civclient.h"
48
 
#include "climap.h"
49
 
#include "climisc.h"
50
 
#include "clinet.h"             /* aconnection */
51
 
#include "connectdlg_common.h"
52
48
#include "connectdlg_g.h"
53
 
#include "control.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"
65
 
#include "options.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"
 
62
#include "wldlg_g.h"
 
63
 
 
64
/* client */
 
65
#include "agents.h"
 
66
#include "attribute.h"
 
67
#include "audio.h"
 
68
#include "client_main.h"
 
69
#include "climap.h"
 
70
#include "climisc.h"
 
71
#include "connectdlg_common.h"
 
72
#include "control.h"
 
73
#include "editor.h"
 
74
#include "ggzclient.h"
 
75
#include "goto.h"               /* client_goto_init() */
 
76
#include "helpdata.h"           /* boot_help_texts() */
 
77
#include "mapview_common.h"
 
78
#include "options.h"
 
79
#include "overview_common.h"
71
80
#include "tilespec.h"
72
81
#include "voteinfo.h"
73
 
#include "wldlg_g.h"
74
82
 
75
83
#include "packhand.h"
76
84
 
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);
 
90
 
 
91
 
80
92
static int *reports_thaw_requests = NULL;
81
93
static int reports_thaw_requests_size = 0;
82
94
 
 
95
/* The dumbest of cities, placeholders for unknown and unseen cities. */
 
96
static struct city_list *invisible_cities = NULL;
 
97
 
 
98
 
 
99
/****************************************************************************
 
100
  Called below, and by client/civclient.c client_game_free()
 
101
****************************************************************************/
 
102
void packhand_free(void)
 
103
{
 
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;
 
109
 
 
110
    city_list_free(invisible_cities);
 
111
    invisible_cities = NULL;
 
112
  }
 
113
}
 
114
 
 
115
/****************************************************************************
 
116
  Called only by handle_map_info() below.
 
117
****************************************************************************/
 
118
static void packhand_init(void)
 
119
{
 
120
  packhand_free();
 
121
 
 
122
  invisible_cities = city_list_new();
 
123
}
 
124
 
83
125
/**************************************************************************
84
126
  Unpackage the unit information into a newly allocated unit structure.
 
127
 
 
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)
87
132
{
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),
 
134
                                           NULL,
89
135
                                           utype_by_number(packet->type),
90
136
                                           packet->veteran);
91
137
 
94
140
  punit->id = packet->id;
95
141
  punit->tile = map_pos_to_tile(packet->x, packet->y);
96
142
  punit->homecity = packet->homecity;
 
143
  output_type_iterate(o) {
 
144
    punit->upkeep[o] = packet->upkeep[o];
 
145
  } output_type_iterate_end;
97
146
  punit->moves_left = packet->movesleft;
98
147
  punit->hp = packet->hp;
99
148
  punit->activity = packet->activity;
100
149
  punit->activity_count = packet->activity_count;
101
 
  punit->unhappiness = packet->unhappiness;
102
 
  output_type_iterate(o) {
103
 
    punit->upkeep[o] = packet->upkeep[o];
104
 
  } output_type_iterate_end;
105
150
  punit->ai.control = packet->ai;
106
151
  punit->fuel = packet->fuel;
107
152
  if (is_normal_map_pos(packet->goto_dest_x, packet->goto_dest_y)) {
111
156
    punit->goto_tile = NULL;
112
157
  }
113
158
  punit->activity_target = packet->activity_target;
 
159
  punit->activity_base = packet->activity_base;
114
160
  punit->paradropped = packet->paradropped;
115
161
  punit->done_moving = packet->done_moving;
116
162
  punit->occupy = packet->occupy;
134
180
      punit->orders.list[i].order = packet->orders[i];
135
181
      punit->orders.list[i].dir = packet->orders_dirs[i];
136
182
      punit->orders.list[i].activity = packet->orders_activities[i];
 
183
      punit->orders.list[i].base = packet->orders_bases[i];
137
184
    }
138
185
  }
139
186
  return punit;
143
190
  Unpackage a short_unit_info packet.  This extracts a limited amount of
144
191
  information about the unit, and is sent for units we shouldn't know
145
192
  everything about (like our enemies' units).
 
193
 
 
194
  Information for the client must also be processed in
 
195
  handle_unit_packet_common()!
146
196
**************************************************************************/
147
197
static struct unit *unpackage_short_unit(struct packet_unit_short_info *packet)
148
198
{
149
 
  struct unit *punit = create_unit_virtual(get_player(packet->owner), NULL,
 
199
  struct unit *punit = create_unit_virtual(valid_player_by_number(packet->owner),
 
200
                                           NULL,
150
201
                                           utype_by_number(packet->type),
151
202
                                           FALSE);
152
203
 
156
207
  punit->veteran = packet->veteran;
157
208
  punit->hp = packet->hp;
158
209
  punit->activity = packet->activity;
 
210
  punit->activity_base = packet->activity_base;
159
211
  punit->occupy = (packet->occupied ? 1 : 0);
160
212
  if (packet->transported) {
161
213
    punit->transported_by = packet->transported_by;
174
226
                              char *capability, char *challenge_file,
175
227
                              int conn_id)
176
228
{
177
 
  char msg[MAX_LEN_MSG];
 
229
  char *s_capability = client.conn.capability;
178
230
 
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.
182
 
   */
183
 
  sz_strlcpy(aconnection.capability,
184
 
             ('\0' == capability[0] || is_ascii_name(capability))
185
 
             ? capability
186
 
             : "?");
 
231
  sz_strlcpy(client.conn.capability, capability);
187
232
  close_connection_dialog();
188
233
 
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;
 
236
 
 
237
    freelog(LOG_VERBOSE, "join game accept:%s", message);
 
238
    client.conn.established = TRUE;
 
239
    client.conn.id = conn_id;
 
240
 
193
241
    agents_game_joined();
194
242
    update_menus();
195
 
 
196
243
    set_server_busy(FALSE);
197
244
    
198
 
    switch (get_client_page()) {
199
 
    case PAGE_MAIN:
200
 
    case PAGE_NETWORK:
201
 
    case PAGE_GGZ:
 
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);
203
 
      break;
204
 
    default:
205
 
      /* no change */
206
 
      break;
207
 
    };
 
249
    }
 
250
 
 
251
    client_info.gui = get_gui_type();
 
252
    send_packet_client_info(&client.conn, &client_info);
208
253
 
209
254
    /* we could always use hack, verify we're local */ 
210
255
    send_client_wants_hack(challenge_file);
 
256
 
 
257
    set_client_state(C_S_PREPARING);
211
258
  } else {
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);
216
 
    aconnection.id = 0;
 
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 */
 
262
 
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);
220
265
    }
221
266
    gui_server_connect();
 
267
 
222
268
    if (!with_ggz) {
223
269
      set_client_page(in_ggz ? PAGE_MAIN : PAGE_GGZ);
224
270
    }
225
271
  }
226
 
  if (0 == strcmp(aconnection.capability, our_capability)) {
 
272
  if (strcmp(s_capability, our_capability) == 0) {
227
273
    return;
228
274
  }
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"),
 
276
                       our_capability);
 
277
  output_window_printf(ftc_client, _("Server capability string: %s"),
 
278
                       s_capability);
235
279
}
236
280
 
237
281
/****************************************************************************
241
285
void handle_city_remove(int city_id)
242
286
{
243
287
  struct city *pcity = game_find_city_by_number(city_id);
244
 
  struct tile *ptile;
245
288
 
246
 
  if (!pcity)
 
289
  if (NULL == pcity) {
 
290
    freelog(LOG_ERROR,
 
291
            "handle_city_remove() bad city %d.",
 
292
            city_id);
247
293
    return;
 
294
  }
248
295
 
249
296
  agents_city_remove(pcity);
250
 
 
251
 
  ptile = pcity->tile;
 
297
  editgui_notify_object_changed(OBJTYPE_CITY, pcity->id, TRUE);
252
298
  client_remove_city(pcity);
253
299
 
254
300
  /* update menus if the focus unit is on the tile. */
280
326
  powner = unit_owner(punit);
281
327
 
282
328
  agents_unit_remove(punit);
 
329
  editgui_notify_object_changed(OBJTYPE_UNIT, punit->id, TRUE);
283
330
  client_remove_unit(punit);
284
331
 
285
 
  if (powner == game.player_ptr) {
 
332
  if (powner == client.conn.playing) {
286
333
    activeunits_report_dialog_update();
287
334
  }
288
335
}
314
361
        tile_visible_mapcanvas(punit1->tile)) {
315
362
      show_combat = TRUE;
316
363
    } else if (auto_center_on_combat) {
317
 
      if (unit_owner(punit0) == game.player_ptr)
 
364
      if (unit_owner(punit0) == client.conn.playing)
318
365
        center_tile_mapcanvas(punit0->tile);
319
366
      else
320
367
        center_tile_mapcanvas(punit1->tile);
350
397
}
351
398
 
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,
 
406
                                           bool have_impr)
359
407
{
360
408
  if (have_impr) {
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);
363
411
    }
364
412
  } else {
365
 
    if (pcity->improvements[impr] != I_NONE) {
366
 
      city_remove_improvement(pcity, impr);
367
 
    }
368
 
  }
369
 
}
370
 
 
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)
376
 
{
377
 
  bool changed = (client_state() != value);
378
 
 
379
 
  if (C_S_PREPARING == client_state()
380
 
      && C_S_RUNNING == value) {
381
 
    popdown_races_dialog();
382
 
  }
383
 
  
384
 
  set_client_state(value);
385
 
 
386
 
  if (C_S_RUNNING == client_state()) {
387
 
    refresh_overview_canvas();
388
 
 
389
 
    update_info_label();        /* get initial population right */
390
 
    update_unit_focus();
391
 
    update_unit_info_label(get_units_in_focus());
392
 
 
393
 
    /* Find something sensible to display instead of the intro gfx. */
394
 
    center_on_something();
395
 
    
396
 
    free_intro_radar_sprites();
397
 
    agents_game_start();
398
 
  }
399
 
 
400
 
  if (C_S_OVER == client_state()) {
401
 
    refresh_overview_canvas();
402
 
 
403
 
    update_info_label();
404
 
    update_unit_focus();
405
 
    update_unit_info_label(NULL); 
406
 
  }
407
 
 
408
 
  if (changed) {
409
 
    if (can_client_change_view()) {
410
 
      update_map_canvas_visible();
411
 
    }
412
 
 
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);
 
415
    }
415
416
  }
416
417
}
417
418
 
421
422
****************************************************************************/
422
423
void handle_city_info(struct packet_city_info *packet)
423
424
{
 
425
  struct universal product;
424
426
  int caravan_city_id;
425
427
  int i;
 
428
  bool popup;
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);
435
 
 
436
 
  if (pcity && (player_number(city_owner(pcity)) != packet->owner)) {
437
 
    client_remove_city(pcity);
438
 
    pcity = NULL;
439
 
    city_has_changed_owner = TRUE;
440
 
  }
441
 
 
442
 
  if(!pcity) {
 
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);
 
443
 
 
444
  if (NULL == powner) {
 
445
    freelog(LOG_ERROR,
 
446
            "handle_city_info() bad player number %d.",
 
447
            packet->owner);
 
448
    return;
 
449
  }
 
450
 
 
451
  if (NULL == pcenter) {
 
452
    freelog(LOG_ERROR,
 
453
            "handle_city_info() invalid tile (%d,%d).",
 
454
            TILE_XY(packet));
 
455
    return;
 
456
  }
 
457
 
 
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;
 
463
  } else {
 
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;
 
472
    }
 
473
  }
 
474
 
 
475
  if (NULL != pcity) {
 
476
    ptile = city_tile(pcity);
 
477
 
 
478
    if (NULL == ptile) {
 
479
      /* invisible worked city */
 
480
      city_list_unlink(invisible_cities, pcity);
 
481
      city_is_new = TRUE;
 
482
 
 
483
      pcity->tile = pcenter;
 
484
      ptile = pcenter;
 
485
      pcity->owner = powner;
 
486
      pcity->original = powner;
 
487
 
 
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();
 
495
          }
 
496
          tile_list_append(worked_tiles, pworked);
 
497
        }
 
498
      } city_tile_iterate_skip_free_cxy_end;
 
499
      client_remove_city(pcity);
 
500
      pcity = NULL;
 
501
      city_has_changed_owner = TRUE;
 
502
    }
 
503
  }
 
504
 
 
505
  if (NULL == pcity) {
443
506
    city_is_new = TRUE;
444
 
    pcity = create_city_virtual(get_player(packet->owner),
445
 
                                map_pos_to_tile(packet->x, packet->y),
446
 
                                packet->name);
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.",
 
514
            pcity->id,
 
515
            packet->id);
 
516
    return;
 
517
  } else if (ptile != pcenter) {
 
518
    freelog(LOG_ERROR, "handle_city_info()"
 
519
            " city tile (%d,%d) != (%d,%d).",
 
520
            TILE_XY(ptile),
 
521
            TILE_XY(packet));
 
522
    return;
450
523
  } else {
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)));
452
531
 
453
532
    /* Descriptions should probably be updated if the
454
533
     * city name, production or time-to-grow changes.
457
536
     * have changed as well. */
458
537
    update_descriptions = (draw_city_names && name_changed)
459
538
      || (draw_city_productions
460
 
          && (pcity->production.is_unit != packet->production_is_unit
461
 
              || pcity->production.value != packet->production_value
 
539
          && (!are_universals_equal(&pcity->production, &product)
462
540
              || pcity->surplus[O_SHIELD] != packet->surplus[O_SHIELD]
463
541
              || pcity->shield_stock != packet->shield_stock))
464
542
      || (draw_city_growth
465
543
          && (pcity->food_stock != packet->food_stock
466
 
              || pcity->surplus[O_FOOD] != packet->surplus[O_FOOD]));
467
 
 
468
 
    assert(pcity->id == packet->id);
 
544
              || pcity->surplus[O_FOOD] != packet->surplus[O_FOOD]))
 
545
      || (draw_city_trade_routes && trade_routes_changed);
469
546
  }
470
547
  
471
 
  pcity->owner = player_by_number(packet->owner);
472
 
  pcity->tile = map_pos_to_tile(packet->x, packet->y);
473
548
  sz_strlcpy(pcity->name, packet->name);
474
549
  
475
550
  /* check data */
499
574
 
500
575
  pcity->city_options = packet->city_options;
501
576
 
502
 
  for (i = 0; i < NUM_TRADEROUTES; i++) {
503
 
    if (pcity->trade[i] != packet->trade[i]) {
504
 
      pcity->trade[i] = packet->trade[i];
505
 
      traderoutes_changed = TRUE;
506
 
    }
 
577
  for (i = 0; i < NUM_TRADE_ROUTES; i++) {
 
578
    pcity->trade[i] = packet->trade[i];
507
579
    pcity->trade_value[i] = packet->trade_value[i];
508
580
  }
509
581
 
522
594
    pcity->shield_stock = packet->shield_stock;
523
595
  }
524
596
  pcity->pollution=packet->pollution;
 
597
  pcity->illness = packet->illness;
525
598
 
526
599
  if (city_is_new
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;
530
602
  }
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;
534
605
  }
535
 
  pcity->production.is_unit = packet->production_is_unit;
536
 
  pcity->production.value = packet->production_value;
 
606
  pcity->production = product;
 
607
 
 
608
#ifdef DONE_BY_create_city_virtual
537
609
  if (city_is_new) {
538
610
    worklist_init(&pcity->worklist);
539
611
 
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;
542
614
    }
543
615
  }
 
616
#endif
 
617
 
544
618
  worklist_copy(&pcity->worklist, &packet->worklist);
 
619
 
 
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;
549
624
 
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;
 
627
  
 
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;
 
632
  } else {
 
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;
 
639
    }
 
640
  }
 
641
  pcity->changed_from = product;
 
642
 
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;
558
647
 
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;
561
 
 
562
 
    if (city_is_new) {
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;
566
 
    }
567
 
    if (is_valid_city_coords(x, y)) {
568
 
      set_worker_city(pcity, x, y, packet->city_map[i]);
569
 
    }
570
 
  }
571
 
  
572
 
  impr_type_iterate(i) {
573
 
    if (pcity->improvements[i] == I_NONE
574
 
        && BV_ISSET(packet->improvements, i)
575
 
        && !city_is_new) {
576
 
      audio_play_sound(improvement_by_number(i)->soundtag,
577
 
                       improvement_by_number(i)->soundtag_alt);
578
 
    }
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);
 
653
    }
 
654
    update_improvement_from_packet(pcity, pimprove, have);
 
655
  } improvement_iterate_end;
582
656
 
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);
590
664
  }
591
665
 
 
666
  pcity->client.walls = packet->walls;
 
667
 
592
668
  pcity->client.happy = city_happy(pcity);
593
669
  pcity->client.unhappy = city_unhappy(pcity);
594
670
 
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
 
673
           && popup_new_cities)
597
674
          || packet->diplomat_investigate;
598
675
 
 
676
  city_packet_common(pcity, pcenter, powner, worked_tiles,
 
677
                     city_is_new, popup, packet->diplomat_investigate);
 
678
 
599
679
  if (city_is_new && !city_has_changed_owner) {
600
680
    agents_city_new(pcity);
601
681
  } else {
602
682
    agents_city_changed(pcity);
603
683
  }
604
684
 
605
 
  pcity->client.walls = packet->walls;
606
 
 
607
 
  handle_city_packet_common(pcity, city_is_new, popup,
608
 
                            packet->diplomat_investigate);
609
 
 
610
685
  /* Update the description if necessary. */
611
686
  if (update_descriptions) {
612
687
    update_city_description(pcity);
637
712
    caravan_dialog_update();
638
713
  }
639
714
 
640
 
  if (traderoutes_changed && draw_city_traderoutes) {
 
715
  if (draw_city_trade_routes
 
716
      && (trade_routes_changed
 
717
          || (city_is_new && 0 < city_num_trade_routes(pcity)))) {
641
718
    update_map_canvas_visible();
642
719
  }
643
720
}
647
724
  Naturally, both require many of the same operations to be done on the
648
725
  data.
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)
652
731
{
653
 
  int i;
 
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);
 
739
  }
654
740
 
655
 
  if(is_new) {
 
741
  if (is_new) {
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();
659
745
 
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);
662
748
 
663
 
    if (city_owner(pcity) == game.player_ptr) {
 
749
    if (powner == client.conn.playing) {
664
750
      city_report_dialog_update();
665
751
    }
666
752
 
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;
672
 
    }
 
758
    } players_iterate_end;
673
759
  } else {
674
 
    if (city_owner(pcity) == game.player_ptr) {
 
760
    if (powner == client.conn.playing) {
675
761
      city_report_dialog_update_city(pcity);
676
762
    }
677
763
  }
678
764
 
679
765
  if (can_client_change_view()) {
680
 
    refresh_city_mapcanvas(pcity, pcity->tile, FALSE, FALSE);
 
766
    refresh_city_mapcanvas(pcity, pcenter, FALSE, FALSE);
681
767
  }
682
768
 
683
769
  if (city_workers_display==pcity)  {
685
771
  }
686
772
 
687
773
  if (popup
688
 
      && can_client_issue_orders()
689
 
      && game.player_ptr
690
 
      && !game.player_ptr->ai.control) {
 
774
      && NULL != client.conn.playing
 
775
      && !client.conn.playing->ai_data.control
 
776
      && can_client_issue_orders()) {
691
777
    update_menus();
692
778
    if (!city_dialog_is_open(pcity)) {
693
779
      popup_city_dialog(pcity);
695
781
  }
696
782
 
697
783
  if (!is_new
698
 
      && (can_player_see_city_internals(game.player_ptr, pcity) || popup)) {
 
784
      && (popup || can_player_see_city_internals(client.conn.playing, pcity))) {
699
785
    refresh_city_dialog(pcity);
700
786
  }
701
787
 
702
788
  /* update menus if the focus unit is on the tile. */
703
 
  if (get_focus_unit_on_tile(pcity->tile)) {
 
789
  if (get_focus_unit_on_tile(pcenter)) {
704
790
    update_menus();
705
791
  }
706
792
 
707
 
  if(is_new) {
708
 
    freelog(LOG_DEBUG, "New %s city %s id %d (%d %d)",
 
793
  if (is_new) {
 
794
    freelog(LOG_DEBUG, "(%d,%d) creating city %d, %s %s",
 
795
            TILE_XY(pcenter),
 
796
            pcity->id,
709
797
            nation_rule_name(nation_of_city(pcity)),
710
 
            city_name(pcity), pcity->id, TILE_XY(pcity->tile));
 
798
            city_name(pcity));
711
799
  }
 
800
 
 
801
  editgui_notify_object_changed(OBJTYPE_CITY, pcity->id, FALSE);
712
802
}
713
803
 
714
804
/****************************************************************************
720
810
{
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);
725
 
 
726
 
  if (pcity && (player_number(city_owner(pcity)) != packet->owner)) {
727
 
    client_remove_city(pcity);
728
 
    pcity = NULL;
729
 
    city_has_changed_owner = TRUE;
730
 
  }
731
 
 
732
 
  if (!pcity) {
 
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);
 
820
 
 
821
  if (NULL == powner) {
 
822
    freelog(LOG_ERROR,
 
823
            "handle_city_short_info() bad player number %d.",
 
824
            packet->owner);
 
825
    return;
 
826
  }
 
827
 
 
828
  if (NULL == pcenter) {
 
829
    freelog(LOG_ERROR,
 
830
            "handle_city_short_info() invalid tile (%d,%d).",
 
831
            TILE_XY(packet));
 
832
    return;
 
833
  }
 
834
 
 
835
  if (NULL != pcity) {
 
836
    ptile = city_tile(pcity);
 
837
 
 
838
    if (NULL == ptile) {
 
839
      /* invisible worked city */
 
840
      city_list_unlink(invisible_cities, pcity);
 
841
      city_is_new = TRUE;
 
842
 
 
843
      pcity->tile = pcenter;
 
844
      ptile = 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();
 
854
          }
 
855
          tile_list_append(worked_tiles, pworked);
 
856
        }
 
857
      } city_tile_iterate_skip_free_cxy_end;
 
858
      client_remove_city(pcity);
 
859
      pcity = NULL;
 
860
      city_has_changed_owner = TRUE;
 
861
    }
 
862
  }
 
863
 
 
864
  if (NULL == pcity) {
733
865
    city_is_new = TRUE;
734
 
    pcity = create_city_virtual(get_player(packet->owner),
735
 
                                map_pos_to_tile(packet->x, packet->y),
736
 
                                packet->name);
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.",
 
872
            pcity->id,
 
873
            packet->id);
 
874
    return;
 
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)),
 
879
            TILE_XY(packet));
 
880
    return;
739
881
  } else {
 
882
    name_changed = (0 != strncmp(packet->name, pcity->name,
 
883
                                 sizeof(pcity->name)));
 
884
 
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;
743
888
    }
744
889
 
745
 
    pcity->owner = player_by_number(packet->owner);
746
890
    sz_strlcpy(pcity->name, packet->name);
747
891
    
748
 
    assert(pcity->id == packet->id);
749
 
 
750
892
    memset(pcity->feel, 0, sizeof(pcity->feel));
751
893
    memset(pcity->specialists, 0, sizeof(pcity->specialists));
752
894
  }
 
895
 
753
896
  pcity->specialists[DEFAULT_SPECIALIST] =
754
897
  pcity->size = packet->size;
755
898
 
764
907
      update_descriptions = TRUE;
765
908
    }
766
909
  }
 
910
  pcity->client.walls = packet->walls;
 
911
 
767
912
  pcity->client.happy = packet->happy;
768
913
  pcity->client.unhappy = packet->unhappy;
769
914
 
 
915
#ifdef DONE_BY_create_city_virtual
770
916
  if (city_is_new) {
771
917
    int i;
772
918
 
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;
775
921
    }
776
922
  }
777
 
 
778
 
  impr_type_iterate(i) {
779
 
    update_improvement_from_packet(pcity, i,
780
 
                                   BV_ISSET(packet->improvements, i));
781
 
  } impr_type_iterate_end;
782
 
 
 
923
#endif
 
924
 
 
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;
 
929
 
 
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. */
785
933
  {
786
934
    int i;
787
935
    int x, y;
788
936
 
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;
792
940
    }
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;
 
947
    pcity->illness            = 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;
807
 
 
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;
811
 
      }
812
 
    }
813
956
  } /* Dumb values */
 
957
#endif
 
958
 
 
959
  city_packet_common(pcity, pcenter, powner, worked_tiles,
 
960
                     city_is_new, FALSE, FALSE);
814
961
 
815
962
  if (city_is_new && !city_has_changed_owner) {
816
963
    agents_city_new(pcity);
818
965
    agents_city_changed(pcity);
819
966
  }
820
967
 
821
 
  pcity->client.walls = packet->walls;
822
 
 
823
 
  handle_city_packet_common(pcity, city_is_new, FALSE, FALSE);
824
 
 
825
968
  /* Update the description if necessary. */
826
969
  if (update_descriptions) {
827
970
    update_city_description(pcity);
851
994
#if 0
852
995
  /* This information shouldn't be needed, but if it is this is the only
853
996
   * way we can get it. */
854
 
  if (game.player_ptr) {
855
 
    turn_gold_difference
856
 
      = game.player_ptr->economic.gold - last_turn_gold_amount;
857
 
    last_turn_gold_amount = game.player_ptr->economic.gold;
 
997
  if (NULL != client.conn.playing) {
 
998
    turn_gold_difference =
 
999
      client.conn.playing->economic.gold - last_turn_gold_amount;
 
1000
    last_turn_gold_amount = client.conn.playing->economic.gold;
858
1001
  }
859
1002
#endif
860
1003
 
861
1004
  update_city_descriptions();
 
1005
  link_marks_decrease_turn_counters();
862
1006
 
863
1007
  if (sound_bell_at_new_turn) {
864
 
    create_event(NULL, E_TURN_BELL, _("Start of turn %d"), game.info.turn);
 
1008
    create_event(NULL, E_TURN_BELL, ftc_client,
 
1009
                 _("Start of turn %d"), game.info.turn);
865
1010
  }
866
1011
 
867
1012
  agents_new_turn();
893
1038
**************************************************************************/
894
1039
void handle_start_phase(int phase)
895
1040
{
896
 
 
897
 
  if (phase < 0 || phase >= game.info.nplayers) {
898
 
    /* Illegal phase */
899
 
    freelog(LOG_ERROR, "Illegal phase %d received from server!", phase);
900
 
    return;
901
 
  }
 
1041
  if (!client_has_player() && !client_is_observer()) {
 
1042
    /* We are on detached state, let ignore this packet. */
 
1043
    return;
 
1044
  }
 
1045
 
 
1046
  if (phase < 0
 
1047
      || (game.info.phase_mode == PMT_PLAYERS_ALTERNATE
 
1048
          && phase >= player_count())
 
1049
      || (game.info.phase_mode == PMT_TEAMS_ALTERNATE
 
1050
          && phase >= team_count())) {
 
1051
    freelog(LOG_ERROR,
 
1052
            "handle_start_phase() illegal phase %d.",
 
1053
            phase);
 
1054
    return;
 
1055
  }
 
1056
 
 
1057
  set_client_state(C_S_RUNNING);
902
1058
 
903
1059
  game.info.phase = phase;
904
1060
 
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;
908
1065
 
909
 
    turn_done_sent = FALSE;
910
1066
    update_turn_done_button_state();
911
1067
 
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();
914
1070
    }
915
1071
 
916
 
    player_set_unit_focus_status(game.player_ptr);
 
1072
    player_set_unit_focus_status(client.conn.playing);
917
1073
 
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) {
 
1077
 
 
1078
    unit_list_iterate(client.conn.playing->units, punit) {
922
1079
      punit->client.colored = FALSE;
923
1080
    } unit_list_iterate_end;
 
1081
 
924
1082
    update_map_canvas_visible();
925
1083
  }
926
1084
 
978
1136
 
979
1137
  handle_event(message, ptile, event, conn_id);
980
1138
}
981
 
 
 
1139
 
 
1140
/**************************************************************************
 
1141
  Handle a connect message packet. Server sends connect message to
 
1142
  client immediately when client connects.
 
1143
**************************************************************************/
 
1144
void handle_connect_msg(char *message)
 
1145
{
 
1146
  popup_connect_msg(_("Welcome"), message);
 
1147
}
 
1148
 
982
1149
/**************************************************************************
983
1150
...
984
1151
**************************************************************************/
1003
1170
    lines = "";
1004
1171
  }
1005
1172
 
1006
 
  if (!game.player_ptr
1007
 
      || !game.player_ptr->ai.control
 
1173
  if (NULL == client.conn.playing
 
1174
      || !client.conn.playing->ai_data.control
1008
1175
      || event != E_BROADCAST_REPORT) {
1009
1176
    popup_notify_dialog(caption, headline, lines);
1010
1177
    play_sound_for_event(event);
1056
1223
  bool check_focus = FALSE;     /* conservative focus change */
1057
1224
  bool moved = FALSE;
1058
1225
  bool ret = FALSE;
1059
 
  
 
1226
 
1060
1227
  punit = player_find_unit_by_id(unit_owner(packet_unit), packet_unit->id);
1061
1228
  if (!punit && game_find_unit_by_number(packet_unit->id)) {
1062
1229
    /* This means unit has changed owner. We deal with this here
1080
1247
 
1081
1248
    if (punit->activity != packet_unit->activity
1082
1249
        || punit->activity_target != packet_unit->activity_target
 
1250
        || punit->activity_base != packet_unit->activity_base
1083
1251
        || punit->transported_by != packet_unit->transported_by
1084
1252
        || punit->occupy != packet_unit->occupy
1085
1253
        || punit->has_orders != packet_unit->has_orders
1102
1270
 
1103
1271
      /* Wakeup Focus */
1104
1272
      if (wakeup_focus 
1105
 
          && game.player_ptr
1106
 
          && !game.player_ptr->ai.control
1107
 
          && unit_owner(punit) == game.player_ptr
 
1273
          && NULL != client.conn.playing
 
1274
          && !client.conn.playing->ai_data.control
 
1275
          && unit_owner(punit) == client.conn.playing
1108
1276
          && punit->activity == ACTIVITY_SENTRY
1109
1277
          && packet_unit->activity == ACTIVITY_IDLE
1110
 
          && !unit_is_in_focus(punit)
1111
 
          && is_player_phase(game.player_ptr, game.info.phase)) {
 
1278
          && !unit_is_in_focus(punit)
 
1279
          && is_player_phase(client.conn.playing, game.info.phase)) {
1112
1280
        /* many wakeup units per tile are handled */
1113
1281
        urgent_unit_focus(punit);
1114
1282
        check_focus = FALSE; /* and keep it */
1116
1284
 
1117
1285
      punit->activity = packet_unit->activity;
1118
1286
      punit->activity_target = packet_unit->activity_target;
 
1287
      punit->activity_base = packet_unit->activity_base;
1119
1288
 
1120
1289
      punit->transported_by = packet_unit->transported_by;
1121
1290
      if (punit->occupy != packet_unit->occupy
1140
1309
      punit->orders.list = packet_unit->orders.list;
1141
1310
      packet_unit->orders.list = NULL;
1142
1311
 
1143
 
      if (!game.player_ptr || unit_owner(punit) == game.player_ptr) {
 
1312
      if (NULL == client.conn.playing
 
1313
          || unit_owner(punit) == client.conn.playing) {
1144
1314
        refresh_unit_city_dialogs(punit);
1145
1315
      }
1146
1316
    } /*** End of Change in activity or activity's target. ***/
1174
1344
 
1175
1345
    if (punit->utype != unit_type(packet_unit)) {
1176
1346
      /* Unit type has changed (been upgraded) */
1177
 
      struct city *pcity = tile_get_city(punit->tile);
 
1347
      struct city *pcity = tile_city(punit->tile);
1178
1348
      
1179
1349
      punit->utype = unit_type(packet_unit);
1180
1350
      repaint_unit = TRUE;
1196
1366
 
1197
1367
    if (!same_pos(punit->tile, packet_unit->tile)) { 
1198
1368
      /*** Change position ***/
1199
 
      struct city *pcity = tile_get_city(punit->tile);
 
1369
      struct city *pcity = tile_city(punit->tile);
1200
1370
 
1201
1371
      old_tile = punit->tile;
1202
1372
      moved = TRUE;
1205
1375
      do_move_unit(punit, packet_unit);
1206
1376
 
1207
1377
      if(pcity)  {
1208
 
        if (can_player_see_units_in_city(game.player_ptr, pcity)) {
 
1378
        if (can_player_see_units_in_city(client.conn.playing, pcity)) {
1209
1379
          /* Unit moved out of a city - update the occupied status. */
1210
1380
          bool new_occupied =
1211
1381
            (unit_list_size(pcity->tile->units) > 0);
1225
1395
          refresh_city_dialog(pcity);
1226
1396
      }
1227
1397
      
1228
 
      if((pcity=tile_get_city(punit->tile)))  {
1229
 
        if (can_player_see_units_in_city(game.player_ptr, pcity)) {
1230
 
          /* Unit moved into a city - obviously it's occupied. */
1231
 
          if (!pcity->client.occupied) {
1232
 
            pcity->client.occupied = TRUE;
1233
 
            refresh_city_mapcanvas(pcity, pcity->tile, FALSE, FALSE);
 
1398
      if ((pcity = tile_city(unit_tile(punit)))) {
 
1399
        if (can_player_see_units_in_city(client.conn.playing, pcity)) {
 
1400
          /* Unit moved into a city - obviously it's occupied. */
 
1401
          if (!pcity->client.occupied) {
 
1402
            pcity->client.occupied = TRUE;
 
1403
            refresh_city_mapcanvas(pcity, pcity->tile, FALSE, FALSE);
1234
1404
            if (draw_full_citybar) {
1235
1405
              update_city_description(pcity);
1236
1406
            }
1237
 
          }
1238
 
        }
 
1407
          }
 
1408
        }
1239
1409
 
1240
1410
        if(pcity->id == punit->homecity)
1241
1411
          repaint_city = TRUE;
1243
1413
          refresh_city_dialog(pcity);
1244
1414
 
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);
1255
1425
          }
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);
1264
1434
            }
1265
1435
          } unit_list_iterate_end;
1268
1438
 
1269
1439
    }  /*** End of Change position. ***/
1270
1440
 
1271
 
    if (punit->unhappiness != packet_unit->unhappiness) {
1272
 
      punit->unhappiness = packet_unit->unhappiness;
1273
 
      repaint_city = TRUE;
1274
 
    }
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;
1279
 
      }
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);
1286
1446
      }
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));
1290
1450
      }
1291
1451
    }
1292
1452
 
 
1453
    /* unit upkeep information */
 
1454
    output_type_iterate(o) {
 
1455
      punit->upkeep[o] = packet_unit->upkeep[o];
 
1456
    } output_type_iterate_end;
 
1457
 
1293
1458
    punit->veteran = packet_unit->veteran;
1294
1459
    punit->moves_left = packet_unit->moves_left;
1295
1460
    punit->fuel = packet_unit->fuel;
1302
1467
 
1303
1468
    /* This won't change punit; it enqueues the call for later handling. */
1304
1469
    agents_unit_changed(punit);
 
1470
    editgui_notify_object_changed(OBJTYPE_UNIT, punit->id, FALSE);
1305
1471
  } else {
1306
1472
    /*** Create new unit ***/
1307
1473
    punit = packet_unit;
1327
1493
    repaint_unit = (punit->transported_by == -1);
1328
1494
    agents_unit_new(punit);
1329
1495
 
1330
 
    if ((pcity = tile_get_city(punit->tile))) {
 
1496
    if ((pcity = tile_city(punit->tile))) {
1331
1497
      /* The unit is in a city - obviously it's occupied. */
1332
1498
      pcity->client.occupied = TRUE;
1333
1499
    }
1346
1512
  }
1347
1513
 
1348
1514
  if ((check_focus || get_num_units_in_focus() == 0)
1349
 
      && game.player_ptr
1350
 
      && !game.player_ptr->ai.control
1351
 
      && is_player_phase(game.player_ptr, game.info.phase)) {
 
1515
      && NULL != client.conn.playing
 
1516
      && !client.conn.playing->ai_data.control
 
1517
      && is_player_phase(client.conn.playing, game.info.phase)) {
1352
1518
    update_unit_focus();
1353
1519
  }
1354
1520
 
1395
1561
      unit_list_iterate(pcity->info_units_supported, psunit) {
1396
1562
        destroy_unit_virtual(psunit);
1397
1563
      } unit_list_iterate_end;
1398
 
      unit_list_unlink_all(pcity->info_units_supported);
 
1564
      unit_list_clear(pcity->info_units_supported);
1399
1565
      unit_list_iterate(pcity->info_units_present, ppunit) {
1400
1566
        destroy_unit_virtual(ppunit);
1401
1567
      } unit_list_iterate_end;
1402
 
      unit_list_unlink_all(pcity->info_units_present);
 
1568
      unit_list_clear(pcity->info_units_present);
1403
1569
    }
1404
1570
 
1405
1571
    /* Okay, append a unit struct to the proper list. */
1415
1581
    return;
1416
1582
  }
1417
1583
 
1418
 
  if (packet->owner == game.info.player_idx) {
 
1584
  if (valid_player_by_number(packet->owner) == client.conn.playing) {
1419
1585
    freelog(LOG_ERROR, "handle_unit_short_info() for own unit.");
1420
1586
  }
1421
1587
 
1449
1615
  generate_citydlg_dimensions();
1450
1616
 
1451
1617
  calculate_overview_dimensions();
 
1618
 
 
1619
  packhand_init();
1452
1620
}
1453
1621
 
1454
1622
/**************************************************************************
1464
1632
    update_aifill_button = TRUE;
1465
1633
  }
1466
1634
  
 
1635
  if (game.info.is_edit_mode != pinfo->is_edit_mode) {
 
1636
    popdown_all_city_dialogs();
 
1637
  }
 
1638
 
1467
1639
  game.info = *pinfo;
1468
1640
 
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;                                        \
 
1648
  }
 
1649
 
 
1650
  VALIDATE(granary_num_inis,    MAX_GRANARY_INIS,       "granary entries");
 
1651
  VALIDATE(num_teams,           MAX_NUM_TEAMS,          "teams");
 
1652
#undef VALIDATE
 
1653
 
 
1654
  game.government_during_revolution =
 
1655
    government_by_number(game.info.government_during_revolution_id);
1472
1656
 
1473
1657
  boot_help = (can_client_change_view()
1474
1658
               && game.info.spacerace != pinfo->spacerace);
1476
1660
    set_seconds_to_turndone(pinfo->seconds_to_phasedone);
1477
1661
  }
1478
1662
  if (boot_help) {
1479
 
    boot_help_texts();          /* reboot, after setting game.spacerace */
 
1663
    boot_help_texts(client.conn.playing); /* reboot, after setting game.spacerace */
1480
1664
  }
1481
1665
  update_unit_focus();
 
1666
  update_menus();
 
1667
  update_players_dialog();
1482
1668
  if (update_aifill_button) {
1483
1669
    update_start_page();
1484
1670
  }
 
1671
  
 
1672
  if (can_client_change_view()) {
 
1673
    update_info_label();
 
1674
  }
 
1675
 
 
1676
  editgui_notify_object_changed(OBJTYPE_GAME, 1, FALSE);
1485
1677
}
1486
1678
 
1487
1679
/**************************************************************************
1492
1684
{
1493
1685
  bool need_effect_update = FALSE;
1494
1686
 
1495
 
  tech_type_iterate(i) {
1496
 
    enum tech_state oldstate
1497
 
      = get_player_research(pplayer)->inventions[i].state;
 
1687
#ifdef DEBUG
 
1688
  freelog(LOG_VERBOSE, "Player%d inventions:%s",
 
1689
          player_number(pplayer),
 
1690
          inventions);
 
1691
#endif
 
1692
 
 
1693
  advance_index_iterate(A_NONE, i) {
1498
1694
    enum tech_state newstate = inventions[i] - '0';
 
1695
    enum tech_state oldstate = player_invention_set(pplayer, i, newstate);
1499
1696
 
1500
 
    get_player_research(pplayer)->inventions[i].state = newstate;
1501
1697
    if (newstate != oldstate
1502
1698
        && (newstate == TECH_KNOWN || oldstate == TECH_KNOWN)) {
1503
1699
      need_effect_update = TRUE;
1504
1700
    }
1505
 
  } tech_type_iterate_end;
 
1701
  } advance_index_iterate_end;
1506
1702
 
1507
1703
  if (need_effect_update) {
1508
1704
    update_menus();
1509
1705
  }
1510
1706
 
1511
 
  update_research(pplayer);
 
1707
  player_research_update(pplayer);
1512
1708
  return need_effect_update;
1513
1709
}
1514
1710
 
1518
1714
**************************************************************************/
1519
1715
void set_government_choice(struct government *government)
1520
1716
{
1521
 
  if (can_client_issue_orders()
1522
 
      && game.player_ptr
1523
 
      && government != government_of_player(game.player_ptr)) {
1524
 
    dsend_packet_player_change_government(&aconnection, government->index);
 
1717
  if (NULL != client.conn.playing
 
1718
      && can_client_issue_orders()
 
1719
      && government != government_of_player(client.conn.playing)) {
 
1720
    dsend_packet_player_change_government(&client.conn, government_number(government));
1525
1721
  }
1526
1722
}
1527
1723
 
1531
1727
**************************************************************************/
1532
1728
void start_revolution(void)
1533
1729
{
1534
 
  dsend_packet_player_change_government(&aconnection,
1535
 
                                        game.info.government_when_anarchy_id);
1536
 
}
1537
 
 
1538
 
/**************************************************************************
1539
 
...
 
1730
  dsend_packet_player_change_government(&client.conn,
 
1731
                                    game.info.government_during_revolution_id);
 
1732
}
 
1733
 
 
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)
 
1740
{
 
1741
  struct player *pplayer;
 
1742
  pplayer = player_slot_by_number(playerno);
 
1743
 
 
1744
  if (NULL == pplayer) {
 
1745
    freelog(LOG_ERROR, "Invalid player slot number %d in "
 
1746
            "handle_player_remove().", playerno);
 
1747
    return;
 
1748
  }
 
1749
 
 
1750
  if (!player_slot_is_used(pplayer)) {
 
1751
    /* Ok, just ignore. */
 
1752
    return;
 
1753
  }
 
1754
 
 
1755
  game_remove_player(pplayer);
 
1756
  player_init(pplayer);
 
1757
 
 
1758
  player_slot_set_used(pplayer, FALSE);
 
1759
  set_player_count(player_count() - 1);
 
1760
 
 
1761
  update_players_dialog();
 
1762
  update_conn_list_dialog();
 
1763
 
 
1764
  if (can_client_change_view()) {
 
1765
    update_intel_dialog(pplayer);
 
1766
  }
 
1767
 
 
1768
  editgui_refresh();
 
1769
  editgui_notify_object_changed(OBJTYPE_PLAYER, player_number(pplayer),
 
1770
                                TRUE);
 
1771
}
 
1772
 
 
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)
1542
1779
{
1543
 
  int i;
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;
1548
 
  bool is_new_nation;
 
1780
  bool is_new_nation = FALSE;
 
1781
  bool new_tech = FALSE;
 
1782
  bool poptechup = FALSE;
 
1783
  bool turn_done_changed = FALSE;
 
1784
  int i, my_id;
 
1785
  struct player_research *research;
 
1786
  struct player *pplayer, *my_player;
 
1787
  struct nation_type *pnation;
 
1788
  struct government *pgov, *ptarget_gov;
 
1789
 
 
1790
 
 
1791
  /* First verify packet fields. */
 
1792
 
 
1793
  pplayer = player_slot_by_number(pinfo->playerno);
 
1794
 
 
1795
  if (NULL == pplayer) {
 
1796
    freelog(LOG_ERROR, "Invalid player slot number %d in "
 
1797
            "handle_player_info().", pinfo->playerno);
 
1798
    return;
 
1799
  }
 
1800
 
 
1801
  pnation = nation_by_number(pinfo->nation);
 
1802
  pgov = government_by_number(pinfo->government);
 
1803
  ptarget_gov = government_by_number(pinfo->target_government);
 
1804
 
 
1805
 
 
1806
  /* Now update the player information. */
 
1807
 
 
1808
  if (!player_slot_is_used(pplayer)) {
 
1809
    player_slot_set_used(pplayer, TRUE);
 
1810
    set_player_count(player_count() + 1);
 
1811
  }
1549
1812
 
1550
1813
  sz_strlcpy(pplayer->name, pinfo->name);
 
1814
  sz_strlcpy(pplayer->username, pinfo->username);
1551
1815
 
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;
1558
 
  } else {
1559
 
    pplayer->was_created = FALSE;
1560
 
  }
 
1820
  pplayer->was_created = pinfo->was_created;
1561
1821
 
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));
1572
1832
    }
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];
1578
1838
  }
1579
1839
 
 
1840
  my_id = client_player_number();
 
1841
  my_player = client_player();
 
1842
 
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. */
1583
 
  if (game.player_ptr
1584
 
      && pplayer->diplstates[player_index(game.player_ptr)].type
1585
 
      != DS_ARMISTICE
1586
 
      && pinfo->diplstates[player_index(game.player_ptr)].type
1587
 
      == DS_ARMISTICE) {
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) {
1590
1852
        continue;
1591
1853
      }
1592
1854
      if (punit->focus_status == FOCUS_WAIT) {
1598
1860
    } unit_list_iterate_end;
1599
1861
  }
1600
1862
 
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;
1610
1870
  }
1611
1871
  pplayer->is_connected = pinfo->is_connected;
1612
1872
 
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];
1615
1875
  }
1616
1876
 
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."));
 
1883
      } else {
 
1884
        output_window_append(ftc_client, _("AI mode is now OFF."));
 
1885
      }
1624
1886
    }
1625
1887
  }
1626
1888
 
1627
 
  pplayer->ai.science_cost = pinfo->science_cost;
 
1889
  pplayer->ai_data.science_cost = pinfo->science_cost;
1628
1890
 
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
1645
1907
 
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 */
1652
1914
  } else {
1653
1915
    research->researching = pinfo->researching;
1654
1916
  }
1655
1917
  research->future_tech = pinfo->future_tech;
1656
 
  research->tech_goal=pinfo->tech_goal;
 
1918
  research->tech_goal = pinfo->tech_goal;
1657
1919
  
1658
 
  if (can_client_change_view() && pplayer == game.player_ptr) {
1659
 
    if (poptechup || new_tech) {
1660
 
      science_dialog_update();
1661
 
    }
1662
 
    if (poptechup) {
1663
 
      if (game.player_ptr && !game.player_ptr->ai.control) {
1664
 
        popup_science_dialog(FALSE);
1665
 
      }
1666
 
    }
1667
 
    if (new_tech) {
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) {
1672
 
        update_menus();
1673
 
      }
1674
 
    }
1675
 
    economy_report_dialog_update();
1676
 
    activeunits_report_dialog_update();
1677
 
    city_report_dialog_update();
1678
 
  }
 
1920
  turn_done_changed = (pplayer->phase_done != pinfo->phase_done
 
1921
                       || pplayer->ai_data.control != pinfo->ai);
 
1922
  pplayer->phase_done = pinfo->phase_done;
1679
1923
 
1680
1924
  pplayer->is_ready = pinfo->is_ready;
1681
 
 
1682
 
  phase_done_changed = (pplayer->phase_done != pinfo->phase_done);
1683
 
  pplayer->phase_done = pinfo->phase_done;
1684
 
 
1685
 
  pplayer->nturns_idle=pinfo->nturns_idle;
1686
 
  pplayer->is_alive=pinfo->is_alive;
1687
 
 
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;
1691
 
 
1692
 
  if (pplayer == game.player_ptr && phase_done_changed) {
1693
 
    update_turn_done_button_state();
1694
 
  }
1695
 
  update_players_dialog();
1696
 
  update_worklist_report_dialog();
1697
 
  upgrade_canvas_clipboard();
1698
 
 
1699
 
  if (pplayer == game.player_ptr && can_client_change_view()) {
1700
 
    update_info_label();
1701
 
  }
 
1929
  pplayer->ai_data.skill_level = pinfo->ai_skill_level;
1702
1930
 
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;
1717
1945
  }
1718
1946
 
1719
 
  sz_strlcpy(pplayer->username, pinfo->username);
 
1947
 
 
1948
  /* The player information is now fully set. Update the GUI. */
 
1949
 
 
1950
  if (pplayer == my_player && can_client_change_view()) {
 
1951
    if (poptechup || new_tech) {
 
1952
      science_dialog_update();
 
1953
    }
 
1954
    if (poptechup) {
 
1955
      if (client_has_player() && !my_player->ai_data.control) {
 
1956
        popup_science_dialog(FALSE);
 
1957
      }
 
1958
    }
 
1959
    if (new_tech) {
 
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) {
 
1964
        update_menus();
 
1965
      }
 
1966
    }
 
1967
    if (turn_done_changed) {
 
1968
      update_turn_done_button_state();
 
1969
    }
 
1970
    economy_report_dialog_update();
 
1971
    activeunits_report_dialog_update();
 
1972
    city_report_dialog_update();
 
1973
    update_info_label();
 
1974
  }
 
1975
 
 
1976
  upgrade_canvas_clipboard();
 
1977
 
 
1978
  update_players_dialog();
 
1979
  update_conn_list_dialog();
1720
1980
 
1721
1981
  if (is_new_nation) {
1722
1982
    races_toggles_set_sensitive();
 
1983
 
 
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();
1723
1987
  }
 
1988
 
1724
1989
  if (can_client_change_view()) {
1725
1990
    /* Just about any changes above require an update to the intelligence
1726
1991
     * dialog. */
1727
1992
    update_intel_dialog(pplayer);
1728
1993
  }
1729
 
  update_conn_list_dialog();
 
1994
 
 
1995
  editgui_refresh();
 
1996
  editgui_notify_object_changed(OBJTYPE_PLAYER, player_number(pplayer),
 
1997
                                FALSE);
1730
1998
}
1731
1999
 
1732
2000
/**************************************************************************
1738
2006
void handle_conn_info(struct packet_conn_info *pinfo)
1739
2007
{
1740
2008
  struct connection *pconn = find_conn_by_id(pinfo->id);
 
2009
  bool preparing_client_state = FALSE;
1741
2010
 
1742
2011
  freelog(LOG_DEBUG, "conn_info id%d used%d est%d plr%d obs%d acc%d",
1743
2012
          pinfo->id, pinfo->used, pinfo->established, pinfo->player_num,
1754
2023
    client_remove_cli_conn(pconn);
1755
2024
    pconn = NULL;
1756
2025
  } else {
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);
1763
 
    
 
2026
    struct player *pplayer = player_slot_by_number(pinfo->player_num);
 
2027
 
1764
2028
    if (!pconn) {
1765
2029
      freelog(LOG_VERBOSE, "Server reports new connection %d %s",
1766
 
              pinfo->id, pinfo->username);
1767
 
 
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;
 
2034
      } else {
 
2035
        pconn = fc_calloc(1, sizeof(struct connection));
 
2036
        pconn->buffer = NULL;
 
2037
        pconn->send_buffer = NULL;
 
2038
        pconn->ping_time = -1.0;
 
2039
      }
1772
2040
      if (pplayer) {
1773
2041
        conn_list_append(pplayer->connections, pconn);
1774
2042
      }
1775
2043
      conn_list_append(game.all_connections, pconn);
1776
2044
      conn_list_append(game.est_connections, pconn);
1777
2045
    } else {
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);
1783
2051
        }
1784
2052
        if (pplayer) {
1785
2053
          conn_list_append(pplayer->connections, pconn);
1786
2054
        }
1787
2055
      }
1788
2056
    }
 
2057
 
 
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
 
2062
       * the game. */
 
2063
      preparing_client_state = TRUE;
 
2064
    }
 
2065
 
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;
 
2071
 
1794
2072
    sz_strlcpy(pconn->username, pinfo->username);
1795
2073
    sz_strlcpy(pconn->addr, pinfo->addr);
1796
2074
    sz_strlcpy(pconn->capability, pinfo->capability);
 
2075
  }
1797
2076
 
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;
1803
 
    }
1804
 
  }
1805
2077
  update_players_dialog();
1806
2078
  update_conn_list_dialog();
 
2079
 
 
2080
  if (pinfo->used && pconn == &client.conn) {
 
2081
    /* For updating the sensitivity of the "Edit Mode" menu item,
 
2082
     * among other things. */
 
2083
    update_menus();
 
2084
  }
 
2085
 
 
2086
  if (preparing_client_state) {
 
2087
    set_client_state(C_S_PREPARING);
 
2088
  }
1807
2089
}
1808
2090
 
1809
2091
/*************************************************************************
1881
2163
    }
1882
2164
    assert(num <= NUM_SS_MODULES / 3);
1883
2165
 
1884
 
    dsend_packet_spaceship_place(&aconnection, type, num);
 
2166
    dsend_packet_spaceship_place(&client.conn, type, num);
1885
2167
    return TRUE;
1886
2168
  }
1887
2169
  if (ship->components > ship->fuel + ship->propulsion) {
1892
2174
      type = SSHIP_PLACE_PROPULSION;
1893
2175
      num = ship->propulsion + 1;
1894
2176
    }
1895
 
    dsend_packet_spaceship_place(&aconnection, type, num);
 
2177
    dsend_packet_spaceship_place(&client.conn, type, num);
1896
2178
    return TRUE;
1897
2179
  }
1898
2180
  if (ship->structurals > num_spaceship_structurals_placed(ship)) {
1907
2189
      /* if we don't have the first structural, place that! */
1908
2190
      type = SSHIP_PLACE_STRUCTURAL;
1909
2191
      num = 0;
1910
 
      dsend_packet_spaceship_place(&aconnection, type, num);
 
2192
      dsend_packet_spaceship_place(&client.conn, type, num);
1911
2193
      return TRUE;
1912
2194
    }
1913
2195
    
1965
2247
    }
1966
2248
    type = SSHIP_PLACE_STRUCTURAL;
1967
2249
    num = req;
1968
 
    dsend_packet_spaceship_place(&aconnection, type, num);
 
2250
    dsend_packet_spaceship_place(&client.conn, type, num);
1969
2251
    return TRUE;
1970
2252
  }
1971
2253
  return FALSE;
1977
2259
void handle_spaceship_info(struct packet_spaceship_info *p)
1978
2260
{
1979
2261
  int i;
1980
 
  struct player *pplayer = &game.players[p->player_num];
1981
 
  struct player_spaceship *ship = &pplayer->spaceship;
1982
 
  
 
2262
  struct player_spaceship *ship;
 
2263
  struct player *pplayer = valid_player_by_number(p->player_num);
 
2264
 
 
2265
  if (NULL == pplayer) {
 
2266
    freelog(LOG_ERROR,
 
2267
            "handle_spaceship_info() bad player number %d.",
 
2268
            p->player_num);
 
2269
    return;
 
2270
  }
 
2271
  ship = &pplayer->spaceship;
1983
2272
  ship->state        = p->sship_state;
1984
2273
  ship->structurals  = p->structurals;
1985
2274
  ship->components   = p->components;
2012
2301
    }
2013
2302
  }
2014
2303
 
2015
 
  if (pplayer != game.player_ptr) {
 
2304
  if (pplayer != client.conn.playing) {
2016
2305
    refresh_spaceship_dialog(pplayer);
2017
2306
    return;
2018
2307
  }
2028
2317
**************************************************************************/
2029
2318
void handle_tile_info(struct packet_tile_info *packet)
2030
2319
{
 
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);
2036
 
 
2037
 
  if (!ptile->terrain || ptile->terrain->index != packet->type) {
 
2328
  const struct nation_type *pnation;
 
2329
 
 
2330
  if (NULL == ptile) {
 
2331
    freelog(LOG_ERROR,
 
2332
            "handle_tile_info() invalid tile (%d,%d).",
 
2333
            TILE_XY(packet));
 
2334
    return;
 
2335
  }
 
2336
  old_known = client_tile_get_known(ptile);
 
2337
 
 
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);
2042
2343
      break;
2043
 
    case TILE_KNOWN_FOGGED:
2044
 
    case TILE_KNOWN:
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);
2047
2348
      } else {
2048
2349
        tile_changed = FALSE;
2049
2350
        freelog(LOG_ERROR,
2053
2354
      break;
2054
2355
    };
2055
2356
  }
 
2357
 
2056
2358
  tile_special_type_iterate(spe) {
2057
2359
    if (packet->special[spe]) {
2058
2360
      if (!tile_has_special(ptile, spe)) {
2066
2368
      }
2067
2369
    }
2068
2370
  } tile_special_type_iterate_end;
2069
 
 
2070
 
  if (NULL != ptile->resource) {
2071
 
    tile_changed |= (ptile->resource->index != packet->resource);
2072
 
  } else {
2073
 
    tile_changed |= (-1 != packet->resource);
 
2371
  if (!BV_ARE_EQUAL(ptile->bases, packet->bases)) {
 
2372
    ptile->bases = packet->bases;
 
2373
    tile_changed = TRUE;
2074
2374
  }
2075
2375
 
 
2376
  tile_changed = tile_changed || (tile_resource(ptile) != presource);
 
2377
 
2076
2378
  /* always called after setting terrain */
2077
 
  tile_set_resource(ptile, resource_by_number(packet->resource));
2078
 
 
2079
 
  if (packet->owner == MAP_TILE_OWNER_NULL) {
2080
 
    if (tile_owner(ptile)) {
2081
 
      tile_set_owner(ptile, NULL);
2082
 
      tile_changed = TRUE;
2083
 
    }
2084
 
  } else {
2085
 
    struct player *newowner = player_by_number(packet->owner);
2086
 
 
2087
 
    if (tile_owner(ptile) != newowner) {
2088
 
      tile_set_owner(ptile, newowner);
2089
 
      tile_changed = TRUE;
2090
 
    }
2091
 
  }
 
2379
  tile_set_resource(ptile, presource);
 
2380
 
 
2381
  if (tile_owner(ptile) != powner) {
 
2382
    tile_set_owner(ptile, powner, NULL);
 
2383
    tile_changed = TRUE;
 
2384
  }
 
2385
 
 
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);
 
2390
 
 
2391
      if (NULL == pwork) {
 
2392
        char named[MAX_LEN_NAME];
 
2393
        struct player *placeholder = powner;
 
2394
 
 
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.
 
2399
           */
 
2400
          placeholder = player_by_number(MAX_NUM_PLAYERS);
 
2401
        }
 
2402
        my_snprintf(named, sizeof(named), "%06u", packet->worked);
 
2403
 
 
2404
        pwork = create_city_virtual(placeholder, NULL, named);
 
2405
        pwork->id = packet->worked;
 
2406
        idex_register_city(pwork);
 
2407
 
 
2408
        city_list_prepend(invisible_cities, pwork);
 
2409
 
 
2410
        freelog(LOG_DEBUG, "(%d,%d) invisible city %d, %s",
 
2411
                TILE_XY(ptile),
 
2412
                pwork->id,
 
2413
                city_name(pwork));
 
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 */
 
2418
          pwork->owner =
 
2419
          pwork->original = powner;
 
2420
        }
 
2421
      }
 
2422
 
 
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);
 
2427
    } else {
 
2428
      tile_set_worked(ptile, NULL);
 
2429
    }
 
2430
 
 
2431
    tile_changed = TRUE;
 
2432
  }
 
2433
 
2092
2434
  if (old_known != packet->known) {
2093
2435
    known_changed = TRUE;
2094
2436
  }
2095
 
  if (game.player_ptr) {
2096
 
    BV_CLR(ptile->tile_known, game.info.player_idx);
 
2437
 
 
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;
2100
2443
 
2101
2444
    switch (packet->known) {
2102
 
    case TILE_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;
2107
2450
      break;
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));
2110
2453
      break;
2111
2454
    case TILE_UNKNOWN:
2112
2455
      break;
2117
2460
      break;
2118
2461
    };
2119
2462
  }
 
2463
  new_known = client_tile_get_known(ptile);
2120
2464
 
2121
2465
  if (packet->spec_sprite[0] != '\0') {
2122
2466
    if (!ptile->spec_sprite
2135
2479
    }
2136
2480
  }
2137
2481
 
2138
 
  if (client_tile_get_known(ptile) <= TILE_KNOWN_FOGGED
2139
 
      && old_known == TILE_KNOWN) {
 
2482
  if (packet->nation_start == NATION_ANY) {
 
2483
    if (!map_has_startpos(ptile) || map_get_startpos(ptile) != NULL) {
 
2484
      map_set_startpos(ptile, NULL);
 
2485
      tile_changed = TRUE;
 
2486
    }
 
2487
  } else {
 
2488
    pnation = nation_by_number(packet->nation_start);
 
2489
    if (pnation == NULL) {
 
2490
      if (map_has_startpos(ptile)) {
 
2491
        map_clear_startpos(ptile);
 
2492
        tile_changed = TRUE;
 
2493
      }
 
2494
    } else if (map_get_startpos(ptile) != pnation) {
 
2495
      map_set_startpos(ptile, pnation);
 
2496
      tile_changed = TRUE;
 
2497
    }
 
2498
  }
 
2499
 
 
2500
  if (TILE_KNOWN_SEEN == old_known && TILE_KNOWN_SEEN != new_known) {
2140
2501
    /* This is an error.  So first we log the error, then make an assertion.
2141
2502
     * But for NDEBUG clients we fix the error. */
2142
2503
    unit_list_iterate(ptile->units, punit) {
2148
2509
              player_name(unit_owner(punit)));
2149
2510
    } unit_list_iterate_end;
2150
2511
    assert(unit_list_size(ptile->units) == 0);
2151
 
    unit_list_unlink_all(ptile->units);
 
2512
    unit_list_clear(ptile->units);
2152
2513
  }
2153
2514
 
2154
2515
  ptile->continent = packet->continent;
2159
2520
     * A tile can only change if it was known before and is still
2160
2521
     * known. In the other cases the tile is new or removed.
2161
2522
     */
2162
 
    if (known_changed && client_tile_get_known(ptile) == TILE_KNOWN) {
 
2523
    if (known_changed && TILE_KNOWN_SEEN == new_known) {
2163
2524
      agents_tile_new(ptile);
2164
 
    } else if (known_changed && client_tile_get_known(ptile) == TILE_KNOWN_FOGGED) {
 
2525
    } else if (known_changed && TILE_KNOWN_UNSEEN == new_known) {
2165
2526
      agents_tile_remove(ptile);
2166
2527
    } else {
2167
2528
      agents_tile_changed(ptile);
2168
2529
    }
 
2530
    editgui_notify_object_changed(OBJTYPE_TILE, tile_index(ptile), FALSE);
2169
2531
  }
2170
2532
 
2171
2533
  /* refresh tiles */
2172
2534
  if (can_client_change_view()) {
2173
2535
    /* the tile itself (including the necessary parts of adjacent tiles) */
2174
 
    if (tile_changed || old_known != client_tile_get_known(ptile)) {
 
2536
    if (tile_changed || old_known != new_known) {
2175
2537
      refresh_tile_mapcanvas(ptile, TRUE, FALSE);
2176
2538
    }
2177
2539
  }
2185
2547
}
2186
2548
 
2187
2549
/**************************************************************************
2188
 
...
 
2550
  Received packet containing info about current scenario
2189
2551
**************************************************************************/
2190
 
void handle_player_remove(int player_id)
 
2552
void handle_scenario_info(struct packet_scenario_info *packet)
2191
2553
{
2192
 
  if (player_id < 0 || player_id >= MAX_NUM_PLAYERS) {
2193
 
    freelog(LOG_ERROR, "Illegal player_remove packet from server (%d)",
2194
 
            player_id);
2195
 
    return;
2196
 
  }
 
2554
  game.scenario.is_scenario = packet->is_scenario;
 
2555
  sz_strlcpy(game.scenario.name, packet->name);
 
2556
  sz_strlcpy(game.scenario.description, packet->description);
 
2557
  game.scenario.players = packet->players;
2197
2558
 
2198
 
  client_remove_player(player_id);
2199
 
  update_conn_list_dialog();
 
2559
  editgui_notify_object_changed(OBJTYPE_GAME, 1, FALSE);
2200
2560
}
2201
2561
 
2202
2562
/**************************************************************************
2206
2566
**************************************************************************/
2207
2567
void handle_ruleset_control(struct packet_ruleset_control *packet)
2208
2568
{
2209
 
  int i;
2210
 
 
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();
2214
2572
 
2215
 
  ruleset_data_free();
2216
 
 
2217
 
  ruleset_cache_init();
2218
 
 
 
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);
 
2576
 
 
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;                                     \
 
2584
  }
 
2585
 
 
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");
 
2591
 
 
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. */
 
2595
 
 
2596
  VALIDATE(terrain_count,       MAX_NUM_TERRAINS,       "terrains");
 
2597
  VALIDATE(resource_count,      MAX_NUM_RESOURCES,      "resources");
 
2598
 
 
2599
  VALIDATE(num_specialist_types, SP_MAX,                "specialists");
 
2600
#undef VALIDATE
 
2601
 
 
2602
  governments_alloc(game.control.government_count);
 
2603
  nations_alloc(game.control.nation_count);
 
2604
  city_styles_alloc(game.control.styles_count);
2223
2605
 
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;
2231
 
  }
 
2611
  player_slots_iterate(pslot) {
 
2612
    pslot->nation = NULL;
 
2613
  } player_slots_iterate_end;
2232
2614
 
2233
2615
  if (packet->prefered_tileset[0] != '\0') {
2234
2616
    /* There is tileset suggestion */
2242
2624
/**************************************************************************
2243
2625
...
2244
2626
**************************************************************************/
 
2627
void handle_ruleset_unit_class(struct packet_ruleset_unit_class *p)
 
2628
{
 
2629
  struct unit_class *c = uclass_by_number(p->id);
 
2630
 
 
2631
  if (!c) {
 
2632
    freelog(LOG_ERROR,
 
2633
            "handle_ruleset_unit_class() bad unit_class %d.",
 
2634
            p->id);
 
2635
    return;
 
2636
  }
 
2637
 
 
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;
 
2645
}
 
2646
 
 
2647
 
 
2648
/**************************************************************************
 
2649
...
 
2650
**************************************************************************/
2245
2651
void handle_ruleset_unit(struct packet_ruleset_unit *p)
2246
2652
{
2247
 
  struct unit_type *u;
2248
2653
  int i;
 
2654
  struct unit_type *u = utype_by_number(p->id);
2249
2655
 
2250
 
  if(p->id < 0 || p->id >= game.control.num_unit_types || p->id >= U_LAST) {
 
2656
  if(!u) {
2251
2657
    freelog(LOG_ERROR,
2252
2658
            "handle_ruleset_unit() bad unit_type %d.",
2253
2659
            p->id);
2254
2660
    return;
2255
2661
  }
2256
 
  u = utype_by_number(p->id);
2257
2662
 
2258
2663
  sz_strlcpy(u->name.vernacular, p->name);
2259
2664
  u->name.translated = NULL;    /* unittype.c utype_name_translation */
2264
2669
  sz_strlcpy(u->sound_fight, p->sound_fight);
2265
2670
  sz_strlcpy(u->sound_fight_alt, p->sound_fight_alt);
2266
2671
 
2267
 
  u->move_type          = p->move_type;
2268
2672
  u->uclass             = uclass_by_number(p->unit_class_id);
2269
2673
  u->build_cost         = p->build_cost;
2270
2674
  u->pop_cost           = p->pop_cost;
2271
2675
  u->attack_strength    = p->attack_strength;
2272
2676
  u->defense_strength   = p->defense_strength;
2273
2677
  u->move_rate          = p->move_rate;
2274
 
  u->tech_requirement   = p->tech_requirement;
2275
 
  u->impr_requirement   = p->impr_requirement;
2276
 
  u->gov_requirement = government_by_number(p->gov_requirement);
 
2678
  u->require_advance    = advance_by_number(p->tech_requirement);
 
2679
  u->need_improvement   = improvement_by_number(p->impr_requirement);
 
2680
  u->need_government    = government_by_number(p->gov_requirement);
2277
2681
  u->vision_radius_sq = p->vision_radius_sq;
2278
2682
  u->transport_capacity = p->transport_capacity;
2279
2683
  u->hp                 = p->hp;
2290
2694
  u->paratroopers_mr_req = p->paratroopers_mr_req;
2291
2695
  u->paratroopers_mr_sub = p->paratroopers_mr_sub;
2292
2696
  u->bombard_rate       = p->bombard_rate;
 
2697
  u->city_size          = p->city_size;
 
2698
  u->cargo              = p->cargo;
 
2699
  u->targets            = p->targets;
2293
2700
 
2294
2701
  for (i = 0; i < MAX_VET_LEVELS; i++) {
2295
2702
    sz_strlcpy(u->veteran[i].name, p->veteran_name[i]);
2307
2714
**************************************************************************/
2308
2715
void handle_ruleset_tech(struct packet_ruleset_tech *p)
2309
2716
{
2310
 
  struct advance *a;
 
2717
  struct advance *a = advance_by_number(p->id);
2311
2718
 
2312
 
  if(p->id < 0 || p->id >= game.control.num_tech_types || p->id >= A_LAST) {
 
2719
  if(!a) {
2313
2720
    freelog(LOG_ERROR,
2314
2721
            "handle_ruleset_tech() bad advance %d.",
2315
2722
            p->id);
2316
2723
    return;
2317
2724
  }
2318
 
  a = &advances[p->id];
2319
2725
 
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);
2331
 
  
2332
 
  tileset_setup_tech_type(tileset, p->id);
 
2737
 
 
2738
  tileset_setup_tech_type(tileset, a);
2333
2739
}
2334
2740
 
2335
2741
/**************************************************************************
2356
2762
    requirement_vector_append(&b->reqs, &p->reqs[i]);
2357
2763
  }
2358
2764
  assert(b->reqs.size == p->reqs_count);
2359
 
  b->obsolete_by = p->obsolete_by;
 
2765
  b->obsolete_by = advance_by_number(p->obsolete_by);
 
2766
  b->replaced_by = improvement_by_number(p->replaced_by);
2360
2767
  b->build_cost = p->build_cost;
2361
2768
  b->upkeep = p->upkeep;
2362
2769
  b->sabotage = p->sabotage;
2366
2773
  sz_strlcpy(b->soundtag_alt, p->soundtag_alt);
2367
2774
 
2368
2775
#ifdef DEBUG
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",
2376
 
                b->obsolete_by,
 
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));
2378
 
      } else {
2379
 
        freelog(LOG_DEBUG, "  obsolete_by %2d/Never", b->obsolete_by);
2380
2784
      }
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;
2386
2790
  }
2387
2791
#endif
2388
2792
 
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;
2393
2797
      break;
2394
2798
    }
2395
2799
  } unit_type_iterate_end;
2396
2800
 
2397
 
  tileset_setup_impr_type(tileset, p->id);
 
2801
  tileset_setup_impr_type(tileset, b);
2398
2802
}
2399
2803
 
2400
2804
/**************************************************************************
2402
2806
**************************************************************************/
2403
2807
void handle_ruleset_government(struct packet_ruleset_government *p)
2404
2808
{
2405
 
  struct government *gov;
2406
2809
  int j;
 
2810
  struct government *gov = government_by_number(p->id);
2407
2811
 
2408
 
  if (p->id < 0 || p->id >= game.control.government_count) {
 
2812
  if (!gov) {
2409
2813
    freelog(LOG_ERROR,
2410
2814
            "handle_ruleset_government() bad government %d.",
2411
2815
            p->id);
2412
2816
    return;
2413
2817
  }
2414
 
  gov = &governments[p->id];
2415
2818
 
2416
 
  gov->index             = p->id;
 
2819
  gov->item_number = p->id;
2417
2820
 
2418
2821
  for (j = 0; j < p->reqs_count; j++) {
2419
2822
    requirement_vector_append(&gov->reqs, &p->reqs[j]);
2432
2835
 
2433
2836
  gov->helptext = mystrdup(p->helptext);
2434
2837
  
2435
 
  tileset_setup_government(tileset, p->id);
 
2838
  tileset_setup_government(tileset, gov);
2436
2839
}
2437
2840
 
2438
2841
/**************************************************************************
2441
2844
void handle_ruleset_government_ruler_title
2442
2845
  (struct packet_ruleset_government_ruler_title *p)
2443
2846
{
2444
 
  struct government *gov;
 
2847
  struct government *gov = government_by_number(p->gov);
2445
2848
 
2446
 
  if(p->gov < 0 || p->gov >= game.control.government_count) {
 
2849
  if(!gov) {
2447
2850
    freelog(LOG_ERROR,
2448
2851
            "handle_ruleset_government_ruler_title()"
2449
2852
            " bad government %d.",
2450
2853
            p->gov);
2451
2854
    return;
2452
2855
  }
2453
 
  gov = &governments[p->gov];
 
2856
 
2454
2857
  if(p->id < 0 || p->id >= gov->num_ruler_titles) {
2455
2858
    freelog(LOG_ERROR,
2456
2859
            "handle_ruleset_government_ruler_title()"
2481
2884
    return;
2482
2885
  }
2483
2886
 
 
2887
  pterrain->native_to = p->native_to;
2484
2888
  sz_strlcpy(pterrain->name.vernacular, p->name_orig);
2485
2889
  pterrain->name.translated = NULL;     /* terrain.c terrain_name_translation */
2486
2890
  sz_strlcpy(pterrain->graphic_str, p->graphic_str);
2520
2924
  pterrain->transform_result = terrain_by_number(p->transform_result);
2521
2925
  pterrain->transform_time = p->transform_time;
2522
2926
  pterrain->rail_time = p->rail_time;
2523
 
  pterrain->airbase_time = p->airbase_time;
2524
 
  pterrain->fortress_time = p->fortress_time;
2525
2927
  pterrain->clean_pollution_time = p->clean_pollution_time;
2526
2928
  pterrain->clean_fallout_time = p->clean_fallout_time;
2527
2929
 
2561
2963
  tileset_setup_resource(tileset, presource);
2562
2964
}
2563
2965
 
 
2966
/****************************************************************************
 
2967
  Handle a packet about a particular base type.
 
2968
****************************************************************************/
 
2969
void handle_ruleset_base(struct packet_ruleset_base *p)
 
2970
{
 
2971
  int i;
 
2972
  struct base_type *pbase = base_by_number(p->id);
 
2973
 
 
2974
  if (!pbase) {
 
2975
    freelog(LOG_ERROR,
 
2976
            "handle_ruleset_base() bad base %d.",
 
2977
            p->id);
 
2978
    return;
 
2979
  }
 
2980
 
 
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;
 
2988
 
 
2989
  for (i = 0; i < p->reqs_count; i++) {
 
2990
    requirement_vector_append(&pbase->reqs, &p->reqs[i]);
 
2991
  }
 
2992
  assert(pbase->reqs.size == p->reqs_count);
 
2993
 
 
2994
  pbase->native_to = p->native_to;
 
2995
 
 
2996
  pbase->gui_type = p->gui_type;
 
2997
 
 
2998
  pbase->build_time = p->build_time;
 
2999
  pbase->border_sq  = p->border_sq;
 
3000
 
 
3001
  pbase->flags = p->flags;
 
3002
 
 
3003
  tileset_setup_base(tileset, pbase);
 
3004
}
 
3005
 
2564
3006
/**************************************************************************
2565
3007
  Handle the terrain control ruleset packet sent by the server.
2566
3008
**************************************************************************/
2616
3058
  pl->city_style = p->city_style;
2617
3059
 
2618
3060
  pl->is_playable = p->is_playable;
2619
 
  pl->is_barbarian = p->is_barbarian;
 
3061
  pl->barb_type = p->barbarian_type;
2620
3062
 
2621
3063
  memcpy(pl->init_techs, p->init_techs, sizeof(pl->init_techs));
2622
3064
  memcpy(pl->init_buildings, p->init_buildings, 
2636
3078
  for (i = 0; i < p->ngroups; i++) {
2637
3079
    pl->groups[i] = nation_group_by_number(p->groups[i]);
2638
3080
    if (!pl->groups[i]) {
2639
 
      freelog(LOG_FATAL, "Nation %s: Unknown group %d.",
2640
 
                nation_rule_name(pl),
2641
 
                p->groups[i]);
2642
 
      exit(EXIT_FAILURE);
 
3081
      freelog(LOG_ERROR,
 
3082
              "handle_ruleset_nation() \"%s\" have unknown group %d.",
 
3083
              nation_rule_name(pl),
 
3084
              p->groups[i]);
 
3085
      pl->groups[i] = nation_group_by_number(0); /* default group */
2643
3086
    }
2644
3087
  }
2645
3088
 
2646
3089
  pl->is_available = p->is_available;
2647
3090
 
2648
 
  tileset_setup_nation_flag(tileset, p->id);
 
3091
  tileset_setup_nation_flag(tileset, pl);
2649
3092
}
2650
3093
 
2651
3094
/**************************************************************************
2652
 
...
 
3095
  Handle city style packet.
2653
3096
**************************************************************************/
2654
3097
void handle_ruleset_city(struct packet_ruleset_city *packet)
2655
3098
{
2664
3107
    return;
2665
3108
  }
2666
3109
  cs = &city_styles[id];
2667
 
  
 
3110
 
2668
3111
  for (j = 0; j < packet->reqs_count; j++) {
2669
3112
    requirement_vector_append(&cs->reqs, &packet->reqs[j]);
2670
3113
  }
2675
3118
  cs->name.translated = NULL;
2676
3119
  sz_strlcpy(cs->graphic, packet->graphic);
2677
3120
  sz_strlcpy(cs->graphic_alt, packet->graphic_alt);
 
3121
  sz_strlcpy(cs->oceanic_graphic, packet->oceanic_graphic);
 
3122
  sz_strlcpy(cs->oceanic_graphic_alt, packet->oceanic_graphic_alt);
2678
3123
  sz_strlcpy(cs->citizens_graphic, packet->citizens_graphic);
2679
3124
  sz_strlcpy(cs->citizens_graphic_alt, packet->citizens_graphic_alt);
2680
3125
 
2692
3137
  DEFAULT_SPECIALIST = packet->default_specialist;
2693
3138
 
2694
3139
  for (i = 0; i < MAX_VET_LEVELS; i++) {
2695
 
    game.trireme_loss_chance[i] = packet->trireme_loss_chance[i];
2696
3140
    game.work_veteran_chance[i] = packet->work_veteran_chance[i];
2697
3141
    game.veteran_chance[i] = packet->work_veteran_chance[i];
2698
3142
  }
2704
3148
void handle_ruleset_specialist(struct packet_ruleset_specialist *p)
2705
3149
{
2706
3150
  int j;
2707
 
  struct specialist *s;
 
3151
  struct specialist *s = specialist_by_number(p->id);
2708
3152
 
2709
 
  if (p->id < 0 || p->id >= game.control.num_specialist_types) {
 
3153
  if (!s) {
2710
3154
    freelog(LOG_ERROR,
2711
3155
            "handle_ruleset_specialist() bad specialist %d.",
2712
3156
            p->id);
 
3157
    return;
2713
3158
  }
2714
3159
 
2715
 
  s = get_specialist(p->id);
2716
 
 
2717
 
  sz_strlcpy(s->name, p->name);
2718
 
  sz_strlcpy(s->short_name, p->short_name);
 
3160
  sz_strlcpy(s->name.vernacular, p->name);
 
3161
  s->name.translated = NULL;
 
3162
  sz_strlcpy(s->abbreviation.vernacular, p->short_name);
 
3163
  s->abbreviation.translated = NULL;
2719
3164
 
2720
3165
  for (j = 0; j < p->reqs_count; j++) {
2721
3166
    requirement_vector_append(&s->reqs, &p->reqs[j]);
2730
3175
**************************************************************************/
2731
3176
void handle_city_name_suggestion_info(int unit_id, char *name)
2732
3177
{
2733
 
  struct unit *punit = player_find_unit_by_id(game.player_ptr, unit_id);
 
3178
  struct unit *punit = player_find_unit_by_id(client.conn.playing, unit_id);
2734
3179
 
2735
3180
  if (!can_client_issue_orders()) {
2736
3181
    return;
2740
3185
    if (ask_city_name) {
2741
3186
      popup_newcity_dialog(punit, name);
2742
3187
    } else {
2743
 
      dsend_packet_unit_build_city(&aconnection, unit_id,name);
 
3188
      dsend_packet_unit_build_city(&client.conn, unit_id,name);
2744
3189
    }
2745
3190
  }
2746
3191
}
2753
3198
{
2754
3199
  struct city *pcity = game_find_city_by_number(target_id);
2755
3200
  struct unit *punit = game_find_unit_by_number(target_id);
2756
 
  struct unit *pdiplomat =
2757
 
      player_find_unit_by_id(game.player_ptr, diplomat_id);
 
3201
  struct unit *pdiplomat = player_find_unit_by_id(client.conn.playing, diplomat_id);
2758
3202
 
2759
3203
  if (NULL == pdiplomat) {
 
3204
    freelog(LOG_ERROR,
 
3205
            "handle_unit_diplomat_answer() bad diplomat %d.",
 
3206
            diplomat_id);
2760
3207
    return;
2761
3208
  }
2762
3209
 
2763
3210
  switch (action_type) {
2764
3211
  case DIPLOMAT_BRIBE:
2765
3212
    if (punit) {
2766
 
      if (game.player_ptr && !game.player_ptr->ai.control) {
 
3213
      if (NULL != client.conn.playing
 
3214
          && !client.conn.playing->ai_data.control) {
2767
3215
        popup_bribe_dialog(punit, cost);
2768
3216
      }
2769
3217
    }
2770
3218
    break;
2771
3219
  case DIPLOMAT_INCITE:
2772
3220
    if (pcity) {
2773
 
      if (game.player_ptr && !game.player_ptr->ai.control) {
 
3221
      if (NULL != client.conn.playing
 
3222
          && !client.conn.playing->ai_data.control) {
2774
3223
        popup_incite_dialog(pcity, cost);
2775
3224
      }
2776
3225
    }
2795
3244
void handle_city_sabotage_list(int diplomat_id, int city_id,
2796
3245
                               bv_imprs improvements)
2797
3246
{
2798
 
  struct unit *punit = player_find_unit_by_id(game.player_ptr, diplomat_id);
2799
3247
  struct city *pcity = game_find_city_by_number(city_id);
2800
 
 
2801
 
  if (punit && pcity && can_client_issue_orders()) {
2802
 
    impr_type_iterate(i) {
2803
 
      pcity->improvements[i] = BV_ISSET(improvements, i) ? I_ACTIVE : I_NONE;
2804
 
    } impr_type_iterate_end;
 
3248
  struct unit *pdiplomat = player_find_unit_by_id(client.conn.playing, diplomat_id);
 
3249
 
 
3250
  if (NULL == pdiplomat) {
 
3251
    freelog(LOG_ERROR,
 
3252
            "handle_city_sabotage_list() bad diplomat %d.",
 
3253
            diplomat_id);
 
3254
    return;
 
3255
  }
 
3256
 
 
3257
  if (NULL == pcity) {
 
3258
    freelog(LOG_ERROR,
 
3259
            "handle_city_sabotage_list() bad city %d.",
 
3260
            city_id);
 
3261
    return;
 
3262
  }
 
3263
 
 
3264
  if (can_client_issue_orders()) {
 
3265
    improvement_iterate(pimprove) {
 
3266
      if (!BV_ISSET(improvements, improvement_index(pimprove))) {
 
3267
        update_improvement_from_packet(pcity, pimprove, FALSE);
 
3268
      }
 
3269
    } improvement_iterate_end;
2805
3270
 
2806
3271
    popup_sabotage_dialog(pcity);
2807
3272
  }
2812
3277
**************************************************************************/
2813
3278
void handle_endgame_report(struct packet_endgame_report *packet)
2814
3279
{
 
3280
  set_client_state(C_S_OVER);
 
3281
 
2815
3282
  popup_endgame_report_dialog(packet);
2816
3283
}
2817
3284
 
2820
3287
**************************************************************************/
2821
3288
void handle_player_attribute_chunk(struct packet_player_attribute_chunk *packet)
2822
3289
{
2823
 
  if (!game.player_ptr) {
 
3290
  if (NULL == client.conn.playing) {
2824
3291
    return;
2825
3292
  }
2826
 
  generic_handle_player_attribute_chunk(game.player_ptr, packet);
 
3293
 
 
3294
  generic_handle_player_attribute_chunk(client.conn.playing, packet);
2827
3295
 
2828
3296
  if (packet->offset + packet->chunk_length == packet->total_length) {
2829
3297
    /* We successful received the last chunk. The attribute block is
2839
3307
{
2840
3308
  agents_processing_started();
2841
3309
 
2842
 
  assert(aconnection.client.request_id_of_currently_handled_packet == 0);
2843
 
  aconnection.client.request_id_of_currently_handled_packet =
2844
 
      get_next_request_id(aconnection.
 
3310
  assert(client.conn.client.request_id_of_currently_handled_packet == 0);
 
3311
  client.conn.client.request_id_of_currently_handled_packet =
 
3312
      get_next_request_id(client.conn.
2845
3313
                          client.last_processed_request_id_seen);
2846
3314
 
2847
3315
  freelog(LOG_DEBUG, "start processing packet %d",
2848
 
          aconnection.client.request_id_of_currently_handled_packet);
 
3316
          client.conn.client.request_id_of_currently_handled_packet);
2849
3317
}
2850
3318
 
2851
3319
/**************************************************************************
2856
3324
  int i;
2857
3325
 
2858
3326
  freelog(LOG_DEBUG, "finish processing packet %d",
2859
 
          aconnection.client.request_id_of_currently_handled_packet);
2860
 
 
2861
 
  assert(aconnection.client.request_id_of_currently_handled_packet != 0);
2862
 
 
2863
 
  aconnection.client.last_processed_request_id_seen =
2864
 
      aconnection.client.request_id_of_currently_handled_packet;
2865
 
 
2866
 
  aconnection.client.request_id_of_currently_handled_packet = 0;
 
3327
          client.conn.client.request_id_of_currently_handled_packet);
 
3328
 
 
3329
  assert(client.conn.client.request_id_of_currently_handled_packet != 0);
 
3330
 
 
3331
  client.conn.client.last_processed_request_id_seen =
 
3332
      client.conn.client.request_id_of_currently_handled_packet;
 
3333
 
 
3334
  client.conn.client.request_id_of_currently_handled_packet = 0;
2867
3335
 
2868
3336
  for (i = 0; i < reports_thaw_requests_size; i++) {
2869
3337
    if (reports_thaw_requests[i] != 0 &&
2870
3338
        reports_thaw_requests[i] ==
2871
 
        aconnection.client.last_processed_request_id_seen) {
 
3339
        client.conn.client.last_processed_request_id_seen) {
2872
3340
      reports_thaw();
2873
3341
      reports_thaw_requests[i] = 0;
2874
3342
    }
2883
3351
void notify_about_incoming_packet(struct connection *pc,
2884
3352
                                   int packet_type, int size)
2885
3353
{
2886
 
  assert(pc == &aconnection);
 
3354
  assert(pc == &client.conn);
2887
3355
  freelog(LOG_DEBUG, "incoming packet={type=%d, size=%d}", packet_type,
2888
3356
          size);
2889
3357
}
2895
3363
                                  int packet_type, int size,
2896
3364
                                  int request_id)
2897
3365
{
2898
 
  assert(pc == &aconnection);
 
3366
  assert(pc == &client.conn);
2899
3367
  freelog(LOG_DEBUG, "outgoing packet={type=%d, size=%d, request_id=%d}",
2900
3368
          packet_type, size, request_id);
2901
3369
 
2969
3437
**************************************************************************/
2970
3438
void handle_conn_ping(void)
2971
3439
{
2972
 
  send_packet_conn_pong(&aconnection);
 
3440
  send_packet_conn_pong(&client.conn);
2973
3441
}
2974
3442
 
2975
3443
/**************************************************************************
2997
3465
}
2998
3466
 
2999
3467
/**************************************************************************
 
3468
  Handle a notification from the server that an object was successfully
 
3469
  created. The 'tag' was previously sent to the server when the client
 
3470
  requested the creation. The 'id' is the identifier of the newly created
 
3471
  object.
 
3472
**************************************************************************/
 
3473
void handle_edit_object_created(int tag, int id)
 
3474
{
 
3475
  editgui_notify_object_created(tag, id);
 
3476
}
 
3477
 
 
3478
/**************************************************************************
3000
3479
  A vote no longer exists. Remove from queue and update gui.
3001
3480
**************************************************************************/
3002
3481
void handle_vote_remove(int vote_no)