[Steam] Add native callback interface

This commit is contained in:
momo5502 2017-01-25 22:38:38 +01:00
parent e70a289b97
commit c8a41139cf
6 changed files with 282 additions and 7 deletions

View File

@ -30,4 +30,79 @@ namespace Steam
virtual void ActivateGameOverlayToStore(unsigned int nAppID);
virtual void SetPlayedWith(SteamID steamIDUserPlayedWith);
};
class Friends15
{
public:
virtual const char *GetPersonaName() = 0;
virtual uint64_t SetPersonaName(const char *pchPersonaName) = 0;
virtual int GetPersonaState() = 0;
virtual int GetFriendCount(int iFriendFlags) = 0;
virtual SteamID GetFriendByIndex(int iFriend, int iFriendFlags) = 0;
virtual int GetFriendRelationship(SteamID steamIDFriend) = 0;
virtual int GetFriendPersonaState(SteamID steamIDFriend) = 0;
virtual const char *GetFriendPersonaName(SteamID steamIDFriend) = 0;
virtual bool GetFriendGamePlayed(SteamID steamID, void *pGamePlayInfo) = 0;
virtual const char *GetFriendPersonaNameHistory(SteamID steamIDFriend, int iPersonaName) = 0;
virtual int GetFriendSteamLevel(SteamID steamIDFriend) = 0;
virtual const char *GetPlayerNickname(SteamID steamIDPlayer) = 0;
virtual int16_t GetFriendsGroupCount() = 0;
virtual int16_t GetFriendsGroupIDByIndex(int32_t) = 0;
virtual const char * GetFriendsGroupName(int16_t) = 0;
virtual int GetFriendsGroupMembersCount(int16_t) = 0;
virtual int GetFriendsGroupMembersList(int16_t, SteamID *, int32_t) = 0;
virtual bool HasFriend(SteamID steamIDFriend, int iFriendFlags) = 0;
virtual int GetClanCount() = 0;
virtual SteamID GetClanByIndex(int iClan) = 0;
virtual const char *GetClanName(SteamID steamIDClan) = 0;
virtual const char *GetClanTag(SteamID steamIDClan) = 0;
virtual bool GetClanActivityCounts(SteamID steamID, int *pnOnline, int *pnInGame, int *pnChatting) = 0;
virtual uint64_t DownloadClanActivityCounts(SteamID groupIDs[], int nIds) = 0;
virtual int GetFriendCountFromSource(SteamID steamIDSource) = 0;
virtual SteamID GetFriendFromSourceByIndex(SteamID steamIDSource, int iFriend) = 0;
virtual bool IsUserInSource(SteamID steamIDUser, SteamID steamIDSource) = 0;
virtual void SetInGameVoiceSpeaking(SteamID steamIDUser, bool bSpeaking) = 0;
virtual void ActivateGameOverlay(const char *pchDialog) = 0;
virtual void ActivateGameOverlayToUser(const char *pchDialog, SteamID steamID) = 0;
virtual void ActivateGameOverlayToWebPage(const char *pchURL) = 0;
virtual void ActivateGameOverlayToStore(uint32_t nAppID, int eFlag) = 0;
virtual void SetPlayedWith(SteamID steamIDUserPlayedWith) = 0;
virtual void ActivateGameOverlayInviteDialog(SteamID steamIDLobby) = 0;
virtual int GetSmallFriendAvatar(SteamID steamIDFriend) = 0;
virtual int GetMediumFriendAvatar(SteamID steamIDFriend) = 0;
virtual int GetLargeFriendAvatar(SteamID steamIDFriend) = 0;
virtual bool RequestUserInformation(SteamID steamIDUser, bool bRequireNameOnly) = 0;
virtual uint64_t RequestClanOfficerList(SteamID steamIDClan) = 0;
virtual SteamID GetClanOwner(SteamID steamIDClan) = 0;
virtual int GetClanOfficerCount(SteamID steamIDClan) = 0;
virtual SteamID GetClanOfficerByIndex(SteamID steamIDClan, int iOfficer) = 0;
virtual int GetUserRestrictions() = 0;
virtual bool SetRichPresence(const char *pchKey, const char *pchValue) = 0;
virtual void ClearRichPresence() = 0;
virtual const char *GetFriendRichPresence(SteamID steamIDFriend, const char *pchKey) = 0;
virtual int GetFriendRichPresenceKeyCount(SteamID steamIDFriend) = 0;
virtual const char *GetFriendRichPresenceKeyByIndex(SteamID steamIDFriend, int iKey) = 0;
virtual void RequestFriendRichPresence(SteamID steamIDFriend) = 0;
virtual bool InviteUserToGame(SteamID steamIDFriend, const char *pchConnectString) = 0;
virtual int GetCoplayFriendCount() = 0;
virtual SteamID GetCoplayFriend(int iCoplayFriend) = 0;
virtual int GetFriendCoplayTime(SteamID steamIDFriend) = 0;
virtual uint32_t GetFriendCoplayGame(SteamID steamIDFriend) = 0;
virtual uint64_t JoinClanChatRoom(SteamID steamIDClan) = 0;
virtual bool LeaveClanChatRoom(SteamID steamIDClan) = 0;
virtual int GetClanChatMemberCount(SteamID steamIDClan) = 0;
virtual SteamID GetChatMemberByIndex(SteamID steamIDClan, int iUser) = 0;
virtual bool SendClanChatMessage(SteamID steamIDClanChat, const char *pchText) = 0;
virtual int GetClanChatMessage(SteamID steamIDClanChat, int iMessage, void *prgchText, int cchTextMax, int *peChatEntryType, SteamID *pSteamIDChatter) = 0;
virtual bool IsClanChatAdmin(SteamID steamIDClanChat, SteamID steamIDUser) = 0;
virtual bool IsClanChatWindowOpenInSteam(SteamID steamIDClanChat) = 0;
virtual bool OpenClanChatWindowInSteam(SteamID steamIDClanChat) = 0;
virtual bool CloseClanChatWindowInSteam(SteamID steamIDClanChat) = 0;
virtual bool SetListenForFriendsMessages(bool bInterceptEnabled) = 0;
virtual bool ReplyToFriendMessage(SteamID steamIDFriend, const char *pchMsgToSend) = 0;
virtual int GetFriendMessage(SteamID steamIDFriend, int iMessageID, void *pvData, int cubData, int *peChatEntryType) = 0;
virtual uint64_t GetFollowerCount(SteamID steamID) = 0;
virtual uint64_t IsFollowing(SteamID steamID) = 0;
virtual uint64_t EnumerateFollowingList(uint32_t unStartIndex) = 0;
};
}

View File

@ -12,11 +12,19 @@ namespace Steam
void* Proxy::SteamPipe;
void* Proxy::SteamUser;
Friends* Proxy::SteamFriends;
Friends15* Proxy::SteamFriends;
Utils* Proxy::SteamUtils;
uint32_t Proxy::AppId;
std::recursive_mutex Proxy::CallMutex;
std::vector<Proxy::CallContainer> Proxy::Calls;
std::unordered_map<int32_t, void*> Proxy::Callbacks;
std::function<Proxy::SteamBGetCallbackFn> Proxy::SteamBGetCallback;
std::function<Proxy::SteamFreeLastCallbackFn> Proxy::SteamFreeLastCallback;
std::function<Proxy::SteamGetAPICallResultFn> Proxy::SteamGetAPICallResult;
void Proxy::SetGame(uint32_t appId)
{
Proxy::AppId = appId;
@ -73,6 +81,125 @@ namespace Steam
}
}
void Proxy::RegisterCall(int32_t callId, uint32_t size, uint64_t call)
{
std::lock_guard<std::recursive_mutex> _(Proxy::CallMutex);
Proxy::CallContainer contianer;
contianer.call = call;
contianer.dataSize = size;
contianer.callId = callId;
contianer.handled = false;
Proxy::Calls.push_back(contianer);
}
void Proxy::UnregisterCalls()
{
std::lock_guard<std::recursive_mutex> _(Proxy::CallMutex);
for(auto i = Proxy::Calls.begin(); i != Proxy::Calls.end(); ++i)
{
if(i->handled)
{
i = Proxy::Calls.erase(i);
}
else
{
++i;
}
}
}
void Proxy::RegisterCallback(int32_t callId, void* callback)
{
std::lock_guard<std::recursive_mutex> _(Proxy::CallMutex);
Proxy::Callbacks[callId] = callback;
}
void Proxy::UnregisterCallback(int32_t callId)
{
std::lock_guard<std::recursive_mutex> _(Proxy::CallMutex);
Proxy::Callbacks.erase(callId);
}
void Proxy::RunCallback(int32_t callId, void* data)
{
std::lock_guard<std::recursive_mutex> _(Proxy::CallMutex);
auto callback = Proxy::Callbacks.find(callId);
if (callback != Proxy::Callbacks.end())
{
::Utils::Hook::Call<void(void*)>(callback->second)(data);
}
}
void Proxy::RunFrame()
{
std::lock_guard<std::recursive_mutex> _(Proxy::CallMutex);
if (Proxy::SteamUtils)
{
Proxy::SteamUtils->RunFrame();
}
Proxy::CallbackMsg message;
while (Proxy::SteamBGetCallback(Proxy::SteamPipe, &message))
{
#ifdef DEBUG
Components::Logger::Print("Steam::Proxy: Callback dispatched: %d\n", message.m_iCallback);
#endif
Steam::Callbacks::RunCallback(message.m_iCallback, message.m_pubParam);
Proxy::RunCallback(message.m_iCallback, message.m_pubParam);
Proxy::SteamFreeLastCallback(Proxy::SteamPipe);
}
if (Proxy::SteamUtils)
{
for (auto &call : Proxy::Calls)
{
bool failed = false;
if (Proxy::SteamUtils->IsAPICallCompleted(call.call, &failed))
{
::Utils::Memory::Allocator allocator;
#ifdef DEBUG
Components::Logger::Print("Steam::Proxy: Handling call: %d\n", call.callId);
#endif
call.handled = true;
if (failed)
{
#ifdef DEBUG
auto error = Proxy::SteamUtils->GetAPICallFailureReason(call.call);
Components::Logger::Print("Steam::Proxy: API call failed: %X Handle: %llX\n", error, call.call);
#endif
continue;
}
char* buffer = allocator.allocateArray<char>(call.dataSize);
Proxy::SteamUtils->GetAPICallResult(call.call, buffer, call.dataSize, call.callId, &failed);
if (failed)
{
#ifdef DEBUG
auto error = Proxy::SteamUtils->GetAPICallFailureReason(call.call);
Components::Logger::Print("Steam::Proxy: GetAPICallResult failed: %X Handle: %llX\n", error, call.call);
#endif
continue;
}
Proxy::RunCallback(call.callId, buffer);
}
}
}
Proxy::UnregisterCalls();
}
bool Proxy::Inititalize()
{
std::string directoy = Proxy::GetSteamDirectory();
@ -87,6 +214,18 @@ namespace Steam
Proxy::SteamClient = Proxy::Client.get<ISteamClient008*(const char*, int*)>("CreateInterface")("SteamClient008", nullptr);
if(!Proxy::SteamClient) return false;
Proxy::SteamBGetCallback = Proxy::Client.get<Proxy::SteamBGetCallbackFn>("Steam_BGetCallback");
if (!Proxy::SteamBGetCallback) return false;
Proxy::SteamFreeLastCallback = Proxy::Client.get<Proxy::SteamFreeLastCallbackFn>("Steam_FreeLastCallback");
if (!Proxy::SteamFreeLastCallback) return false;
Proxy::SteamGetAPICallResult = Proxy::Client.get<Proxy::SteamGetAPICallResultFn>("Steam_GetAPICallResult");
if (!Proxy::SteamGetAPICallResult) return false;
Proxy::SteamClient = Proxy::Client.get<ISteamClient008*(const char*, int*)>("CreateInterface")("SteamClient008", nullptr);
if (!Proxy::SteamClient) return false;
Proxy::SteamPipe = Proxy::SteamClient->CreateSteamPipe();
if (!Proxy::SteamPipe) return false;
@ -99,7 +238,7 @@ namespace Steam
Proxy::ClientUser = Proxy::ClientEngine->GetIClientUser(Proxy::SteamUser, Proxy::SteamPipe, "CLIENTUSER_INTERFACE_VERSION001");
if (!Proxy::ClientUser) return false;
Proxy::SteamFriends = reinterpret_cast<Friends*>(Proxy::SteamClient->GetISteamFriends(Proxy::SteamUser, Proxy::SteamPipe, "SteamFriends005"));
Proxy::SteamFriends = reinterpret_cast<Friends15*>(Proxy::SteamClient->GetISteamFriends(Proxy::SteamUser, Proxy::SteamPipe, "SteamFriends015"));
if (!Proxy::SteamFriends) return false;
Proxy::SteamUtils = reinterpret_cast<Utils*>(Proxy::SteamClient->GetISteamFriends(Proxy::SteamUser, Proxy::SteamPipe, "SteamUtils005"));

View File

@ -346,10 +346,38 @@ namespace Steam
static bool IsOverlayEnabled();
static bool BOverlayNeedsPresent();
static Friends* SteamFriends;
static void RunFrame();
static void RegisterCall(int32_t callId, uint32_t size, uint64_t call);
static void RegisterCallback(int32_t callId, void* callback);
static inline void RegisterCallback(int32_t callId, void(*callback)(void*)) { RegisterCallback(callId, static_cast<void*>(callback)); }
static void UnregisterCallback(int32_t callId);
static Friends15* SteamFriends;
static Utils* SteamUtils;
private:
typedef bool(SteamBGetCallbackFn)(void* hpipe, void *pCallbackMsg);
typedef void(SteamFreeLastCallbackFn)(void* hpipe);
typedef bool(SteamGetAPICallResultFn)(void* hpipe, uint64_t hSteamAPICall, void* pCallback, int cubCallback, int iCallbackExpected, bool* pbFailed);
struct CallContainer
{
uint64_t call;
bool handled;
int32_t callId;
uint32_t dataSize;
};
struct CallbackMsg
{
int32_t m_hSteamUser;
int m_iCallback;
uint8_t *m_pubParam;
int m_cubParam;
};
static ::Utils::Library Client;
static ::Utils::Library Overlay;
@ -362,6 +390,18 @@ namespace Steam
static uint32_t AppId;
static std::recursive_mutex CallMutex;
static std::vector<CallContainer> Calls;
static std::unordered_map<int32_t, void*> Callbacks;
static std::function<SteamBGetCallbackFn> SteamBGetCallback;
static std::function<SteamFreeLastCallbackFn> SteamFreeLastCallback;
static std::function<SteamGetAPICallResultFn> SteamGetAPICallResult;
static void RunCallback(int32_t callId, void* data);
static void UnregisterCalls();
static std::string GetSteamDirectory();
};
}

View File

@ -74,6 +74,19 @@ namespace Steam
}
}
void Callbacks::RunCallback(int32_t callback, void* data)
{
std::lock_guard<std::recursive_mutex> _(Callbacks::Mutex);
for (auto cb : Callbacks::CallbackList)
{
if (cb && cb->GetICallback() == callback)
{
cb->Run(data);
}
}
}
void Callbacks::Uninitialize()
{
std::lock_guard<std::recursive_mutex> _(Callbacks::Mutex);
@ -94,9 +107,9 @@ namespace Steam
bool SteamAPI_Init()
{
#ifndef DISABLE_STEAM_GAME
if (!Components::Flags::HasFlag("-nosteam"))
if (!Components::Flags::HasFlag("nosteam"))
{
Proxy::SetGame(10190);
//Proxy::SetGame(10190);
}
#endif
@ -107,9 +120,9 @@ namespace Steam
else
{
#ifndef DISABLE_STEAM_GAME
if (!Components::Flags::HasFlag("-nosteam"))
if (!Components::Flags::HasFlag("nosteam"))
{
Proxy::SetMod("IW4x - Modern Warfare 2");
//Proxy::SetMod("IW4x - Modern Warfare 2");
}
#endif
}
@ -130,6 +143,7 @@ namespace Steam
void SteamAPI_RunCallbacks()
{
Callbacks::RunCallbacks();
Proxy::RunFrame();
}
void SteamAPI_Shutdown()

View File

@ -81,6 +81,8 @@ namespace Steam
static void ReturnCall(void* data, int size, int type, uint64_t call);
static void RunCallbacks();
static void RunCallback(int32_t callback, void* data);
static void Uninitialize();
private:

View File

@ -76,6 +76,11 @@ namespace Utils
return Call<T>(reinterpret_cast<DWORD>(function));
}
template <typename T> static std::function<T> Call(void* function)
{
return Call<T>(reinterpret_cast<DWORD>(function));
}
static void SetString(void* place, const char* string, size_t length);
static void SetString(DWORD place, const char* string, size_t length);