diff --git a/Makefile b/Makefile index 817f0ff..f64e965 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ PROJECT = SteamWorks #USEMETA = true USESH = true -OBJECTS = sdk/smsdk_ext.cpp extension.cpp swgameserver.cpp swgamedata.cpp swforwards.cpp gsnatives.cpp +OBJECTS = sdk/smsdk_ext.cpp extension.cpp swgameserver.cpp swgamedata.cpp swforwards.cpp gsnatives.cpp swgshooks.cpp ############################################## ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### diff --git a/extension.cpp b/extension.cpp index 45f0786..a9d1601 100644 --- a/extension.cpp +++ b/extension.cpp @@ -47,11 +47,13 @@ bool SteamWorks::SDK_OnLoad(char *error, size_t maxlength, bool late) this->pSWForward = new SteamWorksForwards; this->pGSNatives = new SteamWorksGSNatives; + this->pGSHooks = new SteamWorksGSHooks; return true; } void SteamWorks::SDK_OnUnload() { + delete this->pGSHooks; delete this->pGSNatives; delete this->pSWForward; diff --git a/extension.h b/extension.h index bc95e38..269de09 100644 --- a/extension.h +++ b/extension.h @@ -46,6 +46,7 @@ #include "swforwards.h" #include "gsnatives.h" +#include "swgshooks.h" /** * @brief Sample implementation of the SDK Extension. @@ -129,6 +130,7 @@ public: SteamWorksGameData *pSWGameData; SteamWorksGameServer *pSWGameServer; SteamWorksGSNatives *pGSNatives; + SteamWorksGSHooks *pGSHooks; }; extern SteamWorks g_SteamWorks; diff --git a/swgshooks.cpp b/swgshooks.cpp new file mode 100644 index 0000000..bccd579 --- /dev/null +++ b/swgshooks.cpp @@ -0,0 +1,91 @@ +/* + 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, either version 3 of the License, or + (at your option) any later version. + + 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 . + + Author: Kyle Sanderson (KyleS). +*/ + +#include "swgshooks.h" + +SH_DECL_HOOK0(ISteamGameServer, WasRestartRequested, SH_NOATTRIB, 0, bool); /* From SteamTools. */ + +static ISteamGameServer *GetGameServerPointer() +{ + return g_SteamWorks.pSWGameServer->GetGameServer(); +} + +SteamWorksGSHooks::SteamWorksGSHooks() +{ + this->bHooked = false; + this->pFORR = forwards->CreateForward("SteamWorks_RestartRequested", ET_Hook, 0, NULL); + + smutils->AddGameFrameHook(OurGameFrameHook); +} + +SteamWorksGSHooks::~SteamWorksGSHooks() +{ + smutils->RemoveGameFrameHook(OurGameFrameHook); + + this->RemoveHooks(GetGameServerPointer()); + forwards->ReleaseForward(this->pFORR); +} + +bool SteamWorksGSHooks::WasRestartRequested(void) /* Mimic SteamTools. */ +{ + bool bWasRestartRequested = SH_CALL(GetGameServerPointer(), &ISteamGameServer::WasRestartRequested)(); + if (bWasRestartRequested && this->pFORR->GetFunctionCount() != 0) + { + cell_t Result = Pl_Continue; + this->pFORR->Execute(&Result); + bWasRestartRequested = (Result >= Pl_Handled); + } + + /* With how this function works, all following will be given poisoned values from SH_Call. */ + RETURN_META_VALUE(MRES_SUPERCEDE, bWasRestartRequested); +} + +void SteamWorksGSHooks::AddHooks(ISteamGameServer *pGameServer) +{ + if (this->bHooked == true || pGameServer == NULL) + { + return; + } + + this->bHooked = true; + SH_ADD_HOOK(ISteamGameServer, WasRestartRequested, pGameServer, SH_MEMBER(this, &SteamWorksGSHooks::WasRestartRequested), false); +} + +void SteamWorksGSHooks::RemoveHooks(ISteamGameServer *pGameServer) +{ + if (this->bHooked == false || pGameServer == NULL) + { + return; + } + + this->bHooked = false; + SH_REMOVE_HOOK(ISteamGameServer, WasRestartRequested, pGameServer, SH_MEMBER(this, &SteamWorksGSHooks::WasRestartRequested), false); +} + +void OurGameFrameHook(bool simulating) /* What we do for SDK independence. */ +{ + ISteamGameServer *pGameServer = GetGameServerPointer(); + if (pGameServer == NULL) + { + return; + } + + g_SteamWorks.pGSHooks->AddHooks(pGameServer); + smutils->RemoveGameFrameHook(OurGameFrameHook); +} diff --git a/swgshooks.h b/swgshooks.h new file mode 100644 index 0000000..46cf95a --- /dev/null +++ b/swgshooks.h @@ -0,0 +1,46 @@ +/* + 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, either version 3 of the License, or + (at your option) any later version. + + 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 . + + Author: Kyle Sanderson (KyleS). +*/ + +#pragma once +#include "isteamgameserver.h" +#include "steam_gameserver.h" +#include "smsdk_ext.h" +#include "sourcehook.h" + +class SteamWorksGSHooks +{ + public: + SteamWorksGSHooks(); + ~SteamWorksGSHooks(); + + public: + void AddHooks(ISteamGameServer *pGameServer); + void RemoveHooks(ISteamGameServer *pGameServer); + + public: + bool WasRestartRequested(void); + + private: + IForward *pFORR; /* On Restart Requested. */ + bool bHooked; +}; + +void OurGameFrameHook(bool simulating); + +#include "extension.h" \ No newline at end of file