lg->return_value = return_value;
- if (! lm_connection_close (lg->connection, &error))
- g_print ("An error occurred during lm_connection_close: %s\n",
- error->message);
-
- lm_connection_unref (lg->connection);
+ if (lg->connection)
+ {
+ if (! lm_connection_close (lg->connection, &error))
+ {
+ g_print ("An error occurred during lm_connection_close: %s\n",
+ error->message);
+ }
+ lm_connection_unref (lg->connection);
+ lg->connection = NULL;
+ }
g_main_loop_quit (lg->main_loop);
}
connection_open_cb (LmConnection *connection, gboolean result, loudgame_t *lg)
{
lm_connection_authenticate (connection,
- lg->name, lg->passwd, "TestLM",
+ lg->name, lg->passwd, "loudgame",
authentication_cb, lg, FALSE, NULL);
}
-static void
-send_reply (LmConnection *connection,
- const char *peer,
- const char *message,
- loudgame_t *lg)
+void
+loudgame_send (loudgame_t *lg,
+ const char *peer,
+ const char *message)
{
LmMessage *reply;
gboolean result;
lm_message_node_add_child (reply->node, "body", message);
- result = lm_connection_send (connection, reply, &error);
+ result = lm_connection_send (lg->connection, reply, &error);
lm_message_unref (reply);
if (! result) {
- g_error ("lm_connection_send failed: error->message");
+ g_error ("lm_connection_send failed: %s\n",
+ error->message);
loudgame_quit (lg, 1);
}
}
-static void
-handle_command (LmConnection *connection,
+void
+loudgame_vsendf (loudgame_t *lg,
+ const char *peer,
+ const char *format,
+ va_list va)
+{
+ char *str;
+
+ str = g_strdup_vprintf (format, va);
+
+ loudgame_send (lg, peer, str);
+
+ free (str);
+}
+
+void
+loudgame_sendf (loudgame_t *lg,
const char *peer,
- const char *command,
- loudgame_t *lg)
+ const char *format,
+ ...)
+{
+ va_list va;
+
+ va_start (va, format);
+
+ loudgame_vsendf (lg, peer, format, va);
+
+ va_end (va);
+}
+
+typedef struct _loudgame_broadcast_data
+{
+ loudgame_t *lg;
+ const char *message;
+} loudgame_broadcast_data_t;
+
+static void
+loudgame_broadcast_cb (void *key,
+ void *data,
+ void *closure)
{
- char *error;
+ loudgame_broadcast_data_t *lbd = closure;
+ char *peer = key;
+
+ loudgame_send (lbd->lg, peer, lbd->message);
+}
+
+void
+loudgame_broadcast (loudgame_t *lg,
+ const char *message)
+{
+ loudgame_broadcast_data_t lbd;
+
+ lbd.lg = lg;
+ lbd.message = message;
+
+ g_hash_table_foreach (lg->players,
+ loudgame_broadcast_cb, &lbd);
+}
+
+void
+loudgame_vbroadcastf (loudgame_t *lg,
+ const char *format,
+ va_list va)
+{
+ char *str;
+
+ str = g_strdup_vprintf (format, va);
+
+ loudgame_broadcast (lg, str);
+ free (str);
+}
+
+void
+loudgame_broadcastf (loudgame_t *lg,
+ const char *format,
+ ...)
+{
+ va_list va;
+
+ va_start (va,format);
+
+ loudgame_vbroadcastf (lg, format, va);
+
+ va_end (va);
+}
+
+static void
+handle_command (loudgame_t *lg,
+ const char *peer,
+ const char *command)
+{
if (strcmp (command, "quit") == 0) {
loudgame_quit (lg, 0);
return;
}
- error = g_strdup_printf ("Unknown command: '%s'", command);
- send_reply (connection, peer, error, lg);
- free (error);
+ loudgame_sendf (lg, "Unknown command: '%s'", command);
+}
+
+static void
+handle_say (loudgame_t *lg,
+ const char *peer,
+ const char *message)
+{
+ loudgame_broadcastf (lg, "%s: %s", peer, message);
+}
+
+static void
+handle_whisper (loudgame_t *lg,
+ const char *peer,
+ const char *body)
+{
+ const char *recipient, *space, *message;
+
+ space = strchr (body, ' ');
+ if (space == NULL) {
+ loudgame_sendf (lg, peer,
+ "Error: whisper should be of the form 'user message'");
+ return;
+ }
+
+ recipient = g_strndup (body, space - body);
+
+ message = space + 1;
+
+ loudgame_sendf (lg, recipient, "*%s*: %s", peer, message);
}
static LmHandlerResult
peer = lm_message_node_get_attribute (m->node, "from");
body = lm_message_node_get_child (m->node, "body");
- if (body) {
- body_str = lm_message_node_get_value (body);
+ if (! body)
+ return LM_HANDLER_RESULT_REMOVE_MESSAGE;
+
+ if (! g_hash_table_lookup_extended (lg->players, peer,
+ NULL, NULL))
+ {
+ char *peer_copy = g_strdup (peer);
+ g_hash_table_insert (lg->players, peer_copy, NULL);
+ loudgame_broadcastf (lg, "%s has joined the game", peer);
+ }
+
+ body_str = lm_message_node_get_value (body);
- if (body_str && body_str[0] == '%')
- handle_command (connection, peer, body_str + 1, lg);
+ if (body_str) {
+ if (body_str[0] == '%')
+ handle_command (lg, peer, body_str + 1);
+ else if (strncmp (body_str, "say ", 4) == 0)
+ handle_say (lg, peer, body_str + 4);
+ else if (strncmp (body_str, "whisper ", 8) == 0)
+ handle_whisper (lg, peer, body_str + 8);
else if (lg->handle_message)
- (lg->handle_message) (lg, peer, body_str);
+ (lg->handle_message) (lg, peer, body_str);
}
return LM_HANDLER_RESULT_REMOVE_MESSAGE;
loudgame_quit (lg, 1);
}
+ /* It seems to be necessary to explicitly tell the server we're
+ * still here. Let's see if one keep-alive every 60 seconds is
+ * sufficient. */
+ lm_connection_set_keep_alive_rate (lg->connection, 60);
+
/* Return false to not schedule another call. */
return 0;
}
lg->connection = NULL;
lg->main_loop = g_main_loop_new (NULL, FALSE);
+ lg->players = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, /* key_destroy */
+ NULL /*value_destroy */);
lg->return_value = 0;
return 0;
}
+static void
+loudgame_fini (loudgame_t *lg)
+{
+ g_main_loop_unref (lg->main_loop);
+ g_hash_table_destroy (lg->players);
+}
+
int
loudgame_run (loudgame_t *lg)
{
g_main_loop_run (lg->main_loop);
- g_main_loop_unref (lg->main_loop);
+ loudgame_fini (lg);
return lg->return_value;
}