Add Game Coordinator Hooks (untested).
This commit is contained in:
committed by
Josh Allard
parent
66100139ee
commit
9f70645270
@@ -13,6 +13,7 @@ project.sources += [
|
||||
'ssnatives.cpp',
|
||||
'swhttp.cpp',
|
||||
'swhttprequest.cpp',
|
||||
'swgchooks.cpp',
|
||||
'sdk/smsdk_ext.cpp',
|
||||
'CDetour/detours.cpp',
|
||||
'asm/asm.c'
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user