This repository has been archived on 2020-04-11. You can view files and clone it, but cannot push or open issues or pull requests.
gnoemoe/gnoemoe/mcp/gm-mcp-icecrew-playerdb.c

375 lines
9.5 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;
pklass->min_version = 1.0;
pklass->max_version = 1.1;
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;
}