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

« back to all changes in this revision

Viewing changes to server/edithand.c

  • Committer: Package Import Robot
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2011-08-28 22:40:00 UTC
  • mfrom: (1.2.19 upstream)
  • Revision ID: package-import@ubuntu.com-20110828224000-j2r1erewlem25dox
Tags: 2.3.0-1
[ Karl Goetz ]
* New upstream version.
* Fix themes_sdl_use_system_fonts.diff to apply cleanly on 2.3.0
* Massage work_around_unity_induced_breakage.diff to get it
  applying to the new codebase (The patch assumes commits made
  after 2.3.0 was tagged upstream).

[ Clint Adams ]
* Fudge build system to think there is no libtool mismatch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#include <config.h>
16
16
#endif
17
17
 
18
 
#include <assert.h>
19
18
#include <limits.h> /* USHRT_MAX */
20
19
 
21
20
/* utility */
 
21
#include "bitvector.h"
22
22
#include "fcintl.h"
23
 
#include "hash.h"
24
23
#include "log.h"
25
24
#include "shared.h"
26
25
#include "support.h"
33
32
#include "movement.h"
34
33
#include "nation.h"
35
34
#include "terrain.h"
 
35
#include "research.h"
36
36
#include "unitlist.h"
37
37
 
38
38
/* generator */
47
47
#include "maphand.h"
48
48
#include "plrhand.h"
49
49
#include "notify.h"
 
50
#include "sanitycheck.h"
50
51
#include "srv_main.h"
51
52
#include "stdinhand.h"
52
53
#include "techtools.h"
54
55
 
55
56
#include "edithand.h"
56
57
 
57
 
/* This table holds pointers to tiles for which expensive
58
 
 * checks (e.g. assign_continent_numbers) have been left
59
 
 * until after a sequence of edits is complete. */
60
 
static struct hash_table *unfixed_tile_table;
 
58
/* This table holds pointers to tiles for which expensive checks (e.g.
 
59
 * assign_continent_numbers) have been left until after a sequence of
 
60
 * edits is complete. */
 
61
static struct tile_hash *unfixed_tile_table = NULL;
61
62
 
62
63
/* Array of size player_slot_count() indexed by player
63
64
 * number to tell whether a given player has fog of war
69
70
****************************************************************************/
70
71
void edithand_init(void)
71
72
{
72
 
  if (unfixed_tile_table != NULL) {
73
 
    hash_free(unfixed_tile_table);
 
73
  if (NULL != unfixed_tile_table) {
 
74
    tile_hash_destroy(unfixed_tile_table);
74
75
  }
75
 
  unfixed_tile_table = hash_new(hash_fval_keyval, hash_fcmp_keyval);
 
76
  unfixed_tile_table = tile_hash_new();
76
77
 
77
78
  if (unfogged_players != NULL) {
78
79
    free(unfogged_players);
85
86
****************************************************************************/
86
87
void edithand_free(void)
87
88
{
88
 
  if (unfixed_tile_table != NULL) {
89
 
    hash_free(unfixed_tile_table);
 
89
  if (NULL != unfixed_tile_table) {
 
90
    tile_hash_destroy(unfixed_tile_table);
90
91
    unfixed_tile_table = NULL;
91
92
  }
92
93
 
97
98
}
98
99
 
99
100
/****************************************************************************
 
101
  Send the needed packets for connections entering in the editing mode.
 
102
****************************************************************************/
 
103
void edithand_send_initial_packets(struct conn_list *dest)
 
104
{
 
105
  struct packet_edit_startpos startpos;
 
106
  struct packet_edit_startpos_full startpos_full;
 
107
 
 
108
  if (NULL == dest) {
 
109
    dest = game.est_connections;
 
110
  }
 
111
 
 
112
  /* Send map start positions. */
 
113
  map_startpos_iterate(psp) {
 
114
    startpos.id = tile_index(startpos_tile(psp));
 
115
    startpos.remove = FALSE;
 
116
    startpos.tag = 0;
 
117
 
 
118
    startpos_pack(psp, &startpos_full);
 
119
 
 
120
    conn_list_iterate(dest, pconn) {
 
121
      if (can_conn_edit(pconn)) {
 
122
        send_packet_edit_startpos(pconn, &startpos);
 
123
        send_packet_edit_startpos_full(pconn, &startpos_full);
 
124
      }
 
125
    } conn_list_iterate_end;
 
126
  } map_startpos_iterate_end;
 
127
}
 
128
 
 
129
/****************************************************************************
100
130
  Do the potentially slow checks required after some tile's terrain changes.
101
131
****************************************************************************/
102
132
static void check_edited_tile_terrains(void)
103
133
{
104
 
  if (hash_num_entries(unfixed_tile_table) < 1) {
 
134
  if (0 >= tile_hash_size(unfixed_tile_table)) {
105
135
    return;
106
136
  }
107
137
 
108
 
  hash_keys_iterate(unfixed_tile_table, ptile) {
 
138
  tile_hash_iterate(unfixed_tile_table, ptile) {
109
139
    fix_tile_on_terrain_change(ptile, FALSE);
110
 
  } hash_keys_iterate_end;
111
 
  hash_delete_all_entries(unfixed_tile_table);
 
140
    bounce_units_on_terrain_change(ptile);
 
141
    sanity_check_tile(ptile);
 
142
  } tile_hash_iterate_end;
 
143
  tile_hash_clear(unfixed_tile_table);
112
144
 
113
145
  assign_continent_numbers();
114
 
  send_all_known_tiles(NULL, FALSE);
 
146
  send_all_known_tiles(NULL);
115
147
}
116
148
 
117
149
/****************************************************************************
157
189
 
158
190
  if (game.info.is_edit_mode && !is_edit_mode) {
159
191
    notify_conn(NULL, NULL, E_SETTING, ftc_editor,
160
 
                _(" *** Edit mode cancelled by %s. *** "),
 
192
                _(" *** Edit mode canceled by %s. *** "),
161
193
                conn_description(pc));
162
194
 
163
195
    check_leaving_edit_mode();
166
198
  if (game.info.is_edit_mode != is_edit_mode) {
167
199
    game.info.is_edit_mode = is_edit_mode;
168
200
 
169
 
    /* We make startpos information available to clients only when in edit
170
 
     * mode. */
171
 
    whole_map_iterate(ptile) {
172
 
      if (map_has_startpos(ptile)) {
173
 
        send_tile_info(NULL, ptile, TRUE, FALSE);
174
 
      }
175
 
    } whole_map_iterate_end;
176
 
 
177
201
    send_game_info(NULL);
 
202
    edithand_send_initial_packets(NULL);
178
203
  }
179
204
}
180
205
 
196
221
 
197
222
  tile_change_terrain(ptile, pterrain);
198
223
  if (need_to_fix_terrain_change(old_terrain, pterrain)) {
199
 
    hash_insert(unfixed_tile_table, ptile, ptile);
 
224
    tile_hash_insert(unfixed_tile_table, ptile, NULL);
200
225
  }
201
226
 
202
227
  if (send_tile_info) {
303
328
  square of "radius" 'size' should be affected. So size=1 corresponds to
304
329
  the single tile case.
305
330
****************************************************************************/
306
 
void handle_edit_tile_terrain(struct connection *pc, int x, int y,
 
331
void handle_edit_tile_terrain(struct connection *pc, int tile,
307
332
                              Terrain_type_id terrain, int size)
308
333
{
309
334
  struct terrain *pterrain;
310
335
  struct tile *ptile_center;
311
336
 
312
 
  ptile_center = map_pos_to_tile(x, y);
 
337
  ptile_center = index_to_tile(tile);
313
338
  if (!ptile_center) {
314
339
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
315
 
                _("Cannot edit the tile (%d, %d) because "
316
 
                  "it is not on the map!"), x, y);
 
340
                _("Cannot edit the tile because %d is not a valid "
 
341
                  "tile index on this map!"), tile);
317
342
    return;
318
343
  }
319
344
 
337
362
/****************************************************************************
338
363
  Handle a request to change one or more tiles' resources.
339
364
****************************************************************************/
340
 
void handle_edit_tile_resource(struct connection *pc, int x, int y,
 
365
void handle_edit_tile_resource(struct connection *pc, int tile,
341
366
                               Resource_type_id resource, int size)
342
367
{
343
368
  struct resource *presource;
344
369
  struct tile *ptile_center;
345
 
  
346
 
  ptile_center = map_pos_to_tile(x, y);
 
370
 
 
371
  ptile_center = index_to_tile(tile);
347
372
  if (!ptile_center) {
348
373
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
349
 
                _("Cannot edit the tile (%d, %d) because "
350
 
                  "it is not on the map!"), x, y);
 
374
                _("Cannot edit the tile because %d is not a valid "
 
375
                  "tile index on this map!"), tile);
351
376
    return;
352
377
  }
353
378
  presource = resource_by_number(resource); /* May be NULL. */
364
389
  argument controls whether to remove or add the given special of type
365
390
  'special' from the tile.
366
391
****************************************************************************/
367
 
void handle_edit_tile_special(struct connection *pc, int x, int y,
 
392
void handle_edit_tile_special(struct connection *pc, int tile,
368
393
                              enum tile_special_type special,
369
394
                              bool remove, int size)
370
395
{
371
396
  struct tile *ptile_center;
372
397
 
373
 
  ptile_center = map_pos_to_tile(x, y);
 
398
  ptile_center = index_to_tile(tile);
374
399
  if (!ptile_center) {
375
400
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
376
 
                _("Cannot edit the tile (%d, %d) because "
377
 
                  "it is not on the map!"), x, y);
 
401
                _("Cannot edit the tile because %d is not a valid "
 
402
                  "tile index on this map!"), tile);
378
403
    return;
379
404
  }
380
405
 
397
422
/****************************************************************************
398
423
  Handle a request to change the military base at one or more than one tile.
399
424
****************************************************************************/
400
 
void handle_edit_tile_base(struct connection *pc, int x, int y,
 
425
void handle_edit_tile_base(struct connection *pc, int tile,
401
426
                           Base_type_id id, bool remove, int size)
402
427
{
403
428
  struct tile *ptile_center;
404
429
  struct base_type *pbase;
405
430
 
406
 
  ptile_center = map_pos_to_tile(x, y);
 
431
  ptile_center = index_to_tile(tile);
407
432
  if (!ptile_center) {
408
433
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
409
 
                _("Cannot edit the tile (%d, %d) because "
410
 
                  "it is not on the map!"), x, y);
 
434
                _("Cannot edit the tile because %d is not a valid "
 
435
                  "tile index on this map!"), tile);
411
436
    return;
412
437
  }
413
438
 
433
458
  Handles tile information from the client, to make edits to tiles.
434
459
****************************************************************************/
435
460
void handle_edit_tile(struct connection *pc,
436
 
                      struct packet_edit_tile *packet)
 
461
                      const struct packet_edit_tile *packet)
437
462
{
438
463
  struct tile *ptile;
439
 
  int id;
440
464
  bool changed = FALSE;
441
465
 
442
 
  id = packet->id;
443
 
  ptile = index_to_tile(id);
444
 
 
 
466
  ptile = index_to_tile(packet->tile);
445
467
  if (!ptile) {
446
468
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
447
 
                _("No such tile (ID %d)."), id);
 
469
                _("Cannot edit the tile because %d is not a valid "
 
470
                  "tile index on this map!"), packet->tile);
448
471
    return;
449
472
  }
450
473
 
473
496
  /* Send the new state to all affected. */
474
497
  if (changed) {
475
498
    update_tile_knowledge(ptile);
476
 
    send_tile_info(NULL, ptile, FALSE, FALSE);
 
499
    send_tile_info(NULL, ptile, FALSE);
477
500
  }
478
501
}
479
502
 
481
504
  Handle a request to create 'count' units of type 'utid' at the tile given
482
505
  by the x, y coordinates and owned by player with number 'owner'.
483
506
****************************************************************************/
484
 
void handle_edit_unit_create(struct connection *pc,
485
 
                             struct packet_edit_unit_create *packet)
 
507
void handle_edit_unit_create(struct connection *pc, int owner, int tile,
 
508
                             Unit_type_id utid, int count, int tag)
486
509
{
487
 
  int owner, x, y, utid, count, tag;
488
510
  struct tile *ptile;
489
511
  struct unit_type *punittype;
490
512
  struct player *pplayer;
491
513
  struct city *homecity;
492
514
  struct unit *punit;
493
 
  bool coastal;
 
515
  bool only_ocean;
494
516
  int id, i;
495
517
 
496
 
  owner = packet->owner;
497
 
  x = packet->x;
498
 
  y = packet->y;
499
 
  utid = packet->type;
500
 
  count = packet->count;
501
 
  tag = packet->tag;
502
 
 
503
 
  ptile = map_pos_to_tile(x, y);
 
518
  ptile = index_to_tile(tile);
504
519
  if (!ptile) {
505
520
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
506
 
                _("Cannot create units at tile (%d, %d) because "
507
 
                  "it is not on the map!"), x, y);
 
521
                _("Cannot create units because %d is not a valid "
 
522
                  "tile index on this map!"), tile);
508
523
    return;
509
524
  }
510
525
 
518
533
    return;
519
534
  }
520
535
 
521
 
  pplayer = valid_player_by_number(owner);
 
536
  pplayer = player_by_number(owner);
522
537
  if (!pplayer) {
523
538
    notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
524
539
                /* TRANS: ..." type <unit-type> at <tile-coordinates>"... */
553
568
 
554
569
  if (count > 0 && !pplayer->is_alive) {
555
570
    pplayer->is_alive = TRUE;
556
 
    send_player_info(pplayer, NULL);
 
571
    send_player_info_c(pplayer, NULL);
557
572
  }
558
573
 
559
574
  /* FIXME: Make this more general? */
560
 
  coastal = is_sailing_unittype(punittype);
 
575
  only_ocean = is_sailing_unittype(punittype);
561
576
 
562
 
  homecity = find_closest_owned_city(pplayer, ptile, coastal, NULL);
 
577
  homecity = find_closest_city(ptile, NULL, pplayer, only_ocean, FALSE, FALSE,
 
578
                               TRUE, FALSE);
563
579
  id = homecity ? homecity->id : 0;
564
580
 
565
581
  conn_list_do_buffer(game.est_connections);
580
596
  tile (x, y).
581
597
****************************************************************************/
582
598
void handle_edit_unit_remove(struct connection *pc, int owner,
583
 
                             int x, int y, Unit_type_id utid, int count)
 
599
                             int tile, Unit_type_id utid, int count)
584
600
{
585
601
  struct tile *ptile;
586
602
  struct unit_type *punittype;
587
603
  struct player *pplayer;
588
604
  int i;
589
605
 
590
 
  ptile = map_pos_to_tile(x, y);
 
606
  ptile = index_to_tile(tile);
591
607
  if (!ptile) {
592
608
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
593
 
                _("Cannot remove units at tile (%d, %d) because "
594
 
                  "it is not on the map!"), x, y);
 
609
                _("Cannot remove units because %d is not a valid "
 
610
                  "tile index on this map!"), tile);
595
611
    return;
596
612
  }
597
613
 
605
621
    return;
606
622
  }
607
623
 
608
 
  pplayer = valid_player_by_number(owner);
 
624
  pplayer = player_by_number(owner);
609
625
  if (!pplayer) {
610
626
    notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
611
627
                /* TRANS: ..." type <unit-type> at <tile-coordinates>
638
654
{
639
655
  struct unit *punit;
640
656
 
641
 
  punit = game_find_unit_by_number(id);
 
657
  punit = game_unit_by_number(id);
642
658
  if (!punit) {
643
659
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
644
660
                _("No such unit (ID %d)."), id);
652
668
  Handles unit information from the client, to make edits to units.
653
669
****************************************************************************/
654
670
void handle_edit_unit(struct connection *pc,
655
 
                      struct packet_edit_unit *packet)
 
671
                      const struct packet_edit_unit *packet)
656
672
{
657
673
  struct tile *ptile;
658
674
  struct unit_type *putype;
663
679
  int moves_left, fuel, hp;
664
680
 
665
681
  id = packet->id;
666
 
  punit = game_find_unit_by_number(id);
 
682
  punit = game_unit_by_number(id);
667
683
  if (!punit) {
668
684
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
669
685
                _("No such unit (ID %d)."), id);
705
721
  if (packet->veteran != punit->veteran
706
722
      && !unit_has_type_flag(punit, F_NO_VETERAN)) {
707
723
    int v = packet->veteran;
708
 
    if (putype->veteran[v].name[0] == '\0') {
 
724
    if (rule_name(&putype->veteran[v].name) == '\0') {
709
725
      notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
710
726
                  _("Invalid veteran level %d for unit %d (%s)."),
711
727
                  v, id, unit_link(punit));
728
744
  Allows the editing client to create a city at the given position and
729
745
  of size 'size'.
730
746
****************************************************************************/
731
 
void handle_edit_city_create(struct connection *pc, int owner, int x, int y,
 
747
void handle_edit_city_create(struct connection *pc, int owner, int tile,
732
748
                             int size, int tag)
733
749
{
734
750
  struct tile *ptile;
735
751
  struct city *pcity;
736
752
  struct player *pplayer;
737
 
  
738
 
  ptile = map_pos_to_tile(x, y);
 
753
 
 
754
  ptile = index_to_tile(tile);
739
755
  if (!ptile) {
740
756
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
741
 
                _("Cannot create a city at (%d, %d) because "
742
 
                  "it is not on the map!"), x, y);
 
757
                _("Cannot create a city because %d is not a valid "
 
758
                  "tile index on this map!"), tile);
743
759
    return;
744
760
  }
745
761
 
765
781
 
766
782
  if (!pplayer->is_alive) {
767
783
    pplayer->is_alive = TRUE;
768
 
    send_player_info(pplayer, NULL);
 
784
    send_player_info_c(pplayer, NULL);
769
785
  }
770
786
 
771
787
  conn_list_do_buffer(game.est_connections);
792
808
  Handle a request to change the internal state of a city.
793
809
****************************************************************************/
794
810
void handle_edit_city(struct connection *pc,
795
 
                      struct packet_edit_city *packet)
 
811
                      const struct packet_edit_city *packet)
796
812
{
797
813
  struct tile *ptile;
798
814
  struct city *pcity, *oldcity;
803
819
  bool need_game_info = FALSE;
804
820
  bv_player need_player_info;
805
821
 
806
 
  pcity = game_find_city_by_number(packet->id);
 
822
  pcity = game_city_by_number(packet->id);
807
823
  if (!pcity) {
808
824
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
809
825
                _("Cannot edit city with invalid city ID %d."),
865
881
               && packet->built[id] >= 0) {
866
882
 
867
883
      if (is_great_wonder(pimprove)) {
868
 
        oldcity = find_city_from_great_wonder(pimprove);
 
884
        oldcity = city_from_great_wonder(pimprove);
869
885
        if (oldcity != pcity) {
870
886
          BV_SET(need_player_info, player_index(pplayer));
871
887
        }
875
891
          BV_SET(need_player_info, player_index(city_owner(oldcity)));
876
892
        }
877
893
      } else if (is_small_wonder(pimprove)) {
878
 
        oldcity = find_city_from_small_wonder(pplayer, pimprove);
 
894
        oldcity = city_from_small_wonder(pplayer, pimprove);
879
895
        if (oldcity != pcity) {
880
896
          BV_SET(need_player_info, player_index(pplayer));
881
897
        }
941
957
    players_iterate(aplayer) {
942
958
      if (BV_ISSET(need_player_info, player_index(aplayer))) {
943
959
        /* No need to send to detached connections. */
944
 
        send_player_info(aplayer, NULL);
 
960
        send_player_info_c(aplayer, NULL);
945
961
      }
946
962
    } players_iterate_end;
947
963
  }
980
996
  }
981
997
 
982
998
 
983
 
  pplayer = server_create_player();
 
999
  pplayer = server_create_player(-1);
984
1000
  if (!pplayer) {
985
1001
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
986
1002
                _("Player creation failed."));
987
1003
    return;
988
1004
  }
989
1005
 
990
 
  player_map_free(pplayer);
991
1006
  server_player_init(pplayer, TRUE, TRUE);
992
1007
  player_set_nation(pplayer, pnation);
993
 
  pick_random_player_name(pnation, pplayer->name);
 
1008
  server_player_set_name(pplayer, pick_random_player_name(pnation));
994
1009
  sz_strlcpy(pplayer->username, ANON_USER_NAME);
995
1010
  pplayer->is_connected = FALSE;
996
 
  pplayer->government = pnation->init_government;
997
 
  pplayer->capital = FALSE;
 
1011
  pplayer->government = pnation->server.init_government;
 
1012
  pplayer->server.capital = FALSE;
998
1013
 
999
1014
  pplayer->economic.gold = 0;
1000
1015
  pplayer->economic = player_limit_to_max_rates(pplayer);
1003
1018
  give_global_initial_techs(pplayer);
1004
1019
  give_nation_initial_techs(pplayer);
1005
1020
 
1006
 
  send_player_info(pplayer, NULL);
 
1021
  send_player_all_c(pplayer, NULL);
1007
1022
  if (tag > 0) {
1008
1023
    dsend_packet_edit_object_created(pc, tag, player_number(pplayer));
1009
1024
  }
1016
1031
{
1017
1032
  struct player *pplayer;
1018
1033
 
1019
 
  pplayer = valid_player_by_number(id);
 
1034
  pplayer = player_by_number(id);
1020
1035
  if (pplayer == NULL) {
1021
1036
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1022
1037
                _("No such player (ID %d)."), id);
1034
1049
    map_clear_known(ptile, pplayer);
1035
1050
  } whole_map_iterate_end;
1036
1051
  server_remove_player(pplayer);
1037
 
  send_player_slot_info_c(pplayer, NULL);
1038
1052
}
1039
1053
 
1040
1054
/**************************************************************************
1041
1055
  Handle editing of any or all player properties.
1042
1056
***************************************************************************/
1043
1057
void handle_edit_player(struct connection *pc, 
1044
 
                        struct packet_edit_player *packet)
 
1058
                        const struct packet_edit_player *packet)
1045
1059
{
1046
1060
  struct player *pplayer;
1047
1061
  bool changed = FALSE, update_research = FALSE;
1049
1063
  struct player_research *research;
1050
1064
  enum tech_state known;
1051
1065
 
1052
 
  pplayer = valid_player_by_number(packet->id);
 
1066
  pplayer = player_by_number(packet->id);
1053
1067
  if (!pplayer) {
1054
1068
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1055
1069
                _("Cannot edit player with invalid player ID %d."),
1057
1071
    return;
1058
1072
  }
1059
1073
 
1060
 
  research = get_player_research(pplayer);
 
1074
  research = player_research_get(pplayer);
1061
1075
 
1062
1076
 
1063
1077
  /* Handle player name change. */
1064
1078
  if (0 != strcmp(packet->name, player_name(pplayer))) {
1065
 
    if (packet->name[0] == '\0') {
 
1079
    char error_buf[256];
 
1080
 
 
1081
    if (server_player_set_name_full(pc, pplayer, NULL, packet->name,
 
1082
                                    error_buf, sizeof(error_buf))) {
 
1083
      changed = TRUE;
 
1084
    } else {
1066
1085
      notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1067
 
                  _("Cannot set empty name for player (%d) '%s'."),
1068
 
                  player_number(pplayer), player_name(pplayer));
1069
 
    } else {
1070
 
      bool valid = TRUE;
1071
 
 
1072
 
      players_iterate(other_player) {
1073
 
        if (other_player == pplayer) {
1074
 
          continue;
1075
 
        }
1076
 
        if (0 != mystrcasecmp(player_name(other_player), packet->name)) {
1077
 
          continue;
1078
 
        }
1079
 
        notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1080
 
                    _("Cannot change name of player (%d) '%s' to '%s': "
1081
 
                      "another player (%d) already has that name."),
1082
 
                    player_number(pplayer), player_name(pplayer),
1083
 
                    packet->name, player_number(other_player));
1084
 
        valid = FALSE;
1085
 
        break;
1086
 
      } players_iterate_end;
1087
 
 
1088
 
      if (valid) {
1089
 
        sz_strlcpy(pplayer->name, packet->name);
1090
 
        changed = TRUE;
1091
 
      }
 
1086
                  _("Cannot change name of player (%d) '%s' to '%s': %s"),
 
1087
                  player_number(pplayer), player_name(pplayer),
 
1088
                  packet->name, error_buf);
1092
1089
    }
1093
1090
  }
1094
1091
 
1182
1179
  }
1183
1180
 
1184
1181
  if (changed) {
1185
 
    send_player_info(pplayer, NULL);
 
1182
    send_player_all_c(pplayer, NULL);
1186
1183
  }
1187
1184
}
1188
1185
 
1190
1187
  Handles vision editing requests from client.
1191
1188
****************************************************************************/
1192
1189
void handle_edit_player_vision(struct connection *pc, int plr_no,
1193
 
                               int x, int y, bool known, int size)
 
1190
                               int tile, bool known, int size)
1194
1191
{
1195
1192
  struct player *pplayer;
1196
1193
  struct tile *ptile_center;
1197
1194
 
1198
 
  ptile_center = map_pos_to_tile(x, y);
 
1195
  ptile_center = index_to_tile(tile);
1199
1196
  if (!ptile_center) {
1200
1197
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1201
 
                _("Cannot edit vision for the tile at (%d, %d) because "
1202
 
                  "it is not on the map!"), x, y);
 
1198
                _("Cannot edit vision because %d is not a valid "
 
1199
                  "tile index on this map!"), tile);
1203
1200
    return;
1204
1201
  }
1205
1202
 
1206
 
  pplayer = valid_player_by_number(plr_no);
 
1203
  pplayer = player_by_number(plr_no);
1207
1204
  if (!pplayer) {
1208
1205
    notify_conn(pc->self, ptile_center, E_BAD_COMMAND, ftc_editor,
1209
1206
                /* TRANS: ..." at <tile-coordinates> because"... */
1277
1274
{
1278
1275
  struct city *pcity;
1279
1276
 
1280
 
  pcity = game_find_city_by_number(id);
 
1277
  pcity = game_city_by_number(id);
1281
1278
  if (pcity == NULL) {
1282
1279
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1283
1280
                _("No such city (ID %d)."), id);
1311
1308
    return;
1312
1309
  }
1313
1310
 
1314
 
  pplayer = valid_player_by_number(plr_no);
 
1311
  pplayer = player_by_number(plr_no);
1315
1312
  if (!pplayer) {
1316
1313
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1317
1314
                _("Cannot toggle fog-of-war for invalid player ID %d."),
1331
1328
}
1332
1329
 
1333
1330
/****************************************************************************
1334
 
  Set the given position to be the start position for the given nation.
 
1331
  Create or remove a start position at a tile.
1335
1332
****************************************************************************/
1336
 
void handle_edit_startpos(struct connection *pc, int x, int y,
1337
 
                          Nation_type_id nation)
 
1333
void handle_edit_startpos(struct connection *pconn,
 
1334
                          const struct packet_edit_startpos *packet)
1338
1335
{
1339
 
  struct tile *ptile;
1340
 
  const struct nation_type *pnation, *old;
1341
 
  bool removed = FALSE;
 
1336
  struct tile *ptile = index_to_tile(packet->id);
 
1337
  bool changed;
1342
1338
 
1343
 
  ptile = map_pos_to_tile(x, y);
1344
 
  if (!ptile) {
1345
 
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1346
 
                _("Cannot place a start position at (%d, %d) because "
1347
 
                  "it is not on the map!"), x, y);
 
1339
  /* Check. */
 
1340
  if (NULL == ptile) {
 
1341
    notify_conn(pconn->self, NULL, E_BAD_COMMAND, ftc_editor,
 
1342
                _("Invalid tile index %d for start position."), packet->id);
1348
1343
    return;
1349
1344
  }
1350
1345
 
1351
 
  old = map_get_startpos(ptile);
1352
 
 
1353
 
  if (nation == NATION_NONE) {
1354
 
    if (map_has_startpos(ptile)) {
1355
 
      map_clear_startpos(ptile);
1356
 
      removed = TRUE;
 
1346
  /* Handle. */
 
1347
  if (packet->remove) {
 
1348
    changed = map_startpos_remove(ptile);
 
1349
  } else {
 
1350
    if (NULL != map_startpos_get(ptile)) {
 
1351
      changed = FALSE;
 
1352
    } else {
 
1353
      map_startpos_new(ptile);
 
1354
      changed = TRUE;
1357
1355
    }
1358
 
    pnation = NULL;
1359
 
  } else if (nation == NATION_ANY) {
1360
 
    map_set_startpos(ptile, NULL);
1361
 
    pnation = NULL;
1362
 
  } else {
1363
 
    pnation = nation_by_number(nation);
1364
 
    map_set_startpos(ptile, pnation);
1365
 
  }
1366
 
 
1367
 
  if (old != pnation || removed) {
1368
 
    send_tile_info(NULL, ptile, FALSE, FALSE);
 
1356
  }
 
1357
 
 
1358
  /* Notify. */
 
1359
  if (changed) {
 
1360
    conn_list_iterate(game.est_connections, aconn) {
 
1361
      if (can_conn_edit(aconn)) {
 
1362
        send_packet_edit_startpos(aconn, packet);
 
1363
      }
 
1364
    } conn_list_iterate_end;
 
1365
  }
 
1366
}
 
1367
 
 
1368
/****************************************************************************
 
1369
  Setup which nations can start at a start position.
 
1370
****************************************************************************/
 
1371
void handle_edit_startpos_full(struct connection *pconn,
 
1372
                               const struct packet_edit_startpos_full *
 
1373
                               packet)
 
1374
{
 
1375
  struct tile *ptile = index_to_tile(packet->id);
 
1376
  struct startpos *psp;
 
1377
 
 
1378
  /* Check. */
 
1379
  if (NULL == ptile) {
 
1380
    notify_conn(pconn->self, NULL, E_BAD_COMMAND, ftc_editor,
 
1381
                _("Invalid tile index %d for start position."),
 
1382
                packet->id);
 
1383
    return;
 
1384
  }
 
1385
 
 
1386
  psp = map_startpos_get(ptile);
 
1387
  if (NULL == psp) {
 
1388
    notify_conn(pconn->self, ptile, E_BAD_COMMAND, ftc_editor,
 
1389
                _("Cannot edit start position nations at (%d, %d) "
 
1390
                  "because there is no start position there."),
 
1391
                TILE_XY(ptile));
 
1392
    return;
 
1393
  }
 
1394
 
 
1395
  /* Handle. */
 
1396
  if (startpos_unpack(psp, packet)) {
 
1397
    /* Notify. */
 
1398
    conn_list_iterate(game.est_connections, aconn) {
 
1399
      if (can_conn_edit(aconn)) {
 
1400
        send_packet_edit_startpos_full(aconn, packet);
 
1401
      }
 
1402
    } conn_list_iterate_end;
1369
1403
  }
1370
1404
}
1371
1405
 
1373
1407
  Handle edit requests to the main game data structure.
1374
1408
****************************************************************************/
1375
1409
void handle_edit_game(struct connection *pc,
1376
 
                      struct packet_edit_game *packet)
 
1410
                      const struct packet_edit_game *packet)
1377
1411
{
1378
1412
  bool changed = FALSE;
1379
1413
 
1423
1457
/****************************************************************************
1424
1458
  Make scenario file out of current game.
1425
1459
****************************************************************************/
1426
 
void handle_save_scenario(struct connection *pc, char *name)
 
1460
void handle_save_scenario(struct connection *pc, const char *name)
1427
1461
{
1428
1462
  if (pc->access_level != ALLOW_HACK) {
1429
1463
    notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
1445
1479
  Handle scenario information packet
1446
1480
****************************************************************************/
1447
1481
void handle_scenario_info(struct connection *pc,
1448
 
                          struct packet_scenario_info *packet)
 
1482
                          const struct packet_scenario_info *packet)
1449
1483
{
1450
1484
  game.scenario.is_scenario = packet->is_scenario;
1451
1485
  sz_strlcpy(game.scenario.name, packet->name);