Crossfire Server, Trunk  R20513
cflogger.c
Go to the documentation of this file.
1 /*****************************************************************************/
2 /* Logger plugin version 1.0 alpha. */
3 /* Contact: */
4 /*****************************************************************************/
5 /* That code is placed under the GNU General Public Licence (GPL) */
6 /* (C)2007 by Weeger Nicolas (Feel free to deliver your complaints) */
7 /*****************************************************************************/
8 /* CrossFire, A Multiplayer game for X-windows */
9 /* */
10 /* Copyright (C) 2000 Mark Wedel */
11 /* Copyright (C) 1992 Frank Tore Johansen */
12 /* */
13 /* This program is free software; you can redistribute it and/or modify */
14 /* it under the terms of the GNU General Public License as published by */
15 /* the Free Software Foundation; either version 2 of the License, or */
16 /* (at your option) any later version. */
17 /* */
18 /* This program is distributed in the hope that it will be useful, */
19 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
20 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
21 /* GNU General Public License for more details. */
22 /* */
23 /* You should have received a copy of the GNU General Public License */
24 /* along with this program; if not, write to the Free Software */
25 /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
26 /* */
27 /*****************************************************************************/
28 
48 #include <cflogger.h>
49 #include <cflogger_proto.h>
50 #include <sqlite3.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <svnversion.h>
54 
55 CF_PLUGIN char SvnRevPlugin[] = SVN_REV;
56 
58 #define CFLOGGER_CURRENT_FORMAT 3
59 
61 static sqlite3 *database;
62 
64 static int last_stored_day = -1;
65 
81 static int check_tables_callback(void *param, int argc, char **argv, char **azColName) {
82  int *format = (int *)param;
83 
84  *format = atoi(argv[0]);
85  return 0;
86 }
87 
103 static int do_sql(const char *sql) {
104  int err;
105  char *msg;
106 
107  if (!database)
108  return -1;
109 
110  err = sqlite3_exec(database, sql, NULL, NULL, &msg);
111  if (err != SQLITE_OK) {
112  cf_log(llevError, " [%s] error: %d [%s] for sql = %s\n", PLUGIN_NAME, err, msg, sql);
113  sqlite3_free(msg);
114  }
115  return err;
116 }
117 
144 static int update_table_format(const char *table, const char *newschema,
145  const char *select_columns) {
146  char *sql;
147  int err;
148 
149  sql = sqlite3_mprintf("ALTER TABLE %s RENAME TO %s_old;", table, table);
150  err = do_sql(sql);
151  sqlite3_free(sql);
152  if (err != SQLITE_OK)
153  return err;
154 
155  sql = sqlite3_mprintf("CREATE TABLE %s(%s);", table, newschema);
156  err = do_sql(sql);
157  sqlite3_free(sql);
158  if (err != SQLITE_OK)
159  return err;
160 
161  sql = sqlite3_mprintf("INSERT INTO %s SELECT %s FROM %s_old;",
162  table, select_columns, table);
163  err = do_sql(sql);
164  sqlite3_free(sql);
165  if (err != SQLITE_OK)
166  return err;
167 
168  sql = sqlite3_mprintf("DROP TABLE %s_old;", table, table);
169  err = do_sql(sql);
170  sqlite3_free(sql);
171  /* Final return. */
172  return err;
173 }
174 
181 #define DO_OR_ROLLBACK(sqlstring) \
182  if (do_sql(sqlstring) != SQLITE_OK) { \
183  do_sql("rollback transaction;"); \
184  cf_log(llevError, " [%s] Logger database format update failed! Couldn't upgrade from format %d to fromat %d!. Won't log.\n", PLUGIN_NAME, format, CFLOGGER_CURRENT_FORMAT);\
185  sqlite3_close(database); \
186  database = NULL; \
187  return; \
188  }
189 
190 #define UPDATE_OR_ROLLBACK(tbl, newschema, select_columns) \
191  if (update_table_format((tbl), (newschema), (select_columns)) != SQLITE_OK) { \
192  do_sql("rollback transaction;"); \
193  cf_log(llevError, " [%s] Logger database format update failed! Couldn't upgrade from format %d to fromat %d!. Won't log.\n", PLUGIN_NAME, format, CFLOGGER_CURRENT_FORMAT);\
194  sqlite3_close(database); \
195  database = NULL; \
196  return; \
197  }
198 
202 static void check_tables(void) {
203  int format;
204  /*int err;*/
205  format = 0;
206 
207  /*err =*/ sqlite3_exec(database, "select param_value from parameters where param_name = 'version';", check_tables_callback, &format, NULL);
208 
209  /* Safety check. */
210  if (format > CFLOGGER_CURRENT_FORMAT) {
211  cf_log(llevError, " [%s] Logger database format (%d) is newer than supported (%d) by this binary!. Won't log.\n", PLUGIN_NAME, format, CFLOGGER_CURRENT_FORMAT);
212  /* This will disable using the db since do_sql() checks if database is
213  * NULL.
214  */
215  sqlite3_close(database);
216  database = NULL;
217  }
218 
219  /* Check if we need to upgrade/create database. */
220  if (format < 1) {
221  cf_log(llevDebug, " [%s] Creating logger database schema (format 1).\n", PLUGIN_NAME);
222  if (do_sql("BEGIN EXCLUSIVE TRANSACTION;") != SQLITE_OK) {
223  cf_log(llevError, " [%s] Logger database format update failed! Couldn't acquire exclusive lock to database when upgrading from format %d to format %d!. Won't log.\n", PLUGIN_NAME, format, CFLOGGER_CURRENT_FORMAT);
224  sqlite3_close(database);
225  database = NULL;
226  return;
227  }
228  DO_OR_ROLLBACK("create table living(liv_id integer primary key autoincrement, liv_name text, liv_is_player integer, liv_level integer);");
229  DO_OR_ROLLBACK("create table region(reg_id integer primary key autoincrement, reg_name text);");
230  DO_OR_ROLLBACK("create table map(map_id integer primary key autoincrement, map_path text, map_reg_id integer);");
231  DO_OR_ROLLBACK("create table time(time_real integer, time_ingame text);");
232 
233  DO_OR_ROLLBACK("create table living_event(le_liv_id integer, le_time integer, le_code integer, le_map_id integer);");
234  DO_OR_ROLLBACK("create table map_event(me_map_id integer, me_time integer, me_code integer, me_living_id integer);");
235  DO_OR_ROLLBACK("create table kill_event(ke_time integer, ke_victim_id integer, ke_victim_level integer, ke_map_id integer , ke_killer_id integer, ke_killer_level integer);");
236 
237  DO_OR_ROLLBACK("create table parameters(param_name text, param_value text);");
238  DO_OR_ROLLBACK("insert into parameters values( 'version', '1' );");
239  do_sql("COMMIT TRANSACTION;");
240  }
241 
242  /* Must be able to handle update from format 1. If we are creating a new
243  * database, format 1 is still created first, then updated.
244  *
245  * This way is simpler than having to create two ways to make a format 2 db.
246  */
247  if (format < 2) {
248  cf_log(llevDebug, " [%s] Upgrading logger database schema (to format 2).\n", PLUGIN_NAME);
249  if (do_sql("BEGIN EXCLUSIVE TRANSACTION;") != SQLITE_OK) {
250  cf_log(llevError, " [%s] Logger database format update failed! Couldn't acquire exclusive lock to database when upgrading from format %d to format %d!. Won't log.\n", PLUGIN_NAME, format, CFLOGGER_CURRENT_FORMAT);
251  sqlite3_close(database);
252  database = NULL;
253  return;
254  }
255  /* Update schema for various tables. Why so complex? Because ALTER TABLE
256  * can't add the "primary key" bit or other constraints...
257  */
258  UPDATE_OR_ROLLBACK("living", "liv_id INTEGER PRIMARY KEY AUTOINCREMENT, liv_name TEXT NOT NULL, liv_is_player INTEGER NOT NULL, liv_level INTEGER NOT NULL", "*");
259  UPDATE_OR_ROLLBACK("region", "reg_id INTEGER PRIMARY KEY AUTOINCREMENT, reg_name TEXT UNIQUE NOT NULL", "*");
260  UPDATE_OR_ROLLBACK("map", "map_id INTEGER PRIMARY KEY AUTOINCREMENT, map_path TEXT NOT NULL, map_reg_id INTEGER NOT NULL, CONSTRAINT map_path_reg_id UNIQUE(map_path, map_reg_id)", "*");
261 #if 0
262  /* Turned out this was incorrect. And version 1 -> 3 directly works for this. */
263  UPDATE_OR_ROLLBACK("time", "time_real INTEGER PRIMARY KEY, time_ingame TEXT UNIQUE NOT NULL");
264 #endif
265  UPDATE_OR_ROLLBACK("living_event", "le_liv_id INTEGER NOT NULL, le_time INTEGER NOT NULL, le_code INTEGER NOT NULL, le_map_id INTEGER NOT NULL", "*");
266  UPDATE_OR_ROLLBACK("map_event", "me_map_id INTEGER NOT NULL, me_time INTEGER NOT NULL, me_code INTEGER NOT NULL, me_living_id INTEGER NOT NULL", "*");
267  UPDATE_OR_ROLLBACK("kill_event", "ke_time INTEGER NOT NULL, ke_victim_id INTEGER NOT NULL, ke_victim_level INTEGER NOT NULL, ke_map_id INTEGER NOT NULL, ke_killer_id INTEGER NOT NULL, ke_killer_level INTEGER NOT NULL", "*");
268 
269  /* Handle changed parameters table format: */
270  /* Due to backward compatiblity "primary key" in SQLite doesn't imply
271  * "not null" (http://www.sqlite.org/lang_createtable.html), unless it
272  * is "integer primary key".
273  *
274  * We don't need to save anything stored in this in format 1, it was
275  * only used for storing what format was used.
276  */
277  DO_OR_ROLLBACK("DROP TABLE parameters;");
278  DO_OR_ROLLBACK("CREATE TABLE parameters(param_name TEXT NOT NULL PRIMARY KEY, param_value TEXT);");
279  DO_OR_ROLLBACK("INSERT INTO parameters (param_name, param_value) VALUES( 'version', '2' );");
280 
281  /* Create various indexes. */
282  DO_OR_ROLLBACK("CREATE INDEX living_name_player_level ON living(liv_name,liv_is_player,liv_level);");
283 
284  /* Newspaper module could make use of some indexes too: */
285  DO_OR_ROLLBACK("CREATE INDEX kill_event_time ON kill_event(ke_time);");
286  DO_OR_ROLLBACK("CREATE INDEX map_reg_id ON map(map_reg_id);");
287 
288  /* Finally commit the transaction. */
289  do_sql("COMMIT TRANSACTION;");
290  }
291 
292  if (format < 3) {
293  cf_log(llevDebug, " [%s] Upgrading logger database schema (to format 3).\n", PLUGIN_NAME);
294  if (do_sql("BEGIN EXCLUSIVE TRANSACTION;") != SQLITE_OK) {
295  cf_log(llevError, " [%s] Logger database format update failed! Couldn't acquire exclusive lock to database when upgrading from format %d to format %d!. Won't log.\n", PLUGIN_NAME, format, CFLOGGER_CURRENT_FORMAT);
296  sqlite3_close(database);
297  database = NULL;
298  return;
299  }
300  UPDATE_OR_ROLLBACK("time", "time_ingame TEXT NOT NULL PRIMARY KEY, time_real INTEGER NOT NULL", "time_ingame, time_real");
301  DO_OR_ROLLBACK("UPDATE parameters SET param_value = '3' WHERE param_name = 'version';");
302  do_sql("COMMIT TRANSACTION;");
303  /* After all these changes better vacuum... The tables could have been
304  * huge, and since we recreated several of them above there could be a
305  * lot of wasted space.
306  */
307  do_sql("VACUUM;");
308  }
309 }
310 
326 static int get_living_id(object *living) {
327  char **line;
328  char *sql;
329  int nrow, ncolumn, id;
330 
331  if (living->type == PLAYER)
332  sql = sqlite3_mprintf("select liv_id from living where liv_name='%q' and liv_is_player = 1", living->name);
333  else
334  sql = sqlite3_mprintf("select liv_id from living where liv_name='%q' and liv_is_player = 0 and liv_level = %d", living->name, living->level);
335  sqlite3_get_table(database, sql, &line, &nrow, &ncolumn, NULL);
336 
337  if (nrow > 0)
338  id = atoi(line[ncolumn]);
339  else {
340  sqlite3_free(sql);
341  sql = sqlite3_mprintf("insert into living(liv_name, liv_is_player, liv_level) values('%q', %d, %d)", living->name, living->type == PLAYER ? 1 : 0, living->level);
342  do_sql(sql);
343  id = sqlite3_last_insert_rowid(database);
344  }
345  sqlite3_free(sql);
346  sqlite3_free_table(line);
347  return id;
348 }
349 
360 static int get_region_id(region *reg) {
361  char **line;
362  char *sql;
363  int nrow, ncolumn, id;
364 
365  if (!reg)
366  return 0;
367 
368  sql = sqlite3_mprintf("select reg_id from region where reg_name='%q'", reg->name);
369  sqlite3_get_table(database, sql, &line, &nrow, &ncolumn, NULL);
370 
371  if (nrow > 0)
372  id = atoi(line[ncolumn]);
373  else {
374  sqlite3_free(sql);
375  sql = sqlite3_mprintf("insert into region(reg_name) values( '%q' )", reg->name);
376  do_sql(sql);
377  id = sqlite3_last_insert_rowid(database);
378  }
379  sqlite3_free(sql);
380  sqlite3_free_table(line);
381  return id;
382 }
383 
396 static int get_map_id(mapstruct *map) {
397  char **line;
398  char *sql;
399  int nrow, ncolumn, id, reg_id;
400  const char *path = map->path;
401 
402  if (strncmp(path, "/random/", 7) == 0)
403  path = "/random/";
404 
405  reg_id = get_region_id(map->region);
406  sql = sqlite3_mprintf("select map_id from map where map_path='%q' and map_reg_id = %d", path, reg_id);
407  sqlite3_get_table(database, sql, &line, &nrow, &ncolumn, NULL);
408 
409  if (nrow > 0)
410  id = atoi(line[ncolumn]);
411  else {
412  sqlite3_free(sql);
413  sql = sqlite3_mprintf("insert into map(map_path, map_reg_id) values( '%q', %d)", path, reg_id);
414  do_sql(sql);
415  id = sqlite3_last_insert_rowid(database);
416  }
417  sqlite3_free(sql);
418  sqlite3_free_table(line);
419 
420  return id;
421 }
422 
429 static int store_time(void) {
430  char **line;
431  char *sql;
432  int nrow, ncolumn;
433  char date[50];
434  time_t now;
435  timeofday_t tod;
436 
437  cf_get_time(&tod);
438  now = time(NULL);
439 
440  if (tod.day == last_stored_day)
441  return 0;
442  last_stored_day = tod.day;
443 
444  snprintf(date, 50, "%10d-%2d-%2d %2d:%2d", tod.year, tod.month, tod.day, tod.hour, tod.minute);
445 
446  sql = sqlite3_mprintf("select * from time where time_ingame='%q'", date);
447  sqlite3_get_table(database, sql, &line, &nrow, &ncolumn, NULL);
448  sqlite3_free(sql);
449  sqlite3_free_table(line);
450  if (nrow > 0)
451  return 0;
452 
453  sql = sqlite3_mprintf("insert into time (time_ingame, time_real) values( '%s', %d )", date, now);
454  do_sql(sql);
455  sqlite3_free(sql);
456  return 1;
457 }
458 
467 static void add_player_event(object *pl, int event_code) {
468  int id = get_living_id(pl);
469  int map_id = 0;
470  char *sql;
471 
472  if (pl == NULL)
473  return;
474 
475  if (pl->map)
476  map_id = get_map_id(pl->map);
477 
478  sql = sqlite3_mprintf("insert into living_event values( %d, %d, %d, %d)", id, time(NULL), event_code, map_id);
479  do_sql(sql);
480  sqlite3_free(sql);
481 }
482 
493 static void add_map_event(mapstruct *map, int event_code, object *pl) {
494  int mapid;
495  int playerid = 0;
496  char *sql;
497 
498  if (pl && pl->type == PLAYER)
499  playerid = get_living_id(pl);
500 
501  mapid = get_map_id(map);
502  sql = sqlite3_mprintf("insert into map_event values( %d, %d, %d, %d)", mapid, time(NULL), event_code, playerid);
503  do_sql(sql);
504  sqlite3_free(sql);
505 }
506 
517 static void add_death(object *victim, object *killer) {
518  int vid, kid, map_id;
519  char *sql;
520 
521  if (!victim || !killer)
522  return;
523  if (victim->type != PLAYER && killer->type != PLAYER) {
524  /* Killer might be a bullet, which might be owned by the player. */
526  if (owner != NULL && owner->type == PLAYER)
527  killer = owner;
528  else
529  return;
530  }
531 
532  vid = get_living_id(victim);
533  kid = get_living_id(killer);
534  map_id = get_map_id(victim->map);
535  sql = sqlite3_mprintf("insert into kill_event values( %d, %d, %d, %d, %d, %d)", time(NULL), vid, victim->level, map_id, kid, killer->level);
536  do_sql(sql);
537  sqlite3_free(sql);
538 }
539 
550 CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr) {
551  cf_init_plugin(gethooksptr);
552  cf_log(llevInfo, "%s init\n", PLUGIN_VERSION);
553  return 0;
554 }
555 
566 CF_PLUGIN void *getPluginProperty(int *type, ...) {
567  va_list args;
568  const char *propname;
569  char *buf;
570  int size;
571 
572  va_start(args, type);
573  propname = va_arg(args, const char *);
574 
575  if (!strcmp(propname, "Identification")) {
576  buf = va_arg(args, char *);
577  size = va_arg(args, int);
578  va_end(args);
579  snprintf(buf, size, PLUGIN_NAME);
580  return NULL;
581  } else if (!strcmp(propname, "FullName")) {
582  buf = va_arg(args, char *);
583  size = va_arg(args, int);
584  va_end(args);
585  snprintf(buf, size, PLUGIN_VERSION);
586  return NULL;
587  }
588  va_end(args);
589  return NULL;
590 }
591 
602 CF_PLUGIN int cflogger_runPluginCommand(object *op, char *params) {
603  return -1;
604 }
605 
614 CF_PLUGIN int eventListener(int *type, ...) {
615  return 0;
616 }
617 
627  va_list args;
628  int rv = 0;
629  player *pl;
630  object *op/*, *op2*/;
631  int event_code;
632  mapstruct *map;
633 
634  va_start(args, type);
635  event_code = va_arg(args, int);
636 
637  switch (event_code) {
638  case EVENT_BORN:
639  case EVENT_REMOVE:
640  case EVENT_MUZZLE:
641  case EVENT_KICK:
642  op = va_arg(args, object *);
643  add_player_event(op, event_code);
644  break;
645 
646  case EVENT_PLAYER_DEATH:
647  op = va_arg(args, object *);
648  /*op2 =*/ va_arg(args, object *);
649  add_player_event(op, event_code);
650  break;
651 
652  case EVENT_LOGIN:
653  case EVENT_LOGOUT:
654  pl = va_arg(args, player *);
655  add_player_event(pl->ob, event_code);
656  break;
657 
658  case EVENT_MAPENTER:
659  case EVENT_MAPLEAVE:
660  op = va_arg(args, object *);
661  map = va_arg(args, mapstruct *);
662  add_map_event(map, event_code, op);
663  break;
664 
665  case EVENT_MAPLOAD:
666  case EVENT_MAPUNLOAD:
667  case EVENT_MAPRESET:
668  map = va_arg(args, mapstruct *);
669  add_map_event(map, event_code, NULL);
670  break;
671 
672  case EVENT_GKILL: {
673  object *killer;
674  op = va_arg(args, object *);
675  killer = va_arg(args, object *);
676  add_death(op, killer);
677  }
678  break;
679 
680  case EVENT_CLOCK:
681  store_time();
682  break;
683  }
684  va_end(args);
685 
686  return rv;
687 }
688 
698  char path[500];
699  const char *dir;
700 
701  cf_log(llevInfo, "%s post init\n", PLUGIN_VERSION);
702 
703  dir = cf_get_directory(4);
704  snprintf(path, sizeof(path), "%s/cflogger.db", dir);
705  cf_log(llevDebug, " [%s] database file: %s\n", PLUGIN_NAME, path);
706 
707  if (sqlite3_open(path, &database) != SQLITE_OK) {
708  cf_log(llevError, " [%s] database error!\n", PLUGIN_NAME);
709  sqlite3_close(database);
710  database = NULL;
711  return 0;
712  }
713 
714  check_tables();
715 
716  store_time();
717 
723 
725 
731 
734 
736 
737  return 0;
738 }
739 
749  cf_log(llevInfo, "%s closing.\n", PLUGIN_VERSION);
750  if (database) {
751  sqlite3_close(database);
752  database = NULL;
753  }
754  return 0;
755 }
Error, serious thing.
Definition: logger.h:11
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:365
One player.
Definition: player.h:92
static sqlite3 * database
Pointer to the logging database.
Definition: cflogger.c:61
#define EVENT_REMOVE
A Player character has been removed.
Definition: plugin.h:93
Information.
Definition: logger.h:12
void cf_get_time(timeofday_t *tod)
#define EVENT_KICK
A player was Kicked by a DM.
Definition: plugin.h:97
CF_PLUGIN int closePlugin(void)
Close the plugin.
Definition: cflogger.c:748
#define EVENT_LOGIN
Player login.
Definition: plugin.h:88
int minute
Definition: tod.h:38
#define EVENT_MAPLEAVE
A player left a map.
Definition: plugin.h:91
#define EVENT_LOGOUT
Player logout.
Definition: plugin.h:89
#define CFAPI_OBJECT_PROP_OWNER
Definition: plugin.h:242
Various statistics of objects.
Definition: living.h:34
CF_PLUGIN int eventListener(int *type,...)
Handles an object-related event.
Definition: cflogger.c:614
int year
Definition: tod.h:33
void cf_log(LogLevel logLevel, const char *format,...)
Wrapper for LOG().
#define UPDATE_OR_ROLLBACK(tbl, newschema, select_columns)
Definition: cflogger.c:190
static int do_sql(const char *sql)
Helper function to run a SQL query.
Definition: cflogger.c:103
static void add_death(object *victim, object *killer)
Logs a death.
Definition: cflogger.c:517
char * name
Shortend name of the region as maps refer to it.
Definition: map.h:278
#define EVENT_MAPENTER
A player entered a map.
Definition: plugin.h:90
int cf_init_plugin(f_plug_api getHooks)
static int update_table_format(const char *table, const char *newschema, const char *select_columns)
Updates a table to a new schema, used for when ALTER TABLE doesn&#39;t work.
Definition: cflogger.c:144
static int get_map_id(mapstruct *map)
Gets the unique identifier for a map.
Definition: cflogger.c:396
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
This is a game region.
Definition: map.h:276
#define snprintf
Definition: win32.h:46
static int last_stored_day
To keep track of stored ingame/real time matching.
Definition: cflogger.c:64
static void add_player_event(object *pl, int event_code)
Logs an event for a living object.
Definition: cflogger.c:467
int month
Definition: tod.h:34
#define DO_OR_ROLLBACK(sqlstring)
Helper macros for rolling back and returning if query failed.
Definition: cflogger.c:181
#define PLUGIN_NAME
Definition: cfanim.h:32
const char * name
The name of the object, obviously...
Definition: object.h:311
CF_PLUGIN int cflogger_runPluginCommand(object *op, char *params)
Runs a plugin command.
Definition: cflogger.c:602
void cf_system_register_global_event(int event, const char *name, f_plug_event hook)
int day
Definition: tod.h:35
#define EVENT_MAPLOAD
A map is loaded.
Definition: plugin.h:99
static void add_map_event(mapstruct *map, int event_code, object *pl)
Logs an event for a map.
Definition: cflogger.c:493
#define EVENT_MAPUNLOAD
A map is freed (includes swapping out)
Definition: plugin.h:98
#define EVENT_MAPRESET
A map is resetting.
Definition: plugin.h:92
static int get_living_id(object *living)
Returns a unique identifier for specified object.
Definition: cflogger.c:326
#define CFLOGGER_CURRENT_FORMAT
Current database format.
Definition: cflogger.c:58
#define EVENT_GKILL
Triggered when anything got killed by anyone.
Definition: plugin.h:87
static void check_tables(void)
Checks the database format, and applies changes if old version.
Definition: cflogger.c:202
object * ob
The object representing the player.
Definition: player.h:158
object * cf_object_get_object_property(object *op, int propcode)
#define EVENT_CLOCK
Global time event.
Definition: plugin.h:84
See Player.
Definition: object.h:107
CF_PLUGIN char SvnRevPlugin[]
Definition: cflogger.c:55
#define CF_PLUGIN
Definition: plugin_common.h:38
Only for debugging purposes.
Definition: logger.h:13
Represents the ingame time.
Definition: tod.h:32
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
int hour
Definition: tod.h:37
const char * cf_get_directory(int id)
Gets a directory Crossfire uses.
#define EVENT_PLAYER_DEATH
Global Death event.
Definition: plugin.h:86
CF_PLUGIN void * getPluginProperty(int *type,...)
Gets a plugin property.
Definition: cflogger.c:566
CF_PLUGIN int initPlugin(const char *iversion, f_plug_api gethooksptr)
Main plugin entry point.
Definition: cflogger.c:550
static int store_time(void)
Stores a line to match current ingame and real time.
Definition: cflogger.c:429
This is a game-map.
Definition: map.h:325
CF_PLUGIN int cflogger_globalEventListener(int *type,...)
Handles a global event.
Definition: cflogger.c:626
int16_t level
Level of creature or object.
Definition: object.h:351
static int get_region_id(region *reg)
Gets the unique identifier for a region.
Definition: cflogger.c:360
struct regiondef * region
What jurisdiction in the game world this map is ruled by points to the struct containing all the prop...
Definition: map.h:329
#define EVENT_BORN
A new character has been created.
Definition: plugin.h:83
static int check_tables_callback(void *param, int argc, char **argv, char **azColName)
Simple callback to get an integer from a query.
Definition: cflogger.c:81
CF_PLUGIN int postInitPlugin(void)
Plugin was initialized, now to finish.
Definition: cflogger.c:697
void(* f_plug_api)(int *type,...)
General API function.
Definition: plugin.h:125
#define EVENT_MUZZLE
A player was Muzzled (no_shout set).
Definition: plugin.h:96
#define PLUGIN_VERSION
Definition: cfanim.h:33