X-Git-Url: https://git.cworth.org/git?p=loudgame;a=blobdiff_plain;f=loudgame.c;h=7c9114e4fffd7783763e9c1af8f3aee0d54832e3;hp=e2f0af2d5b751968725dfdd427b2e08b93e8f059;hb=88c5b7fb802cd1eab050dc67289d86dcb37dec6c;hpb=1b9383bc1758fa4b49ab029c730b7ba434b0f7ad diff --git a/loudgame.c b/loudgame.c index e2f0af2..7c9114e 100644 --- a/loudgame.c +++ b/loudgame.c @@ -33,11 +33,16 @@ loudgame_quit (loudgame_t *lg, int return_value) 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); } @@ -66,7 +71,7 @@ static void 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); } @@ -93,22 +98,134 @@ loudgame_send (loudgame_t *lg, } } -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) +{ + 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, + ...) { - char *error; + 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); - loudgame_send (lg, peer, error); - 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 @@ -125,13 +242,28 @@ handle_messages (LmMessageHandler *handler, 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; @@ -170,6 +302,11 @@ make_connection (gpointer closure) 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; } @@ -189,6 +326,9 @@ loudgame_init (loudgame_t *lg, int argc, char **argv) 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; @@ -197,6 +337,13 @@ loudgame_init (loudgame_t *lg, int argc, char **argv) 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) { @@ -204,7 +351,7 @@ 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; }