Freeciv21
Develop your civilization from humble roots to a global empire
edithand.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file
3  is part of Freeciv21. Freeciv21 is free software:
4 |\_/|,,_____,~~` you can redistribute it and/or modify it under the
5 (.".)~~ )`~}} terms of the GNU General Public License as published
6  \o/\ /---~\\ ~}} by the Free Software Foundation, either version 3 of
7  _// _// ~} the License, or (at your option) any later version.
8  You should have received a copy of the GNU General
9  Public License along with Freeciv21. If not, see
10  https://www.gnu.org/licenses/.
11  */
12 
13 #include <QSet>
14 #include <climits> // USHRT_MAX
15 
16 // utility
17 #include "bitvector.h"
18 #include "fcintl.h"
19 #include "log.h"
20 #include "shared.h"
21 #include "support.h"
22 
23 // common
24 #include "events.h"
25 #include "game.h"
26 #include "government.h"
27 #include "map.h"
28 #include "movement.h"
29 #include "nation.h"
30 #include "research.h"
31 #include "terrain.h"
32 #include "unitlist.h"
33 
34 // server
35 #include "aiiface.h"
36 #include "citytools.h"
37 #include "cityturn.h"
38 #include "connecthand.h"
39 #include "gamehand.h"
40 #include "hand_gen.h"
41 #include "maphand.h"
42 #include "notify.h"
43 #include "plrhand.h"
44 #include "sanitycheck.h"
45 #include "techtools.h"
46 #include "unittools.h"
47 
48 /* server/generator */
49 #include "mapgen_utils.h"
50 
51 /* server/savegame */
52 #include "savemain.h"
53 
54 #include "edithand.h"
55 
56 /* Set if anything in a sequence of edits triggers the expensive
57  * assign_continent_numbers() check, which will be done once when the
58  * sequence is complete. */
59 static bool need_continents_reassigned = false;
60 /* Hold pointers to tiles which were changed during the edit sequence,
61  * so that they can be sanity-checked when the sequence is complete
62  * and final global fix-ups have been done. */
63 Q_GLOBAL_STATIC(QSet<const struct tile *>, modified_tile_table)
64 /* Array of size player_slot_count() indexed by player
65  * number to tell whether a given player has fog of war
66  * disabled in edit mode. */
67 static bool *unfogged_players;
68 
73 {
74  modified_tile_table->clear();
75 
77 
78  delete[] unfogged_players;
80 }
81 
86 {
87  delete[] unfogged_players;
88  unfogged_players = nullptr;
89 }
90 
94 void edithand_send_initial_packets(struct conn_list *dest)
95 {
96  struct packet_edit_startpos startpos;
97  struct packet_edit_startpos_full startpos_full;
98 
99  if (nullptr == dest) {
100  dest = game.est_connections;
101  }
102 
103  // Send map start positions.
104  for (auto *psp : qAsConst(*wld.map.startpos_table)) {
105  if (psp->exclude) {
106  continue;
107  }
108  startpos.id = tile_index(startpos_tile(psp));
109  startpos.removal = false;
110  startpos.tag = 0;
111 
112  startpos_pack(psp, &startpos_full);
113 
114  conn_list_iterate(dest, pconn)
115  {
116  if (can_conn_edit(pconn)) {
117  send_packet_edit_startpos(pconn, &startpos);
118  send_packet_edit_startpos_full(pconn, &startpos_full);
119  }
120  }
122  }
123 }
124 
130 {
133  send_all_known_tiles(nullptr);
135  }
136 
137 #ifdef SANITY_CHECKING
138  for (const auto *ptile : *modified_tile_table) {
139  sanity_check_tile(const_cast<struct tile *>(ptile));
140  }
141 #endif // SANITY_CHECKING
142  modified_tile_table->clear();
143 }
144 
150 {
151  bool unfogged;
152 
154  players_iterate(pplayer)
155  {
156  unfogged = unfogged_players[player_number(pplayer)];
157  if (unfogged && game.info.fogofwar) {
158  enable_fog_of_war_player(pplayer);
159  } else if (!unfogged && !game.info.fogofwar) {
160  disable_fog_of_war_player(pplayer);
161  }
162  }
164 
165  // Clear the whole array.
166  memset(unfogged_players, 0, MAX_NUM_PLAYER_SLOTS * sizeof(bool));
167 
170 }
171 
175 void handle_edit_mode(struct connection *pc, bool is_edit_mode)
176 {
177  if (!can_conn_enable_editing(pc)) {
178  return;
179  }
180 
181  if (!game.info.is_edit_mode && is_edit_mode) {
182  // Someone could be cheating! Warn people.
183  notify_conn(nullptr, nullptr, E_SETTING, ftc_editor,
184  _(" *** Server set to edit mode by %s! *** "),
185  conn_description(pc, false));
186  }
187 
188  if (game.info.is_edit_mode && !is_edit_mode) {
189  notify_conn(nullptr, nullptr, E_SETTING, ftc_editor,
190  _(" *** Edit mode canceled by %s. *** "),
191  conn_description(pc, false));
192 
194  }
195 
196  if (game.info.is_edit_mode != is_edit_mode) {
197  game.info.is_edit_mode = is_edit_mode;
198 
199  send_game_info(nullptr);
201  }
202 }
203 
208 static bool edit_tile_terrain_handling(struct tile *ptile,
209  struct terrain *pterrain,
210  bool send_info)
211 {
212  struct terrain *old_terrain = tile_terrain(ptile);
213 
214  if (old_terrain == pterrain
215  || (terrain_has_flag(pterrain, TER_NO_CITIES)
216  && nullptr != tile_city(ptile))) {
217  return false;
218  }
219 
220  tile_change_terrain(ptile, pterrain);
221  fix_tile_on_terrain_change(ptile, old_terrain, false);
222  modified_tile_table->insert(ptile);
223  if (need_to_reassign_continents(old_terrain, pterrain)) {
225  }
226 
227  if (send_info) {
228  update_tile_knowledge(ptile);
229  }
230 
231  return true;
232 }
233 
238 static bool edit_tile_extra_handling(struct tile *ptile,
239  struct extra_type *pextra,
240  bool remove_mode, bool send_info)
241 {
242  if (remove_mode) {
243  if (!tile_has_extra(ptile, pextra)) {
244  return false;
245  }
246 
247  if (!tile_extra_rm_apply(ptile, pextra)) {
248  return false;
249  }
250 
251  terrain_changed(ptile);
252 
253  } else {
254  if (tile_has_extra(ptile, pextra)) {
255  return false;
256  }
257 
258  if (!tile_extra_apply(ptile, pextra)) {
259  return false;
260  }
261  }
262 
263  if (send_info) {
264  update_tile_knowledge(ptile);
265  }
266 
267  return true;
268 }
269 
278 {
279  struct terrain *pterrain;
280  struct tile *ptile_center;
281 
282  ptile_center = index_to_tile(&(wld.map), tile);
283  if (!ptile_center) {
284  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
285  _("Cannot edit the tile because %d is not a valid "
286  "tile index on this map!"),
287  tile);
288  return;
289  }
290 
291  pterrain = terrain_by_number(terrain);
292  if (!pterrain) {
293  notify_conn(pc->self, ptile_center, E_BAD_COMMAND, ftc_editor,
294  // TRANS: ..." the tile <tile-coordinates> because"...
295  _("Cannot modify terrain for the tile %s because "
296  "%d is not a valid terrain id."),
297  tile_link(ptile_center), terrain);
298  return;
299  }
300 
302  /* This iterates outward, which gives any units that can't survive on
303  * changed terrain the best chance of survival. */
304  square_iterate(&(wld.map), ptile_center, size - 1, ptile)
305  {
306  edit_tile_terrain_handling(ptile, pterrain, true);
307  }
310 }
311 
316 void handle_edit_tile_extra(struct connection *pc, int tile, int id,
317  bool removal, int eowner, int size)
318 {
319  struct tile *ptile_center;
320  struct player *plr_eowner;
321 
322  ptile_center = index_to_tile(&(wld.map), tile);
323  if (!ptile_center) {
324  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
325  _("Cannot edit the tile because %d is not a valid "
326  "tile index on this map!"),
327  tile);
328  return;
329  }
330 
331  if (id < 0 || id >= game.control.num_extra_types) {
332  notify_conn(pc->self, ptile_center, E_BAD_COMMAND, ftc_editor,
333  // TRANS: ..." the tile <tile-coordinates> because"...
334  _("Cannot modify extras for the tile %s because "
335  "%d is not a valid extra id."),
336  tile_link(ptile_center), id);
337  return;
338  }
339 
340  if (eowner != MAP_TILE_OWNER_NULL) {
341  plr_eowner = player_by_number(eowner);
342  } else {
343  plr_eowner = nullptr;
344  }
345 
347  square_iterate(&(wld.map), ptile_center, size - 1, ptile)
348  {
349  ptile->extras_owner = plr_eowner;
350  edit_tile_extra_handling(ptile, extra_by_number(id), removal, true);
351  }
354 }
355 
359 void handle_edit_tile(struct connection *pc,
360  const struct packet_edit_tile *packet)
361 {
362  struct tile *ptile;
363  struct player *eowner;
364  bool changed = false;
365 
366  ptile = index_to_tile(&(wld.map), packet->tile);
367  if (!ptile) {
368  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
369  _("Cannot edit the tile because %d is not a valid "
370  "tile index on this map!"),
371  packet->tile);
372  return;
373  }
374 
375  if (packet->eowner != MAP_TILE_OWNER_NULL) {
376  eowner = player_by_number(packet->eowner);
377  } else {
378  eowner = nullptr;
379  }
380 
381  // Handle changes in extras.
382  if (!BV_ARE_EQUAL(packet->extras, ptile->extras)) {
383  extra_type_iterate(pextra)
384  {
386  ptile, pextra, !BV_ISSET(packet->extras, extra_number(pextra)),
387  false)) {
388  changed = true;
389  }
390  }
392  }
393 
394  if (ptile->extras_owner != eowner) {
395  ptile->extras_owner = eowner;
396  changed = true;
397  }
398 
399  // Handle changes in label
400  if (tile_set_label(ptile, packet->label)) {
401  changed = true;
402  }
403 
404  // TODO: Handle more property edits.
405 
406  // Send the new state to all affected.
407  if (changed) {
408  update_tile_knowledge(ptile);
409  send_tile_info(nullptr, ptile, false);
410  }
411 }
412 
417 void handle_edit_unit_create(struct connection *pc, int owner, int tile,
418  Unit_type_id utid, int count, int tag)
419 {
420  struct tile *ptile;
421  struct unit_type *punittype;
422  struct player *pplayer;
423  struct city *homecity;
424  struct unit *punit;
425  int id, i;
426 
427  ptile = index_to_tile(&(wld.map), tile);
428  if (!ptile) {
429  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
430  _("Cannot create units because %d is not a valid "
431  "tile index on this map!"),
432  tile);
433  return;
434  }
435 
436  punittype = utype_by_number(utid);
437  if (!punittype) {
438  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
439  // TRANS: ..." at <tile-coordinates> because"...
440  _("Cannot create a unit at %s because the "
441  "given unit type id %d is invalid."),
442  tile_link(ptile), utid);
443  return;
444  }
445 
446  pplayer = player_by_number(owner);
447  if (!pplayer) {
448  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
449  // TRANS: ..." type <unit-type> at <tile-coordinates>"...
450  _("Cannot create a unit of type %s at %s "
451  "because the given owner's player id %d is "
452  "invalid."),
453  utype_name_translation(punittype), tile_link(ptile), owner);
454  return;
455  }
456 
457  if (is_non_allied_unit_tile(ptile, pplayer)
458  || (tile_city(ptile)
459  && !pplayers_allied(pplayer, city_owner(tile_city(ptile))))) {
460  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
461  /* TRANS: ..." type <unit-type> on enemy tile
462  * <tile-coordinates>"... */
463  _("Cannot create unit of type %s on enemy tile "
464  "%s."),
465  utype_name_translation(punittype), tile_link(ptile));
466  return;
467  }
468 
469  if (!can_exist_at_tile(&(wld.map), punittype, ptile)) {
470  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
471  /* TRANS: ..." type <unit-type> on the terrain at
472  * <tile-coordinates>"... */
473  _("Cannot create a unit of type %s on the terrain "
474  "at %s."),
475  utype_name_translation(punittype), tile_link(ptile));
476  return;
477  }
478 
479  if (count > 0 && !pplayer->is_alive) {
480  pplayer->is_alive = true;
481  send_player_info_c(pplayer, nullptr);
482  }
483 
484  homecity = find_closest_city(ptile, nullptr, pplayer, false, false, false,
485  true, false, utype_class(punittype));
486  id = homecity ? homecity->id : 0;
487 
489  map_show_circle(pplayer, ptile, punittype->vision_radius_sq);
490  for (i = 0; i < count; i++) {
491  /* As far as I can see create_unit is guaranteed to
492  * never return nullptr. */
493  punit = create_unit(pplayer, ptile, punittype, 0, id, -1);
494  if (tag > 0) {
495  dsend_packet_edit_object_created(pc, tag, punit->id);
496  }
497  }
499 }
500 
505 void handle_edit_unit_remove(struct connection *pc, int owner, int tile,
506  Unit_type_id utid, int count)
507 {
508  struct tile *ptile;
509  struct unit_type *punittype;
510  struct player *pplayer;
511  int i;
512 
513  ptile = index_to_tile(&(wld.map), tile);
514  if (!ptile) {
515  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
516  _("Cannot remove units because %d is not a valid "
517  "tile index on this map!"),
518  tile);
519  return;
520  }
521 
522  punittype = utype_by_number(utid);
523  if (!punittype) {
524  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
525  // TRANS: ..." at <tile-coordinates> because"...
526  _("Cannot remove a unit at %s because the "
527  "given unit type id %d is invalid."),
528  tile_link(ptile), utid);
529  return;
530  }
531 
532  pplayer = player_by_number(owner);
533  if (!pplayer) {
534  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
535  /* TRANS: ..." type <unit-type> at <tile-coordinates>
536  * because"... */
537  _("Cannot remove a unit of type %s at %s "
538  "because the given owner's player id %d is "
539  "invalid."),
540  utype_name_translation(punittype), tile_link(ptile), owner);
541  return;
542  }
543 
544  i = 0;
545  unit_list_iterate_safe(ptile->units, punit)
546  {
547  if (i >= count) {
548  break;
549  }
550  if (unit_type_get(punit) != punittype || unit_owner(punit) != pplayer) {
551  continue;
552  }
553  wipe_unit(punit, ULR_EDITOR, nullptr);
554  i++;
555  }
557 }
558 
563 {
564  struct unit *punit;
565 
566  punit = game_unit_by_number(id);
567  if (!punit) {
568  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
569  _("No such unit (ID %d)."), id);
570  return;
571  }
572 
573  wipe_unit(punit, ULR_EDITOR, nullptr);
574 }
575 
579 void handle_edit_unit(struct connection *pc,
580  const struct packet_edit_unit *packet)
581 {
582  const struct unit_type *putype;
583  struct unit *punit;
584  int id;
585  bool changed = false;
586  int fuel, hp;
587 
588  id = packet->id;
589  punit = game_unit_by_number(id);
590  if (!punit) {
591  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
592  _("No such unit (ID %d)."), id);
593  return;
594  }
595 
596  putype = unit_type_get(punit);
597 
598  if (packet->moves_left != punit->moves_left) {
599  punit->moves_left = packet->moves_left;
600  changed = true;
601  }
602 
603  fuel = CLIP(0, packet->fuel, utype_fuel(putype));
604  if (fuel != punit->fuel) {
605  punit->fuel = fuel;
606  changed = true;
607  }
608 
609  if (packet->moved != punit->moved) {
610  punit->moved = packet->moved;
611  changed = true;
612  }
613 
614  if (packet->done_moving != punit->done_moving) {
615  punit->done_moving = packet->done_moving;
616  changed = true;
617  }
618 
619  hp = CLIP(1, packet->hp, putype->hp);
620  if (hp != punit->hp) {
621  punit->hp = hp;
622  changed = true;
623  }
624 
625  if (packet->veteran != punit->veteran) {
626  int v = packet->veteran;
627  if (!utype_veteran_level(putype, v)) {
628  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
629  _("Invalid veteran level %d for unit %d (%s)."), v, id,
630  unit_link(punit));
631  } else {
632  punit->veteran = v;
633  changed = true;
634  }
635  }
636 
637  if (packet->stay != punit->stay) {
638  punit->stay = packet->stay;
639  changed = true;
640  }
641 
642  // TODO: Handle more property edits.
643 
644  // Send the new state to all affected.
645  if (changed) {
646  send_unit_info(nullptr, punit);
647  }
648 }
649 
654 void handle_edit_city_create(struct connection *pc, int owner, int tile,
655  int size, int tag)
656 {
657  struct tile *ptile;
658  struct city *pcity;
659  struct player *pplayer;
660 
661  ptile = index_to_tile(&(wld.map), tile);
662  if (!ptile) {
663  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
664  _("Cannot create a city because %d is not a valid "
665  "tile index on this map!"),
666  tile);
667  return;
668  }
669 
670  pplayer = player_by_number(owner);
671  if (!pplayer) {
672  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
673  // TRANS: ..." at <tile-coordinates> because"...
674  _("Cannot create a city at %s because the "
675  "given owner's player id %d is invalid"),
676  tile_link(ptile), owner);
677  return;
678  }
679 
680  if (is_enemy_unit_tile(ptile, pplayer) != nullptr
681  || !city_can_be_built_here(ptile, nullptr)) {
682  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
683  // TRANS: ..." at <tile-coordinates>."
684  _("A city may not be built at %s."), tile_link(ptile));
685  return;
686  }
687 
688  if (!pplayer->is_alive) {
689  pplayer->is_alive = true;
690  send_player_info_c(pplayer, nullptr);
691  }
692 
694 
695  map_show_tile(pplayer, ptile);
696  create_city(pplayer, ptile, city_name_suggestion(pplayer, ptile), pplayer);
697  pcity = tile_city(ptile);
698 
699  if (size > 1) {
700  // FIXME: Slow and inefficient for large size changes.
701  city_change_size(pcity, CLIP(1, size, MAX_CITY_SIZE), pplayer, nullptr);
702  send_city_info(nullptr, pcity);
703  }
704 
705  if (tag > 0) {
706  dsend_packet_edit_object_created(pc, tag, pcity->id);
707  }
708 
710 }
711 
715 void handle_edit_city(struct connection *pc,
716  const struct packet_edit_city *packet)
717 {
718  struct tile *ptile;
719  struct city *pcity, *oldcity;
720  struct player *pplayer;
721  char buf[1024];
722  int id;
723  bool changed = false;
724  bool need_game_info = false;
725  bv_player need_player_info;
726 
727  pcity = game_city_by_number(packet->id);
728  if (!pcity) {
729  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
730  _("Cannot edit city with invalid city ID %d."), packet->id);
731  return;
732  }
733 
734  pplayer = city_owner(pcity);
735  ptile = city_tile(pcity);
736  BV_CLR_ALL(need_player_info);
737 
738  // Handle name change.
739  if (0 != strcmp(pcity->name, packet->name)) {
740  if (!is_allowed_city_name(pplayer, packet->name, buf, sizeof(buf))) {
741  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
742  _("Cannot edit city name: %s"), buf);
743  } else {
744  sz_strlcpy(pcity->name, packet->name);
745  changed = true;
746  }
747  }
748 
749  // Handle size change.
750  if (packet->size != city_size_get(pcity)) {
751  if (!(0 < packet->size && packet->size <= MAX_CITY_SIZE)) {
752  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
753  _("Invalid city size %d for city %s."), packet->size,
754  city_link(pcity));
755  } else {
756  // FIXME: Slow and inefficient for large size changes.
757  city_change_size(pcity, packet->size, nullptr, nullptr);
758  changed = true;
759  }
760  }
761 
762  if (packet->history != pcity->history) {
763  pcity->history = packet->history;
764  changed = true;
765  }
766 
767  // Handle city improvement changes.
768  improvement_iterate(pimprove)
769  {
770  oldcity = nullptr;
771  id = improvement_number(pimprove);
772 
773  if (is_special_improvement(pimprove)) {
774  if (packet->built[id] >= 0) {
775  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
776  _("It is impossible for a city to have %s!"),
777  improvement_name_translation(pimprove));
778  }
779  continue;
780  }
781 
782  /* FIXME: game.info.great_wonder_owners and pplayer->wonders
783  * logic duplication with city_build_building. */
784 
785  if (city_has_building(pcity, pimprove) && packet->built[id] < 0) {
786  city_remove_improvement(pcity, pimprove);
787  changed = true;
788 
789  } else if (!city_has_building(pcity, pimprove)
790  && packet->built[id] >= 0) {
791  if (is_great_wonder(pimprove)) {
792  oldcity = city_from_great_wonder(pimprove);
793  if (oldcity != pcity) {
794  BV_SET(need_player_info, player_index(pplayer));
795  }
796  if (nullptr != oldcity && city_owner(oldcity) != pplayer) {
797  // Great wonders make more changes.
798  need_game_info = true;
799  BV_SET(need_player_info, player_index(city_owner(oldcity)));
800  }
801  } else if (is_small_wonder(pimprove)) {
802  oldcity = city_from_small_wonder(pplayer, pimprove);
803  if (oldcity != pcity) {
804  BV_SET(need_player_info, player_index(pplayer));
805  }
806  }
807 
808  if (oldcity) {
809  city_remove_improvement(oldcity, pimprove);
810  city_refresh_queue_add(oldcity);
811  }
812 
813  city_add_improvement(pcity, pimprove);
814  changed = true;
815  }
816  }
818 
819  // Handle food stock change.
820  if (packet->food_stock != pcity->food_stock) {
821  int max = city_granary_size(city_size_get(pcity));
822  if (!(0 <= packet->food_stock && packet->food_stock <= max)) {
823  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
824  _("Invalid city food stock amount %d for city %s "
825  "(allowed range is %d to %d)."),
826  packet->food_stock, city_link(pcity), 0, max);
827  } else {
828  pcity->food_stock = packet->food_stock;
829  changed = true;
830  }
831  }
832 
833  // Handle shield stock change.
834  if (packet->shield_stock != pcity->shield_stock) {
835  int max = USHRT_MAX; // Limited to uint16 by city info packet.
836  if (!(0 <= packet->shield_stock && packet->shield_stock <= max)) {
837  notify_conn(pc->self, ptile, E_BAD_COMMAND, ftc_editor,
838  _("Invalid city shield stock amount %d for city %s "
839  "(allowed range is %d to %d)."),
840  packet->shield_stock, city_link(pcity), 0, max);
841  } else {
842  pcity->shield_stock = packet->shield_stock;
843  changed = true;
844  }
845  }
846 
847  // TODO: Handle more property edits.
848 
849  if (changed) {
850  city_refresh_queue_add(pcity);
853 
854  // FIXME: city_refresh_queue_processing only sends to city owner?
855  send_city_info(nullptr, pcity);
856 
858  }
859 
860  // Update wonder infos.
861  if (need_game_info) {
862  send_game_info(nullptr);
863  }
864  if (BV_ISSET_ANY(need_player_info)) {
865  players_iterate(aplayer)
866  {
867  if (BV_ISSET(need_player_info, player_index(aplayer))) {
868  // No need to send to detached connections.
869  send_player_info_c(aplayer, nullptr);
870  }
871  }
873  }
874 }
875 
879 void handle_edit_player_create(struct connection *pc, int tag)
880 {
881  struct player *pplayer;
882  struct nation_type *pnation;
883  struct research *presearch;
884 
886  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
887  _("No more players can be added because the maximum "
888  "number of players (%d) has been reached."),
890  return;
891  }
892 
893  if (player_count() >= game.control.nation_count) {
894  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
895  _("No more players can be added because there are "
896  "no available nations (%d used)."),
897  game.control.nation_count);
898  return;
899  }
900 
901  pnation = pick_a_nation(nullptr, true, true, NOT_A_BARBARIAN);
902  if (!pnation) {
903  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
904  _("Player cannot be created because random nation "
905  "selection failed."));
906  return;
907  }
908 
909  pplayer = server_create_player(-1, default_ai_type_name(), nullptr, false);
910  if (!pplayer) {
911  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
912  _("Player creation failed."));
913  return;
914  }
915  server_player_init(pplayer, true, true);
916 
917  player_nation_defaults(pplayer, pnation, true);
918  if (game_was_started()) {
919  // Find a color for the new player.
921  }
922  sz_strlcpy(pplayer->username, _(ANON_USER_NAME));
923  pplayer->unassigned_user = true;
924  pplayer->is_connected = false;
925  pplayer->government = init_government_of_nation(pnation);
926  pplayer->server.got_first_city = false;
927 
928  pplayer->economic.gold = 0;
929  pplayer->economic = player_limit_to_max_rates(pplayer);
930 
931  presearch = research_get(pplayer);
932  init_tech(presearch, true);
933  give_initial_techs(presearch, 0);
934 
935  send_player_all_c(pplayer, nullptr);
936  /* Send research info after player info, else the client will complain
937  * about invalid team. */
938  send_research_info(presearch, nullptr);
939  if (tag > 0) {
940  dsend_packet_edit_object_created(pc, tag, player_number(pplayer));
941  }
942 }
943 
947 void handle_edit_player_remove(struct connection *pc, int id)
948 {
949  struct player *pplayer;
950 
951  pplayer = player_by_number(id);
952  if (pplayer == nullptr) {
953  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
954  _("No such player (ID %d)."), id);
955  return;
956  }
957 
958  /* Don't use conn_list_iterate here because connection_detach() can be
959  * recursive and free the next connection pointer. */
960  while (conn_list_size(pplayer->connections) > 0) {
961  connection_detach(conn_list_get(pplayer->connections, 0), false);
962  }
963 
964  kill_player(pplayer);
965  server_remove_player(pplayer);
966 }
967 
972  const struct packet_edit_player *packet)
973 {
974  struct player *pplayer;
975  bool changed = false, update_research = false;
976  struct nation_type *pnation;
977  struct research *research;
978  enum tech_state known;
979  struct government *gov;
980 
981  pplayer = player_by_number(packet->id);
982  if (!pplayer) {
983  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
984  _("Cannot edit player with invalid player ID %d."),
985  packet->id);
986  return;
987  }
988 
989  research = research_get(pplayer);
990 
991  // Handle player name change.
992  if (0 != strcmp(packet->name, player_name(pplayer))) {
993  char error_buf[256];
994 
995  if (server_player_set_name_full(pc, pplayer, nullptr, packet->name,
996  error_buf, sizeof(error_buf))) {
997  changed = true;
998  } else {
999  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1000  _("Cannot change name of player (%d) '%s' to '%s': %s"),
1001  player_number(pplayer), player_name(pplayer), packet->name,
1002  error_buf);
1003  }
1004  }
1005 
1006  // Handle nation change.
1007  pnation = nation_by_number(packet->nation);
1008  if (nation_of_player(pplayer) != pnation) {
1009  if (pnation == nullptr) {
1010  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1011  _("Cannot change nation for player %d (%s) "
1012  "because the given nation ID %d is invalid."),
1013  player_number(pplayer), player_name(pplayer),
1014  packet->nation);
1015  } else if (pnation->player != nullptr) {
1016  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1017  _("Cannot change nation for player %d (%s) "
1018  "to nation %d (%s) because that nation is "
1019  "already assigned to player %d (%s)."),
1020  player_number(pplayer), player_name(pplayer),
1021  packet->nation, nation_plural_translation(pnation),
1022  player_number(pnation->player),
1023  player_name(pnation->player));
1024  } else if (!nation_is_in_current_set(pnation)) {
1025  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1026  _("Cannot change nation for player %d (%s) "
1027  "to nation %d (%s) because that nation is "
1028  "not in the current nation set."),
1029  player_number(pplayer), player_name(pplayer),
1030  packet->nation, nation_plural_translation(pnation));
1031  } else if (pplayer->ai_common.barbarian_type
1032  != nation_barbarian_type(pnation)
1033  || (!is_barbarian(pplayer) && !is_nation_playable(pnation))) {
1034  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1035  _("Cannot change nation for player %d (%s) "
1036  "to nation %d (%s) because that nation is "
1037  "unsuitable for this player."),
1038  player_number(pplayer), player_name(pplayer),
1039  packet->nation, nation_plural_translation(pnation));
1040  } else {
1041  changed = player_set_nation(pplayer, pnation);
1042  }
1043  }
1044 
1045  // Handle a change in research progress.
1046  if (packet->bulbs_researched != research->bulbs_researched) {
1047  research->bulbs_researched = packet->bulbs_researched;
1048  changed = true;
1049  update_research = true;
1050  }
1051 
1052  // Handle a change in known inventions.
1054  {
1055  known = research_invention_state(research, tech);
1056  if ((packet->inventions[tech] && known == TECH_KNOWN)
1057  || (!packet->inventions[tech] && known != TECH_KNOWN)) {
1058  continue;
1059  }
1060  if (packet->inventions[tech]) {
1061  // FIXME: Side-effect modifies game.info.global_advances.
1062  research_invention_set(research, tech, TECH_KNOWN);
1064  } else {
1065  research_invention_set(research, tech, TECH_UNKNOWN);
1067  }
1068  changed = true;
1069  update_research = true;
1070  }
1072 
1073  // Handle a change in the player's gold.
1074  if (packet->gold != pplayer->economic.gold) {
1075  if (!(0 <= packet->gold && packet->gold <= 1000000)) {
1076  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1077  _("Cannot set gold for player %d (%s) because "
1078  "the value %d is outside the allowed range."),
1079  player_number(pplayer), player_name(pplayer),
1080  packet->gold);
1081  } else {
1082  pplayer->economic.gold = packet->gold;
1083  changed = true;
1084  }
1085  }
1086 
1087  // Handle player government change
1088  gov = government_by_number(packet->government);
1089  if (gov != pplayer->government) {
1090  if (gov != game.government_during_revolution) {
1091  government_change(pplayer, gov, false);
1092  } else {
1093  int turns = revolution_length(gov, pplayer);
1094 
1095  if (turns >= 0) {
1096  pplayer->government = gov;
1097  pplayer->revolution_finishes = game.info.turn + turns;
1098  }
1099  }
1100 
1101  changed = true;
1102  }
1103 
1104  if (packet->scenario_reserved) {
1105  if (!player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
1106  changed = true;
1107  BV_SET(pplayer->flags, PLRF_SCENARIO_RESERVED);
1108  }
1109  } else {
1110  if (player_has_flag(pplayer, PLRF_SCENARIO_RESERVED)) {
1111  changed = true;
1112  BV_CLR(pplayer->flags, PLRF_SCENARIO_RESERVED);
1113  }
1114  }
1115 
1116  // TODO: Handle more property edits.
1117 
1118  if (update_research) {
1119  Tech_type_id current, goal;
1120 
1122 
1123  // FIXME: Modifies struct research directly.
1124 
1125  current = research->researching;
1126  goal = research->tech_goal;
1127 
1128  if (current != A_UNSET) {
1129  if (current != A_FUTURE) {
1130  known = research_invention_state(research, current);
1131  if (known != TECH_PREREQS_KNOWN) {
1133  }
1134  } else {
1135  // Future Tech is legal only if all techs are known
1137  {
1138  known = research_invention_state(research, tech_i);
1139  if (known != TECH_KNOWN) {
1141  break;
1142  }
1143  }
1145  }
1146  }
1147  if (goal != A_UNSET) {
1148  if (goal != A_FUTURE) {
1149  known = research_invention_state(research, goal);
1150  if (known == TECH_KNOWN) {
1152  }
1153  }
1154  }
1155  changed = true;
1156 
1157  // Inform everybody about global advances
1158  send_game_info(nullptr);
1159  send_research_info(research, nullptr);
1160  }
1161 
1162  if (changed) {
1163  send_player_all_c(pplayer, nullptr);
1164  }
1165 }
1166 
1170 void handle_edit_player_vision(struct connection *pc, int plr_no, int tile,
1171  bool known, int size)
1172 {
1173  struct player *pplayer;
1174  struct tile *ptile_center;
1175 
1176  ptile_center = index_to_tile(&(wld.map), tile);
1177  if (!ptile_center) {
1178  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1179  _("Cannot edit vision because %d is not a valid "
1180  "tile index on this map!"),
1181  tile);
1182  return;
1183  }
1184 
1185  pplayer = player_by_number(plr_no);
1186  if (!pplayer) {
1187  notify_conn(pc->self, ptile_center, E_BAD_COMMAND, ftc_editor,
1188  // TRANS: ..." at <tile-coordinates> because"...
1189  _("Cannot edit vision for the tile at %s because "
1190  "given player id %d is invalid."),
1191  tile_link(ptile_center), plr_no);
1192  return;
1193  }
1194 
1196  square_iterate(&(wld.map), ptile_center, size - 1, ptile)
1197  {
1198  if (!known) {
1199  struct city *pcity = tile_city(ptile);
1200  bool cannot_make_unknown = false;
1201 
1202  if (pcity && city_owner(pcity) == pplayer) {
1203  continue;
1204  }
1205 
1206  unit_list_iterate(ptile->units, punit)
1207  {
1208  if (unit_owner(punit) == pplayer
1209  || really_gives_vision(pplayer, unit_owner(punit))) {
1210  cannot_make_unknown = true;
1211  break;
1212  }
1213  }
1215 
1216  if (cannot_make_unknown) {
1217  continue;
1218  }
1219 
1220  /* The client expects tiles which become unseen to
1221  * contain no units (client/packhand.c +2368).
1222  * So here we tell it to remove units that do
1223  * not give it vision. */
1224  unit_list_iterate(ptile->units, punit)
1225  {
1226  conn_list_iterate(pplayer->connections, pconn)
1227  {
1228  dsend_packet_unit_remove(pconn, punit->id);
1229  }
1231  }
1233  }
1234 
1235  if (known) {
1236  map_show_tile(pplayer, ptile);
1237  } else {
1238  map_hide_tile(pplayer, ptile);
1239  }
1240  }
1243 }
1244 
1251 {
1253 }
1254 
1258 void handle_edit_city_remove(struct connection *pc, int id)
1259 {
1260  struct city *pcity;
1261 
1262  pcity = game_city_by_number(id);
1263  if (pcity == nullptr) {
1264  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1265  _("No such city (ID %d)."), id);
1266  return;
1267  }
1268 
1269  remove_city(pcity);
1270 }
1271 
1276 {
1278 }
1279 
1285 void handle_edit_toggle_fogofwar(struct connection *pc, int plr_no)
1286 {
1287  struct player *pplayer;
1288 
1289  if (!game.info.fogofwar) {
1290  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1291  _("Cannot toggle fog-of-war when it is already "
1292  "disabled."));
1293  return;
1294  }
1295 
1296  pplayer = player_by_number(plr_no);
1297  if (!pplayer) {
1298  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1299  _("Cannot toggle fog-of-war for invalid player ID %d."),
1300  plr_no);
1301  return;
1302  }
1303 
1305  if (unfogged_players[player_number(pplayer)]) {
1306  enable_fog_of_war_player(pplayer);
1307  unfogged_players[player_number(pplayer)] = false;
1308  } else {
1309  disable_fog_of_war_player(pplayer);
1310  unfogged_players[player_number(pplayer)] = true;
1311  }
1313 }
1314 
1319  const struct packet_edit_startpos *packet)
1320 {
1321  struct tile *ptile = index_to_tile(&(wld.map), packet->id);
1322  bool changed;
1323 
1324  // Check.
1325  if (nullptr == ptile) {
1326  notify_conn(pconn->self, nullptr, E_BAD_COMMAND, ftc_editor,
1327  _("Invalid tile index %d for start position."), packet->id);
1328  return;
1329  }
1330 
1331  // Handle.
1332  if (packet->removal) {
1333  changed = map_startpos_remove(ptile);
1334  } else {
1335  if (nullptr != map_startpos_get(ptile)) {
1336  changed = false;
1337  } else {
1338  map_startpos_new(ptile);
1339  changed = true;
1340  }
1341  }
1342 
1343  // Notify.
1344  if (changed) {
1346  {
1347  if (can_conn_edit(aconn)) {
1348  send_packet_edit_startpos(aconn, packet);
1349  }
1350  }
1352  }
1353 }
1354 
1359  struct connection *pconn, const struct packet_edit_startpos_full *packet)
1360 {
1361  struct tile *ptile = index_to_tile(&(wld.map), packet->id);
1362  struct startpos *psp;
1363 
1364  // Check.
1365  if (nullptr == ptile) {
1366  notify_conn(pconn->self, nullptr, E_BAD_COMMAND, ftc_editor,
1367  _("Invalid tile index %d for start position."), packet->id);
1368  return;
1369  }
1370 
1371  psp = map_startpos_get(ptile);
1372  if (nullptr == psp) {
1373  notify_conn(pconn->self, ptile, E_BAD_COMMAND, ftc_editor,
1374  _("Cannot edit start position nations at (%d, %d) "
1375  "because there is no start position there."),
1376  TILE_XY(ptile));
1377  return;
1378  }
1379 
1380  // Handle.
1381  if (startpos_unpack(psp, packet)) {
1382  // Notify.
1384  {
1385  if (can_conn_edit(aconn)) {
1386  send_packet_edit_startpos_full(aconn, packet);
1387  }
1388  }
1390  }
1391 }
1392 
1397  const struct packet_edit_game *packet)
1398 {
1399  bool changed = false;
1400 
1401  if (packet->scenario != game.scenario.is_scenario) {
1402  game.scenario.is_scenario = packet->scenario;
1403  changed = true;
1404  }
1405 
1406  if (0 != strncmp(packet->scenario_name, game.scenario.name, 256)) {
1407  sz_strlcpy(game.scenario.name, packet->scenario_name);
1408  changed = true;
1409  }
1410 
1411  if (0
1412  != strncmp(packet->scenario_authors, game.scenario.authors,
1413  sizeof(packet->scenario_authors))) {
1414  sz_strlcpy(game.scenario.authors, packet->scenario_authors);
1415  changed = true;
1416  }
1417 
1418  if (packet->scenario_random != game.scenario.save_random) {
1419  game.scenario.save_random = packet->scenario_random;
1420  changed = true;
1421  }
1422 
1423  if (packet->scenario_players != game.scenario.players) {
1424  game.scenario.players = packet->scenario_players;
1425  changed = true;
1426  }
1427 
1428  if (packet->startpos_nations != game.scenario.startpos_nations) {
1429  game.scenario.startpos_nations = packet->startpos_nations;
1430  changed = true;
1431  }
1432 
1433  if (packet->prevent_new_cities != game.scenario.prevent_new_cities) {
1434  game.scenario.prevent_new_cities = packet->prevent_new_cities;
1435  changed = true;
1436  }
1437 
1438  if (packet->lake_flooding != game.scenario.lake_flooding) {
1439  game.scenario.lake_flooding = packet->lake_flooding;
1440  changed = true;
1441  }
1442 
1443  if (packet->ruleset_locked != game.scenario.ruleset_locked) {
1444  game.scenario.ruleset_locked = packet->ruleset_locked;
1445  changed = true;
1446  }
1447 
1448  if (changed) {
1449  send_scenario_info(nullptr);
1450  send_game_info(nullptr);
1451  }
1452 }
1453 
1458  const char *scenario_desc)
1459 {
1460  if (0
1461  != strncmp(scenario_desc, game.scenario_desc.description,
1462  MAX_LEN_PACKET)) {
1463  sz_strlcpy(game.scenario_desc.description, scenario_desc);
1464  send_scenario_description(nullptr);
1465  }
1466 }
1467 
1471 void handle_save_scenario(struct connection *pc, const char *name)
1472 {
1473  if (pc->access_level != ALLOW_HACK) {
1474  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1475  _("No permissions to remotely save scenario."));
1476  return;
1477  }
1478 
1479  if (!game.scenario.is_scenario) {
1480  // Scenario information not available
1481  notify_conn(pc->self, nullptr, E_BAD_COMMAND, ftc_editor,
1482  _("Scenario information not set. Cannot save scenario."));
1483  return;
1484  }
1485 
1486  // Client initiated scenario saving is not handmade
1487  game.scenario.handmade = false;
1488 
1489  save_game(name, "Scenario", true);
1490 }
const char * default_ai_type_name()
Return name of default ai type.
Definition: aiiface.cpp:265
#define BV_CLR_ALL(bv)
Definition: bitvector.h:62
#define BV_SET(bv, bit)
Definition: bitvector.h:44
bool BV_ISSET(const BV &bv, int bit)
Definition: bitvector.h:37
#define BV_ARE_EQUAL(vec1, vec2)
Definition: bitvector.h:80
#define BV_ISSET_ANY(vec)
Definition: bitvector.h:76
#define BV_CLR(bv, bit)
Definition: bitvector.h:49
int city_granary_size(int city_size)
Generalized formula used to calculate granary size.
Definition: city.cpp:2034
bool city_has_building(const struct city *pcity, const struct impr_type *pimprove)
Return TRUE iff the city has this building in it.
Definition: city.cpp:1189
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
void city_remove_improvement(struct city *pcity, const struct impr_type *pimprove)
Removes an improvement (and its effects) from a city.
Definition: city.cpp:3287
struct tile * city_tile(const struct city *pcity)
Return the tile location of the city.
Definition: city.cpp:1095
bool city_can_be_built_here(const struct tile *ptile, const struct unit *punit)
Returns TRUE if the given unit can build a city at the given map coordinates.
Definition: city.cpp:1423
void city_add_improvement(struct city *pcity, const struct impr_type *pimprove)
Adds an improvement (and its effects) to a city.
Definition: city.cpp:3272
citizens city_size_get(const struct city *pcity)
Get the city size.
Definition: city.cpp:1101
#define MAX_CITY_SIZE
Definition: city.h:79
struct city * find_closest_city(const struct tile *ptile, const struct city *pexclcity, const struct player *pplayer, bool only_ocean, bool only_continent, bool only_known, bool only_player, bool only_enemy, const struct unit_class *pclass)
Find the city closest to 'ptile'.
Definition: citytools.cpp:849
void send_city_info(struct player *dest, struct city *pcity)
A wrapper, accessing either broadcast_city_info() (dest == nullptr), or a convenience case of send_ci...
Definition: citytools.cpp:2295
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Come up with a default name when a new city is about to be built.
Definition: citytools.cpp:451
void create_city(struct player *pplayer, struct tile *ptile, const char *name, struct player *nationality)
Creates real city.
Definition: citytools.cpp:1512
bool is_allowed_city_name(struct player *pplayer, const char *cityname, char *error_buf, size_t bufsz)
Checks, if a city name is allowed for a player.
Definition: citytools.cpp:356
void remove_city(struct city *pcity)
Remove a city from the game.
Definition: citytools.cpp:1676
void city_refresh_queue_add(struct city *pcity)
Queue pending city_refresh() for later.
Definition: cityturn.cpp:188
bool city_change_size(struct city *pcity, citizens size, struct player *nationality, const char *reason)
Change the city size.
Definition: cityturn.cpp:1067
void city_refresh_queue_processing()
Refresh the listed cities.
Definition: cityturn.cpp:204
void connection_detach(struct connection *pconn, bool remove_unused_player)
Remove pconn as a client connected to pplayer: Updates pconn->playing, pconn->playing->connections,...
void conn_list_do_unbuffer(struct conn_list *dest)
Convenience functions to unbuffer a list of connections.
Definition: connection.cpp:319
bool can_conn_edit(const struct connection *pconn)
Return TRUE iff the connection is currently allowed to edit.
Definition: connection.cpp:472
const char * conn_description(const struct connection *pconn, bool is_private)
° Return pointer to static string containing a description for this ° connection, based on pconn->nam...
Definition: connection.cpp:431
void conn_list_do_buffer(struct conn_list *dest)
Convenience functions to buffer a list of connections.
Definition: connection.cpp:310
bool can_conn_enable_editing(const struct connection *pconn)
Return TRUE iff the connection is allowed to start editing.
Definition: connection.cpp:481
#define MAX_LEN_PACKET
Definition: connection.h:41
#define conn_list_iterate(connlist, pconn)
Definition: connection.h:99
#define conn_list_iterate_end
Definition: connection.h:101
void handle_edit_unit_remove_by_id(struct connection *pc, Unit_type_id id)
Handle a request to remove a unit given by its id.
Definition: edithand.cpp:562
void handle_edit_tile(struct connection *pc, const struct packet_edit_tile *packet)
Handles tile information from the client, to make edits to tiles.
Definition: edithand.cpp:359
void handle_edit_scenario_desc(struct connection *pc, const char *scenario_desc)
Handle edit requests to scenario description.
Definition: edithand.cpp:1457
void handle_edit_check_tiles(struct connection *pc)
Run any pending tile checks.
Definition: edithand.cpp:1275
static void check_edited_tile_terrains()
Do the potentially slow checks required after one or several tiles' terrain has change.
Definition: edithand.cpp:129
void handle_edit_mode(struct connection *pc, bool is_edit_mode)
Handles a request by the client to enter edit mode.
Definition: edithand.cpp:175
void handle_edit_tile_terrain(struct connection *pc, int tile, Terrain_type_id terrain, int size)
Handles a client request to change the terrain of the tile at the given x, y coordinates.
Definition: edithand.cpp:276
void handle_edit_player(struct connection *pc, const struct packet_edit_player *packet)
Handle editing of any or all player properties.
Definition: edithand.cpp:971
static bool need_continents_reassigned
Definition: edithand.cpp:59
void edithand_send_initial_packets(struct conn_list *dest)
Send the needed packets for connections entering in the editing mode.
Definition: edithand.cpp:94
void edithand_free()
Free all memory used by data structures required for edit mode.
Definition: edithand.cpp:85
static bool * unfogged_players
Definition: edithand.cpp:67
void handle_edit_player_remove(struct connection *pc, int id)
Handle a request to remove a player.
Definition: edithand.cpp:947
static bool edit_tile_terrain_handling(struct tile *ptile, struct terrain *pterrain, bool send_info)
Base function to edit the terrain property of a tile.
Definition: edithand.cpp:208
void handle_edit_city_remove(struct connection *pc, int id)
Remove any city at the given location.
Definition: edithand.cpp:1258
void handle_edit_player_vision(struct connection *pc, int plr_no, int tile, bool known, int size)
Handles vision editing requests from client.
Definition: edithand.cpp:1170
void handle_edit_city(struct connection *pc, const struct packet_edit_city *packet)
Handle a request to change the internal state of a city.
Definition: edithand.cpp:715
void handle_edit_city_create(struct connection *pc, int owner, int tile, int size, int tag)
Allows the editing client to create a city at the given position and of size 'size'.
Definition: edithand.cpp:654
static bool edit_tile_extra_handling(struct tile *ptile, struct extra_type *pextra, bool remove_mode, bool send_info)
Base function to edit the extras property of a tile.
Definition: edithand.cpp:238
void handle_edit_game(struct connection *pc, const struct packet_edit_game *packet)
Handle edit requests to the main game data structure.
Definition: edithand.cpp:1396
void handle_edit_unit_remove(struct connection *pc, int owner, int tile, Unit_type_id utid, int count)
Remove 'count' units of type 'utid' owned by player number 'owner' at tile (x, y).
Definition: edithand.cpp:505
void handle_edit_toggle_fogofwar(struct connection *pc, int plr_no)
Temporarily remove fog-of-war for the player with player number 'plr_no'.
Definition: edithand.cpp:1285
void handle_edit_startpos_full(struct connection *pconn, const struct packet_edit_startpos_full *packet)
Setup which nations can start at a start position.
Definition: edithand.cpp:1358
void handle_edit_player_create(struct connection *pc, int tag)
Handle a request to create a new player.
Definition: edithand.cpp:879
void handle_edit_recalculate_borders(struct connection *pc)
Client editor requests us to recalculate borders.
Definition: edithand.cpp:1250
void handle_save_scenario(struct connection *pc, const char *name)
Make scenario file out of current game.
Definition: edithand.cpp:1471
void edithand_init()
Initialize data structures required for edit mode.
Definition: edithand.cpp:72
static void check_leaving_edit_mode()
Do any necessary checks after leaving edit mode to ensure that the game is in a consistent state.
Definition: edithand.cpp:149
void handle_edit_tile_extra(struct connection *pc, int tile, int id, bool removal, int eowner, int size)
Handle a request to change one or more tiles' extras.
Definition: edithand.cpp:316
void handle_edit_unit_create(struct connection *pc, int owner, int tile, Unit_type_id utid, int count, int tag)
Handle a request to create 'count' units of type 'utid' at the tile given by the x,...
Definition: edithand.cpp:417
void handle_edit_unit(struct connection *pc, const struct packet_edit_unit *packet)
Handles unit information from the client, to make edits to units.
Definition: edithand.cpp:579
void handle_edit_startpos(struct connection *pconn, const struct packet_edit_startpos *packet)
Create or remove a start position at a tile.
Definition: edithand.cpp:1318
struct extra_type * extra_by_number(int id)
Return extras type of given id.
Definition: extras.cpp:154
int extra_number(const struct extra_type *pextra)
Return the extra id.
Definition: extras.cpp:132
#define extra_type_iterate(_p)
Definition: extras.h:279
#define extra_type_iterate_end
Definition: extras.h:285
int Tech_type_id
Definition: fc_types.h:294
int Terrain_type_id
Definition: fc_types.h:290
#define MAX_NUM_PLAYER_SLOTS
Definition: fc_types.h:24
int Unit_type_id
Definition: fc_types.h:299
#define _(String)
Definition: fcintl.h:50
const char * tile_link(const struct tile *ptile)
Get a text link to a tile.
const struct ft_color ftc_editor
const char * city_link(const struct city *pcity)
Get a text link to a city.
const char * unit_link(const struct unit *punit)
Get a text link to an unit.
struct unit * game_unit_by_number(int id)
Find unit out of all units in game: now uses fast idex method, instead of looking through all units o...
Definition: game.cpp:112
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
struct city * game_city_by_number(int id)
Often used function to get a city pointer from a city ID.
Definition: game.cpp:103
void send_scenario_description(struct conn_list *dest)
Send description of the current scenario.
Definition: gamehand.cpp:967
void send_scenario_info(struct conn_list *dest)
Send current scenario info.
Definition: gamehand.cpp:950
void send_game_info(struct conn_list *dest)
Send game_info packet; some server options and various stuff...
Definition: gamehand.cpp:905
struct government * government_by_number(const Government_type_id gov)
Return the government with the given index.
Definition: government.cpp:96
struct city * city_from_great_wonder(const struct impr_type *pimprove)
Get the world city with this great wonder.
bool is_special_improvement(const struct impr_type *pimprove)
Returns TRUE if this is a "special" improvement.
struct city * city_from_small_wonder(const struct player *pplayer, const struct impr_type *pimprove)
Get the player city with this small wonder.
Impr_type_id improvement_number(const struct impr_type *pimprove)
Return the improvement index.
bool is_great_wonder(const struct impr_type *pimprove)
Is this building a great wonder?
const char * improvement_name_translation(const struct impr_type *pimprove)
Return the (translated) name of the given improvement.
bool is_small_wonder(const struct impr_type *pimprove)
Is this building a small wonder?
#define improvement_iterate_end
Definition: improvement.h:199
#define improvement_iterate(_p)
Definition: improvement.h:193
const char * name
Definition: inputfile.cpp:118
struct startpos * map_startpos_get(const struct tile *ptile)
Returns the start position at the given tile, or nullptr if none exists there.
Definition: map.cpp:1548
bool startpos_pack(const struct startpos *psp, struct packet_edit_startpos_full *packet)
Fills the packet with all of the information at this start position.
Definition: map.cpp:1449
bool map_startpos_remove(struct tile *ptile)
Remove the start position at the given tile.
Definition: map.cpp:1565
struct startpos * map_startpos_new(struct tile *ptile)
Create a new start position at the given tile and return it.
Definition: map.cpp:1531
struct tile * startpos_tile(const struct startpos *psp)
Returns the tile where this start position is located.
Definition: map.cpp:1419
bool startpos_unpack(struct startpos *psp, const struct packet_edit_startpos_full *packet)
Fills the start position with the nation information in the packet.
Definition: map.cpp:1469
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Return the tile for the given index position.
Definition: map.cpp:429
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition: map.h:312
#define square_iterate_end
Definition: map.h:315
#define MAP_TILE_OWNER_NULL
Definition: map.h:500
void assign_continent_numbers()
Assigns continent and ocean numbers to all tiles, and set map.num_continents and map....
void map_calculate_borders()
Update borders for all sources.
Definition: maphand.cpp:2244
bool really_gives_vision(struct player *me, struct player *them)
Return TRUE iff the player me really gives shared vision to player them.
Definition: maphand.cpp:325
void send_tile_info(struct conn_list *dest, struct tile *ptile, bool send_unknown)
Send tile information to all the clients in dest which know and see the tile.
Definition: maphand.cpp:485
void send_all_known_tiles(struct conn_list *dest)
Send all tiles known to specified clients.
Definition: maphand.cpp:436
bool need_to_reassign_continents(const struct terrain *oldter, const struct terrain *newter)
Returns TRUE if the terrain change from 'oldter' to 'newter' may require expensive reassignment of co...
Definition: maphand.cpp:1819
void disable_fog_of_war_player(struct player *pplayer)
Turns FoW off for player.
Definition: maphand.cpp:1720
void map_show_tile(struct player *src_player, struct tile *ptile)
Shows the area to the player.
Definition: maphand.cpp:743
void terrain_changed(struct tile *ptile)
Handle local side effects for a terrain change.
Definition: maphand.cpp:1837
void fix_tile_on_terrain_change(struct tile *ptile, struct terrain *oldter, bool extend_rivers)
Handles local side effects for a terrain change (tile and its surroundings).
Definition: maphand.cpp:1856
void enable_fog_of_war_player(struct player *pplayer)
Turns FoW on for player.
Definition: maphand.cpp:1695
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Shows the area to the player.
Definition: maphand.cpp:852
void update_tile_knowledge(struct tile *ptile)
Update playermap knowledge for everybody who sees the tile, and send a packet to everyone whose info ...
Definition: maphand.cpp:1395
void map_hide_tile(struct player *src_player, struct tile *ptile)
Hides the area to the player.
Definition: maphand.cpp:802
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Return TRUE iff a unit of the given unit type can "exist" at this location.
Definition: movement.cpp:236
struct nation_type * nation_by_number(const Nation_type_id nation)
Return the nation with the given index.
Definition: nation.cpp:450
struct government * init_government_of_nation(const struct nation_type *pnation)
Returns initial government type for this nation.
Definition: nation.cpp:545
bool is_nation_playable(const struct nation_type *nation)
Return whether a nation is "playable"; i.e., whether a human player can choose this nation.
Definition: nation.cpp:177
const char * nation_plural_translation(const struct nation_type *pnation)
Return the (translated) plural noun of the given nation.
Definition: nation.cpp:136
struct nation_type * nation_of_player(const struct player *pplayer)
Return the nation of a player.
Definition: nation.cpp:419
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Returns which kind of barbarians can use this nation.
Definition: nation.cpp:188
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
See notify_conn_packet - this is just the "non-v" version, with varargs.
Definition: notify.cpp:235
struct player * player_by_number(const int player_id)
Return struct player pointer for the given player index.
Definition: player.cpp:768
int player_number(const struct player *pplayer)
Return the player index/number/id.
Definition: player.cpp:756
int player_count()
Return the number of players.
Definition: player.cpp:739
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Check if player has given flag.
Definition: player.cpp:1888
int player_index(const struct player *pplayer)
Return the player index.
Definition: player.cpp:748
bool player_set_nation(struct player *pplayer, struct nation_type *pnation)
Set the player's nation to the given nation (may be nullptr).
Definition: player.cpp:780
const char * player_name(const struct player *pplayer)
Return the leader name of the player.
Definition: player.cpp:816
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players are allied.
Definition: player.cpp:1334
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
#define ANON_USER_NAME
Definition: player.h:31
static bool is_barbarian(const struct player *pplayer)
Definition: player.h:474
void send_player_all_c(struct player *src, struct conn_list *dest)
Send all information about a player (player_info and all player_diplstates) to the given connections.
Definition: plrhand.cpp:1031
struct player * server_create_player(int player_id, const char *ai_tname, struct rgbcolor *prgbcolor, bool allow_ai_type_fallbacking)
Creates a new, uninitialized, used player slot.
Definition: plrhand.cpp:1776
bool server_player_set_name_full(const struct connection *caller, struct player *pplayer, const struct nation_type *pnation, const char *name, char *error_buf, size_t error_buf_len)
Try to set the player name to 'name'.
Definition: plrhand.cpp:2059
void assign_player_colors()
Permanently assign colors to any players that don't already have them.
Definition: plrhand.cpp:1608
void kill_player(struct player *pplayer)
Murder a player in cold blood.
Definition: plrhand.cpp:103
void send_player_info_c(struct player *src, struct conn_list *dest)
Send information about player slot 'src', or all valid (i.e.
Definition: plrhand.cpp:1048
struct nation_type * pick_a_nation(const struct nation_list *choices, bool ignore_conflicts, bool needs_startpos, enum barbarian_type barb_type)
This function returns a random-ish nation that is suitable for 'barb_type' and is usable (not already...
Definition: plrhand.cpp:2377
void server_remove_player(struct player *pplayer)
This function does not close any connections attached to this player.
Definition: plrhand.cpp:1825
void government_change(struct player *pplayer, struct government *gov, bool revolution_finished)
Finish the revolution and set the player's government.
Definition: plrhand.cpp:322
void server_player_init(struct player *pplayer, bool initmap, bool needs_team)
Initialize ANY newly-created player on the server.
Definition: plrhand.cpp:1494
struct player_economic player_limit_to_max_rates(struct player *pplayer)
The following limits a player's rates to those that are acceptable for the present form of government...
Definition: plrhand.cpp:1942
bool nation_is_in_current_set(const struct nation_type *pnation)
Is the nation in the currently selected nationset? If not, it's not allowed to appear in the game.
Definition: plrhand.cpp:2520
int revolution_length(struct government *gov, struct player *plr)
Get length of a revolution.
Definition: plrhand.cpp:390
enum tech_state research_invention_set(struct research *presearch, Tech_type_id tech, enum tech_state value)
Set research knowledge about tech to given state.
Definition: research.cpp:627
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
Definition: research.cpp:110
Q_GLOBAL_STATIC(QVector< QString >, future_name_translation)
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Returns state of the tech for current research.
Definition: research.cpp:609
void research_update(struct research *presearch)
Mark as TECH_PREREQS_KNOWN each tech which is available, not known and which has all requirements ful...
Definition: research.cpp:486
#define sanity_check_tile(x)
Definition: sanitycheck.h:36
void save_game(const char *orig_filename, const char *save_reason, bool scenario)
Unconditionally save the game, with specified filename.
Definition: savemain.cpp:139
#define CLIP(lower, current, upper)
Definition: shared.h:51
size_t size
Definition: specvec.h:64
void player_nation_defaults(struct player *pplayer, struct nation_type *pnation, bool set_name)
Set nation for player with nation default values.
Definition: srv_main.cpp:2545
bool game_was_started()
Returns iff the game was started once upon a time.
Definition: srv_main.cpp:251
Definition: city.h:291
int food_stock
Definition: city.h:338
int history
Definition: city.h:379
int id
Definition: city.h:296
char name[MAX_LEN_CITYNAME]
Definition: city.h:292
citizens size
Definition: city.h:301
int shield_stock
Definition: city.h:339
struct packet_scenario_description scenario_desc
Definition: game.h:79
struct packet_ruleset_control control
Definition: game.h:74
struct conn_list * est_connections
Definition: game.h:88
struct packet_game_info info
Definition: game.h:80
struct packet_scenario_info scenario
Definition: game.h:78
struct government * government_during_revolution
Definition: game.h:85
QHash< struct tile *, struct startpos * > * startpos_table
Definition: map_types.h:77
enum cmdlevel access_level
Definition: connection.h:164
struct conn_list * self
Definition: connection.h:150
struct player * player
Definition: nation.h:97
enum barbarian_type barbarian_type
Definition: player.h:115
Definition: player.h:231
struct player_ai ai_common
Definition: player.h:270
bv_plr_flags flags
Definition: player.h:274
char username[MAX_LEN_NAME]
Definition: player.h:234
bool is_connected
Definition: player.h:278
int revolution_finishes
Definition: player.h:255
struct player::@65::@67 server
struct government * government
Definition: player.h:240
struct conn_list * connections
Definition: player.h:280
bool is_alive
Definition: player.h:250
struct player_economic economic
Definition: player.h:266
char name[MAX_LEN_NAME]
Definition: player.h:233
bool unassigned_user
Definition: player.h:235
Tech_type_id researching
Definition: research.h:45
Tech_type_id tech_goal
Definition: research.h:78
int techs_researched
Definition: research.h:35
int bulbs_researched
Definition: research.h:46
Definition: tile.h:42
char * label
Definition: tile.h:57
bv_extras extras
Definition: tile.h:47
struct unit_list * units
Definition: tile.h:50
struct player * extras_owner
Definition: tile.h:55
int vision_radius_sq
Definition: unittype.h:487
int hp
Definition: unittype.h:489
Definition: unit.h:134
int moves_left
Definition: unit.h:147
int id
Definition: unit.h:141
bool moved
Definition: unit.h:170
int hp
Definition: unit.h:148
int fuel
Definition: unit.h:150
bool stay
Definition: unit.h:202
int homecity
Definition: unit.h:142
bool done_moving
Definition: unit.h:178
int veteran
Definition: unit.h:149
struct player * owner
Definition: unit.h:139
struct civ_map map
Definition: world_object.h:21
#define sz_strlcpy(dest, src)
Definition: support.h:140
#define A_FUTURE
Definition: tech.h:39
#define advance_index_iterate_end
Definition: tech.h:226
#define A_FIRST
Definition: tech.h:37
#define A_UNSET
Definition: tech.h:41
#define advance_index_iterate(_start, _index)
Definition: tech.h:221
void init_tech(struct research *research, bool update)
Initializes tech data for the research.
Definition: techtools.cpp:1075
void send_research_info(const struct research *presearch, const struct conn_list *dest)
Send research info for 'presearch' to 'dest'.
Definition: techtools.cpp:273
void give_initial_techs(struct research *presearch, int num_random_techs)
Gives global (read from the game ruleset file) and nation (read from the nation ruleset files) initia...
Definition: techtools.cpp:1179
struct terrain * terrain_by_number(const Terrain_type_id type)
Return the terrain for the given terrain index.
Definition: terrain.cpp:128
#define terrain_has_flag(terr, flag)
Definition: terrain.h:260
void tile_change_terrain(struct tile *ptile, struct terrain *pterrain)
Change the terrain to the given type.
Definition: tile.cpp:491
bool tile_extra_rm_apply(struct tile *ptile, struct extra_type *tgt)
Remove extra and adjust other extras accordingly.
Definition: tile.cpp:605
bool tile_set_label(struct tile *ptile, const char *label)
Sets label for tile.
Definition: tile.cpp:1104
bool tile_extra_apply(struct tile *ptile, const extra_type *tgt)
Add extra and adjust other extras accordingly.
Definition: tile.cpp:578
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
#define tile_index(_pt_)
Definition: tile.h:70
#define tile_terrain(_tile)
Definition: tile.h:93
#define TILE_XY(ptile)
Definition: tile.h:36
#define tile_has_extra(ptile, pextra)
Definition: tile.h:130
struct unit * is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Is there an non-allied unit on this tile?
Definition: unit.cpp:1252
struct unit * is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Is there an enemy unit on this tile? Returns the unit or nullptr if none.
Definition: unit.cpp:1235
#define unit_owner(_pu)
Definition: unit.h:370
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_safe(unitlist, _unit)
Definition: unitlist.h:33
#define unit_list_iterate_end
Definition: unitlist.h:27
#define unit_list_iterate_safe_end
Definition: unitlist.h:54
struct unit * create_unit(struct player *pplayer, struct tile *ptile, const struct unit_type *type, int veteran_level, int homecity_id, int moves_left)
Wrapper of the below.
Definition: unittools.cpp:1762
void send_unit_info(struct conn_list *dest, struct unit *punit)
Send the unit to the players who need the info.
Definition: unittools.cpp:2808
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Remove the unit, and passengers if it is a carrying any.
Definition: unittools.cpp:2248
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
struct unit_type * utype_by_number(const Unit_type_id id)
Return a pointer for the unit type struct for the given unit type id.
Definition: unittype.cpp:103
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Definition: unittype.cpp:1256
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Return veteran level properties of given unit in given veterancy level.
Definition: unittype.cpp:2224
#define utype_class(_t_)
Definition: unittype.h:691
#define utype_fuel(ptype)
Definition: unittype.h:772