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 #include "global.h"
27 #include "object.h"
28 #include "sproto.h"
29 #include <string.h>
30 
31 #include <string>
32 #include <unordered_map>
33 
34 static int last_hr;
35 
37 struct Region {
38  std::unordered_map<std::string, std::string> bells;
39  std::string fallback;
40 };
41 
43 static std::unordered_map<std::string, Region *> regions;
44 
50 static void load_bells(BufferReader *reader, const char *filename) {
51  Region *current = NULL;
52  char *line;
53  char *split[20];
54 
55  while ((line = bufferreader_next_line(reader))) {
56  if (line[0] == '\0' || line[0] == '#') {
57  continue;
58  }
59  char *space = strchr(line, ' ');
60  if (!space) {
61  LOG(llevError, "Invalid bell line '%s' in %s:%zu\n", line, filename, bufferreader_current_line(reader));
62  continue;
63  }
64  *space = '\0';
65  space++;
66 
67  if (strcmp(line, "region") == 0) {
68  current = new Region();
69  regions[space] = current;
70  continue;
71  }
72  if (!current) {
73  LOG(llevError, "Missing 'region' in bell file %s\n", filename);
74  continue;
75  }
76  size_t count = split_string(line, split, sizeof(split), ',');
77  for (size_t i = 0; i < count; i++) {
78  if (strcmp(split[i], "*") == 0) {
79  current->fallback = space;
80  } else {
81  current->bells[split[i]] = space;
82  }
83  }
84  }
85 }
86 
90 static void ring_bell(void) {
91 
92  object *pl = first_player ? first_player->ob : NULL;
93  while (pl) {
94  // If the player is on a map, then try to ring the bell
95  if (pl->map) {
96  region *reg = get_region_by_map(pl->map);
97  if (reg) {
98  auto found = regions.find(reg->name);
99  if (found != regions.end()) {
100  const char *god_name = determine_god(pl);
101  auto god = found->second->bells.find(god_name);
102  std::string msg = god == found->second->bells.end() ? found->second->fallback : god->second;
103  auto r = msg.find("%god");
104  if (r != std::string::npos) {
105  msg.replace(r, 4, god_name);
106  }
108  }
109  }
110  }
111 
112  pl = pl->contr->next ? pl->contr->next->ob : NULL;
113  }
114 }
115 
123 static int clock_listener(int *type, ...) {
124  va_list args;
125  int code;
126  timeofday_t tod;
127 
128  va_start(args, type);
129  code = va_arg(args, int);
130 
131  switch (code) {
132  case EVENT_CLOCK:
133  get_tod(&tod);
134  if (tod.hour != last_hr) {
135  last_hr = tod.hour;
136  ring_bell();
137  }
138  break;
139  }
140 
141  va_end(args);
142 
143  return 0;
144 }
145 
147 
153  timeofday_t tod;
154  get_tod(&tod);
155  last_hr = tod.hour;
157 
158  settings->add_hook(".bells", load_bells);
159 
160  /* Disable the plugin in case it's still there */
161  settings->disabled_plugins.push_back(strdup("cfcitybell"));
162 }
163 
166  for (auto reg : regions) {
167  delete reg.second;
168  }
169  all_regions.clear();
170 }
171 
ring_bell
static void ring_bell(void)
Definition: cfcitybell.cpp:90
global.h
first_player
player * first_player
Definition: init.cpp:106
settings
struct Settings settings
Definition: init.cpp:139
Region::fallback
std::string fallback
Definition: cfcitybell.cpp:39
bufferreader_current_line
size_t bufferreader_current_line(BufferReader *br)
Definition: bufferreader.cpp:140
llevError
@ llevError
Definition: logger.h:11
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
player::ob
object * ob
Definition: player.h:177
timeofday_t
Definition: tod.h:38
Region
Definition: cfcitybell.cpp:37
get_tod
void get_tod(timeofday_t *tod)
Definition: time.cpp:219
region::name
char * name
Definition: map.h:273
Region::bells
std::unordered_map< std::string, std::string > bells
Definition: cfcitybell.cpp:38
last_hr
static int last_hr
Definition: cfcitybell.cpp:34
npc_dialog.filename
filename
Definition: npc_dialog.py:99
MSG_TYPE_MISC
#define MSG_TYPE_MISC
Definition: newclient.h:402
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:235
events_register_global_handler
event_registration events_register_global_handler(int eventcode, f_plug_event hook)
Definition: events.cpp:21
Settings::add_hook
void add_hook(const char *name, collectorHook hook)
Definition: global.h:340
is_valid_types_gen.line
line
Definition: is_valid_types_gen.py:34
determine_god
const char * determine_god(object *op)
Definition: gods.cpp:55
EVENT_CLOCK
#define EVENT_CLOCK
Definition: events.h:40
make_face_from_files.args
args
Definition: make_face_from_files.py:37
events_unregister_global_handler
void events_unregister_global_handler(int eventcode, event_registration id)
Definition: events.cpp:28
split_string
size_t split_string(char *str, char *array[], size_t array_size, char sep)
Definition: utils.cpp:473
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
Settings::disabled_plugins
std::vector< char * > disabled_plugins
Definition: global.h:326
disinfect.count
int count
Definition: disinfect.py:7
sproto.h
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:409
cfcitybell_init
void cfcitybell_init(Settings *settings)
Definition: cfcitybell.cpp:152
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
Settings
Definition: global.h:240
region
Definition: map.h:272
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:251
all_regions
std::vector< region * > all_regions
Definition: init.cpp:108
event_registration
unsigned long event_registration
Definition: events.h:69
timeofday_t::hour
int hour
Definition: tod.h:43
cfcitybell_close
void cfcitybell_close()
Definition: cfcitybell.cpp:164
regions
static std::unordered_map< std::string, Region * > regions
Definition: cfcitybell.cpp:43
global_handler
static event_registration global_handler
Definition: cfcitybell.cpp:146
get_region_by_map
region * get_region_by_map(mapstruct *m)
Definition: region.cpp:72
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.cpp:308
split
static std::vector< std::string > split(const std::string &field, const std::string &by)
Definition: mapper.cpp:2606
replace.current
current
Definition: replace.py:64
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
BufferReader
Definition: bufferreader.cpp:21
clock_listener
static int clock_listener(int *type,...)
Definition: cfcitybell.cpp:123
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:50
is_valid_types_gen.type
list type
Definition: is_valid_types_gen.py:25
bufferreader_next_line
char * bufferreader_next_line(BufferReader *br)
Definition: bufferreader.cpp:102