Crossfire Server, Trunk
cfcitybell.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2021 The Crossfire Development Team
5  *
6  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
7  * welcome to redistribute it under certain conditions. For details, please
8  * see COPYING and LICENSE.
9  *
10  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
11  */
12 
26 extern "C" {
27 #include "global.h"
28 #include "object.h"
29 #include "sproto.h"
30 #include <string.h>
31 }
32 
33 #include <string>
34 #include <unordered_map>
35 
36 static int last_hr;
37 
39 struct Region {
40  std::unordered_map<std::string, std::string> bells;
41  std::string fallback;
42 };
43 
45 static std::unordered_map<std::string, Region *> regions;
46 
52 static void load_bells(BufferReader *reader, const char *filename) {
53  Region *current = NULL;
54  char *line;
55  char *split[20];
56 
57  while ((line = bufferreader_next_line(reader))) {
58  if (line[0] == '\0' || line[0] == '#') {
59  continue;
60  }
61  char *space = strchr(line, ' ');
62  if (!space) {
63  LOG(llevError, "Invalid bell line '%s' in %s:%ld\n", line, filename, bufferreader_current_line(reader));
64  continue;
65  }
66  *space = '\0';
67  space++;
68 
69  if (strcmp(line, "region") == 0) {
70  current = new Region();
71  regions[space] = current;
72  continue;
73  }
74  if (!current) {
75  LOG(llevError, "Missing 'region' in bell file %s\n", filename);
76  continue;
77  }
78  size_t count = split_string(line, split, sizeof(split), ',');
79  for (size_t i = 0; i < count; i++) {
80  if (strcmp(split[i], "*") == 0) {
81  current->fallback = space;
82  } else {
83  current->bells[split[i]] = space;
84  }
85  }
86  }
87 }
88 
92 static void ring_bell(void) {
93 
94  object *pl = first_player ? first_player->ob : NULL;
95  while (pl) {
96  // If the player is on a map, then try to ring the bell
97  if (pl->map) {
98  region *reg = get_region_by_map(pl->map);
99  if (reg) {
100  auto found = regions.find(reg->name);
101  if (found != regions.end()) {
102  const char *god_name = determine_god(pl);
103  auto god = found->second->bells.find(god_name);
104  std::string msg = god == found->second->bells.end() ? found->second->fallback : god->second;
105  auto r = msg.find("%god");
106  if (r != std::string::npos) {
107  msg.replace(r, 4, god_name);
108  }
110  }
111  }
112  }
113 
114  pl = pl->contr->next ? pl->contr->next->ob : NULL;
115  }
116 }
117 
125 static int clock_listener(int *type, ...) {
126  va_list args;
127  int code;
128  timeofday_t tod;
129 
130  va_start(args, type);
131  code = va_arg(args, int);
132 
133  switch (code) {
134  case EVENT_CLOCK:
135  get_tod(&tod);
136  if (tod.hour != last_hr) {
137  last_hr = tod.hour;
138  ring_bell();
139  }
140  break;
141  }
142 
143  va_end(args);
144 
145  return 0;
146 }
147 
149 
154 extern "C"
156  timeofday_t tod;
157  get_tod(&tod);
158  last_hr = tod.hour;
160 
164 
165  /* Disable the plugin in case it's still there */
166  linked_char *disable = static_cast<linked_char *>(calloc(1, sizeof(linked_char)));
167  disable->next = settings->disabled_plugins;
168  disable->name = strdup("cfcitybell");
169  settings->disabled_plugins = disable;
170 }
171 
172 extern "C"
175  for (auto reg : regions) {
176  delete reg.second;
177  }
178  regions.clear();
179 }
180 
ring_bell
static void ring_bell(void)
Definition: cfcitybell.cpp:92
global.h
Settings::hooks_count
uint8_t hooks_count
Definition: global.h:328
Region::fallback
std::string fallback
Definition: cfcitybell.cpp:41
llevError
@ llevError
Definition: logger.h:11
pl
Definition: player.h:92
pl::ob
object * ob
Definition: player.h:162
Region
Definition: cfcitybell.cpp:39
inja::string_view::split
std::pair< nonstd::string_view, nonstd::string_view > split(nonstd::string_view view, char Separator)
Definition: inja.hpp:1886
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.c:102
bufferreader_current_line
size_t bufferreader_current_line(BufferReader *br)
Definition: bufferreader.c:140
Region::bells
std::unordered_map< std::string, std::string > bells
Definition: cfcitybell.cpp:40
last_hr
static int last_hr
Definition: cfcitybell.cpp:36
npc_dialog.filename
filename
Definition: npc_dialog.py:99
MSG_TYPE_MISC
#define MSG_TYPE_MISC
Definition: newclient.h:413
_timeofday
Definition: tod.h:34
linked_char
Definition: global.h:86
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:246
events_register_global_handler
event_registration events_register_global_handler(int eventcode, f_plug_event hook)
Definition: events.cpp:16
settings
struct Settings settings
Definition: init.c:39
pl::next
struct pl * next
Definition: player.h:93
is_valid_types_gen.line
line
Definition: is_valid_types_gen.py:34
linked_char::name
const char * name
Definition: global.h:87
get_tod
void get_tod(timeofday_t *tod)
Definition: time.c:215
determine_god
const char * determine_god(object *op)
Definition: gods.c:106
EVENT_CLOCK
#define EVENT_CLOCK
Definition: events.h:39
make_face_from_files.args
args
Definition: make_face_from_files.py:30
events_unregister_global_handler
void events_unregister_global_handler(int eventcode, event_registration id)
Definition: events.cpp:23
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
regiondef::name
char * name
Definition: map.h:277
first_player
EXTERN player * first_player
Definition: global.h:115
linked_char::next
struct linked_char * next
Definition: global.h:88
disinfect.count
int count
Definition: disinfect.py:7
Settings::hooks_filename
const char * hooks_filename[20]
Definition: global.h:329
sproto.h
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:420
cfcitybell_init
void cfcitybell_init(Settings *settings)
Definition: cfcitybell.cpp:155
split_string
size_t split_string(char *str, char *array[], size_t array_size, char sep)
Definition: utils.c:500
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
Settings
Definition: global.h:237
Settings::disabled_plugins
linked_char * disabled_plugins
Definition: global.h:322
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
get_region_by_map
region * get_region_by_map(mapstruct *m)
Definition: region.c:74
event_registration
unsigned long event_registration
Definition: events.h:62
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
cfcitybell_close
void cfcitybell_close()
Definition: cfcitybell.cpp:173
regions
static std::unordered_map< std::string, Region * > regions
Definition: cfcitybell.cpp:45
Settings::hooks
collectorHook hooks[20]
Definition: global.h:330
global_handler
static event_registration global_handler
Definition: cfcitybell.cpp:148
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:309
replace.current
current
Definition: replace.py:64
BufferReader
Definition: bufferreader.c:21
clock_listener
static int clock_listener(int *type,...)
Definition: cfcitybell.cpp:125
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
object.h
load_bells
static void load_bells(BufferReader *reader, const char *filename)
Definition: cfcitybell.cpp:52
_timeofday::hour
int hour
Definition: tod.h:39
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25
regiondef
Definition: map.h:275