Freeciv21
Develop your civilization from humble roots to a global empire
notify.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2020 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <cstdarg>
15 
16 // utility
17 #include "bitvector.h"
18 #include "fcintl.h"
19 #include "log.h"
20 #include "registry.h"
21 #include "registry_ini.h"
22 
23 // common
24 #include "connection.h"
25 #include "events.h"
26 #include "featured_text.h"
27 #include "game.h"
28 #include "packets.h"
29 #include "player.h"
30 #include "research.h"
31 #include "tile.h"
32 
33 // server
34 #include "maphand.h"
35 #include "srv_main.h"
36 
37 #include "notify.h"
38 
52 static void package_event_full(struct packet_chat_msg *packet,
53  const struct tile *ptile,
54  enum event_type event,
55  const struct connection *pconn,
56  const struct ft_color color,
57  const char *format, va_list vargs)
58 {
59  char buf[MAX_LEN_MSG];
60  char *str;
61 
62  fc_assert_ret(nullptr != packet);
63 
64  packet->tile = (nullptr != ptile ? tile_index(ptile) : -1);
65  packet->event = event;
66  packet->conn_id = pconn ? pconn->id : -1;
67  packet->turn = game.info.turn;
68  packet->phase = game.info.phase;
69 
70  fc_vsnprintf(buf, sizeof(buf), format, vargs);
72  str = capitalized_string(buf);
73  } else {
74  str = buf;
75  }
76 
77  if (ft_color_requested(color)) {
78  featured_text_apply_tag(str, packet->message, sizeof(packet->message),
79  TTT_COLOR, 0, FT_OFFSET_UNSET, color);
80  } else {
81  // Simple case
82  sz_strlcpy(packet->message, str);
83  }
84 
86  delete[] str;
87  str = nullptr;
88  }
89 }
90 
102 void vpackage_chat_msg(struct packet_chat_msg *packet,
103  const struct connection *sender,
104  const struct ft_color color, const char *format,
105  va_list vargs)
106 {
107  package_event_full(packet, nullptr, E_CHAT_MSG, sender, color, format,
108  vargs);
109 }
110 
122 void package_chat_msg(struct packet_chat_msg *packet,
123  const struct connection *sender,
124  const struct ft_color color, const char *format, ...)
125 {
126  va_list args;
127 
128  va_start(args, format);
129  vpackage_chat_msg(packet, sender, color, format, args);
130  va_end(args);
131 }
132 
145 void vpackage_event(struct packet_chat_msg *packet, const struct tile *ptile,
146  enum event_type event, const struct ft_color color,
147  const char *format, va_list vargs)
148 {
149  package_event_full(packet, ptile, event, nullptr, color, format, vargs);
150 }
151 
164 void package_event(struct packet_chat_msg *packet, const struct tile *ptile,
165  enum event_type event, const struct ft_color color,
166  const char *format, ...)
167 {
168  va_list args;
169 
170  va_start(args, format);
171  vpackage_event(packet, ptile, event, color, format, args);
172  va_end(args);
173 }
174 
186 static void notify_conn_packet(struct conn_list *dest,
187  const struct packet_chat_msg *packet,
188  bool early)
189 {
190  struct packet_chat_msg real_packet = *packet;
191  int tile = packet->tile;
192  struct tile *ptile = index_to_tile(&(wld.map), tile);
193 
194  if (!dest) {
195  dest = game.est_connections;
196  }
197 
198  conn_list_iterate(dest, pconn)
199  {
200  /* Avoid sending messages that could potentially reveal
201  * internal information about the server machine to
202  * connections that do not already have hack access. */
203  if ((packet->event == E_LOG_ERROR || packet->event == E_LOG_FATAL)
204  && pconn->access_level != ALLOW_HACK) {
205  continue;
206  }
207 
208  if (S_S_RUNNING <= server_state() && ptile // special case, see above
209  && ((nullptr == pconn->playing && pconn->observer)
210  || (nullptr != pconn->playing
211  && map_is_known(ptile, pconn->playing)))) {
212  // tile info is OK; see above.
213  /* FIXME: in the case this is a city event, we should check if the
214  * city is really known. */
215  real_packet.tile = tile;
216  } else {
217  // No tile info.
218  real_packet.tile = -1;
219  }
220 
221  if (early) {
222  send_packet_early_chat_msg(
223  pconn,
224  reinterpret_cast<struct packet_early_chat_msg *>(&real_packet));
225  } else {
226  send_packet_chat_msg(pconn, &real_packet);
227  }
228  }
230 }
231 
235 void notify_conn(struct conn_list *dest, const struct tile *ptile,
236  enum event_type event, const struct ft_color color,
237  const char *format, ...)
238 {
239  struct packet_chat_msg genmsg;
240  va_list args;
241 
242  va_start(args, format);
243  vpackage_event(&genmsg, ptile, event, color, format, args);
244  va_end(args);
245 
246  notify_conn_packet(dest, &genmsg, false);
247 
248  if (!dest || dest == game.est_connections) {
249  // Add to the cache
250  event_cache_add_for_all(&genmsg);
251  }
252 }
253 
258 void notify_conn_early(struct conn_list *dest, const struct tile *ptile,
259  enum event_type event, const struct ft_color color,
260  const char *format, ...)
261 {
262  struct packet_chat_msg genmsg;
263  va_list args;
264 
265  va_start(args, format);
266  vpackage_event(&genmsg, ptile, event, color, format, args);
267  va_end(args);
268 
269  notify_conn_packet(dest, &genmsg, true);
270 
271  if (!dest || dest == game.est_connections) {
272  // Add to the cache
273  event_cache_add_for_all(&genmsg);
274  }
275 }
276 
284 void notify_player(const struct player *pplayer, const struct tile *ptile,
285  enum event_type event, const struct ft_color color,
286  const char *format, ...)
287 {
288  struct conn_list *dest = pplayer ? pplayer->connections : nullptr;
289  struct packet_chat_msg genmsg;
290  va_list args;
291 
292  va_start(args, format);
293  vpackage_event(&genmsg, ptile, event, color, format, args);
294  va_end(args);
295 
296  notify_conn_packet(dest, &genmsg, false);
297 
298  // Add to the cache
299  event_cache_add_for_player(&genmsg, pplayer);
300 }
301 
306 void notify_embassies(const struct player *pplayer, const struct tile *ptile,
307  enum event_type event, const struct ft_color color,
308  const char *format, ...)
309 {
310  struct packet_chat_msg genmsg;
311  struct event_cache_players *players = nullptr;
312  va_list args;
313 
314  va_start(args, format);
315  vpackage_event(&genmsg, ptile, event, color, format, args);
316  va_end(args);
317 
318  players_iterate(other_player)
319  {
320  if (player_has_embassy(other_player, pplayer)
321  && pplayer != other_player) {
322  notify_conn_packet(other_player->connections, &genmsg, false);
323  players = event_cache_player_add(players, other_player);
324  }
325  }
327 
328  // Add to the cache
329  event_cache_add_for_players(&genmsg, players);
330 }
331 
336 void notify_team(const struct player *pplayer, const struct tile *ptile,
337  enum event_type event, const struct ft_color color,
338  const char *format, ...)
339 {
340  struct conn_list *dest = game.est_connections;
341  struct packet_chat_msg genmsg;
342  struct event_cache_players *players = nullptr;
343  va_list args;
344 
345  va_start(args, format);
346  vpackage_event(&genmsg, ptile, event, color, format, args);
347  va_end(args);
348 
349  if (pplayer) {
350  dest = conn_list_new();
351  players_iterate(other_player)
352  {
353  if (!players_on_same_team(pplayer, other_player)) {
354  continue;
355  }
356  conn_list_iterate(other_player->connections, pconn)
357  {
358  conn_list_append(dest, pconn);
359  }
361  players = event_cache_player_add(players, other_player);
362  }
364 
365  // Add to the cache
366  event_cache_add_for_players(&genmsg, players);
367 
368  } else {
369  // Add to the cache for all players.
370  event_cache_add_for_all(&genmsg);
371  }
372 
373  notify_conn_packet(dest, &genmsg, false);
374 
375  if (pplayer) {
376  conn_list_destroy(dest);
377  }
378 }
379 
386 void notify_research(const struct research *presearch,
387  const struct player *exclude, enum event_type event,
388  const struct ft_color color, const char *format, ...)
389 {
390  struct packet_chat_msg genmsg;
391  struct event_cache_players *players = nullptr;
392  va_list args;
393 
394  va_start(args, format);
395  vpackage_event(&genmsg, nullptr, event, color, format, args);
396  va_end(args);
397 
398  research_players_iterate(presearch, aplayer)
399  {
400  if (exclude != aplayer) {
401  lsend_packet_chat_msg(aplayer->connections, &genmsg);
402  players = event_cache_player_add(players, aplayer);
403  }
404  }
406 
407  // Add to the cache
408  event_cache_add_for_players(&genmsg, players);
409 }
410 
426 void notify_research_embassies(const struct research *presearch,
427  const struct player *exclude,
428  enum event_type event,
429  const struct ft_color color,
430  const char *format, ...)
431 {
432  struct packet_chat_msg genmsg;
433  struct event_cache_players *players = nullptr;
434  va_list args;
435 
436  va_start(args, format);
437  vpackage_event(&genmsg, nullptr, event, color, format, args);
438  va_end(args);
439 
440  players_iterate(aplayer)
441  {
442  if (exclude == aplayer || research_get(aplayer) == presearch) {
443  continue;
444  }
445 
446  research_players_iterate(presearch, rplayer)
447  {
448  if (player_has_embassy(aplayer, rplayer)) {
449  lsend_packet_chat_msg(aplayer->connections, &genmsg);
450  players = event_cache_player_add(players, aplayer);
451  break;
452  }
453  }
455  }
457 
458  // Add to the cache
459  event_cache_add_for_players(&genmsg, players);
460 }
461 
466 
467 // Events are saved in that structure.
469  struct packet_chat_msg packet;
470  time_t timestamp;
471  enum server_states server_state;
473  bv_player target; // Used if target_type == ECT_PLAYERS.
474 };
475 
476 #define SPECLIST_TAG event_cache_data
477 #define SPECLIST_TYPE struct event_cache_data
478 #include "speclist.h"
479 #define event_cache_iterate(pdata) \
480  TYPED_LIST_ITERATE(struct event_cache_data, event_cache, pdata)
481 #define event_cache_iterate_end LIST_ITERATE_END
482 
484  bv_player vector;
485 };
486 
487 // The full list of the events.
488 static struct event_cache_data_list *event_cache = nullptr;
489 
490 /* Event cache status: ON(TRUE) / OFF(FALSE); used for saving the
491  * event cache */
492 static bool event_cache_status = false;
493 
497 static void event_cache_data_free(struct event_cache_data *data)
498 {
499  delete data;
500 }
501 
506 static struct event_cache_data *
507 event_cache_data_new(const struct packet_chat_msg *packet, time_t timestamp,
508  enum server_states server_status,
510  struct event_cache_players *players)
511 {
512  struct event_cache_data *pdata;
513  int max_events;
514 
515  if (nullptr == event_cache) {
516  /* Don't do log for this, because this could make an infinite
517  * recursion. */
518  return nullptr;
519  }
520  fc_assert_ret_val(nullptr != packet, nullptr);
521 
522  if (packet->event == E_MESSAGE_WALL) {
523  // No popups at save game load.
524  return nullptr;
525  }
526 
527  if (!game.server.event_cache.chat && packet->event == E_CHAT_MSG) {
528  // chat messages should _not_ be saved
529  return nullptr;
530  }
531 
532  // check if cache is active
533  if (!event_cache_status) {
534  return nullptr;
535  }
536 
537  pdata = new event_cache_data;
538  pdata->packet = *packet;
539  pdata->timestamp = timestamp;
540  pdata->server_state = server_status;
541  pdata->target_type = target_type;
542  if (players) {
543  pdata->target = players->vector;
544  } else {
545  BV_CLR_ALL(pdata->target);
546  }
547  event_cache_data_list_append(event_cache, pdata);
548 
549  max_events = game.server.event_cache.max_size
550  ? game.server.event_cache.max_size
552  while (event_cache_data_list_size(event_cache) > max_events) {
553  event_cache_data_list_pop_front(event_cache);
554  }
555 
556  return pdata;
557 }
558 
563 {
564  if (event_cache != nullptr) {
566  }
567  event_cache = event_cache_data_list_new_full(event_cache_data_free);
568  event_cache_status = true;
569 }
570 
575 {
576  if (event_cache != nullptr) {
577  event_cache_data_list_destroy(event_cache);
578  event_cache = nullptr;
579  }
580  event_cache_status = false;
581 }
582 
586 void event_cache_clear() { event_cache_data_list_clear(event_cache); }
587 
592 {
593  struct event_cache_data *current;
594 
595  // This assumes that entries are in order, the ones to be removed first.
596  current = event_cache_data_list_get(event_cache, 0);
597 
598  while (current != nullptr
599  && current->packet.turn + game.server.event_cache.turns
600  <= game.info.turn) {
601  event_cache_data_list_pop_front(event_cache);
602  current = event_cache_data_list_get(event_cache, 0);
603  }
604 }
605 
609 void event_cache_add_for_all(const struct packet_chat_msg *packet)
610 {
611  if (0 < game.server.event_cache.turns) {
612  (void) event_cache_data_new(packet, time(nullptr), server_state(),
613  ECT_ALL, nullptr);
614  }
615 }
616 
621  const struct packet_chat_msg *packet)
622 {
623  if (0 < game.server.event_cache.turns) {
624  (void) event_cache_data_new(packet, time(nullptr), server_state(),
625  ECT_GLOBAL_OBSERVERS, nullptr);
626  }
627 }
628 
636 void event_cache_add_for_player(const struct packet_chat_msg *packet,
637  const struct player *pplayer)
638 {
639  if (nullptr == pplayer) {
641  return;
642  }
643 
644  if (0 < game.server.event_cache.turns
645  && (server_state() > S_S_INITIAL || !game.info.is_new_game)) {
646  struct event_cache_data *pdata;
647 
648  pdata = event_cache_data_new(packet, time(nullptr), server_state(),
649  ECT_PLAYERS, nullptr);
650  fc_assert_ret(nullptr != pdata);
651  BV_SET(pdata->target, player_index(pplayer));
652  }
653 }
654 
662 void event_cache_add_for_players(const struct packet_chat_msg *packet,
663  struct event_cache_players *players)
664 {
665  if (0 < game.server.event_cache.turns && nullptr != players
666  && BV_ISSET_ANY(players->vector)
667  && (server_state() > S_S_INITIAL || !game.info.is_new_game)) {
668  (void) event_cache_data_new(packet, time(nullptr), server_state(),
669  ECT_PLAYERS, players);
670  }
671 
672  if (nullptr != players) {
673  delete players;
674  }
675 }
676 
692 struct event_cache_players *
694  const struct player *pplayer)
695 {
696  if (nullptr == players) {
697  players = new event_cache_players;
698  BV_CLR_ALL(players->vector);
699  }
700 
701  if (nullptr != pplayer) {
702  BV_SET(players->vector, player_index(pplayer));
703  }
704 
705  return players;
706 }
707 
711 static bool event_cache_match(const struct event_cache_data *pdata,
712  const struct player *pplayer,
713  bool is_global_observer, bool include_public)
714 {
715  if (server_state() != pdata->server_state) {
716  return false;
717  }
718 
719  if (server_state() == S_S_RUNNING && game.info.turn < pdata->packet.turn
720  && game.info.turn
721  > pdata->packet.turn - game.server.event_cache.turns) {
722  return false;
723  }
724 
725  switch (pdata->target_type) {
726  case ECT_ALL:
727  return include_public;
728  case ECT_PLAYERS:
729  return (nullptr != pplayer
730  && BV_ISSET(pdata->target, player_index(pplayer)));
732  return is_global_observer;
733  }
734 
735  return false;
736 }
737 
742 void send_pending_events(struct connection *pconn, bool include_public)
743 {
744  const struct player *pplayer = conn_get_player(pconn);
745  bool is_global_observer = conn_is_global_observer(pconn);
746  char timestr[64];
747  struct packet_chat_msg pcm;
748 
749  event_cache_iterate(pdata)
750  {
751  if (event_cache_match(pdata, pplayer, is_global_observer,
752  include_public)) {
753  if (game.server.event_cache.info) {
754  // add turn and time to the message
755  strftime(timestr, sizeof(timestr), "%H:%M:%S",
756  localtime(&pdata->timestamp));
757  pcm = pdata->packet;
758  fc_snprintf(pcm.message, sizeof(pcm.message), "(T%d - %s) %s",
759  pdata->packet.turn, timestr, pdata->packet.message);
760  notify_conn_packet(pconn->self, &pcm, false);
761  } else {
762  notify_conn_packet(pconn->self, &pdata->packet, false);
763  }
764  }
765  }
767 }
768 
772 void event_cache_load(struct section_file *file, const char *section)
773 {
774  struct packet_chat_msg packet;
775  enum event_cache_target target_type;
776  enum server_states server_status;
777  struct event_cache_players *players = nullptr;
778  int i, x, y, event_count;
779  time_t timestamp, now;
780  const char *p, *q;
781 
782  event_count = secfile_lookup_int_default(file, 0, "%s.count", section);
783  qDebug("Saved events: %d.", event_count);
784 
785  if (0 >= event_count) {
786  return;
787  }
788 
789  now = time(nullptr);
790  for (i = 0; i < event_count; i++) {
791  int turn;
792  int phase;
793 
794  // restore packet
795  x = secfile_lookup_int_default(file, -1, "%s.events%d.x", section, i);
796  y = secfile_lookup_int_default(file, -1, "%s.events%d.y", section, i);
797  packet.tile =
798  (is_normal_map_pos(x, y) ? map_pos_to_index(&(wld.map), x, y) : -1);
799  packet.conn_id = -1;
800 
801  p = secfile_lookup_str(file, "%s.events%d.event", section, i);
802  if (nullptr == p) {
803  qDebug("[Event cache %4d] Missing event type.", i);
804  continue;
805  }
806  packet.event = event_type_by_name(p, fc_strcasecmp);
807  if (!event_type_is_valid(packet.event)) {
808  qDebug("[Event cache %4d] Not supported event type: %s", i, p);
809  continue;
810  }
811 
812  p = secfile_lookup_str(file, "%s.events%d.message", section, i);
813  if (nullptr == p) {
814  qDebug("[Event cache %4d] Missing message.", i);
815  continue;
816  }
817  sz_strlcpy(packet.message, p);
818 
819  // restore event cache data
820  turn =
821  secfile_lookup_int_default(file, 0, "%s.events%d.turn", section, i);
822  packet.turn = turn;
823 
825  "%s.events%d.phase", section, i);
826  packet.phase = phase;
827 
828  timestamp = secfile_lookup_int_default(
829  file, now, "%s.events%d.timestamp", section, i);
830 
831  p = secfile_lookup_str(file, "%s.events%d.server_state", section, i);
832  if (nullptr == p) {
833  qDebug("[Event cache %4d] Missing server state info.", i);
834  continue;
835  }
836  server_status = server_states_by_name(p, fc_strcasecmp);
837  if (!server_states_is_valid(server_status)) {
838  qDebug("[Event cache %4d] Server state no supported: %s", i, p);
839  continue;
840  }
841 
842  p = secfile_lookup_str(file, "%s.events%d.target", section, i);
843  if (nullptr == p) {
844  qDebug("[Event cache %4d] Missing target info.", i);
845  continue;
846  } else if (0 == fc_strcasecmp(p, "All")) {
847  target_type = ECT_ALL;
848  } else if (0 == fc_strcasecmp(p, "Global Observers")) {
849  target_type = ECT_GLOBAL_OBSERVERS;
850  } else {
851  bool valid = true;
852 
853  target_type = ECT_PLAYERS;
854  q = p;
855  players_iterate(pplayer)
856  {
857  if ('1' == *q) {
858  players = event_cache_player_add(players, pplayer);
859  } else if ('0' != *q) {
860  // a value not '0' or '1' means a corruption of the savegame
861  valid = false;
862  break;
863  }
864 
865  q++;
866  }
868 
869  if (!valid && nullptr == players) {
870  qDebug("[Event cache %4d] invalid target bitmap: %s", i, p);
871  delete players;
872  players = nullptr;
873  }
874  }
875 
876  // insert event into the cache
877  (void) event_cache_data_new(&packet, timestamp, server_status,
878  target_type, players);
879  delete players;
880  players = nullptr;
881  qDebug("Event %4d loaded.", i);
882  }
883 }
884 
888 void event_cache_save(struct section_file *file, const char *section)
889 {
890  int event_count = 0;
891 
892  /* stop event logging; this way events from log_*() will not be added
893  * to the event list while saving the event list */
894  event_cache_status = false;
895 
896  event_cache_iterate(pdata)
897  {
898  struct tile *ptile = index_to_tile(&(wld.map), pdata->packet.tile);
899  char target[MAX_NUM_PLAYER_SLOTS + 1];
900  char *p;
901  int tile_x = -1, tile_y = -1;
902 
903  if (ptile != nullptr) {
904  index_to_map_pos(&tile_x, &tile_y, tile_index(ptile));
905  }
906 
907  secfile_insert_int(file, pdata->packet.turn, "%s.events%d.turn", section,
908  event_count);
909  if (pdata->packet.phase != PHASE_UNKNOWN) {
910  /* Do not save current value of PHASE_UNKNOWN to savegame.
911  * It practically means that "savegame had no phase stored".
912  * Note that the only case where phase might be PHASE_UNKNOWN
913  * may be present is that the event was loaded from previous
914  * savegame created by a freeciv version that did not store event
915  * phases. */
916  secfile_insert_int(file, pdata->packet.phase, "%s.events%d.phase",
917  section, event_count);
918  }
919  secfile_insert_int(file, pdata->timestamp, "%s.events%d.timestamp",
920  section, event_count);
921  secfile_insert_int(file, tile_x, "%s.events%d.x", section, event_count);
922  secfile_insert_int(file, tile_y, "%s.events%d.y", section, event_count);
923  secfile_insert_str(file, server_states_name(pdata->server_state),
924  "%s.events%d.server_state", section, event_count);
925  secfile_insert_str(file, event_type_name(pdata->packet.event),
926  "%s.events%d.event", section, event_count);
927  switch (pdata->target_type) {
928  case ECT_ALL:
929  fc_snprintf(target, sizeof(target), "All");
930  break;
931  case ECT_PLAYERS:
932  p = target;
933  players_iterate(pplayer)
934  {
935  *p++ = (BV_ISSET(pdata->target, player_index(pplayer)) ? '1' : '0');
936  }
938  *p = '\0';
939  break;
941  fc_snprintf(target, sizeof(target), "Global Observers");
942  break;
943  }
944  secfile_insert_str(file, target, "%s.events%d.target", section,
945  event_count);
946  secfile_insert_str(file, pdata->packet.message, "%s.events%d.message",
947  section, event_count);
948 
949  qDebug("Event %4d saved.", event_count);
950 
951  event_count++;
952  }
954 
955  // save the number of events in the event cache
956  secfile_insert_int(file, event_count, "%s.count", section);
957 
958  qDebug("Events saved: %d.", event_count);
959 
960  event_cache_status = true;
961 }
962 
967 {
968  event_cache_iterate(pdata)
969  {
970  if (pdata->packet.phase >= 0) {
971  pdata->packet.phase = PHASE_INVALIDATED;
972  }
973  }
975 }
#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_ISSET_ANY(vec)
Definition: bitvector.h:76
struct player * conn_get_player(const struct connection *pconn)
Returns the player that this connection is attached to, or nullptr.
Definition: connection.cpp:693
bool conn_is_global_observer(const struct connection *pconn)
Returns TRUE if the given connection is a global observer.
Definition: connection.cpp:683
#define conn_list_iterate(connlist, pconn)
Definition: connection.h:99
#define conn_list_iterate_end
Definition: connection.h:101
enum event_type event
Definition: events.cpp:68
#define PHASE_INVALIDATED
Definition: fc_types.h:857
#define MAX_NUM_PLAYER_SLOTS
Definition: fc_types.h:24
#define PHASE_UNKNOWN
Definition: fc_types.h:859
char * capitalized_string(const char *str)
This function tries to capitalize first letter of the string.
Definition: fcintl.cpp:57
bool is_capitalization_enabled()
Automatic capitalization features requested.
Definition: fcintl.cpp:89
size_t featured_text_apply_tag(const char *text_source, char *featured_text, size_t featured_text_len, enum text_tag_type tag_type, ft_offset_t start_offset, ft_offset_t stop_offset,...)
Apply a tag to a text.
#define FT_OFFSET_UNSET
Definition: featured_text.h:95
static bool ft_color_requested(const struct ft_color color)
@ TTT_COLOR
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
#define GAME_MAX_EVENT_CACHE_MAX_SIZE
Definition: game.h:659
#define fc_assert_ret(condition)
Definition: log.h:112
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
bool is_normal_map_pos(int x, int y)
Returns TRUE iff the map position is normal.
Definition: map.cpp:902
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Return the tile for the given index position.
Definition: map.cpp:429
static int map_pos_to_index(struct civ_map *nmap, int map_x, int map_y)
Definition: map.h:596
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition: map.h:164
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Return whether the player knows the tile.
Definition: maphand.cpp:884
void event_cache_clear()
Remove all events from the cache.
Definition: notify.cpp:586
void event_cache_init()
Initializes the event cache.
Definition: notify.cpp:562
struct event_cache_players * event_cache_player_add(struct event_cache_players *players, const struct player *pplayer)
Select players for event_cache_add_for_players().
Definition: notify.cpp:693
void notify_research(const struct research *presearch, const struct player *exclude, enum event_type event, const struct ft_color color, const char *format,...)
Sends a message to all players that share research.
Definition: notify.cpp:386
#define event_cache_iterate(pdata)
Definition: notify.cpp:479
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Similar to notify_conn_packet (see also), but takes player as "destination".
Definition: notify.cpp:284
void send_pending_events(struct connection *pconn, bool include_public)
Send all available events.
Definition: notify.cpp:742
void package_chat_msg(struct packet_chat_msg *packet, const struct connection *sender, const struct ft_color color, const char *format,...)
Fill a packet_chat_msg structure for a chat message.
Definition: notify.cpp:122
void event_cache_add_for_players(const struct packet_chat_msg *packet, struct event_cache_players *players)
Add an event to the cache for selected players.
Definition: notify.cpp:662
void event_cache_load(struct section_file *file, const char *section)
Load the event cache from a savefile.
Definition: notify.cpp:772
void notify_research_embassies(const struct research *presearch, const struct player *exclude, enum event_type event, const struct ft_color color, const char *format,...)
Sends a message to all players that have embassies with someone who shares research.
Definition: notify.cpp:426
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
void event_cache_remove_old()
Remove the old events from the cache.
Definition: notify.cpp:591
void vpackage_event(struct packet_chat_msg *packet, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format, va_list vargs)
Fill a packet_chat_msg structure for common server event.
Definition: notify.cpp:145
event_cache_target
Event cache datas.
Definition: notify.cpp:465
@ ECT_ALL
Definition: notify.cpp:465
@ ECT_PLAYERS
Definition: notify.cpp:465
@ ECT_GLOBAL_OBSERVERS
Definition: notify.cpp:465
void event_cache_free()
Frees the event cache.
Definition: notify.cpp:574
void notify_team(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Sends a message to all players on pplayer's team.
Definition: notify.cpp:336
static struct event_cache_data * event_cache_data_new(const struct packet_chat_msg *packet, time_t timestamp, enum server_states server_status, enum event_cache_target target_type, struct event_cache_players *players)
Creates a new event_cache_data, appened to the list.
Definition: notify.cpp:507
void event_cache_phases_invalidate()
Mark all existing phase values in event cache invalid.
Definition: notify.cpp:966
void notify_embassies(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Send message to all players who have an embassy with pplayer, but excluding pplayer and specified pla...
Definition: notify.cpp:306
static void notify_conn_packet(struct conn_list *dest, const struct packet_chat_msg *packet, bool early)
This is the basis for following notify_* functions.
Definition: notify.cpp:186
void package_event(struct packet_chat_msg *packet, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Fill a packet_chat_msg structure for common server event.
Definition: notify.cpp:164
void notify_conn_early(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:258
void event_cache_add_for_global_observers(const struct packet_chat_msg *packet)
Add an event to the cache for all global observers.
Definition: notify.cpp:620
static void package_event_full(struct packet_chat_msg *packet, const struct tile *ptile, enum event_type event, const struct connection *pconn, const struct ft_color color, const char *format, va_list vargs)
Fill a packet_chat_msg structure.
Definition: notify.cpp:52
static bool event_cache_match(const struct event_cache_data *pdata, const struct player *pplayer, bool is_global_observer, bool include_public)
Returns whether the event may be displayed for the connection.
Definition: notify.cpp:711
static void event_cache_data_free(struct event_cache_data *data)
Callback for freeing event cache data.
Definition: notify.cpp:497
void event_cache_add_for_player(const struct packet_chat_msg *packet, const struct player *pplayer)
Add an event to the cache for one player.
Definition: notify.cpp:636
void vpackage_chat_msg(struct packet_chat_msg *packet, const struct connection *sender, const struct ft_color color, const char *format, va_list vargs)
Fill a packet_chat_msg structure for a chat message.
Definition: notify.cpp:102
#define event_cache_iterate_end
Definition: notify.cpp:481
static bool event_cache_status
Definition: notify.cpp:492
void event_cache_add_for_all(const struct packet_chat_msg *packet)
Add an event to the cache for all connections.
Definition: notify.cpp:609
void event_cache_save(struct section_file *file, const char *section)
Save the event cache into the savegame.
Definition: notify.cpp:888
static struct event_cache_data_list * event_cache
Definition: notify.cpp:488
#define MAX_LEN_MSG
Definition: packets.h:37
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Return TRUE if players are in the same team.
Definition: player.cpp:1405
int player_index(const struct player *pplayer)
Return the player index.
Definition: player.cpp:748
bool player_has_embassy(const struct player *pplayer, const struct player *pplayer2)
Check if pplayer has an embassy with pplayer2.
Definition: player.cpp:195
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
const char * secfile_lookup_str(const struct section_file *secfile, const char *path,...)
Lookup a string value in the secfile.
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
Lookup a integer value in the secfile.
#define secfile_insert_int(secfile, value, path,...)
Definition: registry_ini.h:116
#define secfile_insert_str(secfile, string, path,...)
Definition: registry_ini.h:167
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
Definition: research.cpp:110
#define research_players_iterate(_presearch, _pplayer)
Definition: research.h:151
#define research_players_iterate_end
Definition: research.h:155
enum server_states server_state()
Return current server state.
Definition: srv_main.cpp:238
struct civ_game::@28::@32 server
struct conn_list * est_connections
Definition: game.h:88
struct packet_game_info info
Definition: game.h:80
struct conn_list * self
Definition: connection.h:150
enum server_states server_state
Definition: notify.cpp:471
struct packet_chat_msg packet
Definition: notify.cpp:469
bv_player target
Definition: notify.cpp:473
time_t timestamp
Definition: notify.cpp:470
enum event_cache_target target_type
Definition: notify.cpp:472
bv_player vector
Definition: notify.cpp:484
Definition: player.h:231
struct conn_list * connections
Definition: player.h:280
Definition: tile.h:42
struct civ_map map
Definition: world_object.h:21
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
int fc_strcasecmp(const char *str0, const char *str1)
Compare strings like strcmp(), but ignoring case.
Definition: support.cpp:89
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition: support.cpp:512
#define sz_strlcpy(dest, src)
Definition: support.h:140
#define tile_index(_pt_)
Definition: tile.h:70