From 5271a749bb1297b138e055ac6b68f596345537b2 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Tue, 15 Nov 2005 11:48:19 +0000 Subject: [PATCH] Initial import --- gnoemoe/mcp/gm-mcp-awns-ping.c | 80 ++ gnoemoe/mcp/gm-mcp-awns-ping.h | 58 ++ gnoemoe/mcp/gm-mcp-icecrew-mcpreset.c | 72 ++ gnoemoe/mcp/gm-mcp-icecrew-mcpreset.h | 58 ++ gnoemoe/mcp/gm-mcp-icecrew-playerdb.c | 370 +++++++++ gnoemoe/mcp/gm-mcp-icecrew-playerdb.h | 74 ++ gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c | 388 ++++++++++ gnoemoe/mcp/gm-mcp-icecrew-serverinfo.h | 58 ++ gnoemoe/mcp/gm-mcp-icecrew-userlist.c | 990 ++++++++++++++++++++++++ gnoemoe/mcp/gm-mcp-icecrew-userlist.h | 71 ++ gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.c | 154 ++++ gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.h | 58 ++ gnoemoe/mcp/gm-mcp-userlist-view.c | 275 +++++++ gnoemoe/mcp/gm-mcp-userlist-view.h | 17 + gnoemoe/mcp/gm-mcp-vmoo-client.c | 198 +++++ gnoemoe/mcp/gm-mcp-vmoo-client.h | 58 ++ gnoemoe/mcp/gm-mcp-vmoo-userlist.c | 623 +++++++++++++++ gnoemoe/mcp/gm-mcp-vmoo-userlist.h | 66 ++ 18 files changed, 3668 insertions(+) create mode 100644 gnoemoe/mcp/gm-mcp-awns-ping.c create mode 100644 gnoemoe/mcp/gm-mcp-awns-ping.h create mode 100644 gnoemoe/mcp/gm-mcp-icecrew-mcpreset.c create mode 100644 gnoemoe/mcp/gm-mcp-icecrew-mcpreset.h create mode 100644 gnoemoe/mcp/gm-mcp-icecrew-playerdb.c create mode 100644 gnoemoe/mcp/gm-mcp-icecrew-playerdb.h create mode 100644 gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c create mode 100644 gnoemoe/mcp/gm-mcp-icecrew-serverinfo.h create mode 100644 gnoemoe/mcp/gm-mcp-icecrew-userlist.c create mode 100644 gnoemoe/mcp/gm-mcp-icecrew-userlist.h create mode 100644 gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.c create mode 100644 gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.h create mode 100644 gnoemoe/mcp/gm-mcp-userlist-view.c create mode 100644 gnoemoe/mcp/gm-mcp-userlist-view.h create mode 100644 gnoemoe/mcp/gm-mcp-vmoo-client.c create mode 100644 gnoemoe/mcp/gm-mcp-vmoo-client.h create mode 100644 gnoemoe/mcp/gm-mcp-vmoo-userlist.c create mode 100644 gnoemoe/mcp/gm-mcp-vmoo-userlist.h diff --git a/gnoemoe/mcp/gm-mcp-awns-ping.c b/gnoemoe/mcp/gm-mcp-awns-ping.c new file mode 100644 index 0000000..7ee67a3 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-awns-ping.c @@ -0,0 +1,80 @@ +#include "gm-mcp-awns-ping.h" +#include "gm-mcp.h" +#include "gm-mcp-session.h" + +#define GM_MCP_AWNS_PING_GET_PRIVATE(object)( \ + G_TYPE_INSTANCE_GET_PRIVATE((object), \ + GM_TYPE_MCP_AWNS_PING, GmMcpAwnsPingPrivate)) + +struct _GmMcpAwnsPingPrivate { + +}; + +/* Signals + +enum { + PROTO + NUM_SIGNALS +}; + +static guint gm_mcp_awns_ping_signals[NUM_SIGNALS] = {0};*/ + +G_DEFINE_TYPE(GmMcpAwnsPing, gm_mcp_awns_ping, GM_TYPE_MCP_PACKAGE) + +void gm_mcp_awns_ping_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields); + +static void +gm_mcp_awns_ping_finalize(GObject *object) { + //GmMcpAwnsPing *obj = GM_MCP_AWNS_PING(object); + + G_OBJECT_CLASS(gm_mcp_awns_ping_parent_class)->finalize(object); +} + +static void +gm_mcp_awns_ping_class_init(GmMcpAwnsPingClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); + + object_class->finalize = gm_mcp_awns_ping_finalize; + + /*gm_mcp_awns_ping_signals[PROTO] = + g_signal_new("proto", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpAwnsPingClass, proto), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0);*/ + + pklass->name = "dns-com-awns-ping"; + pklass->handle_simple = &gm_mcp_awns_ping_handle_simple; + + g_type_class_add_private(object_class, sizeof(GmMcpAwnsPingPrivate)); +} + +static void +gm_mcp_awns_ping_init(GmMcpAwnsPing *obj) { + obj->priv = GM_MCP_AWNS_PING_GET_PRIVATE(obj); +} + +GmMcpAwnsPing * +gm_mcp_awns_ping_new() { + GmMcpAwnsPing *obj = GM_MCP_AWNS_PING(g_object_new(GM_TYPE_MCP_AWNS_PING, NULL)); + + return obj; +} + +void +gm_mcp_awns_ping_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields) { + gchar const *id; + + if (!suffix) { + if ((id = gm_mcp_find_value(fields, "id"))) { + gm_mcp_session_send_simple(GM_MCP_PACKAGE_SESSION(package), + "dns-com-awns-ping-reply", "id", id, NULL); + } + } +} diff --git a/gnoemoe/mcp/gm-mcp-awns-ping.h b/gnoemoe/mcp/gm-mcp-awns-ping.h new file mode 100644 index 0000000..9dc4159 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-awns-ping.h @@ -0,0 +1,58 @@ +#ifndef __GM_MCP_AWNS_PING_H__ +#define __GM_MCP_AWNS_PING_H__ + +#include +#include +#include "gm-mcp-package.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GM_TYPE_MCP_AWNS_PING (gm_mcp_awns_ping_get_type()) +#define GM_MCP_AWNS_PING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_MCP_AWNS_PING, GmMcpAwnsPing)) +#define GM_MCP_AWNS_PING_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GM_TYPE_MCP_AWNS_PING, GmMcpAwnsPing const)) +#define GM_MCP_AWNS_PING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + GM_TYPE_MCP_AWNS_PING, GmMcpAwnsPingClass)) +#define GM_IS_MCP_AWNS_PING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + GM_TYPE_MCP_AWNS_PING)) +#define GM_IS_MCP_AWNS_PING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GM_TYPE_MCP_AWNS_PING)) +#define GM_MCP_AWNS_PING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GM_TYPE_MCP_AWNS_PING, GmMcpAwnsPingClass)) + +/* Private structure type */ +typedef struct _GmMcpAwnsPingPrivate GmMcpAwnsPingPrivate; + +/* + * Main object structure + */ +typedef struct _GmMcpAwnsPing GmMcpAwnsPing; + +struct _GmMcpAwnsPing { + GmMcpPackage parent; + + /*< private > */ + GmMcpAwnsPingPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GmMcpAwnsPingClass GmMcpAwnsPingClass; + +struct _GmMcpAwnsPingClass { + GmMcpPackageClass parent_class; + + /* Signals + void (* proto) (GmMcpAwnsPing *obj); */ +}; + +GType gm_mcp_awns_ping_get_type(void) G_GNUC_CONST; +GmMcpAwnsPing *gm_mcp_awns_ping_new(void); + +G_END_DECLS +#endif /* __GM_MCP_AWNS_PING_H__ */ diff --git a/gnoemoe/mcp/gm-mcp-icecrew-mcpreset.c b/gnoemoe/mcp/gm-mcp-icecrew-mcpreset.c new file mode 100644 index 0000000..05196a5 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-icecrew-mcpreset.c @@ -0,0 +1,72 @@ +#include "gm-mcp-icecrew-mcpreset.h" +#include "gm-mcp-session.h" + +#define GM_MCP_ICECREW_MCPRESET_GET_PRIVATE(object)( \ + G_TYPE_INSTANCE_GET_PRIVATE((object), \ + GM_TYPE_MCP_ICECREW_MCPRESET, GmMcpIcecrewMcpresetPrivate)) + +struct _GmMcpIcecrewMcpresetPrivate { + +}; + +/* Signals + +enum { + PROTO + NUM_SIGNALS +}; + +static guint gm_mcp_icecrew_mcpreset_signals[NUM_SIGNALS] = {0};*/ + +G_DEFINE_TYPE(GmMcpIcecrewMcpreset, gm_mcp_icecrew_mcpreset, GM_TYPE_MCP_PACKAGE) + +void gm_mcp_icecrew_mcpreset_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields); + +static void +gm_mcp_icecrew_mcpreset_finalize(GObject *object) { + //GmMcpIcecrewMcpreset *obj = GM_MCP_ICECREW_MCPRESET(object); + + G_OBJECT_CLASS(gm_mcp_icecrew_mcpreset_parent_class)->finalize(object); +} + +static void +gm_mcp_icecrew_mcpreset_class_init(GmMcpIcecrewMcpresetClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); + + object_class->finalize = gm_mcp_icecrew_mcpreset_finalize; + + /*gm_mcp_icecrew_mcpreset_signals[PROTO] = + g_signal_new("proto", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpIcecrewMcpresetClass, proto), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0);*/ + + pklass->name = "dns-nl-icecrew-mcpreset"; + pklass->handle_simple = &gm_mcp_icecrew_mcpreset_handle_simple; + + g_type_class_add_private(object_class, sizeof(GmMcpIcecrewMcpresetPrivate)); +} + +static void +gm_mcp_icecrew_mcpreset_init(GmMcpIcecrewMcpreset *obj) { + obj->priv = GM_MCP_ICECREW_MCPRESET_GET_PRIVATE(obj); +} + +GmMcpIcecrewMcpreset * +gm_mcp_icecrew_mcpreset_new() { + GmMcpIcecrewMcpreset *obj = GM_MCP_ICECREW_MCPRESET(g_object_new(GM_TYPE_MCP_ICECREW_MCPRESET, NULL)); + + return obj; +} + +void +gm_mcp_icecrew_mcpreset_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields) { + gm_mcp_session_reset(GM_MCP_PACKAGE_SESSION(package)); +} diff --git a/gnoemoe/mcp/gm-mcp-icecrew-mcpreset.h b/gnoemoe/mcp/gm-mcp-icecrew-mcpreset.h new file mode 100644 index 0000000..3aeccfe --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-icecrew-mcpreset.h @@ -0,0 +1,58 @@ +#ifndef __GM_MCP_ICECREW_MCPRESET_H__ +#define __GM_MCP_ICECREW_MCPRESET_H__ + +#include +#include +#include "gm-mcp-package.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GM_TYPE_MCP_ICECREW_MCPRESET (gm_mcp_icecrew_mcpreset_get_type()) +#define GM_MCP_ICECREW_MCPRESET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_MCP_ICECREW_MCPRESET, GmMcpIcecrewMcpreset)) +#define GM_MCP_ICECREW_MCPRESET_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GM_TYPE_MCP_ICECREW_MCPRESET, GmMcpIcecrewMcpreset const)) +#define GM_MCP_ICECREW_MCPRESET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + GM_TYPE_MCP_ICECREW_MCPRESET, GmMcpIcecrewMcpresetClass)) +#define GM_IS_MCP_ICECREW_MCPRESET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + GM_TYPE_MCP_ICECREW_MCPRESET)) +#define GM_IS_MCP_ICECREW_MCPRESET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GM_TYPE_MCP_ICECREW_MCPRESET)) +#define GM_MCP_ICECREW_MCPRESET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GM_TYPE_MCP_ICECREW_MCPRESET, GmMcpIcecrewMcpresetClass)) + +/* Private structure type */ +typedef struct _GmMcpIcecrewMcpresetPrivate GmMcpIcecrewMcpresetPrivate; + +/* + * Main object structure + */ +typedef struct _GmMcpIcecrewMcpreset GmMcpIcecrewMcpreset; + +struct _GmMcpIcecrewMcpreset { + GmMcpPackage parent; + + /*< private > */ + GmMcpIcecrewMcpresetPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GmMcpIcecrewMcpresetClass GmMcpIcecrewMcpresetClass; + +struct _GmMcpIcecrewMcpresetClass { + GmMcpPackageClass parent_class; + + /* Signals + void (* proto) (GmMcpIcecrewMcpreset *obj); */ +}; + +GType gm_mcp_icecrew_mcpreset_get_type(void) G_GNUC_CONST; +GmMcpIcecrewMcpreset *gm_mcp_icecrew_mcpreset_new(void); + +G_END_DECLS +#endif /* __GM_MCP_ICECREW_MCPRESET_H__ */ diff --git a/gnoemoe/mcp/gm-mcp-icecrew-playerdb.c b/gnoemoe/mcp/gm-mcp-icecrew-playerdb.c new file mode 100644 index 0000000..baf8b8d --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-icecrew-playerdb.c @@ -0,0 +1,370 @@ +#include +#include + +#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; + GList *signals; +}; + +/* 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; + obj->priv->signals = 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); +} + +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 */ + 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; +} diff --git a/gnoemoe/mcp/gm-mcp-icecrew-playerdb.h b/gnoemoe/mcp/gm-mcp-icecrew-playerdb.h new file mode 100644 index 0000000..0fea253 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-icecrew-playerdb.h @@ -0,0 +1,74 @@ +#ifndef __GM_MCP_ICECREW_PLAYERDB_H__ +#define __GM_MCP_ICECREW_PLAYERDB_H__ + +#include +#include +#include "gm-mcp-package.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GM_TYPE_MCP_ICECREW_PLAYERDB (gm_mcp_icecrew_playerdb_get_type()) +#define GM_MCP_ICECREW_PLAYERDB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_MCP_ICECREW_PLAYERDB, GmMcpIcecrewPlayerdb)) +#define GM_MCP_ICECREW_PLAYERDB_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GM_TYPE_MCP_ICECREW_PLAYERDB, GmMcpIcecrewPlayerdb const)) +#define GM_MCP_ICECREW_PLAYERDB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + GM_TYPE_MCP_ICECREW_PLAYERDB, GmMcpIcecrewPlayerdbClass)) +#define GM_IS_MCP_ICECREW_PLAYERDB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + GM_TYPE_MCP_ICECREW_PLAYERDB)) +#define GM_IS_MCP_ICECREW_PLAYERDB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GM_TYPE_MCP_ICECREW_PLAYERDB)) +#define GM_MCP_ICECREW_PLAYERDB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GM_TYPE_MCP_ICECREW_PLAYERDB, GmMcpIcecrewPlayerdbClass)) + +/* Private structure type */ +typedef struct _GmMcpIcecrewPlayerdbPrivate GmMcpIcecrewPlayerdbPrivate; + +/* + * Main object structure + */ +typedef struct _GmMcpIcecrewPlayerdb GmMcpIcecrewPlayerdb; + +struct _GmMcpIcecrewPlayerdb { + GmMcpPackage parent; + + /*< private > */ + GmMcpIcecrewPlayerdbPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GmMcpIcecrewPlayerdbClass GmMcpIcecrewPlayerdbClass; + +struct _GmMcpIcecrewPlayerdbClass { + GmMcpPackageClass parent_class; + + /* Signals */ + void (* add) (GmMcpIcecrewPlayerdb *obj, gpointer player_info); + void (* set) (GmMcpIcecrewPlayerdb *obj, gpointer player_info, + gchar const *key, gchar const *value, gchar const *old_value); + void (* delete) (GmMcpIcecrewPlayerdb *obj, gpointer player_info); +}; + +typedef struct _GmPlayerdbPlayerInfo { + gint id; + GHashTable *values; +} GmPlayerdbPlayerInfo; + +typedef void (*PlayerdbFindFunc) (GmPlayerdbPlayerInfo *, gpointer user_data); + +GType gm_mcp_icecrew_playerdb_get_type(void) G_GNUC_CONST; +GmMcpIcecrewPlayerdb *gm_mcp_icecrew_playerdb_new(void); + +gchar const *gm_playerdb_player_info_get_prop(GmPlayerdbPlayerInfo *ppi, + gchar const *key); +void gm_mcp_icecrew_playerdb_find_players_with(GmMcpIcecrewPlayerdb *package, + gchar const *key, gchar const *value, PlayerdbFindFunc func, + gpointer user_data); + +G_END_DECLS +#endif /* __GM_MCP_ICECREW_PLAYERDB_H__ */ diff --git a/gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c b/gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c new file mode 100644 index 0000000..ffbae40 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-icecrew-serverinfo.c @@ -0,0 +1,388 @@ +#include +#include "gm-mcp-icecrew-serverinfo.h" +#include "gm-mcp.h" +#include "gm-mcp-session.h" +#include "../widgets/gm-app-view.h" +#include "../gm-world.h" +#include "../dialogs/gm-world-info-dialog.h" +#include "../gm-support.h" +#include "../gm-debug.h" +#include "../gm-options.h" + +#define GM_MCP_ICECREW_SERVERINFO_GET_PRIVATE(object)( \ + G_TYPE_INSTANCE_GET_PRIVATE((object), \ + GM_TYPE_MCP_ICECREW_SERVERINFO, GmMcpIcecrewServerinfoPrivate)) + +typedef struct _GmMcpIcecrewServerinfoView { + GmAppView *view; + GmMcpIcecrewServerinfo *package; +} GmMcpIcecrewServerinfoView; + +struct _GmMcpIcecrewServerinfoPrivate { + gboolean has_info; + GmWorldInfo info; + GmFetchHandle *handle; +}action; + +/* Signals */ + +enum { + GOT_INFO, + NUM_SIGNALS +}; + +static guint gm_mcp_icecrew_serverinfo_signals[NUM_SIGNALS] = {0}; + +G_DEFINE_TYPE(GmMcpIcecrewServerinfo, gm_mcp_icecrew_serverinfo, GM_TYPE_MCP_PACKAGE) + +void gm_mcp_icecrew_serverinfo_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields); +void gm_mcp_icecrew_serverinfo_create_view(GmMcpPackage *package, + GObject *parent); +void gm_mcp_icecrew_serverinfo_set_session(GmMcpPackage *package, + GObject *session); + +void +gm_mcp_icecrew_serverinfo_free_info(GmMcpIcecrewServerinfo *obj) { + g_free(obj->priv->info.homepage); + g_free(obj->priv->info.location); + g_free(obj->priv->info.admin); + g_free(obj->priv->info.contact); + g_free(obj->priv->info.charset); + g_free(obj->priv->info.language); + g_free(obj->priv->info.system); + g_free(obj->priv->info.logo); + + if (obj->priv->handle) { + obj->priv->handle->aborted = TRUE; + } + + memset(&(obj->priv->info), 0, sizeof(GmWorldInfo)); +} + +static void +gm_mcp_icecrew_serverinfo_finalize(GObject *object) { + GmMcpIcecrewServerinfo *obj = GM_MCP_ICECREW_SERVERINFO(object); + + gm_mcp_icecrew_serverinfo_free_info(obj); + + G_OBJECT_CLASS(gm_mcp_icecrew_serverinfo_parent_class)->finalize(object); +} + +static void +gm_mcp_icecrew_serverinfo_class_init(GmMcpIcecrewServerinfoClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); + + object_class->finalize = gm_mcp_icecrew_serverinfo_finalize; + + gm_mcp_icecrew_serverinfo_signals[GOT_INFO] = + g_signal_new("got_info", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpIcecrewServerinfoClass, got_info), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + pklass->name = "dns-nl-icecrew-serverinfo"; + pklass->handle_simple = &gm_mcp_icecrew_serverinfo_handle_simple; + pklass->create_view = &gm_mcp_icecrew_serverinfo_create_view; + pklass->set_session = &gm_mcp_icecrew_serverinfo_set_session; + + g_type_class_add_private(object_class, sizeof(GmMcpIcecrewServerinfoPrivate)); +} + +static void +gm_mcp_icecrew_serverinfo_init(GmMcpIcecrewServerinfo *obj) { + obj->priv = GM_MCP_ICECREW_SERVERINFO_GET_PRIVATE(obj); + + obj->priv->has_info = FALSE; +} + +GmMcpIcecrewServerinfo * +gm_mcp_icecrew_serverinfo_new() { + GmMcpIcecrewServerinfo *obj = GM_MCP_ICECREW_SERVERINFO(g_object_new( \ + GM_TYPE_MCP_ICECREW_SERVERINFO, NULL)); + + return obj; +} + +void +gm_mcp_icecrew_serverinfo_fetch_progress(GmFetchHandle *g, + GmMcpIcecrewServerinfo *package) { + gchar *path; + GdkPixbuf *pixtest; + GError *err = NULL; + + if (g->aborted) { + if (GM_IS_MCP_ICECREW_SERVERINFO(package)) { + package->priv->handle = NULL; + } + + gm_debug_msg(DEBUG_MCP, "GmIcecrewServerInfo.FetchProgress: " + "fetch aborted!"); + return; + } + + if (g->done) { + if (GM_IS_MCP_ICECREW_SERVERINFO(package)) { + package->priv->handle = NULL; + } + + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewServerinfo.FetchProgress: " + "fetch done!"); + return; + } + + if (g->cur_phase == GNOME_VFS_XFER_PHASE_FILECOMPLETED) { + path = gnome_vfs_get_local_path_from_uri(g->cur_file_name); + pixtest = gdk_pixbuf_new_from_file(path, &err); + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewServerinfo.FetchProgress: %s " + "fetched!", path); + + if (pixtest) { + g_object_unref(pixtest); + package->priv->info.logo = path; + + gm_options_set(gm_world_options(GM_MCP_SESSION_WORLD( + GM_MCP_PACKAGE_SESSION(package))), "logo", path); + + g_signal_emit(package, + gm_mcp_icecrew_serverinfo_signals[GOT_INFO], 0); + g->aborted = TRUE; + } else { + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewServerinfo.FetchProgress: " + "Error on loading %s: %s", path, err->message); + g_error_free(err); + g_free(path); + } + } +} + + +void +gm_mcp_icecrew_serverinfo_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields) { + GmMcpIcecrewServerinfo *serverinfo = GM_MCP_ICECREW_SERVERINFO(package); + gchar *base, *path, **alternatives, **ptr; + gchar const *logo; + GList *source = NULL, *dest = NULL; + GnomeVFSResult result; + GnomeVFSFileInfo *finfo; + + if (strcmp(suffix, "set") == 0) { + gm_mcp_icecrew_serverinfo_free_info(serverinfo); + + serverinfo->priv->info.name = + g_strdup(gm_mcp_find_value(fields, "name")); + serverinfo->priv->info.homepage = + g_strdup(gm_mcp_find_value(fields, "homepage")); + serverinfo->priv->info.location = + g_strdup(gm_mcp_find_value(fields, "location")); + serverinfo->priv->info.admin = + g_strdup(gm_mcp_find_value(fields, "admin")); + serverinfo->priv->info.contact = + g_strdup(gm_mcp_find_value(fields, "contact")); + serverinfo->priv->info.charset = + g_strdup(gm_mcp_find_value(fields, "charset")); + serverinfo->priv->info.language = + g_strdup(gm_mcp_find_value(fields, "language")); + serverinfo->priv->info.system = + g_strdup(gm_mcp_find_value(fields, "system")); + + gm_options_set(gm_world_options(GM_MCP_SESSION_WORLD( + GM_MCP_PACKAGE_SESSION(package))), "mooname", + serverinfo->priv->info.name); + + if ((logo = gm_mcp_find_value(fields, "logo")) != NULL) { + alternatives = g_strsplit(logo, ";", 0); + ptr = alternatives; + + while (*ptr) { + finfo = gnome_vfs_file_info_new(); + result = gnome_vfs_get_file_info(*ptr, finfo, + GNOME_VFS_FILE_INFO_DEFAULT); + gnome_vfs_file_info_unref(finfo); + + if (result != GNOME_VFS_OK) { + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewServerinfo.HandleSimple: " + "Ignore logo alternative %s because it's invalid: %s", + *ptr, gnome_vfs_result_to_string(result)); + } else { + base = g_path_get_basename(*ptr); + + if (base && *base != '\0' && base[1] != '\0') { + path = g_strconcat(gm_world_path(GM_MCP_SESSION_WORLD( + GM_MCP_PACKAGE_SESSION(package))), + G_DIR_SEPARATOR_S, "pixmaps", G_DIR_SEPARATOR_S, + base, NULL); + + source = g_list_append(source, g_strdup(*ptr)); + dest = g_list_append(dest, path); + } + + g_free(base); + } + + ++ptr; + } + + g_strfreev(alternatives); + + if (source != NULL) { + if (serverinfo->priv->handle) { + serverinfo->priv->handle->aborted = TRUE; + + while (serverinfo->priv->handle != NULL) { + gm_do_events(); + } + } + + if (serverinfo->priv->info.logo) { + if (g_file_test(serverinfo->priv->info.logo, + G_FILE_TEST_EXISTS)) { + unlink(serverinfo->priv->info.logo); + } + + g_free(serverinfo->priv->info.logo); + serverinfo->priv->info.logo = NULL; + } + + gm_fetch(source, dest, + (GFunc)gm_mcp_icecrew_serverinfo_fetch_progress, + serverinfo); + + gm_g_list_free_simple(source); + gm_g_list_free_simple(dest); + } + } + + serverinfo->priv->has_info = TRUE; + g_signal_emit(serverinfo, gm_mcp_icecrew_serverinfo_signals[GOT_INFO], + 0); + } +} + +void +gm_mcp_icecrew_serverinfo_set_session(GmMcpPackage *package, GObject *session) { + GmMcpPackageClass *parent_class = g_type_class_peek_parent( + GM_MCP_ICECREW_SERVERINFO_GET_CLASS(package)); + gchar *path; + + parent_class->set_session(package, session); + path = g_strconcat(gm_world_path(GM_MCP_SESSION_WORLD( + GM_MCP_SESSION(session))), G_DIR_SEPARATOR_S, "pixmaps", NULL); + + if (!g_file_test(path, G_FILE_TEST_EXISTS)) { + mkdir(path, 0755); + } + + g_free(path); + gm_mcp_session_send_simple(GM_MCP_SESSION(session), + "dns-nl-icecrew-serverinfo-get", NULL); +} + +gboolean +gm_mcp_icecrew_serverinfo_has_info(GmMcpIcecrewServerinfo *package) { + return package->priv->has_info; +} + +GmWorldInfo const * +gm_mcp_icecrew_serverinfo_info(GmMcpIcecrewServerinfo *package) { + return &(package->priv->info); +} + +/* GmMcpIcecrewServerinfoView */ +void +on_gm_mcp_icecrew_serverinfo_view_activate(GtkMenuItem *item, + GmMcpIcecrewServerinfoView *view) { + gm_world_info_dialog_new(gm_mcp_icecrew_serverinfo_info(view->package)); +} + +void +gm_mcp_icecrew_serverinfo_view_set_sensitive(GmMcpIcecrewServerinfoView *view, + gboolean sensitive) { + GtkAction *action = gm_app_view_action(view->view, + "/MenuBar/WorldMenu/WorldInfoMenu"); + + if (gtk_action_get_sensitive(action) == sensitive) { + return; + } + + gtk_action_set_sensitive(action, sensitive); + + if (sensitive) { + g_signal_connect(action, "activate", + G_CALLBACK(on_gm_mcp_icecrew_serverinfo_view_activate), view); + } else { + g_signal_handlers_disconnect_by_func(action, + on_gm_mcp_icecrew_serverinfo_view_activate, view); + } +} + +void +on_gm_mcp_icecrew_serverinfo_view_active_changed(GmWorld *world, + gboolean active, GmMcpIcecrewServerinfoView *view) { + if (active && gm_mcp_icecrew_serverinfo_has_info(view->package)) { + gm_mcp_icecrew_serverinfo_view_set_sensitive(view, TRUE); + } else if (!active) { + gm_mcp_icecrew_serverinfo_view_set_sensitive(view, FALSE); + } +} + +void +on_gm_mcp_icecrew_serverinfo_view_weak_notify(gpointer data, GObject *obj) { + GmMcpIcecrewServerinfoView *view = (GmMcpIcecrewServerinfoView *)(data); + GmWorld *world = GM_MCP_SESSION_WORLD( + GM_MCP_PACKAGE_SESSION(view->package)); + + g_signal_handlers_disconnect_by_func(world, + on_gm_mcp_icecrew_serverinfo_view_active_changed, view); + + if (gm_world_active(world)) { + gm_mcp_icecrew_serverinfo_view_set_sensitive(view, FALSE); + } + + g_free(data); +} + +void on_gm_mcp_icecrew_serverinfo_view_got_info(GmMcpIcecrewServerinfo *package, + GmMcpIcecrewServerinfoView *view) { + if (gm_world_active(GM_MCP_SESSION_WORLD( + GM_MCP_PACKAGE_SESSION(package)))) { + gm_mcp_icecrew_serverinfo_view_set_sensitive(view, TRUE); + } + + // TODO: set logo for world menu item +} + +void +gm_mcp_icecrew_serverinfo_create_view(GmMcpPackage *package, GObject *parent) { + GmMcpIcecrewServerinfoView *view; + + if (!GM_IS_APP_VIEW(parent)) { + return; + } + + view = g_new(GmMcpIcecrewServerinfoView, 1); + view->view = GM_APP_VIEW(parent); + view->package = GM_MCP_ICECREW_SERVERINFO(package); + + // Connect the got_info signal to know when new information has arrived + g_signal_connect(package, "got_info", + G_CALLBACK(on_gm_mcp_icecrew_serverinfo_view_got_info), view); + + // Connect to active_changed signal of the world to alter the sensitivity + // of the info menu item + g_signal_connect(GM_MCP_SESSION_WORLD(GM_MCP_PACKAGE_SESSION(package)), + "active_changed", + G_CALLBACK(on_gm_mcp_icecrew_serverinfo_view_active_changed), + view); + + // Connect a weak ref notifier to the McpPackage to know when to destroy + // ourselfs + g_object_weak_ref(G_OBJECT(package), + on_gm_mcp_icecrew_serverinfo_view_weak_notify, view); +} diff --git a/gnoemoe/mcp/gm-mcp-icecrew-serverinfo.h b/gnoemoe/mcp/gm-mcp-icecrew-serverinfo.h new file mode 100644 index 0000000..b0c22e9 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-icecrew-serverinfo.h @@ -0,0 +1,58 @@ +#ifndef __GM_MCP_ICECREW_SERVERINFO_H__ +#define __GM_MCP_ICECREW_SERVERINFO_H__ + +#include +#include +#include "gm-mcp-package.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GM_TYPE_MCP_ICECREW_SERVERINFO (gm_mcp_icecrew_serverinfo_get_type()) +#define GM_MCP_ICECREW_SERVERINFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_MCP_ICECREW_SERVERINFO, GmMcpIcecrewServerinfo)) +#define GM_MCP_ICECREW_SERVERINFO_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GM_TYPE_MCP_ICECREW_SERVERINFO, GmMcpIcecrewServerinfo const)) +#define GM_MCP_ICECREW_SERVERINFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + GM_TYPE_MCP_ICECREW_SERVERINFO, GmMcpIcecrewServerinfoClass)) +#define GM_IS_MCP_ICECREW_SERVERINFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + GM_TYPE_MCP_ICECREW_SERVERINFO)) +#define GM_IS_MCP_ICECREW_SERVERINFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GM_TYPE_MCP_ICECREW_SERVERINFO)) +#define GM_MCP_ICECREW_SERVERINFO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GM_TYPE_MCP_ICECREW_SERVERINFO, GmMcpIcecrewServerinfoClass)) + +/* Private structure type */ +typedef struct _GmMcpIcecrewServerinfoPrivate GmMcpIcecrewServerinfoPrivate; + +/* + * Main object structure + */ +typedef struct _GmMcpIcecrewServerinfo GmMcpIcecrewServerinfo; + +struct _GmMcpIcecrewServerinfo { + GmMcpPackage parent; + + /*< private > */ + GmMcpIcecrewServerinfoPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GmMcpIcecrewServerinfoClass GmMcpIcecrewServerinfoClass; + +struct _GmMcpIcecrewServerinfoClass { + GmMcpPackageClass parent_class; + + /* Signals */ + void (* got_info) (GmMcpIcecrewServerinfo *obj); +}; + +GType gm_mcp_icecrew_serverinfo_get_type(void) G_GNUC_CONST; +GmMcpIcecrewServerinfo *gm_mcp_icecrew_serverinfo_new(void); + +G_END_DECLS +#endif /* __GM_MCP_ICECREW_SERVERINFO_H__ */ diff --git a/gnoemoe/mcp/gm-mcp-icecrew-userlist.c b/gnoemoe/mcp/gm-mcp-icecrew-userlist.c new file mode 100644 index 0000000..1927883 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-icecrew-userlist.c @@ -0,0 +1,990 @@ +#include +#include +#include +#include +#include + +#include "gm-mcp-icecrew-userlist.h" +#include "gm-mcp-userlist-view.h" +#include "gm-mcp-icecrew-playerdb.h" +#include "gm-mcp-session.h" +#include "gm-mcp.h" +#include "../gm-support.h" +#include "../gm-marshal.h" +#include "../gm-debug.h" +#include "../gm-world.h" + +#define GM_MCP_ICECREW_USERLIST_GET_PRIVATE(object)( \ + G_TYPE_INSTANCE_GET_PRIVATE((object), \ + GM_TYPE_MCP_ICECREW_USERLIST, GmMcpIcecrewUserlistPrivate)) + +#define USERLIST_ICON_SIZE 22 + +static GmKeyValuePair default_states[] = { + {"away+idle", "ice-userlist/away+idle.svg"}, + {"busy+idle", "ice-userlist/busy+idle.svg"}, + {"away", "ice-userlist/away.svg"}, + {"busy", "ice-userlist/busy.svg"}, + {"avail+idle", "ice-userlist/avail+idle.svg"}, + {NULL, NULL} +}; + +static GmKeyValuePair default_ranks[] = { + {"inhabitant", "ice-userlist/inhabitant.svg"}, + {"programmer", "ice-userlist/programmer.svg"}, + {"wizard", "ice-userlist/wizard.svg"}, + {NULL, NULL} +}; + +struct _GmMcpIcecrewUserlistPrivate { + GList *state_icons; + GList *rank_icons; + GList *state_alternatives; + GList *rank_alternatives; + + GList *key_datatags; + GmFetchHandle *rank_fetch; + GmFetchHandle *state_fetch; + + gchar *rank_dir; + gchar *state_dir; +}; + +static gchar *gm_mcp_icecrew_userlist_depends[] = { + "dns-nl-icecrew-playerdb", + NULL +}; +static gchar *gm_mcp_icecrew_userlist_overrides[] = { + "dns-com-vmoo-userlist", + NULL +}; + +/* Signals */ + +enum { + PLAYER_ADDED, + PLAYER_REMOVED, + NAME_CHANGED, + STATE_CHANGED, + RANK_CHANGED, + NUM_SIGNALS +}; + +static guint gm_mcp_icecrew_userlist_signals[NUM_SIGNALS] = {0}; + +G_DEFINE_TYPE(GmMcpIcecrewUserlist, gm_mcp_icecrew_userlist, GM_TYPE_MCP_PACKAGE) + +void on_gm_mcp_icecrew_userlist_add(GmMcpIcecrewPlayerdb *playerdb, + GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist); +void on_gm_mcp_icecrew_userlist_set(GmMcpIcecrewPlayerdb *playerdb, + GmPlayerdbPlayerInfo *ppi, gchar const *key, gchar const *value, + gchar const *old, GmMcpIcecrewUserlist *userlist); +void on_gm_mcp_icecrew_userlist_delete(GmMcpIcecrewPlayerdb *playerdb, + GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist); + +void on_gm_mcp_icecrew_userlist_fetch_progress(GmFetchHandle *g, + GmMcpIcecrewUserlist *package); + +gboolean gm_mcp_icecrew_userlist_handle_multi(GmMcpPackage *package, + gchar const *data_tag, gchar const *key, gchar const *value, + GList *all_values); + +void gm_mcp_icecrew_userlist_set_session(GmMcpPackage *package, + GObject *session); +void gm_mcp_icecrew_userlist_create_view(GmMcpPackage *package, + GObject *parent); + +void gm_mcp_icecrew_userlist_fetch_progress(GmFetchHandle *g, + GmMcpIcecrewUserlist *package); + +void +gm_mcp_icecrew_userlist_pair_free(GmKeyValuePair *pair) { + g_free(pair->key); + g_free(pair->value); + g_free(pair); +} + +void +gm_mcp_icecrew_userlist_free_list(GList *rs) { + GList *item; + + for (item = rs; item; item = item->next) { + gm_mcp_icecrew_userlist_pair_free((GmKeyValuePair *)(item->data)); + } + + g_list_free(rs); +} + +static void +gm_mcp_icecrew_userlist_finalize(GObject *object) { + GmMcpIcecrewUserlist *obj = GM_MCP_ICECREW_USERLIST(object); + GmMcpPackage *playerdb = gm_mcp_session_find_package( + GM_MCP_PACKAGE_SESSION(obj), "dns-nl-icecrew-playerdb"); + + if (playerdb) { + g_signal_handlers_disconnect_by_func(playerdb, + on_gm_mcp_icecrew_userlist_add, obj); + g_signal_handlers_disconnect_by_func(playerdb, + on_gm_mcp_icecrew_userlist_set, obj); + g_signal_handlers_disconnect_by_func(playerdb, + on_gm_mcp_icecrew_userlist_delete, obj); + } + + gm_mcp_icecrew_userlist_free_list(obj->priv->state_icons); + gm_mcp_icecrew_userlist_free_list(obj->priv->rank_icons); + gm_mcp_icecrew_userlist_free_list(obj->priv->key_datatags); + + g_free(obj->priv->rank_dir); + g_free(obj->priv->state_dir); + + if (obj->priv->rank_fetch) { + obj->priv->rank_fetch->aborted = TRUE; + } + + if (obj->priv->state_fetch) { + obj->priv->state_fetch->aborted = TRUE; + } + + G_OBJECT_CLASS(gm_mcp_icecrew_userlist_parent_class)->finalize(object); +} + +static void +gm_mcp_icecrew_userlist_class_init(GmMcpIcecrewUserlistClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); + + object_class->finalize = gm_mcp_icecrew_userlist_finalize; + + gm_mcp_icecrew_userlist_signals[PLAYER_ADDED] = + g_signal_new("player_added", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpIcecrewUserlistClass, player_added), + NULL, NULL, + gm_marshal_VOID__INT_STRING_STRING_STRING, + G_TYPE_NONE, + 4, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + gm_mcp_icecrew_userlist_signals[PLAYER_REMOVED] = + g_signal_new("player_removed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpIcecrewUserlistClass, player_removed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT); + gm_mcp_icecrew_userlist_signals[NAME_CHANGED] = + g_signal_new("name_changed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpIcecrewUserlistClass, name_changed), + NULL, NULL, + gm_marshal_VOID__INT_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING); + gm_mcp_icecrew_userlist_signals[STATE_CHANGED] = + g_signal_new("state_changed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpIcecrewUserlistClass, state_changed), + NULL, NULL, + gm_marshal_VOID__INT_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING); + + gm_mcp_icecrew_userlist_signals[RANK_CHANGED] = + g_signal_new("rank_changed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpIcecrewUserlistClass, rank_changed), + NULL, NULL, + gm_marshal_VOID__INT_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING); + + pklass->name = "dns-nl-icecrew-userlist"; + pklass->depends = gm_mcp_icecrew_userlist_depends; + pklass->overrides = gm_mcp_icecrew_userlist_overrides; + + pklass->set_session = &gm_mcp_icecrew_userlist_set_session; + pklass->handle_multi = &gm_mcp_icecrew_userlist_handle_multi; + pklass->create_view = &gm_mcp_icecrew_userlist_create_view; + + g_type_class_add_private(object_class, sizeof(GmMcpIcecrewUserlistPrivate)); +} + +GmKeyValuePair * +gm_mcp_icecrew_userlist_url_map_new(gchar const *name, gchar const *filename) { + GmKeyValuePair *r = g_new(GmKeyValuePair, 1); + + r->key = g_strdup(name); + r->value = g_strdup(filename); + + return r; +} + +GList * +gm_mcp_icecrew_userlist_find_icon_names(GList *icons, gchar const *path) { + GList *item, *res = NULL; + GmKeyValuePair *map; + + for (item = icons; item; item = item->next) { + map = (GmKeyValuePair *)(item->data); + + if (strcmp(map->value, path) == 0) { + res = g_list_append(res, map->key); + } + } + + return res; +} + +guint +gm_mcp_icecrew_userlist_find_path(GList *icons, gchar const *name, + gchar **path) { + GList *item; + GmKeyValuePair *map; + guint position = 0; + + for (item = icons; item; item = item->next) { + map = (GmKeyValuePair *)(item->data); + + if (strcmp(map->key, name) == 0) { + if (path != NULL) { + *path = map->value; + } + return position; + } + + ++position; + } + + if (path != NULL) { + *path = NULL; + } + + return position + 1; +} + +void +gm_mcp_icecrew_userlist_remove_datatag(GmMcpIcecrewUserlist *package, + gchar const *datatag) { + GList *item; + GmKeyValuePair *map; + + for (item = package->priv->key_datatags; item; item = item->next) { + map = (GmKeyValuePair *)(item->data); + + if (strcmp(map->value, datatag) == 0) { + gm_mcp_icecrew_userlist_pair_free(map); + + package->priv->key_datatags = g_list_remove_link( + package->priv->key_datatags, item); + g_list_free_1(item); + + return; + } + } +} + +gchar const * +gm_mcp_icecrew_userlist_find_key(GmMcpIcecrewUserlist *package, + gchar const *datatag) { + GList *item; + GmKeyValuePair *map; + + for (item = package->priv->key_datatags; item; item = item->next) { + map = (GmKeyValuePair *)(item->data); + + if (strcmp(map->value, datatag) == 0) { + return map->key; + } + } + + return NULL; +} + +gchar const * +gm_mcp_icecrew_userlist_find_name(gchar const *name, + GmKeyValuePair def[]) { + GmKeyValuePair *pair = def; + + while (!(pair->key == NULL && pair->value == NULL)) { + if (strcmp(pair->key, name) == 0) { + return pair->value; + } + + ++pair; + } + + return NULL; +} + +void +gm_mcp_icecrew_userlist_init_states(GmMcpIcecrewUserlist *package) { + GmKeyValuePair *pair = default_states; + + package->priv->state_icons = NULL; + + while (!(pair->key == NULL && pair->value == NULL)) { + package->priv->state_icons = g_list_append(package->priv->state_icons, + gm_mcp_icecrew_userlist_url_map_new(pair->key, pair->value)); + ++pair; + } +} + +void +gm_mcp_icecrew_userlist_init_ranks(GmMcpIcecrewUserlist *package) { + GmKeyValuePair *pair = default_ranks; + + package->priv->rank_icons = NULL; + + while (!(pair->key == NULL && pair->value == NULL)) { + package->priv->rank_icons = g_list_append(package->priv->rank_icons, + gm_mcp_icecrew_userlist_url_map_new(pair->key, pair->value)); + ++pair; + } +} + +static void +gm_mcp_icecrew_userlist_init(GmMcpIcecrewUserlist *obj) { + obj->priv = GM_MCP_ICECREW_USERLIST_GET_PRIVATE(obj); + + obj->priv->rank_alternatives = NULL; + obj->priv->state_alternatives = NULL; + obj->priv->key_datatags = NULL; + obj->priv->rank_dir = NULL; + obj->priv->state_dir = NULL; + obj->priv->rank_fetch = NULL; + obj->priv->state_fetch = NULL; + + gm_mcp_icecrew_userlist_init_states(obj); + gm_mcp_icecrew_userlist_init_ranks(obj); +} + +GmMcpIcecrewUserlist * +gm_mcp_icecrew_userlist_new() { + GmMcpIcecrewUserlist *obj = GM_MCP_ICECREW_USERLIST(g_object_new( + GM_TYPE_MCP_ICECREW_USERLIST, NULL)); + + return obj; +} + +gchar * +gm_mcp_icecrew_userlist_remote_to_local_path(gchar const *url, + gchar const *dirname) { + gchar *base = g_path_get_basename(url); + gchar *result; + + result = g_strconcat(dirname, G_DIR_SEPARATOR_S, base, NULL); + g_free(base); + + return result; +} + +void +gm_mcp_icecrew_userlist_remove_alternatives(GmMcpIcecrewUserlist *package, + gchar *path, gint n, gboolean rank) { + GList *item, **alter; + gint i; + GmKeyValuePair *map; + gchar *name, *pathd, *dir; + + alter = rank ? &(package->priv->rank_alternatives) : + &(package->priv->state_alternatives); + dir = rank ? package->priv->rank_dir : package->priv->state_dir; + + for (item = *alter; item; item = item->next) { + map = (GmKeyValuePair *)(item->data); + pathd = gm_mcp_icecrew_userlist_remote_to_local_path(map->value, dir); + + if (strcmp(pathd, path) == 0) { + name = g_strdup(map->key); + i = 0; + + while (item && (n == 0 || i < n)) { + map = (GmKeyValuePair *)(item->data); + ++i; + + if (strcmp(map->key, name) == 0) { + item = item->next; + *alter = g_list_remove(*alter, map); + gm_mcp_icecrew_userlist_pair_free(map); + } else { + break; + } + } + + g_free(name); + + break; + } + + g_free(path); + } +} + +gchar * +gm_mcp_icecrew_userlist_sort_string(GmMcpIcecrewUserlist *package, + GmPlayerdbPlayerInfo *ppi) { + /* Find the appropriate icon */ + gchar const *state = gm_playerdb_player_info_get_prop(ppi, "P_STATE"); + gchar const *rank = gm_playerdb_player_info_get_prop(ppi, "P_RANK"); + gchar const *name = gm_playerdb_player_info_get_prop(ppi, "P_NAME"); + gint sortid; + + /* Sort on icon, and then on name */ + if (strcmp(state, "avail") == 0) { + sortid = g_list_length(package->priv->rank_icons) - + gm_mcp_icecrew_userlist_find_path(package->priv->rank_icons, + rank, NULL) - 1; + } else { + sortid = (g_list_length(package->priv->state_icons) - + gm_mcp_icecrew_userlist_find_path(package->priv->state_icons, + state, NULL) - 1) + g_list_length(package->priv->rank_icons); + } + + return g_strdup_printf("%.2d%s", sortid, name); +} + +gchar * +gm_mcp_icecrew_userlist_icon_path(GmMcpIcecrewUserlist *package, + GmPlayerdbPlayerInfo *ppi) { + gchar const *state; + gchar *icon_path = NULL; + + state = gm_playerdb_player_info_get_prop(ppi, "P_STATE"); + + if (state && strcmp(state, "avail") == 0) { + gm_mcp_icecrew_userlist_find_path(package->priv->rank_icons, + gm_playerdb_player_info_get_prop(ppi, "P_RANK"), &icon_path); + } else { + gm_mcp_icecrew_userlist_find_path(package->priv->state_icons, + state, &icon_path); + + } + + return icon_path; +} + +void +gm_mcp_icecrew_userlist_update_rank_icon(GmPlayerdbPlayerInfo *ppi, + gpointer user_data) { + GmMcpIcecrewUserlist *package = GM_MCP_ICECREW_USERLIST(user_data); + gchar const *state; + gchar *icon_path; + + state = gm_playerdb_player_info_get_prop(ppi, "P_STATE"); + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.UpdateRankIcon: %s", state); + + if (state && strcmp(state, "avail") == 0) { + gm_mcp_icecrew_userlist_find_path(package->priv->rank_icons, + gm_playerdb_player_info_get_prop(ppi, "P_RANK"), &icon_path); + + g_signal_emit(package, gm_mcp_icecrew_userlist_signals[RANK_CHANGED], + 0, ppi->id, icon_path, NULL); + } +} + +void +gm_mcp_icecrew_userlist_update_state_icon(GmPlayerdbPlayerInfo *ppi, + gpointer user_data) { + GmMcpIcecrewUserlist *package = GM_MCP_ICECREW_USERLIST(user_data); + gchar *icon_path; + + gm_mcp_icecrew_userlist_find_path(package->priv->state_icons, + gm_playerdb_player_info_get_prop(ppi, "P_STATE"), &icon_path); + + g_signal_emit(package, gm_mcp_icecrew_userlist_signals[STATE_CHANGED], + 0, ppi->id, icon_path, NULL); +} + +void +gm_mcp_icecrew_userlist_new_rank_state_icon(GmMcpIcecrewUserlist *package, + gchar *path, gboolean rank) { + GList *names; + GList *tmp; + GmMcpPackage *playerdb; + + playerdb = gm_mcp_session_find_package(GM_MCP_PACKAGE_SESSION(package), + "dns-nl-icecrew-playerdb"); + + g_return_if_fail(playerdb != NULL); + + if (rank) { + names = gm_mcp_icecrew_userlist_find_icon_names( + package->priv->rank_icons, path); + } else { + names = gm_mcp_icecrew_userlist_find_icon_names( + package->priv->state_icons, path); + } + + if (names == NULL) { + return; + } + + for (tmp = names; tmp; tmp = tmp->next) { + if (rank) { + gm_mcp_icecrew_playerdb_find_players_with( + GM_MCP_ICECREW_PLAYERDB(playerdb), "P_RANK", + (gchar *)(tmp->data), + gm_mcp_icecrew_userlist_update_rank_icon, package); + } else { + gm_mcp_icecrew_playerdb_find_players_with( + GM_MCP_ICECREW_PLAYERDB(playerdb), "P_STATE", + (gchar *)(tmp->data), + gm_mcp_icecrew_userlist_update_state_icon, package); + } + } + + g_list_free(names); +} + +void +gm_mcp_icecrew_userlist_remove_not_used_icons(GList *icons, gchar *dir) { + glob_t gl; + guint i; + GList *names; + gchar *g = g_strconcat(dir, G_DIR_SEPARATOR_S, "*", NULL); + + glob(g, 0, NULL, &gl); + + for (i = 0; i < gl.gl_pathc; ++i) { + names = gm_mcp_icecrew_userlist_find_icon_names(icons, gl.gl_pathv[i]); + + if (!names) { + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.RemoveNotUsedIcons: " + "removing %s", gl.gl_pathv[i]); + + if (unlink(gl.gl_pathv[i]) == -1) { + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.RemoveNotUsedIcons: " + "error %s", strerror(errno)); + } + } else { + g_list_free(names); + } + } + + g_free(g); + globfree(&gl); +} + +void +gm_mcp_icecrew_userlist_fetch_next_alternatives(GmMcpIcecrewUserlist *package, + gboolean rank) { + GList *source_uri = NULL, *dest_uri = NULL; + gchar *prev_name = NULL, *path; + GList *item, **alter, *iter; + GmKeyValuePair *map, *itermap; + GnomeVFSResult result; + GnomeVFSFileInfo *finfo; + + /* Select unique name alternatives */ + alter = rank ? &(package->priv->rank_alternatives) : + &(package->priv->state_alternatives); + item = *alter; + + while (item) { + map = (GmKeyValuePair *)(item->data); + + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchNextAlternatives: " + "checking: %s", map->value); + + /* Skip alternatives with names we've already stored to be fetched */ + if (prev_name == NULL || strcmp(map->key, prev_name) != 0) { + finfo = gnome_vfs_file_info_new(); + result = gnome_vfs_get_file_info(map->value, finfo, + GNOME_VFS_FILE_INFO_DEFAULT); + gnome_vfs_file_info_unref(finfo); + + if (result != GNOME_VFS_OK) { + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist." + "FetchNextAlternatives: removing %s because it's " + "invalid: %s", map->value, + gnome_vfs_result_to_string(result)); + item = item->next; + + *alter = g_list_remove(*alter, map); + gm_mcp_icecrew_userlist_pair_free(map); + } else { + prev_name = map->key; + + path = gm_mcp_icecrew_userlist_remote_to_local_path(map->value, + rank ? package->priv->rank_dir : + package->priv->state_dir); + + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist." + "FetchNextAlternatives: adding to be fetched: %s => %s", + map->key, map->value); + + source_uri = g_list_append(source_uri, map->value); + dest_uri = g_list_append(dest_uri, path); + + unlink(path); + + for (iter = rank ? package->priv->rank_icons : + package->priv->state_icons; iter; iter = iter->next) { + itermap = (GmKeyValuePair *)(iter->data); + + if (strcmp(itermap->key, map->key) == 0) { + g_free(itermap->value); + itermap->value = g_strdup(path); + break; + } + } + + item = item->next; + } + } else { + item = item->next; + } + } + + if (source_uri != NULL) { + if (rank) { + package->priv->rank_fetch = gm_fetch(source_uri, dest_uri, + (GFunc)gm_mcp_icecrew_userlist_fetch_progress, package); + } else { + package->priv->state_fetch = gm_fetch(source_uri, dest_uri, + (GFunc)gm_mcp_icecrew_userlist_fetch_progress, package); + } + + gm_g_list_free_simple(dest_uri); + } else { + if (rank) { + gm_mcp_icecrew_userlist_remove_not_used_icons( + package->priv->rank_icons, package->priv->rank_dir); + } else { + gm_mcp_icecrew_userlist_remove_not_used_icons( + package->priv->state_icons, package->priv->state_dir); + } + } +} + +void +gm_mcp_icecrew_userlist_fetch_progress(GmFetchHandle *g, + GmMcpIcecrewUserlist *package) { + gchar *path; + gboolean rank = (package->priv->rank_fetch == g); + GdkPixbuf *pixtest; + GError *err = NULL; + + if (g->aborted) { + if (rank) { + package->priv->rank_fetch = NULL; + gm_mcp_icecrew_userlist_free_list( + package->priv->rank_alternatives); + package->priv->rank_alternatives = NULL; + } else { + package->priv->state_fetch = NULL; + gm_mcp_icecrew_userlist_free_list( + package->priv->state_alternatives); + package->priv->state_alternatives = NULL; + } + + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: " + "fetch aborted!"); + return; + } + + if (g->done) { + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: " + "fetch done!"); + + if (rank) { + package->priv->rank_fetch = NULL; + gm_mcp_icecrew_userlist_fetch_next_alternatives(package, TRUE); + } else { + package->priv->state_fetch = NULL; + gm_mcp_icecrew_userlist_fetch_next_alternatives(package, FALSE); + } + + return; + } + + if (g->status == GNOME_VFS_XFER_PROGRESS_STATUS_VFSERROR) { + /* Skip to the next alternative (in the next run, see on done */ + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: error"); + path = gnome_vfs_get_local_path_from_uri(g->cur_file_name); + gm_mcp_icecrew_userlist_remove_alternatives(package, path, 1, rank); + g_free(path); + } + + if (g->cur_phase == GNOME_VFS_XFER_PHASE_FILECOMPLETED) { + path = gnome_vfs_get_local_path_from_uri(g->cur_file_name); + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: " + "%s fetched!", path); + pixtest = gdk_pixbuf_new_from_file(path, &err); + + if (pixtest) { + /* Remove alternatives which don't need to be fetched anymore */ + g_object_unref(pixtest); + gm_mcp_icecrew_userlist_remove_alternatives(package, path, 0, rank); + + if (rank) { + gm_mcp_icecrew_userlist_new_rank_state_icon(package, path, + TRUE); + } else { + gm_mcp_icecrew_userlist_new_rank_state_icon(package, path, + FALSE); + } + } else { + /* This failed! */ + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.FetchProgress: " + "error, couldn't load file: %s", err->message); + g_error_free(err); + gm_mcp_icecrew_userlist_remove_alternatives(package, path, 1, rank); + } + + g_free(path); + } +} + +void +gm_mcp_icecrew_userlist_handle_ranks_states(GmMcpIcecrewUserlist *package, + GList *values, gboolean rank) { + GList *tmp, *data, *new_list = NULL; + gchar *name, **alternatives, *path, **ptr; + gchar const *cpath; + + for (tmp = values; tmp; tmp = tmp->next) { + data = (GList *)(tmp->data); + + if (data == NULL ) { + continue; + } + + name = (gchar *)(data->data); + gm_mcp_icecrew_userlist_find_path(new_list, name, &path); + + if (path) { + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.HandleRanksStates: " + "duplicate %s, ignored!", name); + continue; + } + + if (data->next == NULL) { + if (rank) { + cpath = gm_mcp_icecrew_userlist_find_name(name, default_ranks); + } else { + cpath = gm_mcp_icecrew_userlist_find_name(name, default_states); + } + + if (cpath) { + new_list = g_list_append(new_list, + gm_mcp_icecrew_userlist_url_map_new(name, cpath)); + } else { + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist." + "HandleRanksStates: couldn't find %s, ignored!", name); + } + } else { + alternatives = g_strsplit(g_list_nth_data(data, 1), ";", 0); + ptr = alternatives; + + while (*ptr) { + /* Initialize to first alternative */ + if (ptr == alternatives) { + path = gm_mcp_icecrew_userlist_remote_to_local_path( + *ptr, rank ? package->priv->rank_dir : + package->priv->state_dir); + new_list = g_list_append(new_list, + gm_mcp_icecrew_userlist_url_map_new(name, path)); + g_free(path); + } + + gm_debug_msg(DEBUG_MCP, "GmMcpIcecrewUserlist.HandleRanksStates: " + "adding alternative: %s => %s", name, *ptr); + + if (rank) { + package->priv->rank_alternatives = g_list_append( + package->priv->rank_alternatives, + gm_mcp_icecrew_userlist_url_map_new(name, + *ptr)); + } else { + package->priv->state_alternatives = g_list_append( + package->priv->state_alternatives, + gm_mcp_icecrew_userlist_url_map_new(name, + *ptr)); + } + + ++ptr; + } + + g_strfreev(alternatives); + } + } + + if (rank) { + gm_mcp_icecrew_userlist_free_list(package->priv->rank_icons); + package->priv->rank_icons = new_list; + } else { + gm_mcp_icecrew_userlist_free_list(package->priv->state_icons); + package->priv->state_icons = new_list; + } + + /* Abort a previous fetch if needed */ + if (rank && package->priv->rank_fetch) { + package->priv->rank_fetch->aborted = TRUE; + } else if (!rank && package->priv->state_fetch) { + package->priv->state_fetch->aborted = TRUE; + } + + /* Wait for vfs async to be aborted */ + while ((rank && package->priv->rank_fetch != NULL) || + (!rank && package->priv->state_fetch != NULL)) { + gm_do_events(); + } + + if (rank && package->priv->rank_alternatives) { + gm_mcp_icecrew_userlist_fetch_next_alternatives(package, rank); + } else if (!rank && package->priv->state_alternatives) { + gm_mcp_icecrew_userlist_fetch_next_alternatives(package, rank); + } +} + +gboolean +gm_mcp_icecrew_userlist_handle_multi(GmMcpPackage *package, + gchar const *data_tag, gchar const *key, gchar const *value, + GList *all_values) { + GmMcpIcecrewUserlist *userlist = GM_MCP_ICECREW_USERLIST(package); + GList *tmp, *l, *vals = NULL; + GmKeyValuePair *m; + + if (key) { + if (!gm_mcp_icecrew_userlist_find_key(userlist, data_tag)) { + m = g_new(GmKeyValuePair, 1); + m->key = g_strdup(key); + m->value = g_strdup(data_tag); + + userlist->priv->key_datatags = g_list_append( + userlist->priv->key_datatags, m); + } + } else if ((key = gm_mcp_icecrew_userlist_find_key(userlist, data_tag)) + != NULL) { + for (tmp = all_values; tmp; tmp = tmp->next) { + l = gm_mcp_parse_list((gchar *)(tmp->data)); + vals = g_list_append(vals, l); + } + + if (strcmp(key, "rank") == 0) { + gm_mcp_icecrew_userlist_handle_ranks_states(userlist, vals, TRUE); + } else if (strcmp(key, "state") == 0) { + gm_mcp_icecrew_userlist_handle_ranks_states(userlist, vals, FALSE); + } + + gm_mcp_icecrew_userlist_remove_datatag(userlist, data_tag); + } else { + gm_debug_msg(DEBUG_ALWAYS, "Datatag %s not found", data_tag); + } + + for (tmp = vals; tmp; tmp = tmp->next) { + gm_mcp_list_free((GList *)(tmp->data)); + } + + g_list_free(vals); + return FALSE; +} + +void +gm_mcp_icecrew_userlist_set_session(GmMcpPackage *package, GObject *session) { + GmMcpPackageClass *parent_class = g_type_class_peek_parent( + GM_MCP_ICECREW_USERLIST_GET_CLASS(package)); + gchar *icons_dir; + GmMcpPackage *playerdb; + GmMcpIcecrewUserlist *userlist = GM_MCP_ICECREW_USERLIST(package); + GmMcpSession *ses; + + parent_class->set_session(package, session); + ses = GM_MCP_SESSION(session); + + playerdb = gm_mcp_session_find_package(ses, "dns-nl-icecrew-playerdb"); + + g_return_if_fail(playerdb != NULL); + + icons_dir = g_strconcat(gm_world_path(GM_MCP_SESSION_WORLD(ses)), + G_DIR_SEPARATOR_S, "icons", NULL); + userlist->priv->rank_dir = g_strconcat(icons_dir, G_DIR_SEPARATOR_S, + "ranks", NULL); + userlist->priv->state_dir = g_strconcat(icons_dir, G_DIR_SEPARATOR_S, + "states", NULL); + + if (!g_file_test(icons_dir, G_FILE_TEST_EXISTS)) + mkdir(icons_dir, 0755); + if (!g_file_test(userlist->priv->rank_dir, G_FILE_TEST_EXISTS)) + mkdir(userlist->priv->rank_dir, 0755); + if (!g_file_test(userlist->priv->state_dir, G_FILE_TEST_EXISTS)) + mkdir(userlist->priv->state_dir, 0755); + + g_free(icons_dir); + + g_signal_connect(playerdb, "add", + G_CALLBACK(on_gm_mcp_icecrew_userlist_add), package); + g_signal_connect(playerdb, "set", + G_CALLBACK(on_gm_mcp_icecrew_userlist_set), package); + g_signal_connect(playerdb, "delete", + G_CALLBACK(on_gm_mcp_icecrew_userlist_delete), package); +} + +void +gm_mcp_icecrew_userlist_create_view(GmMcpPackage *package, GObject *parent) { + gm_mcp_userlist_view_new(package, parent); +} + +/* Callbacks */ +void +on_gm_mcp_icecrew_userlist_add(GmMcpIcecrewPlayerdb *playerdb, + GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist) { + gchar *sort = gm_mcp_icecrew_userlist_sort_string(userlist, ppi); + gchar const *name = gm_playerdb_player_info_get_prop(ppi, "P_NAME"); + gchar const *icon_path = gm_mcp_icecrew_userlist_icon_path(userlist, ppi); + + g_signal_emit(userlist, gm_mcp_icecrew_userlist_signals[PLAYER_ADDED], + 0, ppi->id, name, icon_path, sort); +} + +void +on_gm_mcp_icecrew_userlist_set(GmMcpIcecrewPlayerdb *playerdb, + GmPlayerdbPlayerInfo *ppi, gchar const *key, gchar const *value, + gchar const *old, GmMcpIcecrewUserlist *userlist) { + gchar *sort = NULL; + + if (strcmp(key, "P_STATE") == 0) { + sort = gm_mcp_icecrew_userlist_sort_string(userlist, ppi); + + g_signal_emit(userlist, gm_mcp_icecrew_userlist_signals[STATE_CHANGED], + 0, ppi->id, gm_mcp_icecrew_userlist_icon_path(userlist, ppi), + sort); + } else if (strcmp(key, "P_RANK") == 0) { + sort = gm_mcp_icecrew_userlist_sort_string(userlist, ppi); + + g_signal_emit(userlist, gm_mcp_icecrew_userlist_signals[RANK_CHANGED], + 0, ppi->id, gm_mcp_icecrew_userlist_icon_path(userlist, ppi), + sort); + } else if (strcmp(key, "P_NAME") == 0) { + sort = gm_mcp_icecrew_userlist_sort_string(userlist, ppi); + + g_signal_emit(userlist, gm_mcp_icecrew_userlist_signals[NAME_CHANGED], + 0, ppi->id, value, sort); + } +} + +void +on_gm_mcp_icecrew_userlist_delete(GmMcpIcecrewPlayerdb *playerdb, + GmPlayerdbPlayerInfo *ppi, GmMcpIcecrewUserlist *userlist) { + g_signal_emit(userlist, gm_mcp_icecrew_userlist_signals[PLAYER_REMOVED], + 0, ppi->id); +} diff --git a/gnoemoe/mcp/gm-mcp-icecrew-userlist.h b/gnoemoe/mcp/gm-mcp-icecrew-userlist.h new file mode 100644 index 0000000..f17278a --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-icecrew-userlist.h @@ -0,0 +1,71 @@ +#ifndef __GM_MCP_ICECREW_USERLIST_H__ +#define __GM_MCP_ICECREW_USERLIST_H__ + +#include +#include +#include "gm-mcp-package.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GM_TYPE_MCP_ICECREW_USERLIST \ + (gm_mcp_icecrew_userlist_get_type()) +#define GM_MCP_ICECREW_USERLIST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GM_TYPE_MCP_ICECREW_USERLIST, \ + GmMcpIcecrewUserlist)) +#define GM_MCP_ICECREW_USERLIST_CONST(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GM_TYPE_MCP_ICECREW_USERLIST, \ + GmMcpIcecrewUserlist const)) +#define GM_MCP_ICECREW_USERLIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GM_TYPE_MCP_ICECREW_USERLIST, \ + GmMcpIcecrewUserlistClass)) +#define GM_IS_MCP_ICECREW_USERLIST(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GM_TYPE_MCP_ICECREW_USERLIST)) +#define GM_IS_MCP_ICECREW_USERLIST_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GM_TYPE_MCP_ICECREW_USERLIST)) +#define GM_MCP_ICECREW_USERLIST_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), GM_TYPE_MCP_ICECREW_USERLIST, \ + GmMcpIcecrewUserlistClass)) + +/* Private structure type */ +typedef struct _GmMcpIcecrewUserlistPrivate GmMcpIcecrewUserlistPrivate; + +/* + * Main object structure + */ +typedef struct _GmMcpIcecrewUserlist GmMcpIcecrewUserlist; + +struct _GmMcpIcecrewUserlist { + GmMcpPackage parent; + + /*< private > */ + GmMcpIcecrewUserlistPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GmMcpIcecrewUserlistClass GmMcpIcecrewUserlistClass; + +struct _GmMcpIcecrewUserlistClass { + GmMcpPackageClass parent_class; + + /* Signals */ + void (* player_added) (GmMcpIcecrewUserlist *obj, gint id, + gchar const *name, gchar const *icon, gchar const *sort); + void (* player_removed) (GmMcpIcecrewUserlist *obj, gint id); + void (* name_changed) (GmMcpIcecrewUserlist *obj, gint id, + gchar const *name, gchar const *sort); + void (* state_changed) (GmMcpIcecrewUserlist *obj, gint id, + gchar const *icon, gchar const *sort); + void (* rank_changed) (GmMcpIcecrewUserlist *obj, gint id, + gchar const *icon, gchar const *sort); +}; + +GType gm_mcp_icecrew_userlist_get_type(void) G_GNUC_CONST; +GmMcpIcecrewUserlist *gm_mcp_icecrew_userlist_new(void); + +G_END_DECLS +#endif /* __GM_MCP_ICECREW_USERLIST_H__ */ diff --git a/gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.c b/gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.c new file mode 100644 index 0000000..1ab5c28 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.c @@ -0,0 +1,154 @@ +#include "gm-mcp-mud-moo-simpleedit.h" +#include "gm-mcp-session.h" +#include "gm-mcp.h" +#include "../gm-debug.h" +#include "../gm-world.h" +#include "../gm-editor.h" + +#define GM_MCP_MUD_MOO_SIMPLEEDIT_GET_PRIVATE(object)( \ + G_TYPE_INSTANCE_GET_PRIVATE((object), \ + GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT, GmMcpMudMooSimpleeditPrivate)) + +struct _GmMcpMudMooSimpleeditPrivate { + gchar *ref; + gchar *name; + gchar *type; +}; + +/* Signals + +enum { + PROTO + NUM_SIGNALS +}; + +static guint gm_mcp_mud_moo_simpleedit_signals[NUM_SIGNALS] = {0};*/ + +G_DEFINE_TYPE(GmMcpMudMooSimpleedit, gm_mcp_mud_moo_simpleedit, GM_TYPE_MCP_PACKAGE) + +void gm_mcp_mud_moo_simpleedit_handle_simple(GmMcpPackage *package, + gchar *suffix, GList *fields); +gboolean gm_mcp_mud_moo_simpleedit_handle_multi(GmMcpPackage *package, + gchar const *data_tag, gchar const *key, gchar const *value, + GList *all_values); +void on_gm_mcp_mud_moo_simpleedit_editor_save(GmEditor *editor, + GmMcpMudMooSimpleedit *package); + +static void +gm_mcp_mud_moo_simpleedit_finalize(GObject *object) { + GmMcpMudMooSimpleedit *obj = GM_MCP_MUD_MOO_SIMPLEEDIT(object); + + g_free(obj->priv->ref); + g_free(obj->priv->name); + g_free(obj->priv->type); + + G_OBJECT_CLASS(gm_mcp_mud_moo_simpleedit_parent_class)->finalize(object); +} + +static void +gm_mcp_mud_moo_simpleedit_class_init(GmMcpMudMooSimpleeditClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); + + object_class->finalize = gm_mcp_mud_moo_simpleedit_finalize; + + /*gm_mcp_mud_moo_simpleedit_signals[PROTO] = + g_signal_new("proto", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpMudMooSimpleeditClass, proto), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0);*/ + + pklass->name = "dns-org-mud-moo-simpleedit"; + pklass->handle_simple = &gm_mcp_mud_moo_simpleedit_handle_simple; + pklass->handle_multi = &gm_mcp_mud_moo_simpleedit_handle_multi; + + g_type_class_add_private(object_class, sizeof(GmMcpMudMooSimpleeditPrivate)); +} + +static void +gm_mcp_mud_moo_simpleedit_init(GmMcpMudMooSimpleedit *obj) { + obj->priv = GM_MCP_MUD_MOO_SIMPLEEDIT_GET_PRIVATE(obj); +} + +GmMcpMudMooSimpleedit * +gm_mcp_mud_moo_simpleedit_new() { + GmMcpMudMooSimpleedit *obj = GM_MCP_MUD_MOO_SIMPLEEDIT(g_object_new(GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT, NULL)); + + return obj; +} + +void +gm_mcp_mud_moo_simpleedit_handle_simple(GmMcpPackage *package, + gchar *suffix, GList *fields) { + gchar const *name, *ref, *type; + GmMcpMudMooSimpleedit *simpleedit = GM_MCP_MUD_MOO_SIMPLEEDIT(package); + + if (g_strcasecmp(suffix, "content") == 0) { + if (!(name = gm_mcp_find_value(fields, "name"))) { + gm_debug_msg(DEBUG_MCP, "GmMcpMooMudSimpleedit.HandleSimple: " + "no name found, ignoring!"); + } else if (!(ref = gm_mcp_find_value(fields, "reference"))) { + gm_debug_msg(DEBUG_MCP, "GmMcpMooMudSimpleedit.HandleSimple: " + "no reference found, ignoring!"); + } else if (!(type = gm_mcp_find_value(fields, "type"))) { + gm_debug_msg(DEBUG_MCP, "GmMcpMooMudSimpleedit.HandleSimple: " + "no type found, ignoring!"); + } else { + gm_debug_msg(DEBUG_MCP, "GmMcpMooMudSimpleedit.HandleSimple: " + "accept content: name = %s, reference = %s, type = %s", + name, ref, type); + simpleedit->priv->name = g_strdup(name); + simpleedit->priv->ref = g_strdup(ref); + simpleedit->priv->type = g_strdup(type); + } + } else { + gm_debug_msg(DEBUG_MCP, "GmMcpMooMudSimpleedit.HandleSimple: " + "unknown suffix: %s", suffix); + } +} + +gboolean +gm_mcp_mud_moo_simpleedit_handle_multi(GmMcpPackage *package, + gchar const *data_tag, gchar const *key, gchar const *value, + GList *all_values) { + GmEditor *editor; + GmMcpMudMooSimpleedit *simpleedit = GM_MCP_MUD_MOO_SIMPLEEDIT(package); + + if (key) { + return FALSE; + } else { + // All values arrived! Yeah! + editor = gm_editor_new_mcp(simpleedit->priv->name, + simpleedit->priv->ref, simpleedit->priv->type, all_values); + + g_signal_connect(editor, "save", + G_CALLBACK(on_gm_mcp_mud_moo_simpleedit_editor_save), package); + gm_world_add_editor(GM_MCP_SESSION_WORLD(GM_MCP_PACKAGE_SESSION( + package)), editor); + } + + return TRUE; +} + +/* Callbacks */ +void +on_gm_mcp_mud_moo_simpleedit_editor_save(GmEditor *editor, + GmMcpMudMooSimpleedit *package) { + GmMcpSession *session = GM_MCP_PACKAGE_SESSION(package); + gchar *data_tag = gm_mcp_generate_data_tag(); + + if (session) { + gm_mcp_session_send_simple(session, "dns-org-mud-moo-simpleedit-set", + "reference", gm_editor_upload_cmd(editor), "type", + gm_editor_mcp_type(editor), "content*", "", "_data-tag", + data_tag, NULL); + gm_mcp_session_send_multiline(session, data_tag, "content", + gm_editor_lines(editor)); + } + + g_free(data_tag); +} diff --git a/gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.h b/gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.h new file mode 100644 index 0000000..2d58f04 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-mud-moo-simpleedit.h @@ -0,0 +1,58 @@ +#ifndef __GM_MCP_MUD_MOO_SIMPLEEDIT_H__ +#define __GM_MCP_MUD_MOO_SIMPLEEDIT_H__ + +#include +#include +#include "gm-mcp-package.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT (gm_mcp_mud_moo_simpleedit_get_type()) +#define GM_MCP_MUD_MOO_SIMPLEEDIT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT, GmMcpMudMooSimpleedit)) +#define GM_MCP_MUD_MOO_SIMPLEEDIT_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT, GmMcpMudMooSimpleedit const)) +#define GM_MCP_MUD_MOO_SIMPLEEDIT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT, GmMcpMudMooSimpleeditClass)) +#define GM_IS_MCP_MUD_MOO_SIMPLEEDIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT)) +#define GM_IS_MCP_MUD_MOO_SIMPLEEDIT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT)) +#define GM_MCP_MUD_MOO_SIMPLEEDIT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GM_TYPE_MCP_MUD_MOO_SIMPLEEDIT, GmMcpMudMooSimpleeditClass)) + +/* Private structure type */ +typedef struct _GmMcpMudMooSimpleeditPrivate GmMcpMudMooSimpleeditPrivate; + +/* + * Main object structure + */ +typedef struct _GmMcpMudMooSimpleedit GmMcpMudMooSimpleedit; + +struct _GmMcpMudMooSimpleedit { + GmMcpPackage parent; + + /*< private > */ + GmMcpMudMooSimpleeditPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GmMcpMudMooSimpleeditClass GmMcpMudMooSimpleeditClass; + +struct _GmMcpMudMooSimpleeditClass { + GmMcpPackageClass parent_class; + + /* Signals + void (* proto) (GmMcpMudMooSimpleedit *obj); */ +}; + +GType gm_mcp_mud_moo_simpleedit_get_type(void) G_GNUC_CONST; +GmMcpMudMooSimpleedit *gm_mcp_mud_moo_simpleedit_new(void); + +G_END_DECLS +#endif /* __GM_MCP_MUD_MOO_SIMPLEEDIT_H__ */ diff --git a/gnoemoe/mcp/gm-mcp-userlist-view.c b/gnoemoe/mcp/gm-mcp-userlist-view.c new file mode 100644 index 0000000..eba3720 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-userlist-view.c @@ -0,0 +1,275 @@ +#include + +#include "gm-mcp-package.h" +#include "gm-mcp-userlist-view.h" +#include "../widgets/gm-world-view.h" +#include "../gm-pixbuf.h" +#include "../gm-debug.h" + +#define GM_USERLIST_ICON_SIZE 22 + +enum { + GM_USERLIST_ICON, + GM_USERLIST_NAME, + GM_USERLIST_ID, + GM_USERLIST_SORT, + GM_USERLIST_N_COLUMNS +}; + +typedef struct _GmMcpUserlistView { + GmWorldView *view; + GmMcpPackage *package; + GtkTreeModel *model; + GtkListStore *store; + GtkTreeView *tree_view; + GtkScrolledWindow *scrolled_window; +} GmMcpUserlistView; + +void on_gm_mcp_userlist_view_weak_notify(gpointer data, GObject *obj); + +void on_gm_mcp_userlist_view_player_added(GmMcpPackage *package, gint id, + gchar const *name, gchar const *icon, gchar const *sort, + GmMcpUserlistView *view); +void on_gm_mcp_userlist_view_player_removed(GmMcpPackage *package, gint id, + GmMcpUserlistView *view); +void on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id, + gchar const *name, gchar const *sort, GmMcpUserlistView *view); +void on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id, + gchar const *icon, gchar const *sort, GmMcpUserlistView *view); +void on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id, + gchar const *icon, gchar const *sort, GmMcpUserlistView *view); + + +GtkTreeModel * +gm_mcp_userlist_view_model_create(GmMcpUserlistView *view) { + GtkListStore *store = gtk_list_store_new(GM_USERLIST_N_COLUMNS, + GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING); + GtkTreeModel *model = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL( + store)); + + view->store = store; + view->model = model; + + return model; +} + +GtkWidget * +gm_mcp_userlist_view_create_userlist(GmMcpUserlistView *view) { + GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); + GtkTreeModel *model = gm_mcp_userlist_view_model_create(view); + GtkWidget *tree_view = gtk_tree_view_new_with_model(model); + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), + GTK_SHADOW_IN); + + gtk_widget_set_size_request(scrolled_window, 150, -1); + gtk_widget_set_size_request(tree_view, 150, -1); + + gtk_container_add(GTK_CONTAINER(scrolled_window), tree_view); + + renderer = gtk_cell_renderer_pixbuf_new(); + column = gtk_tree_view_column_new_with_attributes(_("I"), renderer, + "pixbuf", GM_USERLIST_ICON, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); + gtk_tree_view_column_set_min_width(column, 30); + + renderer = gtk_cell_renderer_text_new(); + column = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, + "text", GM_USERLIST_NAME, NULL); + gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column); + + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model), + GM_USERLIST_SORT, GTK_SORT_ASCENDING); + + GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(tree_view), GTK_CAN_FOCUS); + gtk_tree_view_columns_autosize(GTK_TREE_VIEW(tree_view)); + gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE); + + view->tree_view = GTK_TREE_VIEW(tree_view); + view->scrolled_window = GTK_SCROLLED_WINDOW(scrolled_window); + + return scrolled_window; +} + +void +gm_mcp_userlist_view_new(GmMcpPackage *package, GObject *parent) { + GmMcpUserlistView *view; + GtkPaned *paned; + GtkWidget *vbox, *child; + + if (!GM_IS_WORLD_VIEW(parent)) { + return; + } + + view = g_new(GmMcpUserlistView, 1); + view->view = GM_WORLD_VIEW(parent); + view->package = package; + + paned = GTK_PANED(gm_world_view_hpaned(view->view)); + vbox = gtk_paned_get_child2(paned); + + if (vbox == NULL) { + vbox = gtk_vbox_new(FALSE, 6); + gtk_paned_pack2(paned, vbox, FALSE, TRUE); + } + + child = gm_mcp_userlist_view_create_userlist(view); + + gtk_box_pack_end(GTK_BOX(vbox), child, TRUE, TRUE, 0); + gtk_widget_show_all(vbox); + + g_signal_connect(package, "player_added", + G_CALLBACK(on_gm_mcp_userlist_view_player_added), view); + g_signal_connect(package, "player_removed", + G_CALLBACK(on_gm_mcp_userlist_view_player_removed), view); + g_signal_connect(package, "name_changed", + G_CALLBACK(on_gm_mcp_userlist_view_name_changed), view); + g_signal_connect(package, "state_changed", + G_CALLBACK(on_gm_mcp_userlist_view_state_changed), view); + g_signal_connect(package, "rank_changed", + G_CALLBACK(on_gm_mcp_userlist_view_rank_changed), view); + + g_object_weak_ref(G_OBJECT(package), on_gm_mcp_userlist_view_weak_notify, + view); +} + +/* Callbacks */ +void +on_gm_mcp_userlist_view_weak_notify(gpointer data, GObject *obj) { + GmMcpUserlistView *view = (GmMcpUserlistView *)(data); + GtkWidget *vbox; + GList *children; + + if (GM_IS_WORLD_VIEW(view->view)) { + GM_DEBUG("Destroying scrolled window!"); + + gtk_widget_destroy(GTK_WIDGET(view->scrolled_window)); + vbox = gtk_paned_get_child2(GTK_PANED(gm_world_view_hpaned( + view->view))); + + if (vbox != NULL) { + GM_DEBUG("VBox is still there!"); + children = gtk_container_get_children(GTK_CONTAINER(vbox)); + + if (children == NULL) { + GM_DEBUG("VBox is empty, remove it!"); + + gtk_widget_destroy(vbox); + } + + g_list_free(children); + } + } + + g_free(data); +} + +gboolean +gm_mcp_userlist_view_find(GmMcpUserlistView *view, gint id, GtkTreeIter *iter) { + GtkTreeModel *model = GTK_TREE_MODEL(view->store); + gint iterid; + + if (gtk_tree_model_get_iter_first(model, iter)) { + do { + gtk_tree_model_get(model, iter, GM_USERLIST_ID, &iterid, -1); + + if (iterid == id) { + return TRUE; + } + } while (gtk_tree_model_iter_next(model, iter)); + } + + return FALSE; +} + +void +on_gm_mcp_userlist_view_player_added(GmMcpPackage *package, gint id, + gchar const *name, gchar const *icon, gchar const *sort, + GmMcpUserlistView *view) { + GtkTreeIter iter; + + if (gm_mcp_userlist_view_find(view, id, &iter)) { + gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnPlayerAdded: player %d " + "is already in the list, can't be added twice!", id); + return; + } + + gtk_list_store_append(view->store, &iter); + gtk_list_store_set(view->store, &iter, GM_USERLIST_ID, id, GM_USERLIST_ICON, + gm_pixbuf_get_at_size(icon, GM_USERLIST_ICON_SIZE, + GM_USERLIST_ICON_SIZE), GM_USERLIST_NAME, name, GM_USERLIST_SORT, + sort, -1); +} + +void +on_gm_mcp_userlist_view_player_removed(GmMcpPackage *package, gint id, + GmMcpUserlistView *view) { + GtkTreeIter iter; + + if (!gm_mcp_userlist_view_find(view, id, &iter)) { + gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnPlayerRemoved: player %d " + "is not in the list, can't be removed!", id); + return; + } + + gtk_list_store_remove(view->store, &iter); +} + +void on_gm_mcp_userlist_view_name_changed(GmMcpPackage *package, gint id, + gchar const *name, gchar const *sort, GmMcpUserlistView *view) { + GtkTreeIter iter; + + if (!gm_mcp_userlist_view_find(view, id, &iter)) { + gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnNameChanged: player %d " + "is not in the list!", id); + return; + } + + gtk_list_store_set(view->store, &iter, GM_USERLIST_NAME, name, -1); + + if (sort) { + gtk_list_store_set(view->store, &iter, GM_USERLIST_SORT, sort, -1); + } +} + +void on_gm_mcp_userlist_view_rank_changed(GmMcpPackage *package, gint id, + gchar const *icon, gchar const *sort, GmMcpUserlistView *view) { + GtkTreeIter iter; + + if (!gm_mcp_userlist_view_find(view, id, &iter)) { + gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnRankChanged: player %d " + "is not in the list!", id); + return; + } + + gtk_list_store_set(view->store, &iter, GM_USERLIST_ICON, + gm_pixbuf_get_at_size(icon, GM_USERLIST_ICON_SIZE, + GM_USERLIST_ICON_SIZE), -1); + + if (sort) { + gtk_list_store_set(view->store, &iter, GM_USERLIST_SORT, sort, -1); + } +} + +void on_gm_mcp_userlist_view_state_changed(GmMcpPackage *package, gint id, + gchar const *icon, gchar const *sort, GmMcpUserlistView *view) { + GtkTreeIter iter; + + if (!gm_mcp_userlist_view_find(view, id, &iter)) { + gm_debug_msg(DEBUG_MCP, "GmMcpUserlistView.OnStateChanged: player %d " + "is not in the list!", id); + return; + } + + gtk_list_store_set(view->store, &iter, GM_USERLIST_ICON, + gm_pixbuf_get_at_size(icon, GM_USERLIST_ICON_SIZE, + GM_USERLIST_ICON_SIZE), -1); + + if (sort) { + gtk_list_store_set(view->store, &iter, GM_USERLIST_SORT, sort, -1); + } +} diff --git a/gnoemoe/mcp/gm-mcp-userlist-view.h b/gnoemoe/mcp/gm-mcp-userlist-view.h new file mode 100644 index 0000000..bccb427 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-userlist-view.h @@ -0,0 +1,17 @@ +typedef enum _PlayerStateMask { + USERLIST_STATE_IDLE = 1 << 0, + USERLIST_STATE_BUSY = 1 << 1, + USERLIST_STATE_AWAY = 1 << 2 +} PlayerStateMask; + +typedef enum _UserlistEvent { + USERLIST_EVENT_NONE = 0, + USERLIST_EVENT_ONLINE = 1 << 0, + USERLIST_EVENT_OFFLINE = 1 << 1, + USERLIST_EVENT_IDLE_ON = 1 << 2, + USERLIST_EVENT_IDLE_OFF = 1 << 3, + USERLIST_EVENT_AWAY_ON = 1 << 4, + USERLIST_EVENT_AWAY_OFF = 1 << 5 +} UserlistEvent; + +void gm_mcp_userlist_view_new(GmMcpPackage *package, GObject *parent); diff --git a/gnoemoe/mcp/gm-mcp-vmoo-client.c b/gnoemoe/mcp/gm-mcp-vmoo-client.c new file mode 100644 index 0000000..ca9fb81 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-vmoo-client.c @@ -0,0 +1,198 @@ +#include "gm-mcp-vmoo-client.h" +#include "gm-mcp-session.h" +#include "../widgets/gm-world-view.h" +#include "../widgets/gm-world-text-view.h" + +#define GM_MCP_VMOO_CLIENT_GET_PRIVATE(object)( \ + G_TYPE_INSTANCE_GET_PRIVATE((object), \ + GM_TYPE_MCP_VMOO_CLIENT, GmMcpVmooClientPrivate)) + +struct _GmMcpVmooClientPrivate { + +}; + +typedef struct _GmMcpVmooClientView { + GmMcpVmooClient *package; + GmWorldTextView *view; + + guint width; + guint height; + guint margin_width; + guint margin_height; +} GmMcpVmooClientView; + +/* Signals + +enum { + PROTO + NUM_SIGNALS +}; + +static guint gm_mcp_vmoo_client_signals[NUM_SIGNALS] = {0};*/ + +G_DEFINE_TYPE(GmMcpVmooClient, gm_mcp_vmoo_client, GM_TYPE_MCP_PACKAGE) + +void gm_mcp_vmoo_client_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields); +void gm_mcp_vmoo_client_create_view(GmMcpPackage *package, GObject *parent); +void gm_mcp_vmoo_client_set_session(GmMcpPackage *package, GObject *session); + +static void +gm_mcp_vmoo_client_finalize(GObject *object) { + //GmMcpVmooClient *obj = GM_MCP_VMOO_CLIENT(object); + + G_OBJECT_CLASS(gm_mcp_vmoo_client_parent_class)->finalize(object); +} + +static void +gm_mcp_vmoo_client_class_init(GmMcpVmooClientClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); + + object_class->finalize = gm_mcp_vmoo_client_finalize; + + /*gm_mcp_vmoo_client_signals[PROTO] = + g_signal_new("proto", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpVmooClientClass, proto), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0);*/ + + pklass->name = "dns-com-vmoo-client"; + pklass->set_session = &gm_mcp_vmoo_client_set_session; + pklass->handle_simple = &gm_mcp_vmoo_client_handle_simple; + pklass->create_view = &gm_mcp_vmoo_client_create_view; + + g_type_class_add_private(object_class, sizeof(GmMcpVmooClientPrivate)); +} + +static void +gm_mcp_vmoo_client_init(GmMcpVmooClient *obj) { + obj->priv = GM_MCP_VMOO_CLIENT_GET_PRIVATE(obj); +} + +GmMcpVmooClient * +gm_mcp_vmoo_client_new() { + GmMcpVmooClient *obj = GM_MCP_VMOO_CLIENT(g_object_new(GM_TYPE_MCP_VMOO_CLIENT, NULL)); + + return obj; +} + +void +gm_mcp_vmoo_client_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields) { + +} + +void +gm_mcp_vmoo_client_set_session(GmMcpPackage *package, GObject *session) { + GmMcpPackageClass *parent_class = g_type_class_peek_parent( + GM_MCP_VMOO_CLIENT_GET_CLASS(package)); + parent_class->set_session(package, session); + + gm_mcp_session_send_simple(GM_MCP_SESSION(session), + "dns-com-vmoo-client-info", "name", "GnoeMoe", + "text-version", VERSION, "internal-version", IVERSION, + "reg-id", "0", "flags", "", NULL); +} + +/* GmMcpVmooClientView */ +void +gm_mcp_vmoo_client_view_update_metrics(GmMcpVmooClientView *view) { + guint width, height, cwidth, cheight; + gchar *w, *h; + GtkAllocation *allocation = &(GTK_WIDGET(view->view)->allocation); + + width = (allocation->width - view->margin_width); + height = (allocation->height - view->margin_width); + + gm_world_text_view_get_metrics(view->view, &cwidth, &cheight); + + if ((width % cwidth) != 0) { + width = (width / cwidth); + } else { + width = (width / cwidth) - 1; + } + + if ((height % cheight) != 0) { + height = (height / cheight); + } else { + height = (height / cheight) - 1; + } + + if (view->width != width || view->height != height) { + w = g_strdup_printf("%d", width); + h = g_strdup_printf("%d", height); + + gm_mcp_session_send_simple(GM_MCP_PACKAGE_SESSION(view->package), + "dns-com-vmoo-client-screensize", "cols", w, "rows", h, NULL); + g_free(w); + g_free(h); + + view->width = width; + view->height = height; + } +} + +void +on_gm_mcp_vmoo_client_text_view_size_allocate(GtkWidget *widget, + GtkAllocation *allocation, GmMcpVmooClientView *view) { + gm_mcp_vmoo_client_view_update_metrics(view); +} + +void +on_gm_mcp_vmoo_client_character_size_changed(GmWorldTextView *v, + guint width, guint height, GmMcpVmooClientView *view) { + gm_mcp_vmoo_client_view_update_metrics(view); +} + +void +on_gm_mcp_vmoo_client_view_weak_notify(gpointer data, GObject *obj) { + GmMcpVmooClientView *view = (GmMcpVmooClientView *)(data); + + g_signal_handlers_disconnect_by_func(view->view, + on_gm_mcp_vmoo_client_text_view_size_allocate, view); + g_signal_handlers_disconnect_by_func(view->view, + on_gm_mcp_vmoo_client_character_size_changed, view); + + g_free(data); +} + +void +gm_mcp_vmoo_client_create_view(GmMcpPackage *package, GObject *parent) { + GmMcpVmooClientView *client_view; + + if (!GM_IS_WORLD_VIEW(parent)) { + return; + } + + client_view = g_new0(GmMcpVmooClientView, 1); + client_view->package = GM_MCP_VMOO_CLIENT(package); + client_view->view = gm_world_view_text_view(GM_WORLD_VIEW(parent)); + + client_view->width = 0; + client_view->height = 0; + + client_view->margin_width = gtk_text_view_get_left_margin( + GTK_TEXT_VIEW(client_view->view)) + + gtk_text_view_get_right_margin( + GTK_TEXT_VIEW(client_view->view)); + + client_view->margin_height = gtk_text_view_get_pixels_above_lines( + GTK_TEXT_VIEW(client_view->view)) + + gtk_text_view_get_pixels_below_lines( + GTK_TEXT_VIEW(client_view->view)); + + g_signal_connect(client_view->view, "size-allocate", + G_CALLBACK(on_gm_mcp_vmoo_client_text_view_size_allocate), + client_view); + g_signal_connect(client_view->view, "character_size_changed", + G_CALLBACK(on_gm_mcp_vmoo_client_character_size_changed), + client_view); + + g_object_weak_ref(G_OBJECT(package), + on_gm_mcp_vmoo_client_view_weak_notify, client_view); +} diff --git a/gnoemoe/mcp/gm-mcp-vmoo-client.h b/gnoemoe/mcp/gm-mcp-vmoo-client.h new file mode 100644 index 0000000..ac053b8 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-vmoo-client.h @@ -0,0 +1,58 @@ +#ifndef __GM_MCP_VMOO_CLIENT_H__ +#define __GM_MCP_VMOO_CLIENT_H__ + +#include +#include +#include "gm-mcp-package.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GM_TYPE_MCP_VMOO_CLIENT (gm_mcp_vmoo_client_get_type()) +#define GM_MCP_VMOO_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_MCP_VMOO_CLIENT, GmMcpVmooClient)) +#define GM_MCP_VMOO_CLIENT_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GM_TYPE_MCP_VMOO_CLIENT, GmMcpVmooClient const)) +#define GM_MCP_VMOO_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + GM_TYPE_MCP_VMOO_CLIENT, GmMcpVmooClientClass)) +#define GM_IS_MCP_VMOO_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + GM_TYPE_MCP_VMOO_CLIENT)) +#define GM_IS_MCP_VMOO_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GM_TYPE_MCP_VMOO_CLIENT)) +#define GM_MCP_VMOO_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GM_TYPE_MCP_VMOO_CLIENT, GmMcpVmooClientClass)) + +/* Private structure type */ +typedef struct _GmMcpVmooClientPrivate GmMcpVmooClientPrivate; + +/* + * Main object structure + */ +typedef struct _GmMcpVmooClient GmMcpVmooClient; + +struct _GmMcpVmooClient { + GmMcpPackage parent; + + /*< private > */ + GmMcpVmooClientPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GmMcpVmooClientClass GmMcpVmooClientClass; + +struct _GmMcpVmooClientClass { + GmMcpPackageClass parent_class; + + /* Signals + void (* proto) (GmMcpVmooClient *obj); */ +}; + +GType gm_mcp_vmoo_client_get_type(void) G_GNUC_CONST; +GmMcpVmooClient *gm_mcp_vmoo_client_new(void); + +G_END_DECLS +#endif /* __GM_MCP_VMOO_CLIENT_H__ */ diff --git a/gnoemoe/mcp/gm-mcp-vmoo-userlist.c b/gnoemoe/mcp/gm-mcp-vmoo-userlist.c new file mode 100644 index 0000000..d872551 --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-vmoo-userlist.c @@ -0,0 +1,623 @@ +#include +#include +#include "gm-mcp-vmoo-userlist.h" +#include "gm-mcp-userlist-view.h" +#include "gm-mcp-session.h" +#include "gm-mcp.h" +#include "../gm-support.h" +#include "../gm-marshal.h" +#include "../gm-debug.h" +#include "../gm-world.h" +#include "../list.h" + +#define GM_MCP_VMOO_USERLIST_GET_PRIVATE(object)( \ + G_TYPE_INSTANCE_GET_PRIVATE((object), \ + GM_TYPE_MCP_VMOO_USERLIST, GmMcpVmooUserlistPrivate)) + +static const GmKeyValuePair icon_mapping[] = { + {"newbie", "userlist/newbie.svg"}, + {"inhabitant", "userlist/inhabitant.svg"}, + {"inhabitant+", "userlist/inhabitantplus.svg"}, + {"schooled", "userlist/schooled.svg"}, + {"key", "userlist/key.svg"}, + {"star", "userlist/star.svg"}, + {"wizard", "userlist/wizard.svg"}, + {NULL, NULL} +}; + +typedef enum _UserState { + U_NORMAL, + U_AWAY, + U_IDLE, + U_IDLEAWAY +} UserState; + +typedef struct _UserInfo { + gint nr; + guint icon; + gchar *name; + UserState state; +} UserInfo; + +struct _GmMcpVmooUserlistPrivate { + gint you; + GList *fields; + GList *icons; + GList *users; +}; + +/* Signals */ + +enum { + PLAYER_ADDED, + PLAYER_REMOVED, + NAME_CHANGED, + STATE_CHANGED, + RANK_CHANGED, + NUM_SIGNALS +}; + +static guint gm_mcp_vmoo_userlist_signals[NUM_SIGNALS] = {0}; + +G_DEFINE_TYPE(GmMcpVmooUserlist, gm_mcp_vmoo_userlist, GM_TYPE_MCP_PACKAGE) + +void gm_mcp_vmoo_userlist_handle_simple(GmMcpPackage *package, + gchar *suffix, GList *fields); +gboolean gm_mcp_vmoo_userlist_handle_multi(GmMcpPackage *package, + gchar const *data_tag, gchar const *key, gchar const *value, + GList *all_values); + +void gm_mcp_vmoo_userlist_create_view(GmMcpPackage *package, + GObject *parent); + +void +gm_mcp_vmoo_userlist_remove_users(GmMcpVmooUserlist *package) { + GList *users = g_list_copy(package->priv->users); + GList *field; + UserInfo *info; + + for (field = users; field; field = field->next) { + info = (UserInfo *)(field->data); + package->priv->users = g_list_remove(package->priv->users, field->data); + + g_free(info->name); + g_free(info); + } + + g_list_free(users); +} + +static void +gm_mcp_vmoo_userlist_finalize(GObject *object) { + GmMcpVmooUserlist *obj = GM_MCP_VMOO_USERLIST(object); + GList *field; + + for (field = obj->priv->fields; field; field = field->next) { + g_free(field->data); + } + + g_list_free(obj->priv->fields); + + for (field = obj->priv->icons; field; field = field->next) { + g_free(field->data); + } + + g_list_free(obj->priv->icons); + + gm_mcp_vmoo_userlist_remove_users(obj); + g_list_free(obj->priv->users); + + G_OBJECT_CLASS(gm_mcp_vmoo_userlist_parent_class)->finalize(object); +} + +static void +gm_mcp_vmoo_userlist_class_init(GmMcpVmooUserlistClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + GmMcpPackageClass *pklass = GM_MCP_PACKAGE_CLASS(klass); + + object_class->finalize = gm_mcp_vmoo_userlist_finalize; + + gm_mcp_vmoo_userlist_signals[PLAYER_ADDED] = + g_signal_new("player_added", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpVmooUserlistClass, player_added), + NULL, NULL, + gm_marshal_VOID__INT_STRING_STRING_STRING, + G_TYPE_NONE, + 4, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + gm_mcp_vmoo_userlist_signals[PLAYER_REMOVED] = + g_signal_new("player_removed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpVmooUserlistClass, player_removed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, + G_TYPE_INT); + gm_mcp_vmoo_userlist_signals[NAME_CHANGED] = + g_signal_new("name_changed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpVmooUserlistClass, name_changed), + NULL, NULL, + gm_marshal_VOID__INT_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING); + gm_mcp_vmoo_userlist_signals[STATE_CHANGED] = + g_signal_new("state_changed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpVmooUserlistClass, state_changed), + NULL, NULL, + gm_marshal_VOID__INT_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING); + + gm_mcp_vmoo_userlist_signals[RANK_CHANGED] = + g_signal_new("rank_changed", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GmMcpVmooUserlistClass, rank_changed), + NULL, NULL, + gm_marshal_VOID__INT_STRING_STRING, + G_TYPE_NONE, + 3, + G_TYPE_INT, + G_TYPE_STRING, + G_TYPE_STRING); + + pklass->name = "dns-com-vmoo-userlist"; + pklass->handle_simple = &gm_mcp_vmoo_userlist_handle_simple; + pklass->handle_multi = &gm_mcp_vmoo_userlist_handle_multi; + pklass->create_view = &gm_mcp_vmoo_userlist_create_view; + + g_type_class_add_private(object_class, sizeof(GmMcpVmooUserlistPrivate)); +} + +static void +gm_mcp_vmoo_userlist_init(GmMcpVmooUserlist *obj) { + obj->priv = GM_MCP_VMOO_USERLIST_GET_PRIVATE(obj); + + obj->priv->you = 0; + obj->priv->fields = NULL; + obj->priv->icons = NULL; + obj->priv->users = NULL; +} + +GmMcpVmooUserlist * +gm_mcp_vmoo_userlist_new() { + GmMcpVmooUserlist *obj = GM_MCP_VMOO_USERLIST(g_object_new( \ + GM_TYPE_MCP_VMOO_USERLIST, NULL)); + + return obj; +} + +void +gm_mcp_vmoo_userlist_handle_fields(GmMcpVmooUserlist *package, MOOVar *list) { + MOOVar *field; + + for (field = list->list; field; field = field->next) { + if (field->type == STRING) { + package->priv->fields = g_list_append(package->priv->fields, + g_strdup(field->s)); + } + } +} + +gchar const * +gm_mcp_vmoo_userlist_get_icon(GmMcpVmooUserlist *package, UserInfo *ui) { + gchar *field; + guint index = ui->icon; + GmKeyValuePair const *pair; + + if (index < 1 || index > g_list_length(package->priv->icons)) { + return NULL; + } else { + switch (ui->state) { + case U_NORMAL: + field = (gchar *)(g_list_nth_data(package->priv->icons, + index - 1)); + + pair = icon_mapping; + + while (!(pair->key == NULL && pair->value == NULL)) { + if (strcasecmp(pair->key, field) == 0) { + return pair->value; + } + + ++pair; + } + + break; + case U_IDLE: + return "userlist/idle.svg"; + break; + case U_AWAY: + return "userlist/away.svg"; + break; + case U_IDLEAWAY: + return "userlist/idleaway.svg"; + break; + default: + break; + } + } + + return NULL; +} + +void +gm_mcp_vmoo_userlist_handle_icons(GmMcpVmooUserlist *package, MOOVar *list) { + MOOVar *field; + + for (field = list->list; field; field = field->next) { + if (field->type == STRING) { + package->priv->icons = g_list_append(package->priv->icons, + g_strdup(field->s)); + } + } +} + +gchar * +gm_mcp_vmoo_userlist_get_string(GmMcpVmooUserlist *package, MOOVar *v, + MOOType type, gchar *cmp) { + GList *fields = package->priv->fields; + + while (fields && strcasecmp(((gchar *) (fields->data)), cmp) != 0) { + fields = fields->next; + + if (v) { + v = v->next; + } + } + + if (v && v->type == type) { + return g_strdup(v->s); + } + + return NULL; +} + +gint +gm_mcp_vmoo_userlist_get_int(GmMcpVmooUserlist *package, MOOVar *v, MOOType type, + gchar *cmp) { + GList *fields = package->priv->fields; + + while (fields && strcasecmp(((gchar *) (fields->data)), cmp) != 0) { + fields = fields->next; + + if (v) { + v = v->next; + } + } + + if (v && v->type == type) { + return v->i; + } + + return 0; +} + +UserInfo * +gm_mcp_vmoo_userlist_find_user(GmMcpVmooUserlist *package, gint nr) { + UserInfo *result; + GList *users; + + for (users = package->priv->users; users; users = users->next) { + result = (UserInfo *) (users->data); + + if (result->nr == nr) { + return result; + } + } + + return NULL; +} + +void +gm_mcp_vmoo_userlist_remove_user(GmMcpVmooUserlist *package, gint nr) { + GList *elem; + UserInfo *ui; + + for (elem = package->priv->users; elem; elem = elem->next) { + ui = (UserInfo *) (elem->data); + + if (ui->nr == nr) { + package->priv->users = g_list_remove(package->priv->users, ui); + break; + } + } + + g_signal_emit(package, gm_mcp_vmoo_userlist_signals[PLAYER_REMOVED], 0, + nr); +} + +gchar * +gm_mcp_vmoo_userlist_sort_string(GmMcpVmooUserlist *package, UserInfo *ui) { + guint sortid = 0; + + switch (ui->state) { + case U_NORMAL: + sortid = g_list_length(package->priv->icons) - ui->icon; + break; + case U_AWAY: + sortid = g_list_length(package->priv->icons) + 1; + break; + case U_IDLE: + sortid = g_list_length(package->priv->icons) + 2; + break; + case U_IDLEAWAY: + sortid = g_list_length(package->priv->icons) + 3; + break; + } + + return g_strdup_printf("%.2d%s", sortid, ui->name); +} + +void +gm_mcp_vmoo_userlist_handle_user_update(GmMcpVmooUserlist *package, MOOVar *v) { + gint nr = gm_mcp_vmoo_userlist_get_int(package, v, OBJECT, "object"); + gchar *name = gm_mcp_vmoo_userlist_get_string(package, v, STRING, "name"); + gint icon = gm_mcp_vmoo_userlist_get_int(package, v, INT, "icon"); + gchar *sort; + + UserInfo *ui; + + if ((ui = gm_mcp_vmoo_userlist_find_user(package, nr)) == NULL) { + // Add the user + ui = g_new(UserInfo, 1); + ui->name = name; + ui->state = U_NORMAL; + ui->icon = icon; + ui->nr = nr; + + // + package->priv->users = g_list_append(package->priv->users, ui); + sort = gm_mcp_vmoo_userlist_sort_string(package, ui); + g_signal_emit(package, gm_mcp_vmoo_userlist_signals[PLAYER_ADDED], 0, + nr, name, gm_mcp_vmoo_userlist_get_icon(package, ui), sort); + g_free(sort); + } else { + if (ui->name || strcmp(ui->name, name) != 0) { + g_free(ui->name); + ui->name = name; + + sort = gm_mcp_vmoo_userlist_sort_string(package, ui); + g_signal_emit(package, gm_mcp_vmoo_userlist_signals[NAME_CHANGED], + 0, nr, name, sort); + g_free(sort); + } else { + g_free(name); + } + if (ui->icon != (guint)icon) { + ui->icon = (guint)icon; + + sort = gm_mcp_vmoo_userlist_sort_string(package, ui); + g_signal_emit(package, gm_mcp_vmoo_userlist_signals[RANK_CHANGED], + 0, nr, gm_mcp_vmoo_userlist_get_icon(package, ui), sort); + g_free(sort); + } + } +} + +void +gm_mcp_vmoo_userlist_handle_set(GmMcpVmooUserlist *package, MOOVar *v) { + MOOVar *ui; + + if (v->type != LIST) { + return; + } + + gm_mcp_vmoo_userlist_remove_users(package); + + for (ui = v->list; ui; ui = ui->next) { + if (ui->type != LIST) { + return; + } + + gm_mcp_vmoo_userlist_handle_user_update(package, ui->list); + } +} + +void +gm_mcp_vmoo_userlist_handle_add(GmMcpVmooUserlist *package, MOOVar *v) { + if (v->type != LIST) { + return; + } + + gm_mcp_vmoo_userlist_handle_user_update(package, v->list); +} + +void +gm_mcp_vmoo_userlist_handle_remove(GmMcpVmooUserlist *package, MOOVar *v) { + MOOVar *nr; + + if (v->type != LIST) { + return; + } + + for (nr = v->list; nr; nr = nr->next) { + if (nr->type == OBJECT) { + gm_mcp_vmoo_userlist_remove_user(package, nr->i); + } + } +} + +void +gm_mcp_vmoo_userlist_handle_update(GmMcpVmooUserlist *package, MOOVar *v) { + if (v->type != LIST) { + return; + } + + gm_mcp_vmoo_userlist_handle_user_update(package, v->list); +} + +void +gm_mcp_vmoo_userlist_handle_state(GmMcpVmooUserlist *package, MOOVar *v, + UserState state, gboolean onOff) { + MOOVar *nr; + UserInfo *u; + gchar *sort; + + if (v->type != LIST) { + return; + } + + for (nr = v->list; nr; nr = nr->next) { + if (nr->type == OBJECT) { + if ((u = gm_mcp_vmoo_userlist_find_user(package, nr->i))) { + switch (state) { + case U_IDLE: + if (u->state == U_IDLEAWAY && !onOff) { + u->state = U_AWAY; + } else if (u->state == U_AWAY && onOff) { + u->state = U_IDLEAWAY; + } else if (onOff) { + u->state = U_IDLE; + } else if (u->state == U_IDLE) { + u->state = U_NORMAL; + } + break; + case U_AWAY: + if (u->state == U_IDLEAWAY && !onOff) { + u->state = U_IDLE; + } else if (u->state == U_IDLE && onOff) { + u->state = U_IDLEAWAY; + } else if (onOff) { + u->state = U_AWAY; + } else if (u->state == U_AWAY) { + u->state = U_NORMAL; + } + break; + default: + break; + } + + sort = gm_mcp_vmoo_userlist_sort_string(package, u); + + g_signal_emit(package, + gm_mcp_vmoo_userlist_signals[STATE_CHANGED], 0, + nr->i, gm_mcp_vmoo_userlist_get_icon(package, u), sort); + g_free(sort); + } else { + GM_DEBUG("User %d does not exist!", nr->i); + } + } else { + GM_DEBUG("Nr is not an object: %d", nr->type); + } + } +} + +void +gm_mcp_vmoo_userlist_handle_simple(GmMcpPackage *package, gchar *suffix, + GList *fields) { + MOOVar *you; + GmMcpVmooUserlist *userlist = GM_MCP_VMOO_USERLIST(package); + + if (suffix && strcmp(suffix, "you") == 0) { + you = MOOVar_parse(gm_mcp_find_value(fields, "nr")); + + if (you->type == OBJECT) { + userlist->priv->you = you->i; + MOOVar_free(you); + } else { + gm_debug_msg(DEBUG_MCP, "GmMcpVmooUserlist.HandleSimple: " + "you is not an object!"); + } + } +} + +gboolean +gm_mcp_vmoo_userlist_handle_multi(GmMcpPackage *package, + gchar const *data_tag, gchar const *key, gchar const *value, + GList *all_values) { + MOOVar *v = NULL; + GmMcpVmooUserlist *userlist = GM_MCP_VMOO_USERLIST(package); + + if (key) { + if (strcmp(key, "fields") == 0) { + v = MOOVar_parse(value); + + if (!v || v->type != LIST) { + gm_debug_msg(DEBUG_MCP, "GmMcpVmooUserlist.HandleMulti: " + "invalid value: %s", value); + } else { + gm_mcp_vmoo_userlist_handle_fields(userlist, v); + } + } else if (strcmp(key, "icons") == 0) { + v = MOOVar_parse(value); + + if (!v || v->type != LIST) { + gm_debug_msg(DEBUG_MCP, "GmMcpVmooUserlist.HandleMulti: " + "invalid value: %s", value); + } else { + gm_mcp_vmoo_userlist_handle_icons(userlist, v); + } + } else if (strcmp(key, "d") == 0) { + v = MOOVar_parse(value + 1); + + if (!v) { + gm_debug_msg(DEBUG_MCP, "GmMcpVmooUserlist.HandleMulti: " + "invalid value: %s", value + 1); + } else { + switch (*value) { + case '=': + gm_mcp_vmoo_userlist_handle_set(userlist, v); + break; + case '+': + gm_mcp_vmoo_userlist_handle_add(userlist, v); + break; + case '-': + gm_mcp_vmoo_userlist_handle_remove(userlist, v); + break; + case '*': + gm_mcp_vmoo_userlist_handle_update(userlist, v); + break; + case '<': + gm_mcp_vmoo_userlist_handle_state(userlist, v, U_IDLE, + TRUE); + break; + case '>': + gm_mcp_vmoo_userlist_handle_state(userlist, v, U_IDLE, + FALSE); + break; + case '[': + gm_mcp_vmoo_userlist_handle_state(userlist, v, U_AWAY, + TRUE); + break; + case ']': + gm_mcp_vmoo_userlist_handle_state(userlist, v, U_AWAY, + FALSE); + break; + case '(': + gm_mcp_vmoo_userlist_handle_remove(userlist, v); + break; + default: + break; + } + } + } + } + + if (v) { + MOOVar_free(v); + } + return TRUE; +} + +void +gm_mcp_vmoo_userlist_create_view(GmMcpPackage *package, GObject *parent) { + gm_mcp_userlist_view_new(package, parent); +} diff --git a/gnoemoe/mcp/gm-mcp-vmoo-userlist.h b/gnoemoe/mcp/gm-mcp-vmoo-userlist.h new file mode 100644 index 0000000..659ff9a --- /dev/null +++ b/gnoemoe/mcp/gm-mcp-vmoo-userlist.h @@ -0,0 +1,66 @@ +#ifndef __GM_MCP_VMOO_USERLIST_H__ +#define __GM_MCP_VMOO_USERLIST_H__ + +#include +#include +#include "gm-mcp-package.h" + +G_BEGIN_DECLS + +/* + * Type checking and casting macros + */ +#define GM_TYPE_MCP_VMOO_USERLIST (gm_mcp_vmoo_userlist_get_type()) +#define GM_MCP_VMOO_USERLIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GM_TYPE_MCP_VMOO_USERLIST, GmMcpVmooUserlist)) +#define GM_MCP_VMOO_USERLIST_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GM_TYPE_MCP_VMOO_USERLIST, GmMcpVmooUserlist const)) +#define GM_MCP_VMOO_USERLIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \ + GM_TYPE_MCP_VMOO_USERLIST, GmMcpVmooUserlistClass)) +#define GM_IS_MCP_VMOO_USERLIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), \ + GM_TYPE_MCP_VMOO_USERLIST)) +#define GM_IS_MCP_VMOO_USERLIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + GM_TYPE_MCP_VMOO_USERLIST)) +#define GM_MCP_VMOO_USERLIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \ + GM_TYPE_MCP_VMOO_USERLIST, GmMcpVmooUserlistClass)) + +/* Private structure type */ +typedef struct _GmMcpVmooUserlistPrivate GmMcpVmooUserlistPrivate; + +/* + * Main object structure + */ +typedef struct _GmMcpVmooUserlist GmMcpVmooUserlist; + +struct _GmMcpVmooUserlist { + GmMcpPackage parent; + + /*< private > */ + GmMcpVmooUserlistPrivate *priv; +}; + +/* + * Class definition + */ +typedef struct _GmMcpVmooUserlistClass GmMcpVmooUserlistClass; + +struct _GmMcpVmooUserlistClass { + GmMcpPackageClass parent_class; + + /* Signals */ + void (* player_added) (GmMcpVmooUserlist *obj, gint id, + gchar const *name, gchar const *icon, gchar const *sort); + void (* player_removed) (GmMcpVmooUserlist *obj, gint id); + void (* name_changed) (GmMcpVmooUserlist *obj, gint id, + gchar const *name, gchar const *sort); + void (* state_changed) (GmMcpVmooUserlist *obj, gint id, + gchar const *icon, gchar const *sort); + void (* rank_changed) (GmMcpVmooUserlist *obj, gint id, + gchar const *icon, gchar const *sort); +}; + +GType gm_mcp_vmoo_userlist_get_type(void) G_GNUC_CONST; +GmMcpVmooUserlist *gm_mcp_vmoo_userlist_new(void); + +G_END_DECLS +#endif /* __GM_MCP_VMOO_USERLIST_H__ */