55
56
#include "edithand.h"
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;
62
63
/* Array of size player_slot_count() indexed by player
63
64
* number to tell whether a given player has fog of war
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)
105
struct packet_edit_startpos startpos;
106
struct packet_edit_startpos_full startpos_full;
109
dest = game.est_connections;
112
/* Send map start positions. */
113
map_startpos_iterate(psp) {
114
startpos.id = tile_index(startpos_tile(psp));
115
startpos.remove = FALSE;
118
startpos_pack(psp, &startpos_full);
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);
125
} conn_list_iterate_end;
126
} map_startpos_iterate_end;
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)
104
if (hash_num_entries(unfixed_tile_table) < 1) {
134
if (0 >= tile_hash_size(unfixed_tile_table)) {
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);
113
145
assign_continent_numbers();
114
send_all_known_tiles(NULL, FALSE);
146
send_all_known_tiles(NULL);
117
149
/****************************************************************************
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)
309
334
struct terrain *pterrain;
310
335
struct tile *ptile_center;
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);
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)
343
368
struct resource *presource;
344
369
struct tile *ptile_center;
346
ptile_center = map_pos_to_tile(x, y);
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);
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)
371
396
struct tile *ptile_center;
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);
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)
403
428
struct tile *ptile_center;
404
429
struct base_type *pbase;
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);
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)
438
463
struct tile *ptile;
440
464
bool changed = FALSE;
443
ptile = index_to_tile(id);
466
ptile = index_to_tile(packet->tile);
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);
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)
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;
496
owner = packet->owner;
500
count = packet->count;
503
ptile = map_pos_to_tile(x, y);
518
ptile = index_to_tile(tile);
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);
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);
559
574
/* FIXME: Make this more general? */
560
coastal = is_sailing_unittype(punittype);
575
only_ocean = is_sailing_unittype(punittype);
562
homecity = find_closest_owned_city(pplayer, ptile, coastal, NULL);
577
homecity = find_closest_city(ptile, NULL, pplayer, only_ocean, FALSE, FALSE,
563
579
id = homecity ? homecity->id : 0;
565
581
conn_list_do_buffer(game.est_connections);
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)
585
601
struct tile *ptile;
586
602
struct unit_type *punittype;
587
603
struct player *pplayer;
590
ptile = map_pos_to_tile(x, y);
606
ptile = index_to_tile(tile);
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);
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
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)
734
750
struct tile *ptile;
735
751
struct city *pcity;
736
752
struct player *pplayer;
738
ptile = map_pos_to_tile(x, y);
754
ptile = index_to_tile(tile);
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);
983
pplayer = server_create_player();
999
pplayer = server_create_player(-1);
985
1001
notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,
986
1002
_("Player creation failed."));
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;
999
1014
pplayer->economic.gold = 0;
1000
1015
pplayer->economic = player_limit_to_max_rates(pplayer);
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);
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)
1046
1060
struct player *pplayer;
1047
1061
bool changed = FALSE, update_research = FALSE;
1060
research = get_player_research(pplayer);
1074
research = player_research_get(pplayer);
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];
1081
if (server_player_set_name_full(pc, pplayer, NULL, packet->name,
1082
error_buf, sizeof(error_buf))) {
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));
1072
players_iterate(other_player) {
1073
if (other_player == pplayer) {
1076
if (0 != mystrcasecmp(player_name(other_player), packet->name)) {
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));
1086
} players_iterate_end;
1089
sz_strlcpy(pplayer->name, packet->name);
1086
_("Cannot change name of player (%d) '%s' to '%s': %s"),
1087
player_number(pplayer), player_name(pplayer),
1088
packet->name, error_buf);
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)
1195
1192
struct player *pplayer;
1196
1193
struct tile *ptile_center;
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);
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"... */
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)
1340
const struct nation_type *pnation, *old;
1341
bool removed = FALSE;
1336
struct tile *ptile = index_to_tile(packet->id);
1343
ptile = map_pos_to_tile(x, y);
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);
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);
1351
old = map_get_startpos(ptile);
1353
if (nation == NATION_NONE) {
1354
if (map_has_startpos(ptile)) {
1355
map_clear_startpos(ptile);
1347
if (packet->remove) {
1348
changed = map_startpos_remove(ptile);
1350
if (NULL != map_startpos_get(ptile)) {
1353
map_startpos_new(ptile);
1359
} else if (nation == NATION_ANY) {
1360
map_set_startpos(ptile, NULL);
1363
pnation = nation_by_number(nation);
1364
map_set_startpos(ptile, pnation);
1367
if (old != pnation || removed) {
1368
send_tile_info(NULL, ptile, FALSE, FALSE);
1360
conn_list_iterate(game.est_connections, aconn) {
1361
if (can_conn_edit(aconn)) {
1362
send_packet_edit_startpos(aconn, packet);
1364
} conn_list_iterate_end;
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 *
1375
struct tile *ptile = index_to_tile(packet->id);
1376
struct startpos *psp;
1379
if (NULL == ptile) {
1380
notify_conn(pconn->self, NULL, E_BAD_COMMAND, ftc_editor,
1381
_("Invalid tile index %d for start position."),
1386
psp = map_startpos_get(ptile);
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."),
1396
if (startpos_unpack(psp, packet)) {
1398
conn_list_iterate(game.est_connections, aconn) {
1399
if (can_conn_edit(aconn)) {
1400
send_packet_edit_startpos_full(aconn, packet);
1402
} conn_list_iterate_end;
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)
1428
1462
if (pc->access_level != ALLOW_HACK) {
1429
1463
notify_conn(pc->self, NULL, E_BAD_COMMAND, ftc_editor,