53 #include <svnversion.h> 58 #define CFLOGGER_CURRENT_FORMAT 3 82 int *format = (
int *)param;
84 *format = atoi(argv[0]);
110 err = sqlite3_exec(
database, sql, NULL, NULL, &msg);
111 if (err != SQLITE_OK) {
145 const char *select_columns) {
149 sql = sqlite3_mprintf(
"ALTER TABLE %s RENAME TO %s_old;", table, table);
152 if (err != SQLITE_OK)
155 sql = sqlite3_mprintf(
"CREATE TABLE %s(%s);", table, newschema);
158 if (err != SQLITE_OK)
161 sql = sqlite3_mprintf(
"INSERT INTO %s SELECT %s FROM %s_old;",
162 table, select_columns, table);
165 if (err != SQLITE_OK)
168 sql = sqlite3_mprintf(
"DROP TABLE %s_old;", table, table);
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); \ 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); \ 222 if (
do_sql(
"BEGIN EXCLUSIVE TRANSACTION;") != SQLITE_OK) {
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);");
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);");
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;");
249 if (
do_sql(
"BEGIN EXCLUSIVE TRANSACTION;") != SQLITE_OK) {
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)",
"*");
263 UPDATE_OR_ROLLBACK(
"time",
"time_real INTEGER PRIMARY KEY, time_ingame TEXT UNIQUE NOT NULL");
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",
"*");
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' );");
282 DO_OR_ROLLBACK(
"CREATE INDEX living_name_player_level ON living(liv_name,liv_is_player,liv_level);");
285 DO_OR_ROLLBACK(
"CREATE INDEX kill_event_time ON kill_event(ke_time);");
289 do_sql(
"COMMIT TRANSACTION;");
294 if (
do_sql(
"BEGIN EXCLUSIVE TRANSACTION;") != SQLITE_OK) {
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;");
329 int nrow, ncolumn, id;
332 sql = sqlite3_mprintf(
"select liv_id from living where liv_name='%q' and liv_is_player = 1", living->
name);
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);
338 id = atoi(line[ncolumn]);
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);
343 id = sqlite3_last_insert_rowid(
database);
346 sqlite3_free_table(line);
363 int nrow, ncolumn, id;
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);
372 id = atoi(line[ncolumn]);
375 sql = sqlite3_mprintf(
"insert into region(reg_name) values( '%q' )", reg->
name);
377 id = sqlite3_last_insert_rowid(
database);
380 sqlite3_free_table(line);
399 int nrow, ncolumn, id, reg_id;
400 const char *path = map->
path;
402 if (strncmp(path,
"/random/", 7) == 0)
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);
410 id = atoi(line[ncolumn]);
413 sql = sqlite3_mprintf(
"insert into map(map_path, map_reg_id) values( '%q', %d)", path, reg_id);
415 id = sqlite3_last_insert_rowid(
database);
418 sqlite3_free_table(line);
446 sql = sqlite3_mprintf(
"select * from time where time_ingame='%q'", date);
447 sqlite3_get_table(
database, sql, &line, &nrow, &ncolumn, NULL);
449 sqlite3_free_table(line);
453 sql = sqlite3_mprintf(
"insert into time (time_ingame, time_real) values( '%s', %d )", date, now);
478 sql = sqlite3_mprintf(
"insert into living_event values( %d, %d, %d, %d)",
id, time(NULL), event_code, map_id);
502 sql = sqlite3_mprintf(
"insert into map_event values( %d, %d, %d, %d)", mapid, time(NULL), event_code, playerid);
518 int vid, kid, map_id;
521 if (!victim || !killer)
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);
548 const char *propname;
552 va_start(args, type);
553 propname = va_arg(args,
const char *);
555 if (!strcmp(propname,
"Identification")) {
556 buf = va_arg(args,
char *);
557 size = va_arg(args,
int);
561 }
else if (!strcmp(propname,
"FullName")) {
562 buf = va_arg(args,
char *);
563 size = va_arg(args,
int);
606 va_start(args, type);
607 event_code = va_arg(args,
int);
609 switch (event_code) {
614 op = va_arg(args,
object *);
619 op = va_arg(args,
object *);
620 va_arg(args,
object *);
626 pl = va_arg(args,
player *);
632 op = va_arg(args,
object *);
646 op = va_arg(args,
object *);
647 killer = va_arg(args,
object *);
668 snprintf(path,
sizeof(path),
"%s/cflogger.db", dir);
671 if (sqlite3_open(path, &
database) != SQLITE_OK) {
#define DO_OR_ROLLBACK(sqlstring)
Helper macros for rolling back and returning if query failed.
static void add_map_event(mapstruct *map, int event_code, object *pl)
Logs an event for a map.
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't work.
#define EVENT_REMOVE
A Player character has been removed.
void cf_get_time(timeofday_t *tod)
#define EVENT_LOGOUT
Player logout.
#define EVENT_MAPUNLOAD
A map is freed (includes swapping out)
static int get_map_id(mapstruct *map)
Gets the unique identifier for a map.
#define CFAPI_OBJECT_PROP_OWNER
#define EVENT_LOGIN
Player login.
Represents the ingame time.
#define EVENT_KICK
A player was Kicked by a DM.
int initPlugin(const char *iversion, f_plug_api gethooksptr)
The server calls this function after loading the plugin.
int postInitPlugin(void)
The server calls this function to actually initialize the plugin here, after object handlers are regi...
static int check_tables_callback(void *param, int argc, char **argv, char **azColName)
Simple callback to get an integer from a query.
void cf_log(LogLevel logLevel, const char *format,...)
Wrapper for LOG().
int16_t level
Level of creature or object.
int eventListener(int *type,...)
Handles an object-related event.
static int get_region_id(region *reg)
Gets the unique identifier for a region.
int cf_init_plugin(f_plug_api getHooks)
int cflogger_globalEventListener(int *type,...)
Handles a global event.
int closePlugin(void)
Close the plugin.
char path[HUGE_BUF]
Filename of the map.
#define CFLOGGER_CURRENT_FORMAT
Current database format.
#define EVENT_MAPRESET
A map is resetting.
#define EVENT_BORN
A new character has been created.
#define EVENT_GKILL
Triggered when anything got killed by anyone.
#define EVENT_CLOCK
Global time event.
char * name
Shortend name of the region as maps refer to it.
static void add_player_event(object *pl, int event_code)
Logs an event for a living object.
void cf_system_register_global_event(int event, const char *name, f_plug_event hook)
object * ob
The object representing the player.
#define EVENT_MAPLEAVE
A player left a map.
static void add_death(object *victim, object *killer)
Logs a death.
#define EVENT_PLAYER_DEATH
Global Death event.
struct mapstruct * map
Pointer to the map in which this object is present.
static int last_stored_day
To keep track of stored ingame/real time matching.
Various statistics of objects.
object * cf_object_get_object_property(object *op, int propcode)
#define EVENT_MAPENTER
A player entered a map.
CF_PLUGIN char SvnRevPlugin[]
static int store_time(void)
Stores a line to match current ingame and real time.
static void check_tables(void)
Checks the database format, and applies changes if old version.
void * getPluginProperty(int *type,...)
The server calls this function to get information about the plugin, notably the name and version...
static sqlite3 * database
Pointer to the logging database.
int cflogger_runPluginCommand(object *op, char *params)
Runs a plugin command.
sstring name
The name of the object, obviously...
Only for debugging purposes.
#define UPDATE_OR_ROLLBACK(tbl, newschema, select_columns)
uint8_t type
PLAYER, BULLET, etc.
static int get_living_id(object *living)
Returns a unique identifier for specified object.
const char * cf_get_directory(int id)
Gets a directory Crossfire uses.
struct region * region
What jurisdiction in the game world this map is ruled by points to the struct containing all the prop...
#define EVENT_MAPLOAD
A map is loaded (pristine state)
static int do_sql(const char *sql)
Helper function to run a SQL query.
#define EVENT_MUZZLE
A player was Muzzled (no_shout set).
void(* f_plug_api)(int *type,...)
General API function.