Add Game Coordinator Hooks (untested).

This commit is contained in:
Kyle Sanderson
2016-03-03 20:38:00 -08:00
committed by Josh Allard
parent 66100139ee
commit 9f70645270
9 changed files with 284 additions and 1 deletions
+1
View File
@@ -13,6 +13,7 @@ project.sources += [
'ssnatives.cpp',
'swhttp.cpp',
'swhttprequest.cpp',
'swgchooks.cpp',
'sdk/smsdk_ext.cpp',
'CDetour/detours.cpp',
'asm/asm.c'
+2
View File
@@ -55,11 +55,13 @@ bool SteamWorks::SDK_OnLoad(char *error, size_t maxlength, bool late)
this->pGSHooks = new SteamWorksGSHooks;
this->pGSDetours = new SteamWorksGSDetours;
this->pSSNatives = new SteamWorksSSNatives;
this->pGCHooks = new SteamWorksGCHooks;
return true;
}
void SteamWorks::SDK_OnUnload()
{
delete this->pGCHooks;
delete this->pSSNatives;
delete this->pGSDetours;
delete this->pGSHooks;
+2
View File
@@ -47,6 +47,7 @@
#include "swforwards.h"
#include "gsnatives.h"
#include "swgshooks.h"
#include "swgchooks.h"
#include "ssnatives.h"
#include "swgsdetours.h"
#include "swhttp.h"
@@ -142,6 +143,7 @@ public:
SteamWorksGSDetours *pGSDetours;
SteamWorksHTTP *pSWHTTP;
SteamWorksHTTPNatives *pSWHTTPNatives;
SteamWorksGCHooks *pGCHooks;
};
extern SteamWorks g_SteamWorks;
+1 -1
View File
@@ -40,7 +40,7 @@
/* Basic information exposed publicly */
#define SMEXT_CONF_NAME "SteamWorks Extension"
#define SMEXT_CONF_DESCRIPTION "Exposes SteamWorks functions to Developers"
#define SMEXT_CONF_VERSION "1.2"
#define SMEXT_CONF_VERSION "1.2.1"
#define SMEXT_CONF_AUTHOR "Kyle Sanderson"
#define SMEXT_CONF_URL "http://AlliedMods.net"
#define SMEXT_CONF_LOGTAG "STEAMWORKS"
+17
View File
@@ -55,6 +55,7 @@ void SteamWorksGameServer::Reset(void)
this->m_pStats = NULL;
this->m_pHTTP = NULL;
this->m_pMatchmaking = NULL;
this->m_pGC = NULL;
}
ISteamClient *SteamWorksGameServer::GetSteamClient(void)
@@ -156,6 +157,22 @@ ISteamMatchmaking *SteamWorksGameServer::GetMatchmaking(void)
return this->m_pMatchmaking;
}
ISteamGameCoordinator *SteamWorksGameServer::GetGameCoordinator(void)
{
if (this->m_pGC == NULL && this->GetSteamClient() != NULL)
{
HSteamUser hSteamUser;
HSteamPipe hSteamPipe;
GetUserAndPipe(hSteamUser, hSteamPipe);
const char *pVersion = STEAMGAMECOORDINATOR_INTERFACE_VERSION;
GetGameSpecificConfigInterface("SteamGameCoordinatorVersion", pVersion);
this->m_pGC = static_cast<ISteamGameCoordinator *>(this->GetSteamClient()->GetISteamGenericInterface(hSteamUser, hSteamPipe, STEAMGAMECOORDINATOR_INTERFACE_VERSION));
}
return this->m_pGC;
}
void SteamWorksGameServer::GetUserAndPipe(HSteamUser &hSteamUser, HSteamPipe &hSteamPipe)
{
hSteamUser = SteamGameServer_GetHSteamUser();
+4
View File
@@ -19,6 +19,7 @@
#pragma once
#include "smsdk_ext.h"
#include "steam_gameserver.h"
#include "isteamgamecoordinator.h"
class SteamWorksGameServer
{
@@ -34,6 +35,8 @@ class SteamWorksGameServer
ISteamGameServerStats *GetServerStats(void);
ISteamHTTP *GetHTTP(void);
ISteamMatchmaking *GetMatchmaking(void);
ISteamGameCoordinator *GetGameCoordinator(void);
public:
void Reset(void);
private:
@@ -46,6 +49,7 @@ class SteamWorksGameServer
ISteamGameServerStats *m_pStats;
ISteamHTTP *m_pHTTP;
ISteamMatchmaking *m_pMatchmaking;
ISteamGameCoordinator *m_pGC;
bool loaded;
};
+193
View File
@@ -0,0 +1,193 @@
/*
This file is part of SourcePawn SteamWorks.
SourcePawn SteamWorks is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, as per version 3 of the License.
SourcePawn SteamWorks is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SourcePawn SteamWorks. If not, see <http://www.gnu.org/licenses/>.
Author: Kyle Sanderson (KyleS).
*/
#include "swgchooks.h"
enum
{
eUnhooked = 0,
eHooking,
eHooked
};
SH_DECL_HOOK3(ISteamGameCoordinator, SendMessage, SH_NOATTRIB, 0, EGCResults, uint32, const void *, uint32);
SH_DECL_HOOK1(ISteamGameCoordinator, IsMessageAvailable, SH_NOATTRIB, 0, bool, uint32 *);
SH_DECL_HOOK4(ISteamGameCoordinator, RetrieveMessage, SH_NOATTRIB, 0, EGCResults, uint32 *, void *, uint32, uint32 *);
static ISteamGameCoordinator *GetSteamGCPointer()
{
return g_SteamWorks.pSWGameServer->GetGameCoordinator();
}
SteamWorksGCHooks::SteamWorksGCHooks()
{
this->uHooked = eHooking;
this->pGCSendMsg = forwards->CreateForward("SteamWorks_GCSendMessage", ET_Event, 3, NULL, Param_Cell, Param_String, Param_Cell);
this->pGCMsgAvail = forwards->CreateForward("SteamWorks_GCMsgAvailable", ET_Ignore, 1, NULL, Param_Cell);
this->pGCRetMsg = forwards->CreateForward("SteamWorks_RetreiveMessage", ET_Event, 5, NULL, Param_Cell, Param_Cell, Param_String, Param_Cell, Param_Cell);
smutils->AddGameFrameHook(OurGCGameFrameHook);
}
SteamWorksGCHooks::~SteamWorksGCHooks()
{
this->RemoveHooks(GetSteamGCPointer(), true);
smutils->RemoveGameFrameHook(OurGCGameFrameHook);
forwards->ReleaseForward(this->pGCSendMsg);
forwards->ReleaseForward(this->pGCMsgAvail);
forwards->ReleaseForward(this->pGCRetMsg);
}
EGCResults SteamWorksGCHooks::SendMessage(uint32 unMsgType, const void *pubData, uint32 cubData)
{
if (this->pGCSendMsg->GetFunctionCount() == 0)
{
RETURN_META_VALUE(MRES_IGNORED, k_EGCResultOK);
}
cell_t Result = k_EGCResultOK;
this->pGCSendMsg->PushCell(unMsgType);
this->pGCSendMsg->PushStringEx(reinterpret_cast<char *>(const_cast<void *>(pubData)), cubData, SM_PARAM_STRING_BINARY | SM_PARAM_STRING_COPY, 0);
this->pGCSendMsg->PushCell(cubData);
this->pGCSendMsg->Execute(&Result);
if (Result != k_EGCResultOK)
{
if (Result == -1)
{
Result = k_EGCResultOK;
}
RETURN_META_VALUE(MRES_SUPERCEDE, static_cast<EGCResults>(Result));
}
RETURN_META_VALUE(MRES_IGNORED, k_EGCResultOK);
}
bool SteamWorksGCHooks::IsMessageAvailable(uint32_t *pcubMsgSize)
{
if (this->pGCMsgAvail->GetFunctionCount() == 0)
{
RETURN_META_VALUE(MRES_IGNORED, false);
}
bool res = META_RESULT_ORIG_RET(bool);
if (!res)
{
RETURN_META_VALUE(MRES_IGNORED, false);
}
uint32_t shill;
if (!pcubMsgSize)
{
SH_CALL(GetSteamGCPointer(), &ISteamGameCoordinator::IsMessageAvailable)(&shill);
pcubMsgSize = &shill;
}
this->pGCMsgAvail->PushCell(*pcubMsgSize);
this->pGCMsgAvail->Execute(NULL);
RETURN_META_VALUE(MRES_IGNORED, true);
}
EGCResults SteamWorksGCHooks::RetrieveMessage(uint32 *punMsgType, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize)
{
if (this->pGCRetMsg->GetFunctionCount() == 0)
{
RETURN_META_VALUE(MRES_IGNORED, k_EGCResultOK);
}
/* Don't trust a bitch, except for 2GD. https://www.youtube.com/watch?v=MgePh_YJgrc */
cell_t Result;
EGCResults res = SH_CALL(GetSteamGCPointer(), &ISteamGameCoordinator::RetrieveMessage)(punMsgType, pubDest, cubDest, pcubMsgSize);
if (punMsgType)
this->pGCRetMsg->PushCell(*punMsgType);
else
this->pGCRetMsg->PushCell(0);
if (pubDest)
this->pGCSendMsg->PushStringEx(reinterpret_cast<char *>(pubDest), cubDest, SM_PARAM_STRING_BINARY | SM_PARAM_STRING_COPY, 0);
else
this->pGCSendMsg->PushStringEx(const_cast<char *>(""), 1, SM_PARAM_STRING_BINARY | SM_PARAM_STRING_COPY, 0);
this->pGCRetMsg->PushCell(cubDest);
if (pcubMsgSize)
this->pGCRetMsg->PushCell(*pcubMsgSize);
else
this->pGCRetMsg->PushCell(0);
this->pGCRetMsg->Execute(&Result);
if (Result != k_EGCResultOK)
{
if (Result == -1)
{
Result = k_EGCResultOK;
}
RETURN_META_VALUE(MRES_SUPERCEDE, static_cast<EGCResults>(Result));
}
RETURN_META_VALUE(MRES_IGNORED, k_EGCResultOK);
}
void SteamWorksGCHooks::AddHooks(ISteamGameCoordinator *pGC)
{
if (this->uHooked == eHooked || pGC == NULL)
{
return;
}
this->uHooked = eHooked;
SH_ADD_HOOK(ISteamGameCoordinator, SendMessage, pGC, SH_MEMBER(this, &SteamWorksGCHooks::SendMessage), false);
SH_ADD_HOOK(ISteamGameCoordinator, IsMessageAvailable, pGC, SH_MEMBER(this, &SteamWorksGCHooks::IsMessageAvailable), true);
SH_ADD_HOOK(ISteamGameCoordinator, RetrieveMessage, pGC, SH_MEMBER(this, &SteamWorksGCHooks::RetrieveMessage), false);
}
void SteamWorksGCHooks::RemoveHooks(ISteamGameCoordinator *pGC, bool destroyed)
{
if (this->uHooked != eHooked || pGC == NULL)
{
return;
}
SH_REMOVE_HOOK(ISteamGameCoordinator, SendMessage, pGC, SH_MEMBER(this, &SteamWorksGCHooks::SendMessage), false);
SH_REMOVE_HOOK(ISteamGameCoordinator, IsMessageAvailable, pGC, SH_MEMBER(this, &SteamWorksGCHooks::IsMessageAvailable), true);
SH_REMOVE_HOOK(ISteamGameCoordinator, RetrieveMessage, pGC, SH_MEMBER(this, &SteamWorksGCHooks::RetrieveMessage), false);
if (destroyed)
{
this->uHooked = eUnhooked;
return;
}
this->uHooked = eHooking;
smutils->AddGameFrameHook(OurGameFrameHook);
}
void OurGCGameFrameHook(bool simulating) /* What we do for SDK independence. */
{
ISteamGameCoordinator *pGC = GetSteamGCPointer();
if (pGC == NULL)
{
return;
}
g_SteamWorks.pGCHooks->AddHooks(pGC);
smutils->RemoveGameFrameHook(OurGCGameFrameHook);
}
+50
View File
@@ -0,0 +1,50 @@
/*
This file is part of SourcePawn SteamWorks.
SourcePawn SteamWorks is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, as per version 3 of the License.
SourcePawn SteamWorks is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SourcePawn SteamWorks. If not, see <http://www.gnu.org/licenses/>.
Author: Kyle Sanderson (KyleS).
*/
#pragma once
#include "steam_gameserver.h"
#include "isteamgamecoordinator.h"
#include "smsdk_ext.h"
#include "sourcehook.h"
class SteamWorksGCHooks
{
public:
SteamWorksGCHooks();
~SteamWorksGCHooks();
public:
void AddHooks(ISteamGameCoordinator *pGC);
void RemoveHooks(ISteamGameCoordinator *pGC, bool destroyed = false);
public:
EGCResults SendMessage(uint32 unMsgType, const void *pubData, uint32 cubData);
bool IsMessageAvailable(uint32_t *pcubMsgSize);
EGCResults RetrieveMessage(uint32 *punMsgType, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize);
private:
IForward *pGCSendMsg;
IForward *pGCMsgAvail;
IForward *pGCRetMsg;
unsigned char uHooked;
};
void OurGCGameFrameHook(bool simulating);
#include "extension.h"
+14
View File
@@ -175,6 +175,16 @@ enum EHTTPStatusCode
k_EHTTPStatusCode5xxUnknown = 599,
};
/* list of possible return values from the ISteamGameCoordinator API */
enum EGCResults
{
k_EGCResultOK = 0,
k_EGCResultNoMessage = 1, // There is no message in the queue
k_EGCResultBufferTooSmall = 2, // The buffer is too small for the requested message
k_EGCResultNotLoggedOn = 3, // The client is not logged onto Steam
k_EGCResultInvalidMessage = 4, // Something was wrong with the message being sent with SendMessage
};
native bool:SteamWorks_IsVACEnabled();
native bool:SteamWorks_GetPublicIP(ipaddr[4]);
native SteamWorks_GetPublicIPCell();
@@ -258,6 +268,10 @@ forward SteamWorks_TokenRequested(String:sToken[], maxlen);
forward SteamWorks_OnClientGroupStatus(authid, groupid, bool:isMember, bool:isOfficer);
forward EGCResults:SteamWorks_GCSendMessage(unMsgType, const String:pubData[], cubData);
forward SteamWorks_GCMsgAvailable(cubData);
forward EGCResults:SteamWorks_RetreiveMessage(punMsgType, const String:pubDest[], cubDest, pcubMsgSize);
public Extension:__ext_SteamWorks =
{
name = "SteamWorks",