Crossfire Server, Trunk  R22047
events.cpp
Go to the documentation of this file.
1 extern "C" {
2 #include <stdarg.h>
3 #include "global.h"
4 }
5 #include "events.h"
6 #include <map>
7 #include <string>
8 
9 // If set then dump information about found event connectors
10 //#define EVENTS_DEBUG
11 
12 static std::map<event_registration, f_plug_event> global_handlers[NR_EVENTS];
14 static std::map<std::string, f_plug_event> object_handlers;
15 
17  auto eg = next_event_registration;
19  global_handlers[eventcode][eg] = hook;
20  return eg;
21 }
22 
24  global_handlers[eventcode].erase(id);
25 }
26 
27 void events_execute_global_event(int eventcode, ...) {
28  va_list args;
29  mapstruct *map;
30  object *op;
31  object *op2;
32  player *pl;
33  const char *buf;
34  int i, rt;
35 
36  va_start(args, eventcode);
37 
38  switch (eventcode) {
39  case EVENT_BORN:
40  /*BORN: op*/
41  op = va_arg(args, object *);
42  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
43  (*(*gh).second)(&rt, eventcode, op);
44  }
45  break;
46 
47  case EVENT_CLOCK:
48  /*CLOCK: -*/
49  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
50  (*(*gh).second)(&rt, eventcode);
51  }
52  break;
53 
54  case EVENT_CRASH:
55  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
56  (*(*gh).second)(&rt, eventcode);
57  }
58  break;
59 
60  case EVENT_PLAYER_DEATH:
61  /*PLAYER_DEATH: op*/
62  op = va_arg(args, object *);
63  op2 = va_arg(args, object *);
64  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
65  (*(*gh).second)(&rt, eventcode, op, op2);
66  }
67  break;
68 
69  case EVENT_GKILL:
70  /*GKILL: op, hitter*/
71  op = va_arg(args, object *);
72  op2 = va_arg(args, object *);
73  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
74  (*(*gh).second)(&rt, eventcode, op, op2);
75  }
76  break;
77 
78  case EVENT_LOGIN:
79  /*LOGIN: pl, pl->socket.host*/
80  pl = va_arg(args, player *);
81  buf = va_arg(args, char *);
82  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
83  (*(*gh).second)(&rt, eventcode, pl, buf);
84  }
85  break;
86 
87  case EVENT_LOGOUT:
88  /*LOGOUT: pl, pl->socket.host*/
89  pl = va_arg(args, player *);
90  buf = va_arg(args, char *);
91  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
92  (*(*gh).second)(&rt, eventcode, pl, buf);
93  }
94  break;
95 
96  case EVENT_MAPENTER:
97  /*MAPENTER: op, map*/
98  op = va_arg(args, object *);
99  map = va_arg(args, mapstruct *);
100  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
101  (*(*gh).second)(&rt, eventcode, op, map);
102  }
103  break;
104 
105  case EVENT_MAPLEAVE:
106  /*MAPLEAVE: op, map*/
107  op = va_arg(args, object *);
108  map = va_arg(args, mapstruct *);
109  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
110  (*(*gh).second)(&rt, eventcode, op, map);
111  }
112  break;
113 
114  case EVENT_MAPRESET:
115  /*MAPRESET: map*/
116  map = va_arg(args, mapstruct *);
117  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
118  (*(*gh).second)(&rt, eventcode, map);
119  }
120  break;
121 
122  case EVENT_REMOVE:
123  /*REMOVE: op*/
124  op = va_arg(args, object *);
125  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
126  (*(*gh).second)(&rt, eventcode, op);
127  }
128  break;
129 
130  case EVENT_SHOUT:
131  /*SHOUT: op, parms, priority*/
132  op = va_arg(args, object *);
133  buf = va_arg(args, char *);
134  i = va_arg(args, int);
135  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
136  (*(*gh).second)(&rt, eventcode, op, buf, i);
137  }
138  break;
139 
140  case EVENT_TELL:
141  /* Tell: who, what, to who */
142  op = va_arg(args, object *);
143  buf = va_arg(args, const char *);
144  op2 = va_arg(args, object *);
145  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
146  (*(*gh).second)(&rt, eventcode, op, buf, op2);
147  }
148  break;
149 
150  case EVENT_MUZZLE:
151  /*MUZZLE: op, parms*/
152  op = va_arg(args, object *);
153  buf = va_arg(args, char *);
154  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
155  (*(*gh).second)(&rt, eventcode, op, buf);
156  }
157  break;
158 
159  case EVENT_KICK:
160  /*KICK: op, parms*/
161  op = va_arg(args, object *);
162  buf = va_arg(args, char *);
163  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
164  (*(*gh).second)(&rt, eventcode, op, buf);
165  }
166  break;
167 
168  case EVENT_MAPUNLOAD:
169  /*MAPUNLOAD: map*/
170  map = va_arg(args, mapstruct *);
171  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
172  (*(*gh).second)(&rt, eventcode, map);
173  }
174  break;
175 
176  case EVENT_MAPLOAD:
177  /*MAPLOAD: map*/
178  map = va_arg(args, mapstruct *);
179  for (auto gh = global_handlers[eventcode].begin(); gh != global_handlers[eventcode].end(); gh++) {
180  (*(*gh).second)(&rt, eventcode, map);
181  }
182  break;
183  }
184  va_end(args);
185 }
186 
187 static int do_execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix, talk_info *talk) {
188  int rv = 0;
189 
190  FOR_INV_PREPARE(op, tmp) {
191  if (tmp->type == EVENT_CONNECTOR && tmp->subtype == eventcode) {
192 #ifdef EVENTS_DEBUG
193  LOG(llevDebug, "********** EVENT HANDLER **********\n");
194  LOG(llevDebug, " - Who am I :%s\n", op->name);
195  if (activator != NULL)
196  LOG(llevDebug, " - Activator :%s\n", activator->name);
197  if (third != NULL)
198  LOG(llevDebug, " - Other object :%s\n", third->name);
199  LOG(llevDebug, " - Event code :%d\n", tmp->subtype);
200  if (tmp->title != NULL)
201  LOG(llevDebug, " - Event plugin :%s\n", tmp->title);
202  if (tmp->slaying != NULL)
203  LOG(llevDebug, " - Event hook :%s\n", tmp->slaying);
204  if (tmp->name != NULL)
205  LOG(llevDebug, " - Event options :%s\n", tmp->name);
206 #endif
207 
208  if (tmp->title == NULL) {
209  object *env = object_get_env_recursive(tmp);
210  LOG(llevError, "Event object without title at %d/%d in map %s\n", env->x, env->y, env->map->name);
211  object_remove(tmp);
212  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
213  } else if (tmp->slaying == NULL) {
214  object *env = object_get_env_recursive(tmp);
215  LOG(llevError, "Event object without slaying at %d/%d in map %s\n", env->x, env->y, env->map->name);
216  object_remove(tmp);
217  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
218  } else {
219  auto handler = object_handlers.find(tmp->title);
220  if (handler == object_handlers.end()) {
221  object *env = object_get_env_recursive(tmp);
222  LOG(llevError, "The requested handler doesn't exist: %s at %d/%d in map %s\n", tmp->title, env->x, env->y, env->map->name);
223  object_remove(tmp);
224  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
225  } else {
226  int rvt = 0;
227  int rv;
228 
229  tag_t oldtag = op->count;
230  rv = (*(*handler).second)(&rvt, op, activator, third, message, fix, tmp, talk);
231  if (object_was_destroyed(op, oldtag)) {
232  return rv;
233  }
234  if (QUERY_FLAG(tmp, FLAG_UNIQUE)) {
235 #ifdef EVENTS_DEBUG
236  LOG(llevDebug, "Removing unique event %s\n", tmp->slaying);
237 #endif
238  object_remove(tmp);
239  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
240  }
241  return rv;
242  }
243  }
244  }
245  } FOR_INV_FINISH();
246  return rv;
247 }
248 
249 void events_register_object_handler(const char *id, f_plug_event handler) {
250  object_handlers[id] = handler;
251  LOG(llevDebug, "events: registered object handler %s\n", id);
252 }
253 
254 void events_unregister_object_handler(const char *id) {
255  object_handlers.erase(id);
256  LOG(llevDebug, "events: unregistered object handler %s\n", id);
257 }
258 
259 int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix) {
260  return do_execute_event(op, eventcode, activator, third, message, fix, NULL);
261 }
262 
263 int events_execute_object_say(object *npc, talk_info *talk) {
264  return do_execute_event(npc, EVENT_SAY, talk->who, NULL, talk->text, SCRIPT_FIX_ALL, talk);
265 }
266 
267 int events_execute_object_user(object *op, object *activator, object *third, const char *message, int fix) {
268  return events_execute_object_event(op, EVENT_USER, activator, third, message, fix);
269 }
#define EVENT_KICK
Definition: events.h:42
#define EVENT_GKILL
Definition: events.h:41
Definition: player.h:92
void events_register_object_handler(const char *id, f_plug_event handler)
Definition: events.cpp:249
void object_free(object *ob, int flags)
Definition: object.c:1348
static int do_execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix, talk_info *talk)
Definition: events.cpp:187
StringBuffer * buf
Definition: readable.c:1591
static std::map< event_registration, f_plug_event > global_handlers[NR_EVENTS]
Definition: events.cpp:12
object * object_get_env_recursive(object *op)
Definition: object.c:360
#define EVENT_CRASH
Definition: events.h:40
struct obj * who
Definition: dialog.h:52
#define NR_EVENTS
Definition: events.h:57
#define EVENT_LOGIN
Definition: events.h:43
#define EVENT_SAY
Definition: events.h:28
#define EVENT_BORN
Definition: events.h:38
#define SCRIPT_FIX_ALL
Definition: global.h:370
#define EVENT_MAPLEAVE
Definition: events.h:46
void events_execute_global_event(int eventcode,...)
Definition: events.cpp:27
unsigned long event_registration
Definition: events.h:62
#define EVENT_CLOCK
Definition: events.h:39
const char * text
Definition: dialog.h:53
#define EVENT_SHOUT
Definition: events.h:53
#define FOR_INV_FINISH()
Definition: define.h:714
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define EVENT_MUZZLE
Definition: events.h:50
#define EVENT_MAPENTER
Definition: events.h:45
#define EVENT_MAPUNLOAD
Definition: events.h:49
#define EVENT_USER
Definition: events.h:35
int(* f_plug_event)(int *type,...)
Definition: events.h:60
static std::map< std::string, f_plug_event > object_handlers
Definition: events.cpp:14
#define EVENT_MAPLOAD
Definition: events.h:47
#define EVENT_MAPRESET
Definition: events.h:48
void events_unregister_global_handler(int eventcode, event_registration id)
Definition: events.cpp:23
#define EVENT_LOGOUT
Definition: events.h:44
int events_execute_object_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:259
void events_unregister_object_handler(const char *id)
Definition: events.cpp:254
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
event_registration events_register_global_handler(int eventcode, f_plug_event hook)
Definition: events.cpp:16
#define EVENT_TELL
Definition: events.h:54
int events_execute_object_user(object *op, object *activator, object *third, const char *message, int fix)
Definition: events.cpp:267
Definition: map.h:326
#define FLAG_UNIQUE
Definition: define.h:288
#define EVENT_REMOVE
Definition: events.h:52
static event_registration next_event_registration
Definition: events.cpp:13
#define FOR_INV_PREPARE(op_, it_)
Definition: define.h:707
void object_remove(object *op)
Definition: object.c:1588
#define EVENT_PLAYER_DEATH
Definition: events.h:51
int events_execute_object_say(object *npc, talk_info *talk)
Definition: events.cpp:263