From 156bee156485cab1effd5060f8c77c8909f4ee93 Mon Sep 17 00:00:00 2001 From: Nemirtingas Date: Fri, 2 Aug 2019 11:16:30 +0200 Subject: [PATCH] Invitation & Chat support (WIP) --- dll/steam_friends.h | 28 ++++--- overlay_experimental/steam_overlay.cpp | 100 +++++++++++++++++-------- overlay_experimental/steam_overlay.h | 39 +++++++++- 3 files changed, 120 insertions(+), 47 deletions(-) diff --git a/dll/steam_friends.h b/dll/steam_friends.h index dda67f1..b456aec 100644 --- a/dll/steam_friends.h +++ b/dll/steam_friends.h @@ -117,8 +117,6 @@ Steam_Friends(Settings* settings, Networking* network, SteamCallResults* callbac this->network->setCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &Steam_Friends::steam_friends_callback, this); this->run_every_runcb->add(&Steam_Friends::steam_friends_run_every_runcb, this); modified = false; - - overlay->SetupFriends(&friends); } ~Steam_Friends() @@ -990,6 +988,7 @@ void Callback(Common_Message *msg) auto f = std::find_if(friends.begin(), friends.end(), [&id](Friend const& item) { return item.id() == id; }); if (friends.end() != f) { persona_change((uint64)f->id(), k_EPersonaChangeStatus); + overlay->FriendDisconnect(*f); friends.erase(f); } } @@ -1015,6 +1014,7 @@ void Callback(Common_Message *msg) if (!f) { if (msg->friend_().id() != settings->get_local_steam_id().ConvertToUint64()) { friends.push_back(msg->friend_()); + overlay->FriendConnect(msg->friend_()); persona_change((uint64)msg->friend_().id(), k_EPersonaChangeName); } } else { @@ -1036,20 +1036,26 @@ void Callback(Common_Message *msg) if (msg->friend_messages().type() == Friend_Messages::LOBBY_INVITE) { PRINT_DEBUG("Steam_Friends Got Lobby Invite\n"); //TODO: the user should accept the invite first but we auto accept it because there's no gui yet - GameLobbyJoinRequested_t data; - data.m_steamIDLobby = CSteamID((uint64)msg->friend_messages().lobby_id()); - data.m_steamIDFriend = CSteamID((uint64)msg->source_id()); - callbacks->addCBResult(data.k_iCallback, &data, sizeof(data)); + // Then we will handle it ! + overlay->AddLobbyInvite(msg->source_id(), msg->friend_messages().lobby_id()); + + //GameLobbyJoinRequested_t data; + //data.m_steamIDLobby = CSteamID((uint64)msg->friend_messages().lobby_id()); + //data.m_steamIDFriend = CSteamID((uint64)msg->source_id()); + //callbacks->addCBResult(data.k_iCallback, &data, sizeof(data)); } if (msg->friend_messages().type() == Friend_Messages::GAME_INVITE) { PRINT_DEBUG("Steam_Friends Got Game Invite\n"); //TODO: I'm pretty sure that the user should accept the invite before this is posted but we do like above - std::string const& connect_str = msg->friend_messages().connect_str(); - GameRichPresenceJoinRequested_t data = {}; - data.m_steamIDFriend = CSteamID((uint64)msg->source_id()); - strncpy(data.m_rgchConnect, connect_str.c_str(), k_cchMaxRichPresenceValueLength - 1); - callbacks->addCBResult(data.k_iCallback, &data, sizeof(data)); + // Then we will handle it ! + overlay->AddRichInvite(msg->source_id(), msg->friend_messages().connect_str().c_str()); + + //std::string const& connect_str = msg->friend_messages().connect_str(); + //GameRichPresenceJoinRequested_t data = {}; + //data.m_steamIDFriend = CSteamID((uint64)msg->source_id()); + //strncpy(data.m_rgchConnect, connect_str.c_str(), k_cchMaxRichPresenceValueLength - 1); + //callbacks->addCBResult(data.k_iCallback, &data, sizeof(data)); } } } diff --git a/overlay_experimental/steam_overlay.cpp b/overlay_experimental/steam_overlay.cpp index 3dd5d75..aff7657 100644 --- a/overlay_experimental/steam_overlay.cpp +++ b/overlay_experimental/steam_overlay.cpp @@ -173,21 +173,16 @@ void Steam_Overlay::HookReady(void* hWnd) // https://github.com/spazzarama/Direct3DHook/blob/master/Capture/Hook // https://github.com/unknownv2/LinuxDetours -void Steam_Overlay::SetupFriends(const std::vector* friends) -{ - this->friends = friends; -} - void Steam_Overlay::OpenOverlayInvite(CSteamID lobbyId) { //this->lobbyId = lobbyId; - show_overlay = true; + ShowOverlay(true); } void Steam_Overlay::OpenOverlay(const char* pchDialog) { // TODO: Show pages depending on pchDialog - show_overlay = true; + ShowOverlay(true); } void Steam_Overlay::ShowOverlay(bool state) @@ -236,6 +231,38 @@ void Steam_Overlay::ShowOverlay(bool state) overlay_state_changed = true; } +void Steam_Overlay::AddLobbyInvite(uint64 friendId, uint64 lobbyId) +{ + invitation invite; + invite.type = invitation_type_lobby; + invite.friendId = friendId; + invite.lobbyId = lobbyId; + invitations.push_back(invite); +} + +void Steam_Overlay::AddRichInvite(uint64 friendId, const char* connect_str) +{ + invitation invite; + invite.type = invitation_type_rich; + invite.friendId = friendId; + strncpy(invite.connect, connect_str, k_cchMaxRichPresenceValueLength - 1); + invitations.push_back(invite); +} + +void Steam_Overlay::FriendConnect(Friend _friend) +{ + std::lock_guard lock(global_mutex); + friends[_friend] = false; +} + +void Steam_Overlay::FriendDisconnect(Friend _friend) +{ + std::lock_guard lock(global_mutex); + auto it = friends.find(_friend); + if (it != friends.end()) + friends.erase(it); +} + void Steam_Overlay::OverlayProc( int width, int height ) { if (!show_overlay) @@ -243,15 +270,15 @@ void Steam_Overlay::OverlayProc( int width, int height ) std::lock_guard lock(global_mutex); - int friend_size = friends->size(); + int friend_size = friends.size(); // Set the overlay windows to the size of the game window ImGui::SetNextWindowPos({ 0,0 }); ImGui::SetNextWindowSize({ static_cast(width), static_cast(height) }); - bool close = false; - if (ImGui::Begin("SteamOverlay", &close, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse)) + bool open_overlay = show_overlay; + if (ImGui::Begin("SteamOverlay", &open_overlay, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus)) { ImGui::LabelText("", "Username: %s(%llu) playing %u", settings->get_local_name(), @@ -261,33 +288,40 @@ void Steam_Overlay::OverlayProc( int width, int height ) ImGui::Spacing(); ImGui::ListBoxHeader("Friends", friend_size); - if (friend_size) + std::for_each(friends.begin(), friends.end(), [this]( auto& i) { - for (int i = 0; i < friend_size; ++i) + ImGui::PushID(i.first.id()); + ImGui::Selectable(i.first.name().c_str(), false, ImGuiSelectableFlags_AllowDoubleClick); + if (ImGui::BeginPopupContextItem("Friends", 1)) { - ImGui::PushID(i); - ImGui::Selectable(friends->at(i).name().c_str(), false, ImGuiSelectableFlags_AllowDoubleClick); - if (ImGui::BeginPopupContextItem("Friends", 1)) + if (ImGui::Button("Invite")) { - if (ImGui::Button("Invite")) - { - friend_action |= friend_action_invite; - friend_to_action = friends->at(i).id(); - } - if (ImGui::Button("Join")) - { - friend_action |= friend_action_join; - friend_to_action = friends->at(i).id(); - } - ImGui::EndPopup(); + this->friend_action |= friend_action_invite; + this->friend_to_action = i.first.id(); } - else if (ImGui::IsMouseDoubleClicked(0)) + if (ImGui::Button("Join")) { - // Here handle the chat with the user friends->at(i).id() + this->friend_action |= friend_action_join; + this->friend_to_action = i.first.id(); } - ImGui::PopID(); + ImGui::EndPopup(); } - } + //else if (ImGui::IsMouseDoubleClicked(0)) + else if (ImGui::IsItemClicked() && ImGui::IsMouseDoubleClicked(0)) + { + i.second = true; + } + ImGui::PopID(); + + if (i.second) + { + if (ImGui::Begin(i.first.name().c_str(), &i.second)) + { + // Fill this with the chat box and maybe the invitation + } + ImGui::End(); + } + }); ImGui::ListBoxFooter(); //RECT rect; @@ -295,10 +329,10 @@ void Steam_Overlay::OverlayProc( int width, int height ) //auto pos = ImGui::GetMousePos(); //ImGui::LabelText("", "Window pos: %dx%d %dx%d", rect.left, rect.top, rect.right, rect.bottom); //ImGui::LabelText("", "Mouse pos: %dx%d", (int)pos.x, (int)pos.y); - - - ImGui::End(); } + ImGui::End(); + + ShowOverlay(open_overlay); //ImGui::ShowDemoWindow(); } diff --git a/overlay_experimental/steam_overlay.h b/overlay_experimental/steam_overlay.h index 2c61dd4..ac0d725 100644 --- a/overlay_experimental/steam_overlay.h +++ b/overlay_experimental/steam_overlay.h @@ -3,6 +3,7 @@ #include "../dll/base.h" #include "Hook_Manager.h" +#include #include enum friend_action @@ -12,6 +13,31 @@ enum friend_action friend_action_join = 1<<1 }; +enum invitation_type +{ + invitation_type_lobby, + invitation_type_rich +}; + +struct invitation +{ + uint8 type; + uint64 friendId; + union + { + uint64 lobbyId; + char connect[k_cchMaxRichPresenceValueLength]; + }; +}; + +struct Friend_Less +{ + bool operator()(const Friend& lhs, const Friend& rhs) const + { + return lhs.id() < rhs.id(); + } +}; + class Steam_Overlay { Settings* settings; @@ -20,7 +46,8 @@ class Steam_Overlay RunEveryRunCB* run_every_runcb; Networking* network; - const std::vector* friends; + // friend id, show client window (to chat and accept invite maybe) + std::map friends; HWND game_hwnd; WNDPROC game_hwnd_proc; @@ -30,6 +57,8 @@ class Steam_Overlay ENotificationPosition notif_position; int h_inset, v_inset; + std::vector invitations; + // Callback infos uint64 friend_to_action; int friend_action; @@ -70,12 +99,16 @@ public: void OverlayProc(int width, int height); - void SetupFriends(const std::vector* friends); - void OpenOverlayInvite(CSteamID lobbyId); void OpenOverlay(const char* pchDialog); void ShowOverlay(bool state); + + void AddLobbyInvite(uint64 friendId, uint64 lobbyId); + void AddRichInvite(uint64 friendId, const char* connect_str); + + void FriendConnect(Friend _friend); + void FriendDisconnect(Friend _friend); }; #endif//__INCLUDED_STEAM_OVERLAY_H__