diff options
author | eionrobb <eionrobb@8ca6c67d-4297-256d-f884-781da6d5760b> | 2010-09-21 13:48:57 +0400 |
---|---|---|
committer | eionrobb <eionrobb@8ca6c67d-4297-256d-f884-781da6d5760b> | 2010-09-21 13:48:57 +0400 |
commit | 8e4ab2d3974d891dbba55166fce614581b0b987d (patch) | |
tree | 6246abea5228617bb97dbbbc099437d4aba7a222 /libsteamworks.cpp | |
parent | 2bb0be16b962afe3935b2f445e2fc6095211a85a (diff) |
Added support for incoming messages, 'in-game' status messages, typing notifications
Diffstat (limited to 'libsteamworks.cpp')
-rwxr-xr-x | libsteamworks.cpp | 322 |
1 files changed, 268 insertions, 54 deletions
diff --git a/libsteamworks.cpp b/libsteamworks.cpp index 6dd303e..13b170a 100755 --- a/libsteamworks.cpp +++ b/libsteamworks.cpp @@ -1,40 +1,201 @@ #include "libsteamworks.h" +//#pragma comment(lib, "opensteamworks/steamclient")
+typedef bool (*Steam_BGetCallbackFn)( HSteamPipe hSteamPipe, CallbackMsg_t *pCallbackMsg );
+typedef void (*Steam_FreeLastCallbackFn)( HSteamPipe hSteamPipe );
+typedef int (*SteamEnumerateAppFn)( unsigned int uAppId, TSteamApp *pApp, TSteamError *pError );
+static Steam_BGetCallbackFn BGetCallback = NULL;
+static Steam_FreeLastCallbackFn FreeLastCallback = NULL; +static SteamEnumerateAppFn SteamEnumApp = NULL; + +#undef g_new0 +#define g_new0(struct_type, n_structs) \
+ ((struct_type *) g_malloc0 (((gsize) sizeof (struct_type)) * ((gsize) (n_structs)))) + typedef struct { + CSteamAPILoader *loader; + CreateInterfaceFn factory; + HSteamPipe pipe; HSteamUser user; + ISteamClient008 *client; ISteamFriends002 *friends; ISteamUtils002 *utils; + ISteamUser005 *suser; + + guint event_timer; } SteamInfo; -CSteamID +const CSteamID steamworks_name_to_sid(const gchar *name) { - purple_debug_info("steam", "name_to_sid %s\n", name); - guint64 accountkey; - CSteamID steamID; + //purple_debug_info("steam", "name_to_sid %s\n", name); + guint32 accountkey; + static CSteamID steamID; accountkey = g_ascii_strtoull(name, NULL, 10); + //purple_debug_info("steam", "accountkey %ld\n", accountkey); - steamID = CSteamID::CSteamID(accountkey); + steamID = CSteamID(accountkey, 1, EUniverse::k_EUniversePublic, EAccountType::k_EAccountTypeIndividual); + //purple_debug_info("steam", "steamID %d\n", steamID); return steamID; } -gchar * +const gchar * steamworks_sid_to_name(CSteamID steamID) { - purple_debug_info("steam", "sid_to_name\n"); - guint64 accountkey; - gchar *id; + //purple_debug_info("steam", "sid_to_name\n"); + guint32 accountkey; + static gchar *id = NULL; - accountkey = steamID.GetStaticAccountKey(); - id = g_strdup_printf("%" G_GUINT64_FORMAT, accountkey); + g_free(id); + accountkey = steamID.GetAccountID(); + id = g_strdup_printf("%" G_GUINT32_FORMAT, accountkey); return id; } +const gchar * +steamworks_personastate_to_statustype(const EPersonaState state) +{ + const char *status_id; + PurpleStatusPrimitive prim; + switch(state) + { + default: + case k_EPersonaStateOffline: + prim = PURPLE_STATUS_OFFLINE; + break; + case k_EPersonaStateOnline: + prim = PURPLE_STATUS_AVAILABLE; + break; + case k_EPersonaStateBusy: + prim = PURPLE_STATUS_UNAVAILABLE; + break; + case k_EPersonaStateAway: + prim = PURPLE_STATUS_AWAY; + break; + case k_EPersonaStateSnooze: + prim = PURPLE_STATUS_EXTENDED_AWAY; + break; + } + status_id = purple_primitive_get_id_from_type(prim); + return status_id; +} + +gboolean +steamworks_eventloop(gpointer userdata) +{ + PurpleConnection *pc = (PurpleConnection *) userdata; + SteamInfo *steam = (SteamInfo *) pc->proto_data; + CallbackMsg_t CallbackMsg; + + if (BGetCallback(steam->pipe, &CallbackMsg)) + { + purple_debug_info("steam", "Recieved event type %d\n", CallbackMsg.m_iCallback); + switch(CallbackMsg.m_iCallback) + { + case FriendChatMsg_t::k_iCallback: + { + purple_debug_info("steam", "received message event\n"); + //message or typing notification + FriendChatMsg_t *chatMsg = (FriendChatMsg_t *)CallbackMsg.m_pubParam; + + //Check that the message didn't come from ourselves + if (chatMsg->m_ulSender == steam->suser->GetSteamID()) + break; + + EChatEntryType msgType; + gchar *message = g_new0(gchar, 256); + + steam->friends->GetChatMessage(chatMsg->m_ulSender, chatMsg->m_iChatID, message, 256, &msgType); + if (msgType & k_EChatEntryTypeTyping) + { + serv_got_typing(pc, steamworks_sid_to_name(chatMsg->m_ulSender), 999, PURPLE_TYPING); + } else if (msgType & k_EChatEntryTypeChatMsg) { + serv_got_im(pc, steamworks_sid_to_name(chatMsg->m_ulSender), message, PURPLE_MESSAGE_RECV, time(NULL)); + } else if (msgType & k_EChatEntryTypeEmote) { + gchar *emote = g_strconcat("/me ", message, NULL); + serv_got_im(pc, steamworks_sid_to_name(chatMsg->m_ulSender), emote, PURPLE_MESSAGE_RECV, time(NULL)); + g_free(emote); + } else if (msgType & k_EChatEntryTypeInviteGame) { + purple_debug_warning("steam", "invite to game message\n"); + purple_debug_info("steam", "invite message '%s'\n", message); + } + g_free(message); + } break; + case PersonaStateChange_t::k_iCallback: + { + purple_debug_info("steam", "received statechange event\n"); + //state changed + PersonaStateChange_t *state = (PersonaStateChange_t *)CallbackMsg.m_pubParam; + if (state->m_nChangeFlags & k_EPersonaChangeName) + { + const gchar *alias = steam->friends->GetFriendPersonaName( state->m_ulSteamID ); + serv_got_alias(pc, steamworks_sid_to_name(state->m_ulSteamID), alias); + } + if (state->m_nChangeFlags & k_EPersonaChangeStatus) + { + EPersonaState pstate = steam->friends->GetFriendPersonaState(state->m_ulSteamID); + const gchar *status_id = steamworks_personastate_to_statustype(pstate); + purple_prpl_got_user_status(pc->account, steamworks_sid_to_name(state->m_ulSteamID), status_id, NULL); + } + purple_debug_info("steam", "user %d changed state %d\n", state->m_ulSteamID, state->m_nChangeFlags); + } break; + case UserRequestingFriendship_t::k_iCallback: + { + purple_debug_info("steam", "received friendrequest event\n"); + //requesting friendship + UserRequestingFriendship_t *request = (UserRequestingFriendship_t *)CallbackMsg.m_pubParam; + purple_debug_info("steam", "user %d requested auth\n", request->k_iCallback); + } break; + case FriendAdded_t::k_iCallback: + { + purple_debug_info("steam", "received friendadded event\n"); + //friend added to buddylist + FriendAdded_t *friendadd = (FriendAdded_t *)CallbackMsg.m_pubParam; + if(friendadd->m_eResult == k_EResultOK) + { + const gchar *username = steamworks_sid_to_name(friendadd->m_ulSteamID); + PurpleBuddy *buddy = purple_find_buddy(pc->account, username); + if (!buddy) + { + const gchar *alias = steam->friends->GetFriendPersonaName(friendadd->m_ulSteamID); + buddy = purple_buddy_new(pc->account, username, alias); + purple_blist_add_buddy(buddy, NULL, purple_find_group("Steam"), NULL); + } + EPersonaState state = steam->friends->GetFriendPersonaState(friendadd->m_ulSteamID); + purple_debug_info("steam", "Friend state %d ", state); + const gchar *status_id = steamworks_personastate_to_statustype(state); + purple_debug_info("steam", "status_id %s\n", status_id); + purple_prpl_got_user_status(pc->account, username, status_id, NULL); + } + } break; + case LobbyInvite_t::k_iCallback: + { + purple_debug_info("steam", "Game invite\n"); + //steam://joinlobby/630/109775240975659434/76561198011361273 + //steam://joinlobby/gameid/lobbyid/friendid + LobbyInvite_t *invite = (LobbyInvite_t *)CallbackMsg.m_pubParam; + CSteamID user = invite->m_ulSteamIDUser; + CSteamID lobby = invite->m_ulSteamIDLobby; + guint64 gameid; + steam->friends->GetFriendGamePlayed(user, &gameid, NULL, NULL, NULL); + gchar *message = g_strdup_printf("/me has invited you to <a href=\"steam://joinlobby/%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT "\">join their game</a>", + gameid, lobby, user); + } break; + default: + purple_debug_warning("steam", "unhandled event!\n"); + break; + } + FreeLastCallback(steam->pipe); + } + + return TRUE; +} + gchar * steamworks_status_text(PurpleBuddy *buddy) { @@ -43,16 +204,20 @@ steamworks_status_text(PurpleBuddy *buddy) SteamInfo *steam = (SteamInfo *)pc->proto_data; CSteamID steamID = steamworks_name_to_sid(buddy->name); + if (!steam || !steam->friends) + return NULL; + //Get game info to use for status message FriendGameInfo_t friendinfo; guint64 gameid; gchar *appname = NULL; if (steam->friends->GetFriendGamePlayed( steamID, &gameid, NULL, NULL, NULL )) { - TSteamApp app; + /*TSteamApp app; TSteamError error; - //SteamEnumerateApp(gameid, &app, &error); - //appname = g_strdup(app.szName); + SteamEnumApp(gameid, &app, &error); + appname = g_strdup(app.szName);*/ + appname = g_strdup_printf("In-game %" G_GUINT32_FORMAT "\n", gameid); } return appname; @@ -61,7 +226,7 @@ steamworks_status_text(PurpleBuddy *buddy) const gchar * steamworks_list_icon(PurpleAccount *account, PurpleBuddy *buddy) { - purple_debug_info("steam", "list_icon\n"); + //purple_debug_info("steam", "list_icon\n"); return "steam"; } @@ -97,10 +262,10 @@ steamworks_send_typing(PurpleConnection *pc, const char *who, PurpleTypingState if (state == PURPLE_TYPING) { steam->friends->SendMsgToFriend(steamID, k_EChatEntryTypeTyping, "", 0); - return 999; } + //purple_debug_info("steam", "sent typing\n"); - return 0; + return 999; } void @@ -137,6 +302,7 @@ steamworks_set_status(PurpleAccount *account, PurpleStatus *status) break; } + purple_debug_info("steam", "Setting status to %d\n", state); steam->friends->SetPersonaState(state); } @@ -156,21 +322,46 @@ steamworks_send_im(PurpleConnection *pc, const char *who, const char *message, P message[2] == 'e' && message[3] == ' ') { - success = steam->friends->SendMsgToFriend(steamID, k_EChatEntryTypeEmote, &stripped[4], strlen(stripped)-4); + purple_debug_info("steam", "sending emote...\n"); + success = steam->friends->SendMsgToFriend(steamID, k_EChatEntryTypeEmote, &stripped[4], strlen(stripped)-3); } else { - success = steam->friends->SendMsgToFriend(steamID, k_EChatEntryTypeChatMsg, stripped, strlen(stripped)); + purple_debug_info("steam", "sending message...\n"); + success = steam->friends->SendMsgToFriend(steamID, k_EChatEntryTypeChatMsg, stripped, strlen(stripped)+1); } + purple_debug_info("steam", "sent.\n"); g_free(stripped); return success; } + +void steamworks_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) +{ + SteamInfo *steam = (SteamInfo *)pc->proto_data; + + if (g_ascii_strtoull(buddy->name, NULL, 10)) + { + steam->friends->AddFriend(steamworks_name_to_sid(buddy->name)); + } else { + steam->friends->AddFriendByName(buddy->name); + purple_blist_remove_buddy(buddy); + } +} +void steamworks_remove_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) +{ + SteamInfo *steam = (SteamInfo *)pc->proto_data; + steam->friends->RemoveFriend(steamworks_name_to_sid(buddy->name)); +} + void steamworks_close(PurpleConnection *pc) { SteamInfo *steam = (SteamInfo *)pc->proto_data; purple_debug_info("steam", "close\n"); + + purple_timeout_remove(steam->event_timer); + if (!steam) return; @@ -181,7 +372,17 @@ steamworks_close(PurpleConnection *pc) // steam->client->ReleaseSteamPipe(steam->pipe); //} + steam->client = NULL; + steam->factory = NULL; + steam->friends = NULL; + steam->loader = NULL; + steam->pipe = NULL; + steam->suser = NULL; + steam->utils = NULL; + g_free(steam); + + pc->proto_data = NULL; } void @@ -197,9 +398,24 @@ steamworks_login(PurpleAccount *account) steam = g_new0(SteamInfo, 1); pc->proto_data = steam; - CSteamAPILoader loader; - CreateInterfaceFn factory = loader.Load(); - steam->client = (ISteamClient008 *)factory( STEAMCLIENT_INTERFACE_VERSION_008, NULL ); + steam->loader = new CSteamAPILoader(); + if (!steam->loader) + { + purple_connection_error(pc, "Could not load loader\n"); + return; + } + steam->factory = steam->loader->Load(); + if (!steam->factory) + { + purple_connection_error(pc, "Could not load factory\n"); + return; + } + + BGetCallback = (Steam_BGetCallbackFn)steam->loader->GetSteamClientModule()->GetSymbol("Steam_BGetCallback"); + FreeLastCallback = (Steam_FreeLastCallbackFn)steam->loader->GetSteamClientModule()->GetSymbol("Steam_FreeLastCallback"); + SteamEnumApp = (SteamEnumerateAppFn)steam->loader->GetSteamModule()->GetSymbol("SteamEnumerateApp"); + + steam->client = (ISteamClient008 *)steam->factory( STEAMCLIENT_INTERFACE_VERSION_008, NULL ); if (!steam->client) { purple_connection_error(pc, "Could not load client\n"); @@ -230,6 +446,18 @@ steamworks_login(PurpleAccount *account) purple_connection_error(pc, "Could not load utils\n"); return; } + purple_connection_set_state(pc, PURPLE_CONNECTED); + steamworks_set_status(account, purple_account_get_active_status(account)); + + purple_account_set_alias(account, steam->friends->GetPersonaName()); + + steam->suser = (ISteamUser005 *)steam->client->GetISteamUser(steam->user, steam->pipe, STEAMUSER_INTERFACE_VERSION_005); + if (steam->suser) + { + if (!steam->suser->LoggedOn()) + steam->suser->LogOn(steam->suser->GetSteamID()); + steam->suser->SetSelfAsPrimaryChatDestination(); + } PurpleGroup *group; group = purple_find_group("Steam"); @@ -244,7 +472,8 @@ steamworks_login(PurpleAccount *account) purple_debug_info("steam", "Friend number %d\n", i); CSteamID steamID = steam->friends->GetFriendByIndex(i, k_EFriendFlagImmediate); - gchar *id = steamworks_sid_to_name(steamID); + purple_debug_info("steam", "CSteam id %d\n", steamID); + const gchar *id = steamworks_sid_to_name(steamID); purple_debug_info("steam", "Friend id %s\n", id); const gchar *alias = steam->friends->GetFriendPersonaName( steamID ); purple_debug_info("steam", "Friend alias %s\n", alias); @@ -258,48 +487,33 @@ steamworks_login(PurpleAccount *account) } EPersonaState state = steam->friends->GetFriendPersonaState(steamID); - purple_debug_info("steam", "Friend state %d\n", state); - const char *status_id; - PurpleStatusPrimitive prim; - switch(state) - { - default: - case k_EPersonaStateOffline: - prim = PURPLE_STATUS_OFFLINE; - break; - case k_EPersonaStateOnline: - prim = PURPLE_STATUS_AVAILABLE; - break; - case k_EPersonaStateBusy: - prim = PURPLE_STATUS_UNAVAILABLE; - break; - case k_EPersonaStateAway: - prim = PURPLE_STATUS_AWAY; - break; - case k_EPersonaStateSnooze: - prim = PURPLE_STATUS_EXTENDED_AWAY; - break; - } - status_id = purple_primitive_get_id_from_type(prim); + purple_debug_info("steam", "Friend state %d ", state); + const gchar *status_id = steamworks_personastate_to_statustype(state); + purple_debug_info("steam", "status_id %s\n", status_id); purple_prpl_got_user_status(account, id, status_id, NULL); - - /* - //Need at least ISteamFriends003 for this to work - int avatar_handle = steam->friends->GetFriendAvatar(steamID, 1); + + //Need at least ISteamFriends004 for avatars to work + ISteamFriends004 *friends3 = (ISteamFriends004 *)steam->client->GetISteamFriends(steam->user, steam->pipe, STEAMFRIENDS_INTERFACE_VERSION_004); + int avatar_handle = friends3->GetFriendAvatar(steamID, 1); + purple_debug_info("steam", "avatar_handle %d\n", avatar_handle); uint32 avatar_width, avatar_height; if (steam->utils->GetImageSize(avatar_handle, &avatar_width, &avatar_height)) { int buffer_size = (4 * avatar_width * avatar_height); - guchar *image = g_new(guchar, buffer_size); + purple_debug_info("steam", "avatar_size %d x %d\n", avatar_width, avatar_height); + guchar *image = g_new0(guchar, buffer_size); if (steam->utils->GetImageRGBA(avatar_handle, image, buffer_size)) { //add image into pidgin + purple_debug_info("steam", "image rgba info!!!!!!\n"); purple_buddy_icons_set_for_user(account, id, image, buffer_size, NULL); } else { g_free(image); + purple_debug_info("steam", "no image rgba info :(\n"); } - }*/ - - g_free(id); + } } + + //Finally, start the event loop + steam->event_timer = purple_timeout_add_seconds(1, (GSourceFunc)steamworks_eventloop, pc); } |