374 lines
9.4 KiB
C
374 lines
9.4 KiB
C
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "gm-mcp-icecrew-playerdb.h"
|
|
#include "gm-mcp.h"
|
|
#include "gm-marshal.h"
|
|
#include "gm-debug.h"
|
|
#include "gm-support.h"
|
|
#include "gm-string.h"
|
|
|
|
#define GM_MCP_ICECREW_PLAYERDB_GET_PRIVATE(object)( \
|
|
G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
|
GM_TYPE_MCP_ICECREW_PLAYERDB, GmMcpIcecrewPlayerdbPrivate))
|
|
|
|
struct _GmMcpIcecrewPlayerdbPrivate {
|
|
gint self;
|
|
GList *db;
|
|
GList *last_init_keys;
|
|
};
|
|
|
|
/* Signals */
|
|
|
|
enum {
|
|
ADD,
|
|
SET,
|
|
DELETE,
|
|
NUM_SIGNALS
|
|
};
|
|
|
|
static guint gm_mcp_icecrew_playerdb_signals[NUM_SIGNALS] = {0};
|
|
|
|
G_DEFINE_TYPE(GmMcpIcecrewPlayerdb, gm_mcp_icecrew_playerdb,
|
|
GM_TYPE_MCP_PACKAGE)
|
|
|
|
void gm_mcp_icecrew_playerdb_handle_simple(GmMcpPackage *package, gchar *suffix,
|
|
GList *fields);
|
|
gboolean gm_mcp_icecrew_playerdb_handle_multi(GmMcpPackage *package,
|
|
gchar const *data_tag, gchar const *key, gchar const *value,
|
|
GList *all_values);
|
|
|
|
static void
|
|
gm_mcp_icecrew_playerdb_finalize(GObject *object) {
|
|
GmMcpIcecrewPlayerdb *obj = GM_MCP_ICECREW_PLAYERDB(object);
|
|
GmPlayerdbPlayerInfo *ppi;
|
|
GList *f;
|
|
|
|
for (f = obj->priv->db; f; f = f->next) {
|
|
ppi = (GmPlayerdbPlayerInfo *)(f->data);
|
|
g_hash_table_destroy(ppi->values);
|
|
g_free(ppi);
|
|
}
|
|
|
|
g_list_free(obj->priv->db);
|
|
gm_mcp_list_free(obj->priv->last_init_keys);
|
|
|
|
G_OBJECT_CLASS(gm_mcp_icecrew_playerdb_parent_class)->finalize(object);
|
|
}
|
|
|
|
static void
|
|
gm_mcp_icecrew_playerdb_class_init(GmMcpIcecrewPlayerdbClass *klass) {
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass);
|
|
|
|
object_class->finalize = gm_mcp_icecrew_playerdb_finalize;
|
|
|
|
gm_mcp_icecrew_playerdb_signals[ADD] =
|
|
g_signal_new("add",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmMcpIcecrewPlayerdbClass, add),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_POINTER);
|
|
gm_mcp_icecrew_playerdb_signals[SET] =
|
|
g_signal_new("set",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmMcpIcecrewPlayerdbClass, set),
|
|
NULL, NULL,
|
|
gm_marshal_VOID__POINTER_STRING_STRING_STRING,
|
|
G_TYPE_NONE,
|
|
4,
|
|
G_TYPE_POINTER,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING,
|
|
G_TYPE_STRING);
|
|
gm_mcp_icecrew_playerdb_signals[DELETE] =
|
|
g_signal_new("delete",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmMcpIcecrewPlayerdbClass, delete),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_POINTER);
|
|
|
|
pklass->name = "dns-nl-icecrew-playerdb";
|
|
pklass->handle_simple = &gm_mcp_icecrew_playerdb_handle_simple;
|
|
pklass->handle_multi = &gm_mcp_icecrew_playerdb_handle_multi;
|
|
|
|
g_type_class_add_private(object_class, sizeof(GmMcpIcecrewPlayerdbPrivate));
|
|
}
|
|
|
|
static void
|
|
gm_mcp_icecrew_playerdb_init(GmMcpIcecrewPlayerdb *obj) {
|
|
obj->priv = GM_MCP_ICECREW_PLAYERDB_GET_PRIVATE(obj);
|
|
|
|
obj->priv->self = 0;
|
|
obj->priv->db = NULL;
|
|
obj->priv->last_init_keys = NULL;
|
|
}
|
|
|
|
GmMcpIcecrewPlayerdb *
|
|
gm_mcp_icecrew_playerdb_new() {
|
|
GmMcpIcecrewPlayerdb *obj = GM_MCP_ICECREW_PLAYERDB(g_object_new(
|
|
GM_TYPE_MCP_ICECREW_PLAYERDB, NULL));
|
|
|
|
return obj;
|
|
}
|
|
|
|
GmPlayerdbPlayerInfo *
|
|
gm_mcp_icecrew_playerdb_find(GmMcpIcecrewPlayerdb *package, gint id) {
|
|
GmPlayerdbPlayerInfo *ppi;
|
|
GList *item;
|
|
|
|
for (item = package->priv->db; item; item = item->next) {
|
|
ppi = (GmPlayerdbPlayerInfo *)(item->data);
|
|
|
|
if (ppi->id == id) {
|
|
return ppi;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
gchar const *
|
|
gm_playerdb_player_info_get_prop(GmPlayerdbPlayerInfo *ppi, gchar const *key) {
|
|
return g_hash_table_lookup(ppi->values, key);
|
|
}
|
|
|
|
gboolean
|
|
gm_mcp_icecrew_playerdb_initializing(GmMcpIcecrewPlayerdb *package) {
|
|
return package->priv->last_init_keys != NULL;
|
|
}
|
|
|
|
void
|
|
gm_mcp_icecrew_playerdb_find_players_with(GmMcpIcecrewPlayerdb *package,
|
|
gchar const *key, gchar const *value, PlayerdbFindFunc func,
|
|
gpointer user_data) {
|
|
GmPlayerdbPlayerInfo *ppi;
|
|
gchar const *v;
|
|
GList *db;
|
|
|
|
for (db = package->priv->db; db; db = db->next) {
|
|
ppi = (GmPlayerdbPlayerInfo *)(db->data);
|
|
|
|
v = gm_playerdb_player_info_get_prop(ppi, key);
|
|
|
|
if (v != NULL && (value == NULL || strcmp(v, value) == 0)) {
|
|
func(ppi, user_data);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gm_mcp_icecrew_playerdb_set_prop(GmMcpIcecrewPlayerdb *package,
|
|
GmPlayerdbPlayerInfo *ppi, gchar const *key, gchar const *value,
|
|
gboolean add) {
|
|
gchar *old;
|
|
|
|
if (strcmp(key, "id") == 0) {
|
|
return;
|
|
}
|
|
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewPlayerdb.SetProp: key: %s, value: %s",
|
|
key, value);
|
|
|
|
old = g_strdup(gm_playerdb_player_info_get_prop(ppi, key));
|
|
|
|
if (old && strcmp(old, value) == 0) {
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewPlayerdb.SetProp: new value is "
|
|
"the same as old value, no changes made");
|
|
g_free(old);
|
|
return;
|
|
}
|
|
|
|
g_hash_table_insert(ppi->values, g_strdup(key), g_strdup(value));
|
|
|
|
if (!add) {
|
|
g_signal_emit(package, gm_mcp_icecrew_playerdb_signals[SET], 0,
|
|
ppi, key, value, old);
|
|
}
|
|
|
|
g_free(old);
|
|
}
|
|
|
|
void
|
|
gm_mcp_icecrew_playerdb_modify_prop(GmMcpIcecrewPlayerdb *package,
|
|
GmPlayerdbPlayerInfo *ppi, gchar const *key, gchar const *value,
|
|
gboolean add) {
|
|
if (ppi) {
|
|
gm_mcp_icecrew_playerdb_set_prop(package, ppi, key, value, add);
|
|
}
|
|
}
|
|
|
|
void
|
|
gm_mcp_icecrew_playerdb_modify_prop_list(GmMcpIcecrewPlayerdb *package,
|
|
GmPlayerdbPlayerInfo *ppi, GList *fields, gboolean add) {
|
|
GmKeyValuePair *data;
|
|
|
|
if (ppi) {
|
|
for (; fields; fields = fields->next) {
|
|
data = (GmKeyValuePair *)(fields->data);
|
|
gm_mcp_icecrew_playerdb_set_prop(package, ppi, data->key,
|
|
data->value, add);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gm_mcp_icecrew_playerdb_remove_player(GmMcpIcecrewPlayerdb *package, gint id) {
|
|
GmPlayerdbPlayerInfo *ppi;
|
|
|
|
if ((ppi = gm_mcp_icecrew_playerdb_find(package, id))) {
|
|
g_signal_emit(package, gm_mcp_icecrew_playerdb_signals[DELETE], 0,
|
|
ppi);
|
|
|
|
package->priv->db = g_list_remove(package->priv->db, ppi);
|
|
g_hash_table_destroy(ppi->values);
|
|
}
|
|
}
|
|
|
|
GmPlayerdbPlayerInfo *
|
|
gm_mcp_icecrew_playerdb_add_player(GmMcpIcecrewPlayerdb *package, gint id) {
|
|
GmPlayerdbPlayerInfo *ppi = g_new(GmPlayerdbPlayerInfo, 1);
|
|
|
|
ppi->values = g_hash_table_new_full(g_str_hash, g_str_equal,
|
|
g_free, g_free);
|
|
ppi->id = id;
|
|
|
|
package->priv->db = g_list_append(package->priv->db, ppi);
|
|
gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewPlayerdb.AddPlayer: adding id %d", id);
|
|
|
|
return ppi;
|
|
}
|
|
|
|
void
|
|
gm_mcp_icecrew_playerdb_handle_simple(GmMcpPackage *package, gchar *suffix,
|
|
GList *fields) {
|
|
GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB(package);
|
|
gchar const *value;
|
|
GmPlayerdbPlayerInfo *ppi;
|
|
gint id, add;
|
|
|
|
if (strcasecmp(suffix, "self") == 0) {
|
|
if ((value = gm_mcp_find_value(fields, "id"))) {
|
|
playerdb->priv->self = atoi(value);
|
|
}
|
|
} else if ((add = strcasecmp(suffix, "add")) == 0 ||
|
|
strcasecmp(suffix, "set") == 0) {
|
|
if ((value = gm_mcp_find_value(fields, "id"))) {
|
|
id = atoi(value);
|
|
ppi = gm_mcp_icecrew_playerdb_find(playerdb, id);
|
|
|
|
if (add == 0 && !ppi) {
|
|
ppi = gm_mcp_icecrew_playerdb_add_player(playerdb, id);
|
|
gm_mcp_icecrew_playerdb_modify_prop_list(playerdb, ppi, fields,
|
|
TRUE);
|
|
|
|
g_signal_emit(playerdb, gm_mcp_icecrew_playerdb_signals[ADD],
|
|
0, ppi);
|
|
} else if (add != 0 && ppi) {
|
|
gm_mcp_icecrew_playerdb_modify_prop_list(playerdb, ppi, fields,
|
|
FALSE);
|
|
}
|
|
}
|
|
} else if (strcasecmp(suffix, "del") == 0) {
|
|
if ((value = gm_mcp_find_value(fields, "id"))) {
|
|
id = atoi(value);
|
|
gm_mcp_icecrew_playerdb_remove_player(playerdb, id);
|
|
}
|
|
} else if (strcasecmp(suffix, "init") == 0) {
|
|
if ((value = gm_mcp_find_value(fields, "keys"))) {
|
|
if (playerdb->priv->last_init_keys) {
|
|
gm_mcp_list_free(playerdb->priv->last_init_keys);
|
|
}
|
|
|
|
playerdb->priv->last_init_keys = gm_mcp_parse_list(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
gm_mcp_icecrew_playerdb_handle_multi(GmMcpPackage *package,
|
|
gchar const *data_tag, gchar const *key, gchar const *value,
|
|
GList *all_values) {
|
|
GmMcpIcecrewPlayerdb *playerdb = GM_MCP_ICECREW_PLAYERDB(package);
|
|
gint i;
|
|
guint counter;
|
|
gchar *id, *list;
|
|
gchar const *ptr = value;
|
|
GList *l;
|
|
GmPlayerdbPlayerInfo *ppi;
|
|
gunichar uc;
|
|
|
|
if (key != NULL) {
|
|
/* We should have a value something like <NUM> <LIST> */
|
|
gm_string_skip_space(&value);
|
|
ptr = value;
|
|
gm_string_skip_nonspace(&ptr);
|
|
|
|
if (*ptr == '\0') {
|
|
return TRUE;
|
|
}
|
|
|
|
id = g_strndup(value, ptr - value);
|
|
|
|
gm_string_skip_space(&ptr);
|
|
value = ptr;
|
|
|
|
if (g_utf8_get_char(ptr) == '"') {
|
|
ptr = g_utf8_next_char(ptr);
|
|
value = ptr;
|
|
i = 0;
|
|
|
|
while (*ptr != '\0' && (uc = g_utf8_get_char(ptr)) != '"') {
|
|
ptr = g_utf8_next_char(ptr);
|
|
|
|
if (uc == '\\' && g_utf8_get_char(ptr) != '\0') {
|
|
ptr = g_utf8_next_char(ptr);
|
|
}
|
|
}
|
|
|
|
list = g_strndup(value, ptr - value);
|
|
|
|
l = gm_mcp_parse_list(list);
|
|
|
|
if (g_list_length(l) ==
|
|
g_list_length(playerdb->priv->last_init_keys)) {
|
|
i = atoi(id);
|
|
|
|
if ((ppi = gm_mcp_icecrew_playerdb_find(playerdb, i))) {
|
|
gm_mcp_icecrew_playerdb_remove_player(playerdb, i);
|
|
}
|
|
|
|
ppi = gm_mcp_icecrew_playerdb_add_player(playerdb, i);
|
|
|
|
for (counter = 0; counter < g_list_length(l); ++counter) {
|
|
gm_mcp_icecrew_playerdb_modify_prop(playerdb, ppi,
|
|
g_list_nth_data(playerdb->priv->last_init_keys,
|
|
counter), g_list_nth_data(l, counter), TRUE);
|
|
}
|
|
|
|
g_signal_emit(playerdb, gm_mcp_icecrew_playerdb_signals[ADD],
|
|
0, ppi);
|
|
}
|
|
|
|
g_free(list);
|
|
gm_mcp_list_free(l);
|
|
}
|
|
|
|
g_free(id);
|
|
} else {
|
|
gm_mcp_list_free(playerdb->priv->last_init_keys);
|
|
playerdb->priv->last_init_keys = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|