Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/EionRobb/pidgin-opensteamworks.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreionrobb <eionrobb@8ca6c67d-4297-256d-f884-781da6d5760b>2010-09-21 13:48:57 +0400
committereionrobb <eionrobb@8ca6c67d-4297-256d-f884-781da6d5760b>2010-09-21 13:48:57 +0400
commit8e4ab2d3974d891dbba55166fce614581b0b987d (patch)
tree6246abea5228617bb97dbbbc099437d4aba7a222 /libsteamworks.cpp
parent2bb0be16b962afe3935b2f445e2fc6095211a85a (diff)
Added support for incoming messages, 'in-game' status messages, typing notifications
Diffstat (limited to 'libsteamworks.cpp')
-rwxr-xr-xlibsteamworks.cpp322
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);
}