Crossfire Server, Trunk
events.cpp
Go to the documentation of this file.
1 #include <stdarg.h>
2 #include "global.h"
3 #include "events.h"
4 #include <map>
5 #include <string>
6 
7 #include "stats.h"
8 
10 int events_total = 0;
11 
17 static std::map<event_registration, f_plug_event> global_handlers[NR_EVENTS];
19 static std::map<std::string, f_plug_event> object_handlers;
20 
24  global_handlers[eventcode][eg] = hook;
25  return eg;
26 }
27 
29  global_handlers[eventcode].erase(id);
30 }
31 
32 void events_execute_global_event(int eventcode, ...) {
33  va_list args;
34  mapstruct *map;
35  object *op;
36  object *op2;
37  player *pl;
38  const char *buf;
39  int i, rt;
40 
41  va_start(args, eventcode);
42 
43  switch (eventcode) {
44  case EVENT_BORN:
45  /*BORN: op*/
46  op = va_arg(args, object *);
47  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
48  (*(*gh).second)(&rt, eventcode, op);
49  }
50  break;
51 
52  case EVENT_CLOCK:
53  /*CLOCK: -*/
54  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
55  (*(*gh).second)(&rt, eventcode);
56  }
57  break;
58 
59  case EVENT_CRASH:
60  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
61  (*(*gh).second)(&rt, eventcode);
62  }
63  break;
64 
65  case EVENT_PLAYER_DEATH:
66  /*PLAYER_DEATH: op*/
67  op = va_arg(args, object *);
68  op2 = va_arg(args, object *);
69  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
70  (*(*gh).second)(&rt, eventcode, op, op2);
71  }
72  break;
73 
74  case EVENT_GKILL:
75  /*GKILL: op, hitter*/
76  op = va_arg(args, object *);
77  op2 = va_arg(args, object *);
78  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
79  (*(*gh).second)(&rt, eventcode, op, op2);
80  }
81  break;
82 
83  case EVENT_LOGIN:
84  /*LOGIN: pl, pl->socket.host*/
85  pl = va_arg(args, player *);
86  buf = va_arg(args, char *);
87  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
88  (*(*gh).second)(&rt, eventcode, pl, buf);
89  }
90  break;
91 
92  case EVENT_LOGOUT:
93  /*LOGOUT: pl, pl->socket.host*/
94  pl = va_arg(args, player *);
95  buf = va_arg(args, char *);
96  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
97  (*(*gh).second)(&rt, eventcode, pl, buf);
98  }
99  break;
100 
101  case EVENT_MAPENTER:
102  /*MAPENTER: op, map*/
103  op = va_arg(args, object *);
104  map = va_arg(args, mapstruct *);
105  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
106  (*(*gh).second)(&rt, eventcode, op, map);
107  }
108  break;
109 
110  case EVENT_MAPLEAVE:
111  /*MAPLEAVE: op, map*/
112  op = va_arg(args, object *);
113  map = va_arg(args, mapstruct *);
114  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
115  (*(*gh).second)(&rt, eventcode, op, map);
116  }
117  break;
118 
119  case EVENT_MAPRESET:
120  /*MAPRESET: map*/
121  map = va_arg(args, mapstruct *);
122  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
123  (*(*gh).second)(&rt, eventcode, map);
124  }
125  break;
126 
127  case EVENT_REMOVE:
128  /*REMOVE: op*/
129  op = va_arg(args, object *);
130  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
131  (*(*gh).second)(&rt, eventcode, op);
132  }
133  break;
134 
135  case EVENT_SHOUT:
136  /*SHOUT: op, parms, priority*/
137  op = va_arg(args, object *);
138  buf = va_arg(args, char *);
139  i = va_arg(args, int);
140  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
141  (*(*gh).second)(&rt, eventcode, op, buf, i);
142  }
143  break;
144 
145  case EVENT_TELL:
146  /* Tell: who, what, to who */
147  op = va_arg(args, object *);
148  buf = va_arg(args, const char *);
149  op2 = va_arg(args, object *);
150  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
151  (*(*gh).second)(&rt, eventcode, op, buf, op2);
152  }
153  break;
154 
155  case EVENT_MUZZLE:
156  /*MUZZLE: op, parms*/
157  op = va_arg(args, object *);
158  buf = va_arg(args, char *);
159  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
160  (*(*gh).second)(&rt, eventcode, op, buf);
161  }
162  break;
163 
164  case EVENT_KICK:
165  /*KICK: op, parms*/
166  op = va_arg(args, object *);
167  buf = va_arg(args, char *);
168  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
169  (*(*gh).second)(&rt, eventcode, op, buf);
170  }
171  break;
172 
173  case EVENT_MAPUNLOAD:
174  /*MAPUNLOAD: map*/
175  map = va_arg(args, mapstruct *);
176  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
177  (*(*gh).second)(&rt, eventcode, map);
178  }
179  break;
180 
181  case EVENT_MAPLOAD:
182  /*MAPLOAD: map*/
183  map = va_arg(args, mapstruct *);
184  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
185  (*(*gh).second)(&rt, eventcode, map);
186  }
187  break;
188 
189  case EVENT_MAPREADY:
190  /*MAPREADY: map*/
191  map = va_arg(args, mapstruct *);
192  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
193  (*(*gh).second)(&rt, eventcode, map);
194  }
195  break;
196 
197  case EVENT_GBOUGHT:
198  // fall through: these have the same arguments
199  case EVENT_GSOLD:
200  /*GBOUGHT/GSOLD: item activator*/
201  op = va_arg(args, object *);
202  op2 = va_arg(args, object *);
203  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
204  (*(*gh).second)(&rt, eventcode, op, op2);
205  }
206  break;
207  }
208  va_end(args);
210 }
211 
212 static void ensure_bitmask(object *op) {
213  if ((op->event_bitmask & BITMASK_VALID) == BITMASK_VALID) {
214  return;
215  }
216 
217  object *inv = op->inv;
218  while (inv) {
219  if (inv->type == EVENT_CONNECTOR) {
220  op->event_bitmask |= BITMASK_EVENT(inv->subtype);
221  }
222  inv = inv->below;
223  }
224  op->event_bitmask |= BITMASK_VALID;
225 }
226 
227 static int do_execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix, talk_info *talk) {
228  int rv = 0;
229  bool debug_events = (getenv("CF_DEBUG_EVENTS") != NULL);
230 
232  if ((op->event_bitmask & BITMASK_EVENT(eventcode)) == 0) {
233  return 0;
234  }
235 
237  if (tmp->type == EVENT_CONNECTOR && tmp->subtype == eventcode) {
238  if (debug_events) {
239  LOG(llevDebug, "********** EVENT HANDLER **********\n");
240  LOG(llevDebug, " - Who am I :%s\n", op->name);
241  if (activator != NULL)
242  LOG(llevDebug, " - Activator :%s\n", activator->name);
243  if (third != NULL)
244  LOG(llevDebug, " - Other object :%s\n", third->name);
245  LOG(llevDebug, " - Event code :%d\n", tmp->subtype);
246  if (tmp->title != NULL)
247  LOG(llevDebug, " - Event plugin :%s\n", tmp->title);
248  if (tmp->slaying != NULL)
249  LOG(llevDebug, " - Event hook :%s\n", tmp->slaying);
250  if (tmp->name != NULL)
251  LOG(llevDebug, " - Event options :%s\n", tmp->name);
252  }
253 
254  if (tmp->title == NULL) {
255  object *env = object_get_env_recursive(tmp);
256  LOG(llevError, "Event object without title at %d/%d in map %s\n", env->x, env->y, env->map ? env->map->name : "(null map)");
259  } else if (tmp->slaying == NULL) {
260  object *env = object_get_env_recursive(tmp);
261  LOG(llevError, "Event object without slaying at %d/%d in map %s\n", env->x, env->y, env->map ? env->map->name : "(null map)");
264  } else {
265  auto handler = object_handlers.find(tmp->title);
266  if (handler == object_handlers.end()) {
267  object *env = object_get_env_recursive(tmp);
268  LOG(llevError, "The requested handler doesn't exist: %s at %d/%d in map %s\n", tmp->title, env->x, env->y, env->map ? env->map->name : "(null map)");
271  } else {
272  int rvt = 0;
273  int rv;
274 
275  tag_t oldtag = op->count;
276  rv = (*(*handler).second)(&rvt, op, activator, third, message, fix, tmp, talk);
277  if (object_was_destroyed(op, oldtag)) {
278  return rv;
279  }
280  if (QUERY_FLAG(tmp, FLAG_UNIQUE)) {
281  if (debug_events) {
282  LOG(llevDebug, "Removing unique event %s\n", tmp->slaying);
283  }
286  }
287  if (rv) {
288  // If non-zero return value, script wants us to stop
289  // applying other methods and return.
290  return rv;
291  }
292  }
293  }
294  }
295  } FOR_INV_FINISH();
296  events_total++;
297  return rv;
298 }
299 
300 void events_register_object_handler(const char *id, f_plug_event handler) {
301  object_handlers[id] = handler;
302  LOG(llevDebug, "events: registered object handler %s\n", id);
303 }
304 
305 void events_unregister_object_handler(const char *id) {
306  object_handlers.erase(id);
307  LOG(llevDebug, "events: unregistered object handler %s\n", id);
308 }
309 
310 int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix) {
311  return do_execute_event(op, eventcode, activator, third, message, fix, NULL);
312 }
313 
315  return do_execute_event(npc, EVENT_SAY, talk->who, NULL, talk->text, SCRIPT_FIX_ALL, talk);
316 }
317 
318 int events_execute_object_user(object *op, object *activator, object *third, const char *message, int fix) {
320 }
object_was_destroyed
#define object_was_destroyed(op, old_tag)
Definition: object.h:70
EVENT_GSOLD
#define EVENT_GSOLD
Definition: events.h:58
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:545
object_get_env_recursive
object * object_get_env_recursive(object *op)
Definition: object.cpp:590
llevError
@ llevError
Definition: logger.h:11
EVENT_CONNECTOR
@ EVENT_CONNECTOR
Definition: object.h:232
NR_EVENTS
#define NR_EVENTS
Definition: events.h:61
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
player
Definition: player.h:105
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
EVENT_GBOUGHT
#define EVENT_GBOUGHT
Definition: events.h:57
BITMASK_EVENT
#define BITMASK_EVENT(evt)
Definition: events.h:64
events_unregister_object_handler
void events_unregister_object_handler(const char *id)
Definition: events.cpp:305
FLAG_UNIQUE
#define FLAG_UNIQUE
Definition: define.h:287
commongive.inv
inv
Definition: commongive.py:29
EVENT_MAPLOAD
#define EVENT_MAPLOAD
Definition: events.h:48
Ice.tmp
int tmp
Definition: Ice.py:207
EVENT_LOGOUT
#define EVENT_LOGOUT
Definition: events.h:45
EVENT_SAY
#define EVENT_SAY
Definition: events.h:29
events_execute_object_event
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:310
buf
StringBuffer * buf
Definition: readable.cpp:1565
events_register_global_handler
event_registration events_register_global_handler(int eventcode, f_plug_event hook)
Definition: events.cpp:21
events_register_object_handler
void events_register_object_handler(const char *id, f_plug_event handler)
Definition: events.cpp:300
EVENT_LOGIN
#define EVENT_LOGIN
Definition: events.h:44
events_total
int events_total
Definition: events.cpp:10
disinfect.map
map
Definition: disinfect.py:4
events.h
EVENT_CLOCK
#define EVENT_CLOCK
Definition: events.h:40
diamondslots.activator
activator
Definition: diamondslots.py:10
make_face_from_files.args
args
Definition: make_face_from_files.py:37
EVENT_CRASH
#define EVENT_CRASH
Definition: events.h:41
stats.h
next_event_registration
static event_registration next_event_registration
Definition: events.cpp:18
events_unregister_global_handler
void events_unregister_global_handler(int eventcode, event_registration id)
Definition: events.cpp:28
EVENT_MAPENTER
#define EVENT_MAPENTER
Definition: events.h:46
EVENT_MAPRESET
#define EVENT_MAPRESET
Definition: events.h:50
SCRIPT_FIX_ALL
#define SCRIPT_FIX_ALL
Definition: global.h:389
EVENT_BORN
#define EVENT_BORN
Definition: events.h:39
events_execute_object_user
int events_execute_object_user(object *op, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:318
EVENT_MAPUNLOAD
#define EVENT_MAPUNLOAD
Definition: events.h:51
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1592
FOR_INV_FINISH
#define FOR_INV_FINISH()
Definition: define.h:677
ensure_bitmask
static void ensure_bitmask(object *op)
Definition: events.cpp:212
tag_t
uint32_t tag_t
Definition: object.h:14
EVENT_USER
#define EVENT_USER
Definition: events.h:36
EVENT_SHOUT
#define EVENT_SHOUT
Definition: events.h:55
global_events_total
int global_events_total
Definition: events.cpp:9
env
static std::shared_ptr< inja::Environment > env
Definition: mapper.cpp:2171
eg
static event_registration eg
Definition: random_house_generator.cpp:205
talk_info::text
const char * text
Definition: dialog.h:52
EVENT_PLAYER_DEATH
#define EVENT_PLAYER_DEATH
Definition: events.h:53
diamondslots.message
string message
Definition: diamondslots.py:57
BITMASK_VALID
#define BITMASK_VALID
Definition: events.h:66
EVENT_MUZZLE
#define EVENT_MUZZLE
Definition: events.h:52
EVENT_TELL
#define EVENT_TELL
Definition: events.h:56
object::name
sstring name
Definition: object.h:319
event_registration
unsigned long event_registration
Definition: events.h:71
global_handlers
static std::map< event_registration, f_plug_event > global_handlers[NR_EVENTS]
Definition: events.cpp:17
mapstruct
Definition: map.h:313
f_plug_event
int(* f_plug_event)(int *type,...)
Definition: events.h:69
give.op
op
Definition: give.py:33
EVENT_MAPLEAVE
#define EVENT_MAPLEAVE
Definition: events.h:47
talk_info
Definition: dialog.h:50
EVENT_REMOVE
#define EVENT_REMOVE
Definition: events.h:54
npc_dialog.npc
npc
Definition: npc_dialog.py:98
object_remove
void object_remove(object *op)
Definition: object.cpp:1833
EVENT_MAPREADY
#define EVENT_MAPREADY
Definition: events.h:49
do_execute_event
static int do_execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix, talk_info *talk)
Definition: events.cpp:227
events_execute_object_say
int events_execute_object_say(object *npc, talk_info *talk)
Definition: events.cpp:314
EVENT_GKILL
#define EVENT_GKILL
Definition: events.h:42
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
FOR_INV_PREPARE
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:670
EVENT_KICK
#define EVENT_KICK
Definition: events.h:43
events_execute_global_event
void events_execute_global_event(int eventcode,...)
Definition: events.cpp:32
llevDebug
@ llevDebug
Definition: logger.h:13
talk_info::who
struct object * who
Definition: dialog.h:51
object_handlers
static std::map< std::string, f_plug_event > object_handlers
Definition: events.cpp:19
diamondslots.id
id
Definition: diamondslots.py:53