11 Commits
Author SHA1 Message Date
dependabot[bot] 25108a5296 Bump actions/setup-python from 6 to 7 (#4)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-26 12:47:56 +00:00
Nicholas Hastings 71ceb89241 Update auto versioning 2026-07-13 17:55:53 -04:00
Nicholas Hastings f1c9faba45 Fix build 2026-07-13 17:55:04 -04:00
A1m` a86fc4af91 Fix circular includes and include cleanup (#3)
* Fix circular includes and include cleanup

Fixed a bug where other *.h header files would include extension.h, which itself
was already included in those same headers, creating a circular dependency cycle.
This caused build errors and made compilation unpredictable.

To resolve this:
- Moved implementation-only includes to .cpp files where they are actually needed.
- Added forward declarations where possible to avoid pulling in unnecessary headers.
- Ensured extension.h only contains declarations that require full type definitions.

This improves build stability and compilation time.

* Clean up includes and fix build errors

- Replaced full includes with forward declarations where possible
- Moved implementation-only includes from .h to .cpp files
- Added missing includes for stdint.h and Steam interfaces
- This significantly reduces compilation time and prevents future dependency issues

* Switch to SourceMod SDK smsdk_ext instead of local copy
2026-07-13 21:43:05 +00:00
A1m` 07fc524d27 Fixed incorrect use of ReferenceToIndex, which caused some functions to be unstable during client connection. (#2)
While this function works well with the client indexes we pass in, as its name
suggests, we should essentially be passing player references, not client indexes.
The problem is that SourceMod looks for this player in the entity list, but they
might not be there when connecting, or they might be another client or a bot.

This makes the code unstable and confusing, and it works intermittently.
Steam doesn't care whether the player is in the entity list—it works with the
Steam ID. Using ReferenceToIndex here is fundamentally wrong and causes random
-1 errors, especially during OnClientConnect when the entity may not exist yet.

This commit replaces it with a direct client index lookup, which is correct and
reliable because params[1] is already a client index.
2026-07-13 21:39:04 +00:00
Nicholas Hastings 8fd7a1988c Update extension author and repository URL 2026-07-12 22:40:00 -04:00
Nicholas Hastings 65936e7d9c Fix size_t truncation warning in SetHTTPRequestRawPostBodyFromFile 2026-07-12 22:10:00 -04:00
Nicholas Hastings 645103735e Fix streaming HTTP response header and data callbacks 2026-07-12 21:20:00 -04:00
Nicholas Hastings a779d6d961 Expose SetAdvertiseServerActive 2026-07-12 15:17:29 -04:00
Nicholas Hastings c82feb1a4a Add methodmap for SteamWorksHTTPRequest 2026-07-12 13:59:38 -04:00
Nicholas Hastings ceeaf66b95 Add function docs to inc 2026-07-12 13:31:37 -04:00
33 changed files with 1223 additions and 1000 deletions
+24 -5
View File
@@ -7,8 +7,27 @@ on:
branches: [ master ] branches: [ master ]
jobs: jobs:
version:
name: Version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.compute.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Compute version
id: compute
run: |
base_version=$(grep -oP 'SMEXT_CONF_VERSION\s+"\K[^"]+' Extension/sdk/smsdk_config.h)
build_number=$(git rev-list --count HEAD)
echo "version=${base_version}.${build_number}" >> "$GITHUB_OUTPUT"
build: build:
name: sm${{ matrix.sm.label }}-${{ matrix.target.os_name }}-${{ matrix.target.arch }} name: sm${{ matrix.sm.label }}-${{ matrix.target.os_name }}-${{ matrix.target.arch }}
needs: version
runs-on: ${{ matrix.target.os }} runs-on: ${{ matrix.target.os }}
container: ${{ matrix.target.container }} container: ${{ matrix.target.container }}
strategy: strategy:
@@ -43,7 +62,7 @@ jobs:
- name: Setup Python (Windows) - name: Setup Python (Windows)
if: matrix.target.os_name == 'windows' if: matrix.target.os_name == 'windows'
uses: actions/setup-python@v6 uses: actions/setup-python@v7
with: with:
python-version: '3.12' python-version: '3.12'
@@ -78,6 +97,7 @@ jobs:
--mms-path ../mmsource \ --mms-path ../mmsource \
--steamworks-path ../SteamworksSDK \ --steamworks-path ../SteamworksSDK \
--target ${{ matrix.target.arch }} \ --target ${{ matrix.target.arch }} \
--version "${{ needs.version.outputs.version }}" \
--enable-optimize --enable-optimize
ambuild ambuild
@@ -91,6 +111,7 @@ jobs:
--mms-path ../mmsource \ --mms-path ../mmsource \
--steamworks-path ../SteamworksSDK \ --steamworks-path ../SteamworksSDK \
--target ${{ matrix.target.arch }} \ --target ${{ matrix.target.arch }} \
--version "${{ needs.version.outputs.version }}" \
--enable-optimize --enable-optimize
ambuild ambuild
@@ -138,7 +159,7 @@ jobs:
release: release:
name: Release name: Release
needs: build needs: [version, build]
if: github.event_name == 'push' && github.ref == 'refs/heads/master' if: github.event_name == 'push' && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
@@ -157,9 +178,7 @@ jobs:
- name: Assemble packages - name: Assemble packages
id: package id: package
run: | run: |
base_version=$(grep -oP 'SMEXT_CONF_VERSION\s+"\K[^"]+' Extension/sdk/smsdk_config.h) version="${{ needs.version.outputs.version }}"
build_number=$(git rev-list --count HEAD)
version="${base_version}-git${build_number}"
echo "version=${version}" >> "$GITHUB_OUTPUT" echo "version=${version}" >> "$GITHUB_OUTPUT"
# One package per SourceMod version per OS: Windows as .zip, Linux as # One package per SourceMod version per OS: Windows as .zip, Linux as
+7 -1
View File
@@ -60,8 +60,8 @@ project.sources += [
'swhttp.cpp', 'swhttp.cpp',
'swhttprequest.cpp', 'swhttprequest.cpp',
'swgchooks.cpp', 'swgchooks.cpp',
'sdk/smsdk_ext.cpp',
os.path.join(SteamWorks.sm_root, 'public', 'CDetour', 'detours.cpp'), os.path.join(SteamWorks.sm_root, 'public', 'CDetour', 'detours.cpp'),
os.path.join(SteamWorks.sm_root, 'public', 'smsdk_ext.cpp'),
] ]
binary = SteamWorks.HL2Config(project, builder.cxx, 'SteamWorks.ext') binary = SteamWorks.HL2Config(project, builder.cxx, 'SteamWorks.ext')
@@ -69,6 +69,12 @@ binary = SteamWorks.HL2Config(project, builder.cxx, 'SteamWorks.ext')
# The Steam API headers all come from the SteamWorks SDK; the extension is built # The Steam API headers all come from the SteamWorks SDK; the extension is built
# with META_NO_HL2SDK, so no HL2SDK is required. # with META_NO_HL2SDK, so no HL2SDK is required.
binary.compiler.defines += ['META_NO_HL2SDK', 'SOURCEMOD_BUILD', 'VERSION_SAFE_STEAM_API_INTERFACES'] binary.compiler.defines += ['META_NO_HL2SDK', 'SOURCEMOD_BUILD', 'VERSION_SAFE_STEAM_API_INTERFACES']
# Let CI bake the generated release version into the binary. The value is passed
# as an unquoted token and stringized in smsdk_config.h, avoiding shell-quoting
# differences between MSVC and gcc/clang.
if builder.options.version:
binary.compiler.defines += ['SMEXT_CONF_VERSION_OVERRIDE={0}'.format(builder.options.version)]
binary.compiler.cxxincludes += [os.path.join(SteamWorks.steamworks_root, 'public', 'steam')] binary.compiler.cxxincludes += [os.path.join(SteamWorks.steamworks_root, 'public', 'steam')]
binary.compiler.cxxincludes += [os.path.join(SteamWorks.sm_root, 'public', 'safetyhook', 'include')] binary.compiler.cxxincludes += [os.path.join(SteamWorks.sm_root, 'public', 'safetyhook', 'include')]
+13 -1
View File
@@ -30,7 +30,18 @@
*/ */
#include "extension.h" #include "extension.h"
#include <stdlib.h>
#include "swgamedata.h"
#include "swgameserver.h"
#include "swhttp.h"
#include "swhttprequest.h"
#include "swforwards.h"
#include "gsnatives.h"
#include "swgshooks.h"
#include "swgsdetours.h"
#include "ssnatives.h"
#include "swgchooks.h"
#include "gcnatives.h"
/** /**
* @file extension.cpp * @file extension.cpp
@@ -72,6 +83,7 @@ void SteamWorks::SDK_OnUnload()
delete this->pSWHTTPNatives; delete this->pSWHTTPNatives;
delete this->pSWHTTP; delete this->pSWHTTP;
this->pSWHTTP = NULL; /* Requests freed via frame actions may outlive us; let their dtor detect this. */
delete this->pSWGameServer; delete this->pSWGameServer;
delete this->pSWGameData; delete this->pSWGameData;
} }
+15 -14
View File
@@ -37,21 +37,21 @@
* @brief Sample extension code header. * @brief Sample extension code header.
*/ */
#include "smsdk_ext.h" #include <smsdk_ext.h>
#include "isteamgameserver.h" #include <isteamgameserver.h>
#include "steam_gameserver.h" #include <steamclientpublic.h>
#include "swgameserver.h" class SteamWorksForwards;
#include "swgamedata.h" class SteamWorksGameData;
class SteamWorksGameServer;
#include "swforwards.h" class SteamWorksGSNatives;
#include "gsnatives.h" class SteamWorksGSHooks;
#include "swgshooks.h" class SteamWorksSSNatives;
#include "swgchooks.h" class SteamWorksGSDetours;
#include "ssnatives.h" class SteamWorksHTTP;
#include "gcnatives.h" class SteamWorksHTTPNatives;
#include "swgsdetours.h" class SteamWorksGCHooks;
#include "swhttp.h" class SteamWorksGCNatives;
/** /**
* @brief Sample implementation of the SDK Extension. * @brief Sample implementation of the SDK Extension.
@@ -149,4 +149,5 @@ public:
}; };
extern SteamWorks g_SteamWorks; extern SteamWorks g_SteamWorks;
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ #endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
+3
View File
@@ -17,6 +17,9 @@
*/ */
#include "gcnatives.h" #include "gcnatives.h"
#include "extension.h"
#include "swgameserver.h"
#include <isteamgamecoordinator.h>
static ISteamGameCoordinator *GetSteamGCPointer(void) static ISteamGameCoordinator *GetSteamGCPointer(void)
{ {
-10
View File
@@ -17,14 +17,6 @@
*/ */
#pragma once #pragma once
#include "steam_gameserver.h"
#include "isteamgamecoordinator.h"
#include "smsdk_ext.h"
#ifdef _WIN32
#undef SendMessage
#endif
class SteamWorksGCNatives class SteamWorksGCNatives
{ {
@@ -32,5 +24,3 @@ class SteamWorksGCNatives
SteamWorksGCNatives(); SteamWorksGCNatives();
~SteamWorksGCNatives(); ~SteamWorksGCNatives();
}; };
#include "extension.h"
+44 -14
View File
@@ -17,6 +17,8 @@
*/ */
#include "gsnatives.h" #include "gsnatives.h"
#include "extension.h"
#include "swgameserver.h"
static bool IsSteamWorksLoaded(void) static bool IsSteamWorksLoaded(void)
{ {
@@ -190,6 +192,19 @@ static cell_t sm_ClearRules(IPluginContext *pContext, const cell_t *params)
return 1; return 1;
} }
static cell_t sm_SetAdvertiseServerActive(IPluginContext *pContext, const cell_t *params)
{
ISteamGameServer *pServer = GetGSPointer();
if (pServer == NULL)
{
return 0;
}
pServer->SetAdvertiseServerActive(!!params[1]);
return 1;
}
static cell_t sm_ForceHeartbeat(IPluginContext *pContext, const cell_t *params) static cell_t sm_ForceHeartbeat(IPluginContext *pContext, const cell_t *params)
{ {
/* Deprecated no-op: newer Steamworks SDKs removed ISteamGameServer::ForceHeartbeat(); /* Deprecated no-op: newer Steamworks SDKs removed ISteamGameServer::ForceHeartbeat();
@@ -206,11 +221,16 @@ static cell_t sm_UserHasLicenseForApp(IPluginContext *pContext, const cell_t *pa
return k_EUserHasLicenseResultNoAuth; return k_EUserHasLicenseResultNoAuth;
} }
int client = gamehelpers->ReferenceToIndex(params[1]); int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); /* Man, including GameHelpers and PlayerHelpers for this native :(. */ if (client < 1 || client > playerhelpers->GetMaxClients())
if (pPlayer == NULL || pPlayer->IsConnected() == false)
{ {
return pContext->ThrowNativeError("Client index %d is invalid", params[1]); return pContext->ThrowNativeError("Client index %d is invalid", client);
}
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (pPlayer == NULL || !pPlayer->IsConnected())
{
return pContext->ThrowNativeError("Client index %d is not connected", client);
} }
CSteamID checkid = CreateCommonCSteamID(pPlayer, params, 3, 4); CSteamID checkid = CreateCommonCSteamID(pPlayer, params, 3, 4);
@@ -232,12 +252,16 @@ static cell_t sm_UserHasLicenseForAppId(IPluginContext *pContext, const cell_t *
static cell_t sm_GetClientSteamID(IPluginContext *pContext, const cell_t *params) static cell_t sm_GetClientSteamID(IPluginContext *pContext, const cell_t *params)
{ {
int client = gamehelpers->ReferenceToIndex(params[1]); int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); if (client < 1 || client > playerhelpers->GetMaxClients())
if (pPlayer == NULL || pPlayer->IsConnected() == false)
{ {
return pContext->ThrowNativeError("Client index %d is invalid", params[1]); return pContext->ThrowNativeError("Client index %d is invalid", client);
}
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (pPlayer == NULL || !pPlayer->IsConnected())
{
return pContext->ThrowNativeError("Client index %d is not connected", client);
} }
CSteamID steamId = CreateCommonCSteamID(pPlayer, params, 4, 5); CSteamID steamId = CreateCommonCSteamID(pPlayer, params, 4, 5);
@@ -257,14 +281,19 @@ static cell_t sm_GetUserGroupStatus(IPluginContext *pContext, const cell_t *para
if (pServer == NULL) if (pServer == NULL)
{ {
return false; return 0;
} }
int client = gamehelpers->ReferenceToIndex(params[1]); int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); /* Man, including GameHelpers and PlayerHelpers for this native :(. */ if (client < 1 || client > playerhelpers->GetMaxClients())
if (pPlayer == NULL || pPlayer->IsConnected() == false)
{ {
return pContext->ThrowNativeError("Client index %d is invalid", params[1]); return pContext->ThrowNativeError("Client index %d is invalid", client);
}
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (pPlayer == NULL || !pPlayer->IsConnected())
{
return pContext->ThrowNativeError("Client index %d is not connected", client);
} }
CSteamID checkid = CreateCommonCSteamID(pPlayer, params, 3, 4); CSteamID checkid = CreateCommonCSteamID(pPlayer, params, 3, 4);
@@ -295,6 +324,7 @@ static sp_nativeinfo_t gsnatives[] = {
{"SteamWorks_IsConnected", sm_IsConnected}, {"SteamWorks_IsConnected", sm_IsConnected},
{"SteamWorks_SetRule", sm_SetRule}, {"SteamWorks_SetRule", sm_SetRule},
{"SteamWorks_ClearRules", sm_ClearRules}, {"SteamWorks_ClearRules", sm_ClearRules},
{"SteamWorks_SetAdvertiseServerActive", sm_SetAdvertiseServerActive},
{"SteamWorks_ForceHeartbeat", sm_ForceHeartbeat}, {"SteamWorks_ForceHeartbeat", sm_ForceHeartbeat},
{"SteamWorks_HasLicenseForApp", sm_UserHasLicenseForApp}, {"SteamWorks_HasLicenseForApp", sm_UserHasLicenseForApp},
{"SteamWorks_HasLicenseForAppId", sm_UserHasLicenseForAppId}, {"SteamWorks_HasLicenseForAppId", sm_UserHasLicenseForAppId},
-3
View File
@@ -17,7 +17,6 @@
*/ */
#pragma once #pragma once
#include "smsdk_ext.h"
class SteamWorksGSNatives class SteamWorksGSNatives
{ {
@@ -25,5 +24,3 @@ class SteamWorksGSNatives
SteamWorksGSNatives(); SteamWorksGSNatives();
~SteamWorksGSNatives(); ~SteamWorksGSNatives();
}; };
#include "extension.h"
+14 -3
View File
@@ -40,9 +40,20 @@
/* Basic information exposed publicly */ /* Basic information exposed publicly */
#define SMEXT_CONF_NAME "SteamWorks Extension" #define SMEXT_CONF_NAME "SteamWorks Extension"
#define SMEXT_CONF_DESCRIPTION "Exposes SteamWorks functions to Developers" #define SMEXT_CONF_DESCRIPTION "Exposes SteamWorks functions to Developers"
#define SMEXT_CONF_VERSION "1.2.3" /* The literal below is the MAJOR.MINOR base and the version used by local builds.
#define SMEXT_CONF_AUTHOR "Kyle Sanderson" CI turns it into a full MAJOR.MINOR.PATCH release version by defining
#define SMEXT_CONF_URL "http://AlliedMods.net" SMEXT_CONF_VERSION_OVERRIDE at build time as an unquoted token (e.g. 1.2.158,
where the patch is the commit count); it is stringized here so no cross-platform
shell quoting is required. Bump the MAJOR/MINOR here by hand. */
#if defined(SMEXT_CONF_VERSION_OVERRIDE)
#define SMEXT_CONF_VERSION_STR_(x) #x
#define SMEXT_CONF_VERSION_STR(x) SMEXT_CONF_VERSION_STR_(x)
#define SMEXT_CONF_VERSION SMEXT_CONF_VERSION_STR(SMEXT_CONF_VERSION_OVERRIDE)
#else
#define SMEXT_CONF_VERSION "1.2"
#endif
#define SMEXT_CONF_AUTHOR "Kyle Sanderson, AlliedModders"
#define SMEXT_CONF_URL "https://github.com/alliedmodders/SM-SteamWorks"
#define SMEXT_CONF_LOGTAG "STEAMWORKS" #define SMEXT_CONF_LOGTAG "STEAMWORKS"
#define SMEXT_CONF_LICENSE "GPLv3" #define SMEXT_CONF_LICENSE "GPLv3"
#define SMEXT_CONF_DATESTRING __DATE__ #define SMEXT_CONF_DATESTRING __DATE__
-485
View File
@@ -1,485 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet:
* =============================================================================
* SourceMod Base Extension Code
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program 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
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include <stdio.h>
#include <stdlib.h>
#include "smsdk_ext.h"
/**
* @file smsdk_ext.cpp
* @brief Contains wrappers for making Extensions easier to write.
*/
IExtension *myself = NULL; /**< Ourself */
IShareSys *g_pShareSys = NULL; /**< Share system */
IShareSys *sharesys = NULL; /**< Share system */
ISourceMod *g_pSM = NULL; /**< SourceMod helpers */
ISourceMod *smutils = NULL; /**< SourceMod helpers */
#if defined SMEXT_ENABLE_FORWARDSYS
IForwardManager *g_pForwards = NULL; /**< Forward system */
IForwardManager *forwards = NULL; /**< Forward system */
#endif
#if defined SMEXT_ENABLE_HANDLESYS
IHandleSys *g_pHandleSys = NULL; /**< Handle system */
IHandleSys *handlesys = NULL; /**< Handle system */
#endif
#if defined SMEXT_ENABLE_PLAYERHELPERS
IPlayerManager *playerhelpers = NULL; /**< Player helpers */
#endif //SMEXT_ENABLE_PLAYERHELPERS
#if defined SMEXT_ENABLE_DBMANAGER
IDBManager *dbi = NULL; /**< DB Manager */
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_GAMECONF
IGameConfigManager *gameconfs = NULL; /**< Game config manager */
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_MEMUTILS
IMemoryUtils *memutils = NULL;
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_GAMEHELPERS
IGameHelpers *gamehelpers = NULL;
#endif
#if defined SMEXT_ENABLE_TIMERSYS
ITimerSystem *timersys = NULL;
#endif
#if defined SMEXT_ENABLE_ADTFACTORY
IADTFactory *adtfactory = NULL;
#endif
#if defined SMEXT_ENABLE_THREADER
IThreader *threader = NULL;
#endif
#if defined SMEXT_ENABLE_LIBSYS
ILibrarySys *libsys = NULL;
#endif
#if defined SMEXT_ENABLE_PLUGINSYS
SourceMod::IPluginManager *plsys;
#endif
#if defined SMEXT_ENABLE_MENUS
IMenuManager *menus = NULL;
#endif
#if defined SMEXT_ENABLE_ADMINSYS
IAdminSystem *adminsys = NULL;
#endif
#if defined SMEXT_ENABLE_TEXTPARSERS
ITextParsers *textparsers = NULL;
#endif
#if defined SMEXT_ENABLE_USERMSGS
IUserMessages *usermsgs = NULL;
#endif
#if defined SMEXT_ENABLE_TRANSLATOR
ITranslator *translator = NULL;
#endif
#if defined SMEXT_ENABLE_NINVOKE
INativeInterface *ninvoke = NULL;
#endif
#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
IRootConsole *rootconsole = NULL;
#endif
/** Exports the main interface */
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
{
return g_pExtensionIface;
}
SDKExtension::SDKExtension()
{
#if defined SMEXT_CONF_METAMOD
m_SourceMMLoaded = false;
m_WeAreUnloaded = false;
m_WeGotPauseChange = false;
#endif
}
bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late)
{
g_pShareSys = sharesys = sys;
myself = me;
#if defined SMEXT_CONF_METAMOD
m_WeAreUnloaded = true;
if (!m_SourceMMLoaded)
{
if (error)
{
snprintf(error, maxlength, "Metamod attach failed");
}
return false;
}
#endif
SM_GET_IFACE(SOURCEMOD, g_pSM);
smutils = g_pSM;
#if defined SMEXT_ENABLE_HANDLESYS
SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys);
handlesys = g_pHandleSys;
#endif
#if defined SMEXT_ENABLE_FORWARDSYS
SM_GET_IFACE(FORWARDMANAGER, g_pForwards);
forwards = g_pForwards;
#endif
#if defined SMEXT_ENABLE_PLAYERHELPERS
SM_GET_IFACE(PLAYERMANAGER, playerhelpers);
#endif
#if defined SMEXT_ENABLE_DBMANAGER
SM_GET_IFACE(DBI, dbi);
#endif
#if defined SMEXT_ENABLE_GAMECONF
SM_GET_IFACE(GAMECONFIG, gameconfs);
#endif
#if defined SMEXT_ENABLE_MEMUTILS
SM_GET_IFACE(MEMORYUTILS, memutils);
#endif
#if defined SMEXT_ENABLE_GAMEHELPERS
SM_GET_IFACE(GAMEHELPERS, gamehelpers);
#endif
#if defined SMEXT_ENABLE_TIMERSYS
SM_GET_IFACE(TIMERSYS, timersys);
#endif
#if defined SMEXT_ENABLE_ADTFACTORY
SM_GET_IFACE(ADTFACTORY, adtfactory);
#endif
#if defined SMEXT_ENABLE_THREADER
SM_GET_IFACE(THREADER, threader);
#endif
#if defined SMEXT_ENABLE_LIBSYS
SM_GET_IFACE(LIBRARYSYS, libsys);
#endif
#if defined SMEXT_ENABLE_PLUGINSYS
SM_GET_IFACE(PLUGINSYSTEM, plsys);
#endif
#if defined SMEXT_ENABLE_MENUS
SM_GET_IFACE(MENUMANAGER, menus);
#endif
#if defined SMEXT_ENABLE_ADMINSYS
SM_GET_IFACE(ADMINSYS, adminsys);
#endif
#if defined SMEXT_ENABLE_TEXTPARSERS
SM_GET_IFACE(TEXTPARSERS, textparsers);
#endif
#if defined SMEXT_ENABLE_USERMSGS
SM_GET_IFACE(USERMSGS, usermsgs);
#endif
#if defined SMEXT_ENABLE_TRANSLATOR
SM_GET_IFACE(TRANSLATOR, translator);
#endif
#if defined SMEXT_ENABLE_NINVOKE
SM_GET_IFACE(NINVOKE, ninvoke);
#endif
#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
SM_GET_IFACE(ROOTCONSOLE, rootconsole);
#endif
if (SDK_OnLoad(error, maxlength, late))
{
#if defined SMEXT_CONF_METAMOD
m_WeAreUnloaded = true;
#endif
return true;
}
return false;
}
bool SDKExtension::IsMetamodExtension()
{
#if defined SMEXT_CONF_METAMOD
return true;
#else
return false;
#endif
}
void SDKExtension::OnExtensionPauseChange(bool state)
{
#if defined SMEXT_CONF_METAMOD
m_WeGotPauseChange = true;
#endif
SDK_OnPauseChange(state);
}
void SDKExtension::OnExtensionsAllLoaded()
{
SDK_OnAllLoaded();
}
void SDKExtension::OnExtensionUnload()
{
#if defined SMEXT_CONF_METAMOD
m_WeAreUnloaded = true;
#endif
SDK_OnUnload();
}
void SDKExtension::OnDependenciesDropped()
{
SDK_OnDependenciesDropped();
}
const char *SDKExtension::GetExtensionAuthor()
{
return SMEXT_CONF_AUTHOR;
}
const char *SDKExtension::GetExtensionDateString()
{
return SMEXT_CONF_DATESTRING;
}
const char *SDKExtension::GetExtensionDescription()
{
return SMEXT_CONF_DESCRIPTION;
}
const char *SDKExtension::GetExtensionVerString()
{
return SMEXT_CONF_VERSION;
}
const char *SDKExtension::GetExtensionName()
{
return SMEXT_CONF_NAME;
}
const char *SDKExtension::GetExtensionTag()
{
return SMEXT_CONF_LOGTAG;
}
const char *SDKExtension::GetExtensionURL()
{
return SMEXT_CONF_URL;
}
bool SDKExtension::SDK_OnLoad(char *error, size_t maxlength, bool late)
{
return true;
}
void SDKExtension::SDK_OnUnload()
{
}
void SDKExtension::SDK_OnPauseChange(bool paused)
{
}
void SDKExtension::SDK_OnAllLoaded()
{
}
void SDKExtension::SDK_OnDependenciesDropped()
{
}
#if defined SMEXT_CONF_METAMOD
PluginId g_PLID = 0; /**< Metamod plugin ID */
ISmmPlugin *g_PLAPI = NULL; /**< Metamod plugin API */
SourceHook::ISourceHook *g_SHPtr = NULL; /**< SourceHook pointer */
ISmmAPI *g_SMAPI = NULL; /**< SourceMM API pointer */
#ifndef META_NO_HL2SDK
IVEngineServer *engine = NULL; /**< IVEngineServer pointer */
IServerGameDLL *gamedll = NULL; /**< IServerGameDLL pointer */
#endif
/** Exposes the extension to Metamod */
SMM_API void *PL_EXPOSURE(const char *name, int *code)
{
#if defined METAMOD_PLAPI_VERSION
if (name && !strcmp(name, METAMOD_PLAPI_NAME))
#else
if (name && !strcmp(name, PLAPI_NAME))
#endif
{
if (code)
{
*code = META_IFACE_OK;
}
return static_cast<void *>(g_pExtensionIface);
}
if (code)
{
*code = META_IFACE_FAILED;
}
return NULL;
}
bool SDKExtension::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
{
PLUGIN_SAVEVARS();
#ifndef META_NO_HL2SDK
#if !defined METAMOD_PLAPI_VERSION
GET_V_IFACE_ANY(serverFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
#else
GET_V_IFACE_ANY(GetServerFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
#endif
#endif //META_NO_HL2SDK
m_SourceMMLoaded = true;
return SDK_OnMetamodLoad(ismm, error, maxlen, late);
}
bool SDKExtension::Unload(char *error, size_t maxlen)
{
if (!m_WeAreUnloaded)
{
if (error)
{
snprintf(error, maxlen, "This extension must be unloaded by SourceMod.");
}
return false;
}
return SDK_OnMetamodUnload(error, maxlen);
}
bool SDKExtension::Pause(char *error, size_t maxlen)
{
if (!m_WeGotPauseChange)
{
if (error)
{
snprintf(error, maxlen, "This extension must be paused by SourceMod.");
}
return false;
}
m_WeGotPauseChange = false;
return SDK_OnMetamodPauseChange(true, error, maxlen);
}
bool SDKExtension::Unpause(char *error, size_t maxlen)
{
if (!m_WeGotPauseChange)
{
if (error)
{
snprintf(error, maxlen, "This extension must be unpaused by SourceMod.");
}
return false;
}
m_WeGotPauseChange = false;
return SDK_OnMetamodPauseChange(false, error, maxlen);
}
const char *SDKExtension::GetAuthor()
{
return GetExtensionAuthor();
}
const char *SDKExtension::GetDate()
{
return GetExtensionDateString();
}
const char *SDKExtension::GetDescription()
{
return GetExtensionDescription();
}
const char *SDKExtension::GetLicense()
{
return SMEXT_CONF_LICENSE;
}
const char *SDKExtension::GetLogTag()
{
return GetExtensionTag();
}
const char *SDKExtension::GetName()
{
return GetExtensionName();
}
const char *SDKExtension::GetURL()
{
return GetExtensionURL();
}
const char *SDKExtension::GetVersion()
{
return GetExtensionVerString();
}
bool SDKExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late)
{
return true;
}
bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t maxlength)
{
return true;
}
bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength)
{
return true;
}
#endif
/* Overload a few things to prevent libstdc++ linking */
#if defined __linux__ || defined __APPLE__
extern "C" void __cxa_pure_virtual(void)
{
}
void *operator new(size_t size)
{
return malloc(size);
}
void *operator new[](size_t size)
{
return malloc(size);
}
void operator delete(void *ptr)
{
free(ptr);
}
void operator delete[](void * ptr)
{
free(ptr);
}
#endif
-358
View File
@@ -1,358 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet:
* =============================================================================
* SourceMod Base Extension Code
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program 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
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
/**
* @file smsdk_ext.h
* @brief Contains wrappers for making Extensions easier to write.
*/
#include "smsdk_config.h"
#include <IExtensionSys.h>
#include <IHandleSys.h>
#include <sp_vm_api.h>
#include <sm_platform.h>
#include <ISourceMod.h>
#if defined SMEXT_ENABLE_FORWARDSYS
#include <IForwardSys.h>
#endif //SMEXT_ENABLE_FORWARDSYS
#if defined SMEXT_ENABLE_PLAYERHELPERS
#include <IPlayerHelpers.h>
#endif //SMEXT_ENABLE_PlAYERHELPERS
#if defined SMEXT_ENABLE_DBMANAGER
#include <IDBDriver.h>
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_GAMECONF
#include <IGameConfigs.h>
#endif
#if defined SMEXT_ENABLE_MEMUTILS
#include <IMemoryUtils.h>
#endif
#if defined SMEXT_ENABLE_GAMEHELPERS
#include <IGameHelpers.h>
#endif
#if defined SMEXT_ENABLE_TIMERSYS
#include <ITimerSystem.h>
#endif
#if defined SMEXT_ENABLE_ADTFACTORY
#include <IADTFactory.h>
#endif
#if defined SMEXT_ENABLE_THREADER
#include <IThreader.h>
#endif
#if defined SMEXT_ENABLE_LIBSYS
#include <ILibrarySys.h>
#endif
#if defined SMEXT_ENABLE_PLUGINSYS
#include <IPluginSys.h>
#endif
#if defined SMEXT_ENABLE_MENUS
#include <IMenuManager.h>
#endif
#if defined SMEXT_ENABLE_ADMINSYS
#include <IAdminSystem.h>
#endif
#if defined SMEXT_ENABLE_TEXTPARSERS
#include <ITextParsers.h>
#endif
#if defined SMEXT_ENABLE_USERMSGS
#include <IUserMessages.h>
#endif
#if defined SMEXT_ENABLE_TRANSLATOR
#include <ITranslator.h>
#endif
#if defined SMEXT_ENABLE_NINVOKE
#include <INativeInvoker.h>
#endif
#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
#include <IRootConsoleMenu.h>
#endif
#if defined SMEXT_CONF_METAMOD
#include <ISmmPlugin.h>
#ifndef META_NO_HL2SDK
#include <eiface.h>
#endif // META_NO_HL2SDK
#endif
using namespace SourceMod;
using namespace SourcePawn;
class SDKExtension :
#if defined SMEXT_CONF_METAMOD
public ISmmPlugin,
#endif
public IExtensionInterface
{
public:
/** Constructor */
SDKExtension();
public:
/**
* @brief This is called after the initial loading sequence has been processed.
*
* @param error Error message buffer.
* @param maxlength Size of error message buffer.
* @param late Whether or not the module was loaded after map load.
* @return True to succeed loading, false to fail.
*/
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
/**
* @brief This is called once the extension unloading process begins.
*/
virtual void SDK_OnUnload();
/**
* @brief This is called once all known extensions have been loaded.
*/
virtual void SDK_OnAllLoaded();
/**
* @brief Called when the pause state is changed.
*/
virtual void SDK_OnPauseChange(bool paused);
/**
* @brief Called after SDK_OnUnload, once all dependencies have been
* removed, and the extension is about to be removed from memory.
*/
virtual void SDK_OnDependenciesDropped();
#if defined SMEXT_CONF_METAMOD
/**
* @brief Called when Metamod is attached, before the extension version is called.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @param late Whether or not Metamod considers this a late load.
* @return True to succeed, false to fail.
*/
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);
/**
* @brief Called when Metamod is detaching, after the extension version is called.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);
/**
* @brief Called when Metamod's pause state is changing.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param paused Pause state being set.
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
#endif
public: //IExtensionInterface
virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late);
virtual void OnExtensionUnload();
virtual void OnExtensionsAllLoaded();
/** Returns whether or not this is a Metamod-based extension */
virtual bool IsMetamodExtension();
/**
* @brief Called when the pause state changes.
*
* @param state True if being paused, false if being unpaused.
*/
virtual void OnExtensionPauseChange(bool state);
/** Returns name */
virtual const char *GetExtensionName();
/** Returns URL */
virtual const char *GetExtensionURL();
/** Returns log tag */
virtual const char *GetExtensionTag();
/** Returns author */
virtual const char *GetExtensionAuthor();
/** Returns version string */
virtual const char *GetExtensionVerString();
/** Returns description string */
virtual const char *GetExtensionDescription();
/** Returns date string */
virtual const char *GetExtensionDateString();
/** Called after OnExtensionUnload, once dependencies have been dropped. */
virtual void OnDependenciesDropped();
#if defined SMEXT_CONF_METAMOD
public: //ISmmPlugin
/** Called when the extension is attached to Metamod. */
virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late);
/** Returns the author to MM */
virtual const char *GetAuthor();
/** Returns the name to MM */
virtual const char *GetName();
/** Returns the description to MM */
virtual const char *GetDescription();
/** Returns the URL to MM */
virtual const char *GetURL();
/** Returns the license to MM */
virtual const char *GetLicense();
/** Returns the version string to MM */
virtual const char *GetVersion();
/** Returns the date string to MM */
virtual const char *GetDate();
/** Returns the logtag to MM */
virtual const char *GetLogTag();
/** Called on unload */
virtual bool Unload(char *error, size_t maxlength);
/** Called on pause */
virtual bool Pause(char *error, size_t maxlength);
/** Called on unpause */
virtual bool Unpause(char *error, size_t maxlength);
private:
bool m_SourceMMLoaded;
bool m_WeAreUnloaded;
bool m_WeGotPauseChange;
#endif
};
extern SDKExtension *g_pExtensionIface;
extern IExtension *myself;
extern IShareSys *g_pShareSys;
extern IShareSys *sharesys; /* Note: Newer name */
extern ISourceMod *g_pSM;
extern ISourceMod *smutils; /* Note: Newer name */
/* Optional interfaces are below */
#if defined SMEXT_ENABLE_FORWARDSYS
extern IForwardManager *g_pForwards;
extern IForwardManager *forwards; /* Note: Newer name */
#endif //SMEXT_ENABLE_FORWARDSYS
#if defined SMEXT_ENABLE_HANDLESYS
extern IHandleSys *g_pHandleSys;
extern IHandleSys *handlesys; /* Note: Newer name */
#endif //SMEXT_ENABLE_HANDLESYS
#if defined SMEXT_ENABLE_PLAYERHELPERS
extern IPlayerManager *playerhelpers;
#endif //SMEXT_ENABLE_PLAYERHELPERS
#if defined SMEXT_ENABLE_DBMANAGER
extern IDBManager *dbi;
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_GAMECONF
extern IGameConfigManager *gameconfs;
#endif //SMEXT_ENABLE_DBMANAGER
#if defined SMEXT_ENABLE_MEMUTILS
extern IMemoryUtils *memutils;
#endif
#if defined SMEXT_ENABLE_GAMEHELPERS
extern IGameHelpers *gamehelpers;
#endif
#if defined SMEXT_ENABLE_TIMERSYS
extern ITimerSystem *timersys;
#endif
#if defined SMEXT_ENABLE_ADTFACTORY
extern IADTFactory *adtfactory;
#endif
#if defined SMEXT_ENABLE_THREADER
extern IThreader *threader;
#endif
#if defined SMEXT_ENABLE_LIBSYS
extern ILibrarySys *libsys;
#endif
#if defined SMEXT_ENABLE_PLUGINSYS
extern SourceMod::IPluginManager *plsys;
#endif
#if defined SMEXT_ENABLE_MENUS
extern IMenuManager *menus;
#endif
#if defined SMEXT_ENABLE_ADMINSYS
extern IAdminSystem *adminsys;
#endif
#if defined SMEXT_ENABLE_USERMSGS
extern IUserMessages *usermsgs;
#endif
#if defined SMEXT_ENABLE_TRANSLATOR
extern ITranslator *translator;
#endif
#if defined SMEXT_ENABLE_NINVOKE
extern INativeInterface *ninvoke;
#endif
#if defined SMEXT_ENABLE_ROOTCONSOLEMENU
extern IRootConsole *rootconsole;
#endif
#if defined SMEXT_CONF_METAMOD
PLUGIN_GLOBALVARS();
#ifndef META_NO_HL2SDK
extern IVEngineServer *engine;
extern IServerGameDLL *gamedll;
#endif //META_NO_HL2SDK
#endif
/** Creates a SourceMod interface macro pair */
#define SM_MKIFACE(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION
/** Automates retrieving SourceMod interfaces */
#define SM_GET_IFACE(prefix, addr) \
if (!g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)) \
{ \
if (error != NULL && maxlength) \
{ \
size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \
if (len >= maxlength) \
{ \
error[maxlength - 1] = '\0'; \
} \
} \
return false; \
}
/** Automates retrieving SourceMod interfaces when needed outside of SDK_OnLoad() */
#define SM_GET_LATE_IFACE(prefix, addr) \
g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)
/** Validates a SourceMod interface pointer */
#define SM_CHECK_IFACE(prefix, addr) \
if (!addr) \
{ \
if (error != NULL && maxlength) \
{ \
size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \
if (len >= maxlength) \
{ \
error[maxlength - 1] = '\0'; \
} \
} \
return false; \
}
#endif // _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
+30 -12
View File
@@ -17,6 +17,9 @@
*/ */
#include "ssnatives.h" #include "ssnatives.h"
#include "extension.h"
#include <steam_gameserver.h>
#include "swgameserver.h"
static bool IsSteamWorksLoaded(void) static bool IsSteamWorksLoaded(void)
{ {
@@ -60,11 +63,16 @@ static cell_t sm_RequestUserStats(IPluginContext *pContext, const cell_t *params
return 0; return 0;
} }
int client = gamehelpers->ReferenceToIndex(params[1]); int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); /* Man, including GameHelpers and PlayerHelpers for this native :(. */ if (client < 1 || client > playerhelpers->GetMaxClients())
if (pPlayer == NULL || pPlayer->IsConnected() == false)
{ {
return pContext->ThrowNativeError("Client index %d is invalid", params[1]); return pContext->ThrowNativeError("Client index %d is invalid", client);
}
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (pPlayer == NULL || !pPlayer->IsConnected())
{
return pContext->ThrowNativeError("Client index %d is not connected", client);
} }
CSteamID checkid = CreateCommonCSteamID(pPlayer, params); CSteamID checkid = CreateCommonCSteamID(pPlayer, params);
@@ -80,11 +88,16 @@ static cell_t sm_GetStatCell(IPluginContext *pContext, const cell_t *params)
return 0; return 0;
} }
int client = gamehelpers->ReferenceToIndex(params[1]); int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); /* Man, including GameHelpers and PlayerHelpers for this native :(. */ if (client < 1 || client > playerhelpers->GetMaxClients())
if (pPlayer == NULL || pPlayer->IsConnected() == false)
{ {
return pContext->ThrowNativeError("Client index %d is invalid", params[1]); return pContext->ThrowNativeError("Client index %d is invalid", client);
}
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (pPlayer == NULL || !pPlayer->IsConnected())
{
return pContext->ThrowNativeError("Client index %d is not connected", client);
} }
char *pName; char *pName;
@@ -123,11 +136,16 @@ static cell_t sm_GetStatFloat(IPluginContext *pContext, const cell_t *params)
return 0; return 0;
} }
int client = gamehelpers->ReferenceToIndex(params[1]); int client = params[1];
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client); /* Man, including GameHelpers and PlayerHelpers for this native :(. */ if (client < 1 || client > playerhelpers->GetMaxClients())
if (pPlayer == NULL || pPlayer->IsConnected() == false)
{ {
return pContext->ThrowNativeError("Client index %d is invalid", params[1]); return pContext->ThrowNativeError("Client index %d is invalid", client);
}
IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
if (pPlayer == NULL || !pPlayer->IsConnected())
{
return pContext->ThrowNativeError("Client index %d is not connected", client);
} }
char *pName; char *pName;
-3
View File
@@ -17,7 +17,6 @@
*/ */
#pragma once #pragma once
#include "smsdk_ext.h"
class SteamWorksSSNatives class SteamWorksSSNatives
{ {
@@ -25,5 +24,3 @@ class SteamWorksSSNatives
SteamWorksSSNatives(); SteamWorksSSNatives();
~SteamWorksSSNatives(); ~SteamWorksSSNatives();
}; };
#include "extension.h"
+2
View File
@@ -17,6 +17,8 @@
*/ */
#include "swforwards.h" #include "swforwards.h"
#include <smsdk_ext.h>
#include <steam_gameserver.h>
SteamWorksForwards::SteamWorksForwards() : SteamWorksForwards::SteamWorksForwards() :
m_CallbackGSClientApprove(this, &SteamWorksForwards::OnGSClientApprove), m_CallbackGSClientApprove(this, &SteamWorksForwards::OnGSClientApprove),
+13 -9
View File
@@ -17,9 +17,13 @@
*/ */
#pragma once #pragma once
#include "isteamgameserver.h"
#include "steam_gameserver.h" #include <steam_gameserver.h>
#include "smsdk_ext.h"
namespace SourceMod
{
class IForward;
}
typedef uint32_t Account_t; typedef uint32_t Account_t;
@@ -41,10 +45,10 @@ class SteamWorksForwards
STEAM_GAMESERVER_CALLBACK(SteamWorksForwards, OnGroupStatusResult, GSClientGroupStatus_t, m_CallbackGroupStatus); STEAM_GAMESERVER_CALLBACK(SteamWorksForwards, OnGroupStatusResult, GSClientGroupStatus_t, m_CallbackGroupStatus);
private: private:
IForward *pFOVC; /* Forward On Validate Client */ SourceMod::IForward *pFOVC; /* Forward On Validate Client */
IForward *pFOVC_Old; /* OLD Forward On Validate Client */ SourceMod::IForward *pFOVC_Old; /* OLD Forward On Validate Client */
IForward *pFOSSC; /* Forward On Steam Servers Connected */ SourceMod::IForward *pFOSSC; /* Forward On Steam Servers Connected */
IForward *pFOSSCF; /* Forward On Steam Servers Connect Failure */ SourceMod::IForward *pFOSSCF; /* Forward On Steam Servers Connect Failure */
IForward *pFOSSD; /* Forward On Steam Servers Disconnected */ SourceMod::IForward *pFOSSD; /* Forward On Steam Servers Disconnected */
IForward *pFOCGS; /* Forward On Client Group Status */ SourceMod::IForward *pFOCGS; /* Forward On Client Group Status */
}; };
+2
View File
@@ -15,7 +15,9 @@
Author: Kyle Sanderson (KyleS). Author: Kyle Sanderson (KyleS).
*/ */
#include "swgamedata.h" #include "swgamedata.h"
#include <smsdk_ext.h>
SteamWorksGameData::SteamWorksGameData() SteamWorksGameData::SteamWorksGameData()
{ {
+7 -5
View File
@@ -17,7 +17,11 @@
*/ */
#pragma once #pragma once
#include "smsdk_ext.h"
namespace SourceMod
{
class IGameConfig;
}
class SteamWorksGameData class SteamWorksGameData
{ {
@@ -27,10 +31,8 @@ class SteamWorksGameData
public: public:
bool HasGameData(void) const; bool HasGameData(void) const;
IGameConfig *GetGameData(void) const; SourceMod::IGameConfig *GetGameData(void) const;
private: private:
IGameConfig *pGameConf; SourceMod::IGameConfig *pGameConf;
}; };
#include "extension.h"
+13
View File
@@ -17,6 +17,19 @@
*/ */
#include "swgameserver.h" #include "swgameserver.h"
#include "extension.h"
#include "swgamedata.h"
#include <smsdk_ext.h>
#include <isteamclient.h>
#include <isteamgameserver.h>
#include <isteamutils.h>
#include <isteamnetworking.h>
#include <isteamgameserverstats.h>
#include <isteamhttp.h>
#include <isteammatchmaking.h>
#include <isteamgamecoordinator.h>
static void GetGameSpecificConfigInterface(const char *pName, const char *&pVersion) static void GetGameSpecificConfigInterface(const char *pName, const char *&pVersion)
{ {
+4 -5
View File
@@ -17,9 +17,10 @@
*/ */
#pragma once #pragma once
#include "smsdk_ext.h"
#include "steam_gameserver.h" #include <steam_api_common.h>
#include "isteamgamecoordinator.h"
class ISteamGameCoordinator;
#if defined(STEAM_API_INTERNAL_H) || !defined(STEAM_API_EXPORTS) #if defined(STEAM_API_INTERNAL_H) || !defined(STEAM_API_EXPORTS)
S_API ISteamClient *g_pSteamClientGameServer; /* This is awful. */ S_API ISteamClient *g_pSteamClientGameServer; /* This is awful. */
@@ -57,5 +58,3 @@ class SteamWorksGameServer
ISteamGameCoordinator *m_pGC; ISteamGameCoordinator *m_pGC;
bool loaded; bool loaded;
}; };
#include "extension.h"
+7
View File
@@ -17,6 +17,13 @@
*/ */
#include "swgchooks.h" #include "swgchooks.h"
#include "extension.h"
#include "swgameserver.h"
#include <isteamgamecoordinator.h>
#ifdef _WIN32
#undef SendMessage
#endif
enum enum
{ {
+9 -12
View File
@@ -17,15 +17,14 @@
*/ */
#pragma once #pragma once
#include "steam_gameserver.h"
#include "isteamgamecoordinator.h"
#include "smsdk_ext.h" #include <isteamgamecoordinator.h>
#include "sourcehook.h" #include <cstdint>
#ifdef _WIN32 namespace SourceMod
#undef SendMessage {
#endif class IForward;
}
class SteamWorksGCHooks class SteamWorksGCHooks
{ {
@@ -43,12 +42,10 @@ class SteamWorksGCHooks
EGCResults RetrieveMessage(uint32 *punMsgType, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize); EGCResults RetrieveMessage(uint32 *punMsgType, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize);
private: private:
IForward *pGCSendMsg; SourceMod::IForward *pGCSendMsg;
IForward *pGCMsgAvail; SourceMod::IForward *pGCMsgAvail;
IForward *pGCRetMsg; SourceMod::IForward *pGCRetMsg;
unsigned char uHooked; unsigned char uHooked;
}; };
void OurGCGameFrameHook(bool simulating); void OurGCGameFrameHook(bool simulating);
#include "extension.h"
+5
View File
@@ -17,6 +17,11 @@
*/ */
#include "swgsdetours.h" #include "swgsdetours.h"
#include "extension.h"
#include "swgameserver.h"
#include "swgshooks.h"
#include "swgamedata.h"
#include <steam_gameserver.h>
DETOUR_DECL_STATIC0(SteamAPIShutdown, void) DETOUR_DECL_STATIC0(SteamAPIShutdown, void)
{ {
+4 -5
View File
@@ -17,9 +17,10 @@
*/ */
#pragma once #pragma once
#include "smsdk_ext.h"
#include "steam_gameserver.h" #include <CDetour/detours.h>
#include "CDetour/detours.h"
class CDetour;
/* SourceMod's safetyhook-based CDetour doesn't ship the "fixed address" helper the /* SourceMod's safetyhook-based CDetour doesn't ship the "fixed address" helper the
old vendored copy had, so define it in terms of the address overload it does expose. */ old vendored copy had, so define it in terms of the address overload it does expose. */
@@ -37,5 +38,3 @@ class SteamWorksGSDetours
CDetour *m_pSafeInitDetour; CDetour *m_pSafeInitDetour;
CDetour *m_pShutdownDetour; CDetour *m_pShutdownDetour;
}; };
#include "extension.h"
+5 -1
View File
@@ -17,7 +17,11 @@
*/ */
#include "swgshooks.h" #include "swgshooks.h"
#include "steamtools/ticket.h" #include "extension.h"
//#include <steamtools/ticket.h> // ????
#include <isteamgameserver.h>
#include <smsdk_ext.h>
#include "swgameserver.h"
enum enum
{ {
+10 -9
View File
@@ -17,10 +17,13 @@
*/ */
#pragma once #pragma once
#include "isteamgameserver.h"
#include "steam_gameserver.h" #include <isteamgameserver.h>
#include "smsdk_ext.h"
#include "sourcehook.h" namespace SourceMod
{
class IForward;
}
class SteamWorksGSHooks class SteamWorksGSHooks
{ {
@@ -38,12 +41,10 @@ class SteamWorksGSHooks
EBeginAuthSessionResult BeginAuthSession(const void*, int, CSteamID); EBeginAuthSessionResult BeginAuthSession(const void*, int, CSteamID);
private: private:
IForward *pFORR; /* On Restart Requested. */ SourceMod::IForward *pFORR; /* On Restart Requested. */
IForward *pFOTR; /* On Token Requested. */ SourceMod::IForward *pFOTR; /* On Token Requested. */
IForward *pOBAS; /* On Begin Auth Session. */ SourceMod::IForward *pOBAS; /* On Begin Auth Session. */
unsigned char uHooked; unsigned char uHooked;
}; };
void OurGameFrameHook(bool simulating); void OurGameFrameHook(bool simulating);
#include "extension.h"
+46 -1
View File
@@ -17,13 +17,18 @@
*/ */
#include "swhttp.h" #include "swhttp.h"
#include "extension.h"
#include "swgameserver.h"
#include "swhttprequest.h"
static ISteamHTTP *GetHTTPPointer() static ISteamHTTP *GetHTTPPointer()
{ {
return g_SteamWorks.pSWGameServer->GetHTTP(); return g_SteamWorks.pSWGameServer->GetHTTP();
} }
SteamWorksHTTP::SteamWorksHTTP() SteamWorksHTTP::SteamWorksHTTP() :
m_CallbackHeadersReceived(this, &SteamWorksHTTP::OnHTTPHeadersReceived),
m_CallbackDataReceived(this, &SteamWorksHTTP::OnHTTPDataReceived)
{ {
this->typeHTTP = handlesys->CreateType("HTTPHandle", this, 0, NULL, NULL, myself->GetIdentity(), NULL); this->typeHTTP = handlesys->CreateType("HTTPHandle", this, 0, NULL, NULL, myself->GetIdentity(), NULL);
} }
@@ -38,6 +43,46 @@ HandleType_t SteamWorksHTTP::GetHTTPHandle(void)
return this->typeHTTP; return this->typeHTTP;
} }
void SteamWorksHTTP::RegisterRequest(SteamWorksHTTPRequest *pRequest)
{
if (pRequest->request != INVALID_HTTPREQUEST_HANDLE)
{
this->m_Requests[pRequest->request] = pRequest;
}
}
void SteamWorksHTTP::UnregisterRequest(SteamWorksHTTPRequest *pRequest)
{
if (pRequest->request != INVALID_HTTPREQUEST_HANDLE)
{
this->m_Requests.erase(pRequest->request);
}
}
SteamWorksHTTPRequest *SteamWorksHTTP::FindRequest(HTTPRequestHandle request)
{
auto it = this->m_Requests.find(request);
return (it == this->m_Requests.end()) ? NULL : it->second;
}
void SteamWorksHTTP::OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *pParam)
{
SteamWorksHTTPRequest *pRequest = this->FindRequest(pParam->m_hRequest);
if (pRequest != NULL)
{
pRequest->OnHTTPHeadersReceived(pParam);
}
}
void SteamWorksHTTP::OnHTTPDataReceived(HTTPRequestDataReceived_t *pParam)
{
SteamWorksHTTPRequest *pRequest = this->FindRequest(pParam->m_hRequest);
if (pRequest != NULL)
{
pRequest->OnHTTPDataReceived(pParam);
}
}
static void DelayedDeleteSteamWorksHTTPRequest(void *object) static void DelayedDeleteSteamWorksHTTPRequest(void *object)
{ {
SteamWorksHTTPRequest *pRequest = reinterpret_cast<SteamWorksHTTPRequest *>(object); SteamWorksHTTPRequest *pRequest = reinterpret_cast<SteamWorksHTTPRequest *>(object);
+23 -6
View File
@@ -17,9 +17,14 @@
*/ */
#pragma once #pragma once
#include "isteamgameserver.h"
#include "steam_gameserver.h" #include <steam_gameserver.h>
#include "smsdk_ext.h" #include <isteamhttp.h>
#include <smsdk_ext.h>
#include <unordered_map>
class SteamWorksHTTPRequest;
class SteamWorksHTTP : class SteamWorksHTTP :
public IHandleTypeDispatch public IHandleTypeDispatch
@@ -35,9 +40,21 @@ class SteamWorksHTTP :
public: public:
HandleType_t GetHTTPHandle(void); HandleType_t GetHTTPHandle(void);
/* Streaming responses report progress through HTTPRequestHeadersReceived_t /
HTTPRequestDataReceived_t. Steam delivers those as broadcast gameserver
callbacks (not as call results of the streaming API call), so a single
dispatcher here receives them and routes each one to the owning request by
its handle. Requests add/remove themselves as they are created/destroyed. */
void RegisterRequest(SteamWorksHTTPRequest *pRequest);
void UnregisterRequest(SteamWorksHTTPRequest *pRequest);
private:
SteamWorksHTTPRequest *FindRequest(HTTPRequestHandle request);
STEAM_GAMESERVER_CALLBACK(SteamWorksHTTP, OnHTTPHeadersReceived, HTTPRequestHeadersReceived_t, m_CallbackHeadersReceived);
STEAM_GAMESERVER_CALLBACK(SteamWorksHTTP, OnHTTPDataReceived, HTTPRequestDataReceived_t, m_CallbackDataReceived);
private: private:
HandleType_t typeHTTP; HandleType_t typeHTTP;
std::unordered_map<HTTPRequestHandle, SteamWorksHTTPRequest *> m_Requests;
}; };
#include "swhttprequest.h"
#include "extension.h"
+53 -19
View File
@@ -17,8 +17,9 @@
*/ */
#include "swhttprequest.h" #include "swhttprequest.h"
#include "extension.h"
#include <cstdio> #include "swgameserver.h"
#include "swhttp.h"
/* SourceMod 1.13 (extension API 9) changed IPluginManager::FindPluginByContext() /* SourceMod 1.13 (extension API 9) changed IPluginManager::FindPluginByContext()
to take an IPluginContext* directly; older SM (API 8) takes the low-level to take an IPluginContext* directly; older SM (API 8) takes the low-level
@@ -67,6 +68,14 @@ SteamWorksHTTPRequest::SteamWorksHTTPRequest() : request(INVALID_HTTPREQUEST_HAN
SteamWorksHTTPRequest::~SteamWorksHTTPRequest() SteamWorksHTTPRequest::~SteamWorksHTTPRequest()
{ {
/* Requests are freed via a frame action, so on extension unload this can run
after the dispatcher itself has been torn down; pSWHTTP is nulled in that
case (see SDK_OnUnload), so guard against it. */
if (g_SteamWorks.pSWHTTP != NULL)
{
g_SteamWorks.pSWHTTP->UnregisterRequest(this);
}
ISteamHTTP *pHTTP = GetHTTPPointer(); ISteamHTTP *pHTTP = GetHTTPPointer();
if (pHTTP != NULL) if (pHTTP != NULL)
{ {
@@ -101,7 +110,10 @@ void SteamWorksHTTPRequest::OnHTTPRequestCompleted(HTTPRequestCompleted_t *pRequ
this->pCompletedForward->Execute(NULL); this->pCompletedForward->Execute(NULL);
} }
void SteamWorksHTTPRequest::OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *pRequest, bool bFailed) /* Streaming header/data notifications are success-only callbacks (unlike the
completion call result, they carry no IO-failure flag), so bFailure is always
false here. Failures still surface through the completion callback. */
void SteamWorksHTTPRequest::OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *pRequest)
{ {
if (this->pHeadersReceivedForward == NULL || this->pHeadersReceivedForward->GetFunctionCount() == 0) if (this->pHeadersReceivedForward == NULL || this->pHeadersReceivedForward->GetFunctionCount() == 0)
{ {
@@ -109,13 +121,13 @@ void SteamWorksHTTPRequest::OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *
} }
this->pHeadersReceivedForward->PushCell(this->handle); this->pHeadersReceivedForward->PushCell(this->handle);
this->pHeadersReceivedForward->PushCell(bFailed); this->pHeadersReceivedForward->PushCell(false);
this->pHeadersReceivedForward->PushCell(pRequest->m_ulContextValue >> 32); this->pHeadersReceivedForward->PushCell(pRequest->m_ulContextValue >> 32);
this->pHeadersReceivedForward->PushCell((pRequest->m_ulContextValue & 0x00000000FFFFFFFF)); this->pHeadersReceivedForward->PushCell((pRequest->m_ulContextValue & 0x00000000FFFFFFFF));
this->pHeadersReceivedForward->Execute(NULL); this->pHeadersReceivedForward->Execute(NULL);
} }
void SteamWorksHTTPRequest::OnHTTPDataReceived(HTTPRequestDataReceived_t *pRequest, bool bFailed) void SteamWorksHTTPRequest::OnHTTPDataReceived(HTTPRequestDataReceived_t *pRequest)
{ {
if (this->pDataReceivedForward == NULL || this->pDataReceivedForward->GetFunctionCount() == 0) if (this->pDataReceivedForward == NULL || this->pDataReceivedForward->GetFunctionCount() == 0)
{ {
@@ -123,7 +135,7 @@ void SteamWorksHTTPRequest::OnHTTPDataReceived(HTTPRequestDataReceived_t *pReque
} }
this->pDataReceivedForward->PushCell(this->handle); this->pDataReceivedForward->PushCell(this->handle);
this->pDataReceivedForward->PushCell(bFailed); this->pDataReceivedForward->PushCell(false);
this->pDataReceivedForward->PushCell(pRequest->m_cOffset); this->pDataReceivedForward->PushCell(pRequest->m_cOffset);
this->pDataReceivedForward->PushCell(pRequest->m_cBytesReceived); this->pDataReceivedForward->PushCell(pRequest->m_cBytesReceived);
this->pDataReceivedForward->PushCell(pRequest->m_ulContextValue >> 32); this->pDataReceivedForward->PushCell(pRequest->m_ulContextValue >> 32);
@@ -160,6 +172,8 @@ static cell_t sm_CreateHTTPRequest(IPluginContext *pContext, const cell_t *param
pRequest->request = request; pRequest->request = request;
pRequest->handle = handle; pRequest->handle = handle;
g_SteamWorks.pSWHTTP->RegisterRequest(pRequest);
return handle; return handle;
} }
@@ -296,23 +310,14 @@ static cell_t sm_SetCallbacks(IPluginContext *pContext, const cell_t *params)
static void SetCallbacks(SteamAPICall_t &hCall, SteamWorksHTTPRequest *pRequest) static void SetCallbacks(SteamAPICall_t &hCall, SteamWorksHTTPRequest *pRequest)
{ {
/* Only completion is a call result of this send. Header/data streaming
notifications are delivered as broadcast callbacks and routed to the request
by SteamWorksHTTP's dispatcher, so there is nothing to bind to hCall here. */
if (pRequest->pCompletedForward != NULL) if (pRequest->pCompletedForward != NULL)
{ {
pRequest->CompletedCallResult.SetGameserverFlag(); pRequest->CompletedCallResult.SetGameserverFlag();
pRequest->CompletedCallResult.Set(hCall, pRequest, &SteamWorksHTTPRequest::OnHTTPRequestCompleted); pRequest->CompletedCallResult.Set(hCall, pRequest, &SteamWorksHTTPRequest::OnHTTPRequestCompleted);
} }
if (pRequest->pHeadersReceivedForward != NULL)
{
pRequest->HeadersCallResult.SetGameserverFlag();
pRequest->HeadersCallResult.Set(hCall, pRequest, &SteamWorksHTTPRequest::OnHTTPHeadersReceived);
}
if (pRequest->pDataReceivedForward != NULL)
{
pRequest->DataCallResult.SetGameserverFlag();
pRequest->DataCallResult.Set(hCall, pRequest, &SteamWorksHTTPRequest::OnHTTPDataReceived);
}
} }
static cell_t sm_SendHTTPRequestAndStreamResponse(IPluginContext *pContext, const cell_t *params) static cell_t sm_SendHTTPRequestAndStreamResponse(IPluginContext *pContext, const cell_t *params)
@@ -500,7 +505,7 @@ static cell_t sm_SetHTTPRequestRawPostBodyFromFile(IPluginContext *pContext, con
} }
char *pBuffer = new char[size + 1]; char *pBuffer = new char[size + 1];
uint32_t itemsRead = fread(pBuffer, sizeof(char), size, pInputFile); size_t itemsRead = fread(pBuffer, sizeof(char), size, pInputFile);
fclose(pInputFile); fclose(pInputFile);
if (itemsRead != size) if (itemsRead != size)
@@ -706,6 +711,35 @@ static sp_nativeinfo_t httpnatives[] = {
{"SteamWorks_WriteHTTPResponseBodyToFile", sm_WriteHTTPResponseBodyToFile}, {"SteamWorks_WriteHTTPResponseBodyToFile", sm_WriteHTTPResponseBodyToFile},
{"SteamWorks_SendHTTPRequestAndStreamResponse", sm_SendHTTPRequestAndStreamResponse}, {"SteamWorks_SendHTTPRequestAndStreamResponse", sm_SendHTTPRequestAndStreamResponse},
{"SteamWorks_GetHTTPStreamingResponseBodyData", sm_GetHTTPStreamingResponseBodyData}, {"SteamWorks_GetHTTPStreamingResponseBodyData", sm_GetHTTPStreamingResponseBodyData},
/* SteamWorksHTTPRequest methodmap. These reuse the functions above; the implicit
`this` handle arrives as params[1], exactly like the hHandle/hRequest first
parameter of the free-function natives (and the constructor maps to the create
native, whose first argument is likewise params[1]). */
{"SteamWorksHTTPRequest.SteamWorksHTTPRequest", sm_CreateHTTPRequest},
{"SteamWorksHTTPRequest.SetContextValue", sm_SetHTTPRequestContextValue},
{"SteamWorksHTTPRequest.SetNetworkActivityTimeout", sm_SetHTTPRequestNetworkActivityTimeout},
{"SteamWorksHTTPRequest.SetHeaderValue", sm_SetHTTPRequestHeaderValue},
{"SteamWorksHTTPRequest.SetGetOrPostParameter", sm_SetHTTPRequestGetOrPostParameter},
{"SteamWorksHTTPRequest.SetUserAgentInfo", sm_SetHTTPRequestUserAgentInfo},
{"SteamWorksHTTPRequest.SetRequiresVerifiedCertificate", sm_SetHTTPRequestRequiresVerifiedCertificate},
{"SteamWorksHTTPRequest.SetAbsoluteTimeoutMS", sm_SetHTTPRequestAbsoluteTimeoutMS},
{"SteamWorksHTTPRequest.SetCallbacks", sm_SetCallbacks},
{"SteamWorksHTTPRequest.Send", sm_SendHTTPRequest},
{"SteamWorksHTTPRequest.SendAndStreamResponse", sm_SendHTTPRequestAndStreamResponse},
{"SteamWorksHTTPRequest.Defer", sm_DeferHTTPRequest},
{"SteamWorksHTTPRequest.Prioritize", sm_PrioritizeHTTPRequest},
{"SteamWorksHTTPRequest.GetResponseHeaderSize", sm_GetHTTPResponseHeaderSize},
{"SteamWorksHTTPRequest.GetResponseHeaderValue", sm_GetHTTPResponseHeaderValue},
{"SteamWorksHTTPRequest.GetResponseBodySize", sm_GetHTTPResponseBodySize},
{"SteamWorksHTTPRequest.GetResponseBodyData", sm_GetHTTPResponseBodyData},
{"SteamWorksHTTPRequest.GetStreamingResponseBodyData", sm_GetHTTPStreamingResponseBodyData},
{"SteamWorksHTTPRequest.GetDownloadProgressPct", sm_GetHTTPDownloadProgressPct},
{"SteamWorksHTTPRequest.GetWasTimedOut", sm_GetHTTPRequestWasTimedOut},
{"SteamWorksHTTPRequest.SetRawPostBody", sm_SetHTTPRequestRawPostBody},
{"SteamWorksHTTPRequest.SetRawPostBodyFromFile", sm_SetHTTPRequestRawPostBodyFromFile},
{"SteamWorksHTTPRequest.GetResponseBodyCallback", sm_GetHTTPResponseBodyCallback},
{"SteamWorksHTTPRequest.WriteResponseBodyToFile", sm_WriteHTTPResponseBodyToFile},
{NULL, NULL} {NULL, NULL}
}; };
+11 -12
View File
@@ -17,9 +17,9 @@
*/ */
#pragma once #pragma once
#include "isteamgameserver.h"
#include "steam_gameserver.h" #include <isteamhttp.h>
#include "smsdk_ext.h" #include <smsdk_ext.h> // HTTPRequestHandle, Handle_t, IChangeableForward
class SteamWorksHTTPRequest class SteamWorksHTTPRequest
{ {
@@ -32,19 +32,20 @@ class SteamWorksHTTPRequest
Handle_t handle; Handle_t handle;
public: public:
/* Completion is a genuine call result of the send API call, so it stays a
CCallResult. Headers/data arrive as broadcast callbacks and are routed here
by SteamWorksHTTP's dispatcher, hence no per-request CCallResult for them. */
void OnHTTPRequestCompleted(HTTPRequestCompleted_t *pRequest, bool bFailed); void OnHTTPRequestCompleted(HTTPRequestCompleted_t *pRequest, bool bFailed);
void OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *pRequest, bool bFailed); void OnHTTPHeadersReceived(HTTPRequestHeadersReceived_t *pRequest);
void OnHTTPDataReceived(HTTPRequestDataReceived_t *pRequest, bool bFailed); void OnHTTPDataReceived(HTTPRequestDataReceived_t *pRequest);
public: public:
CCallResult<SteamWorksHTTPRequest, HTTPRequestCompleted_t> CompletedCallResult; CCallResult<SteamWorksHTTPRequest, HTTPRequestCompleted_t> CompletedCallResult;
CCallResult<SteamWorksHTTPRequest, HTTPRequestHeadersReceived_t> HeadersCallResult;
CCallResult<SteamWorksHTTPRequest, HTTPRequestDataReceived_t> DataCallResult;
public: public:
IChangeableForward *pCompletedForward; SourceMod::IChangeableForward *pCompletedForward;
IChangeableForward *pHeadersReceivedForward; SourceMod::IChangeableForward *pHeadersReceivedForward;
IChangeableForward *pDataReceivedForward; SourceMod::IChangeableForward *pDataReceivedForward;
}; };
class SteamWorksHTTPNatives class SteamWorksHTTPNatives
@@ -53,5 +54,3 @@ class SteamWorksHTTPNatives
SteamWorksHTTPNatives(); SteamWorksHTTPNatives();
~SteamWorksHTTPNatives(); ~SteamWorksHTTPNatives();
}; };
#include "extension.h"
+1 -1
View File
@@ -16,7 +16,7 @@
Author: Kyle Sanderson (KyleS). Author: Kyle Sanderson (KyleS).
*/ */
#include "swmemutils.h" #include "swmemutils.h"
#include "am-utility.h" #include <am-utility.h>
void *SteamWorksMemUtils::ResolveSymbolInt(void *pBase, const char *pSymbol) void *SteamWorksMemUtils::ResolveSymbolInt(void *pBase, const char *pSymbol)
{ {
+2 -3
View File
@@ -17,7 +17,8 @@
*/ */
#pragma once #pragma once
#include "smsdk_ext.h"
//#include <cstddef>
class SteamWorksMemUtils class SteamWorksMemUtils
{ {
@@ -25,5 +26,3 @@ class SteamWorksMemUtils
void *ResolveSymbolInt(void *pBase, const char *pSymbol); void *ResolveSymbolInt(void *pBase, const char *pSymbol);
size_t GetOffsetFromVTable(void *pInterface, void *pToFindFunc, const char *pClassSig = NULL, size_t version = 0); size_t GetOffsetFromVTable(void *pInterface, void *pToFindFunc, const char *pClassSig = NULL, size_t version = 0);
}; };
#include "extension.h"
+851
View File
@@ -245,6 +245,12 @@ enum EHTTPStatusCode
k_EHTTPStatusCode5xxUnknown = 599, k_EHTTPStatusCode5xxUnknown = 599,
}; };
/**
* Returns whether an HTTP status code represents success (a 2xx code).
*
* @param eStatusCode HTTP status code to test.
* @return True if the code is in the 2xx range, false otherwise.
*/
stock bool IsHTTPStatusSuccess(EHTTPStatusCode eStatusCode) stock bool IsHTTPStatusSuccess(EHTTPStatusCode eStatusCode)
{ {
return (eStatusCode >= k_EHTTPStatusCode200OK && eStatusCode < k_EHTTPStatusCode300MultipleChoices); return (eStatusCode >= k_EHTTPStatusCode200OK && eStatusCode < k_EHTTPStatusCode300MultipleChoices);
@@ -260,41 +266,326 @@ enum EGCResults
k_EGCResultInvalidMessage = 4, // Something was wrong with the message being sent with SendMessage k_EGCResultInvalidMessage = 4, // Something was wrong with the message being sent with SendMessage
}; };
/**
* Returns whether the server is VAC (Valve Anti-Cheat) secured.
*
* @return True if the server is VAC secured, false otherwise (including
* when not yet connected to Steam).
*/
native bool SteamWorks_IsVACEnabled(); native bool SteamWorks_IsVACEnabled();
/**
* Retrieves the server's public IP address as four octets.
*
* @param ipaddr Array that receives the IP address, most-significant octet first
* (e.g. 127.0.0.1 becomes {127, 0, 0, 1}).
* @return True on success, false if not connected to Steam or the public
* IP is not yet known.
*/
native bool SteamWorks_GetPublicIP(int ipaddr[4]); native bool SteamWorks_GetPublicIP(int ipaddr[4]);
/**
* Retrieves the server's public IP address packed into a single cell.
*
* @return The IPv4 address as a 32-bit value (host byte order), or 0 if not
* connected to Steam or the public IP is not yet known.
*/
native int SteamWorks_GetPublicIPCell(); native int SteamWorks_GetPublicIPCell();
/**
* Returns whether the Steam client library has been loaded by the extension.
*
* @return True if the Steam library is loaded, false otherwise.
*/
native bool SteamWorks_IsLoaded(); native bool SteamWorks_IsLoaded();
/**
* Sets the "gamedata" string for the server, used for matchmaking/server-browser filtering.
*
* @param sData Game data string.
* @return True on success, false if not connected to Steam.
*/
native bool SteamWorks_SetGameData(const char[] sData); native bool SteamWorks_SetGameData(const char[] sData);
/**
* Sets the game description reported to the server browser and client queries.
*
* @param sDesc Game description string.
* @return True on success, false if not connected to Steam.
*/
native bool SteamWorks_SetGameDescription(const char[] sDesc); native bool SteamWorks_SetGameDescription(const char[] sDesc);
/**
* Sets the map name reported to the server browser and client queries.
*
* @param sMapName Map name string.
* @return True on success, false if not connected to Steam.
*/
native bool SteamWorks_SetMapName(const char[] sMapName); native bool SteamWorks_SetMapName(const char[] sMapName);
/**
* Returns whether the server is currently logged on to Steam.
*
* @return True if logged on to Steam, false otherwise.
*/
native bool SteamWorks_IsConnected(); native bool SteamWorks_IsConnected();
/**
* Adds or updates a key/value pair sent in A2S rules queries.
*
* @param sKey Rule key.
* @param sValue Rule value.
* @return True on success, false if not connected to Steam.
*/
native bool SteamWorks_SetRule(const char[] sKey, const char[] sValue); native bool SteamWorks_SetRule(const char[] sKey, const char[] sValue);
/**
* Clears the entire list of key/value pairs sent in rules queries.
*
* @return True on success, false if not connected to Steam.
*/
native bool SteamWorks_ClearRules(); native bool SteamWorks_ClearRules();
/**
* Sets whether the server should be advertised on the master server list and
* respond to server browser / LAN discovery packets. Defaults to false; set
* other server parameters before enabling advertising.
*
* @param bActive True to advertise the server, false to hide it.
* @return True on success, false if not connected to Steam.
*/
native bool SteamWorks_SetAdvertiseServerActive(bool bActive);
/**
* Deprecated no-op. Newer Steamworks SDKs removed ForceHeartbeat; server list
* heartbeats are now sent implicitly by Steam.
*
* @return Always false.
*/
#pragma deprecated This function is deprecated in the SDK and no longer does anything in this extension #pragma deprecated This function is deprecated in the SDK and no longer does anything in this extension
native bool SteamWorks_ForceHeartbeat(); native bool SteamWorks_ForceHeartbeat();
/**
* Asynchronously requests whether a client is a member of a given Steam group.
* The result is delivered through the SteamWorks_OnClientGroupStatus forward.
*
* @param client Client index.
* @param groupid 32-bit account ID of the Steam group.
* @return True if the request was sent, false if not connected to Steam.
* @error Invalid client index.
*/
native bool SteamWorks_GetUserGroupStatus(int client, int groupid); native bool SteamWorks_GetUserGroupStatus(int client, int groupid);
/**
* Asynchronously requests whether a user is a member of a given Steam group.
* The result is delivered through the SteamWorks_OnClientGroupStatus forward.
*
* @param authid 32-bit account ID of the user to query.
* @param groupid 32-bit account ID of the Steam group.
* @return True if the request was sent, false if not connected to Steam.
*/
native bool SteamWorks_GetUserGroupStatusAuthID(int authid, int groupid); native bool SteamWorks_GetUserGroupStatusAuthID(int authid, int groupid);
/**
* Returns whether a client owns/has a license for the given application.
*
* @param client Client index.
* @param app Application (AppID) to check ownership of.
* @return An EUserHasLicenseForAppResult value; k_EUserHasLicenseResultNoAuth
* if not connected to Steam.
* @error Invalid client index.
*/
native EUserHasLicenseForAppResult SteamWorks_HasLicenseForApp(int client, int app); native EUserHasLicenseForAppResult SteamWorks_HasLicenseForApp(int client, int app);
/**
* Returns whether a user owns/has a license for the given application.
*
* @param authid 32-bit account ID of the user to check.
* @param app Application (AppID) to check ownership of.
* @return An EUserHasLicenseForAppResult value; k_EUserHasLicenseResultNoAuth
* if not connected to Steam.
*/
native EUserHasLicenseForAppResult SteamWorks_HasLicenseForAppId(int authid, int app); native EUserHasLicenseForAppResult SteamWorks_HasLicenseForAppId(int authid, int app);
/**
* Retrieves a client's 64-bit Steam ID (community ID) as a string.
*
* @param client Client index.
* @param sSteamID Buffer to store the rendered 64-bit Steam ID.
* @param length Maximum length of the buffer.
* @return Number of bytes written, including the null terminator.
* @error Invalid client index.
*/
native int SteamWorks_GetClientSteamID(int client, char[] sSteamID, int length); native int SteamWorks_GetClientSteamID(int client, char[] sSteamID, int length);
/**
* Asynchronously requests the stats of a user from Steam. Stats become available
* afterwards through SteamWorks_GetStatAuthIDCell / SteamWorks_GetStatAuthIDFloat.
*
* @param authid 32-bit account ID of the user whose stats to request.
* @param appid Application (AppID) to request stats for.
* @return True if the request was sent, false if not connected to Steam.
*/
native bool SteamWorks_RequestStatsAuthID(int authid, int appid); native bool SteamWorks_RequestStatsAuthID(int authid, int appid);
/**
* Asynchronously requests the stats of a client from Steam. Stats become available
* afterwards through SteamWorks_GetStatCell / SteamWorks_GetStatFloat.
*
* @param client Client index.
* @param appid Application (AppID) to request stats for.
* @return True if the request was sent, false if not connected to Steam.
* @error Invalid client index.
*/
native bool SteamWorks_RequestStats(int client, int appid); native bool SteamWorks_RequestStats(int client, int appid);
/**
* Retrieves an integer stat for a client. The client's stats must have been
* requested first with SteamWorks_RequestStats.
*
* @param client Client index.
* @param sKey Stat name.
* @param value Variable to store the stat value in.
* @return True on success, false on failure or if not connected to Steam.
* @error Invalid client index.
*/
native bool SteamWorks_GetStatCell(int client, const char[] sKey, int &value); native bool SteamWorks_GetStatCell(int client, const char[] sKey, int &value);
/**
* Retrieves an integer stat for a user. The user's stats must have been
* requested first with SteamWorks_RequestStatsAuthID.
*
* @param authid 32-bit account ID of the user.
* @param sKey Stat name.
* @param value Variable to store the stat value in.
* @return True on success, false on failure or if not connected to Steam.
*/
native bool SteamWorks_GetStatAuthIDCell(int authid, const char[] sKey, int &value); native bool SteamWorks_GetStatAuthIDCell(int authid, const char[] sKey, int &value);
/**
* Retrieves a floating-point stat for a client. The client's stats must have been
* requested first with SteamWorks_RequestStats.
*
* @param client Client index.
* @param sKey Stat name.
* @param value Variable to store the stat value in.
* @return True on success, false on failure or if not connected to Steam.
* @error Invalid client index.
*/
native bool SteamWorks_GetStatFloat(int client, const char[] sKey, float &value); native bool SteamWorks_GetStatFloat(int client, const char[] sKey, float &value);
/**
* Retrieves a floating-point stat for a user. The user's stats must have been
* requested first with SteamWorks_RequestStatsAuthID.
*
* @param authid 32-bit account ID of the user.
* @param sKey Stat name.
* @param value Variable to store the stat value in.
* @return True on success, false on failure or if not connected to Steam.
*/
native bool SteamWorks_GetStatAuthIDFloat(int authid, const char[] sKey, float &value); native bool SteamWorks_GetStatAuthIDFloat(int authid, const char[] sKey, float &value);
/**
* Creates a new HTTP request. The URL must be absolute and start with http:// or https://.
*
* The returned handle must be freed with CloseHandle/delete once the request is finished.
*
* @param method HTTP method to use.
* @param sURL Absolute URL for the request.
* @return A handle to the new HTTP request, or INVALID_HANDLE on failure
* (including when not connected to Steam).
*/
native Handle SteamWorks_CreateHTTPRequest(EHTTPMethod method, const char[] sURL); native Handle SteamWorks_CreateHTTPRequest(EHTTPMethod method, const char[] sURL);
/**
* Sets one or two context values that will be passed back to the request's callbacks.
* These let you associate arbitrary data with a request.
*
* @param hHandle HTTP request handle.
* @param data1 First context value.
* @param data2 Second context value.
* @return True on success, false on an invalid handle or if the request was
* already sent.
*/
native bool SteamWorks_SetHTTPRequestContextValue(Handle hHandle, any data1, any data2=0); native bool SteamWorks_SetHTTPRequestContextValue(Handle hHandle, any data1, any data2=0);
/**
* Sets a network-activity timeout, in seconds, for the request. Must be called before sending.
* The default is 60 seconds. The timer resets whenever more data is received.
*
* @param hHandle HTTP request handle.
* @param timeout Timeout in seconds.
* @return True on success, false on an invalid handle or if the request was
* already sent.
*/
native bool SteamWorks_SetHTTPRequestNetworkActivityTimeout(Handle hHandle, int timeout); native bool SteamWorks_SetHTTPRequestNetworkActivityTimeout(Handle hHandle, int timeout);
/**
* Sets a request header value. Must be called before sending the request.
*
* @param hHandle HTTP request handle.
* @param sName Header name.
* @param sValue Header value.
* @return True on success, false on an invalid handle or if the request was
* already sent.
*/
native bool SteamWorks_SetHTTPRequestHeaderValue(Handle hHandle, const char[] sName, const char[] sValue); native bool SteamWorks_SetHTTPRequestHeaderValue(Handle hHandle, const char[] sName, const char[] sValue);
/**
* Sets a GET or POST parameter on the request (which is used depends on the request method).
* Must be called before sending the request.
*
* @param hHandle HTTP request handle.
* @param sName Parameter name.
* @param sValue Parameter value.
* @return True on success, false on an invalid handle or if the request was
* already sent.
*/
native bool SteamWorks_SetHTTPRequestGetOrPostParameter(Handle hHandle, const char[] sName, const char[] sValue); native bool SteamWorks_SetHTTPRequestGetOrPostParameter(Handle hHandle, const char[] sName, const char[] sValue);
/**
* Appends extra user-agent info to the request. This does not clobber the normal user
* agent; it is added to the end.
*
* @param hHandle HTTP request handle.
* @param sUserAgentInfo Extra user-agent info string.
* @return True on success, false on an invalid handle.
*/
native bool SteamWorks_SetHTTPRequestUserAgentInfo(Handle hHandle, const char[] sUserAgentInfo); native bool SteamWorks_SetHTTPRequestUserAgentInfo(Handle hHandle, const char[] sUserAgentInfo);
/**
* Enables or disables verification of SSL/TLS certificates. By default, certificates
* are verified for all HTTPS requests.
*
* @param hHandle HTTP request handle.
* @param bRequireVerifiedCertificate True to require a verified certificate, false to disable.
* @return True on success, false on an invalid handle.
*/
native bool SteamWorks_SetHTTPRequestRequiresVerifiedCertificate(Handle hHandle, bool bRequireVerifiedCertificate); native bool SteamWorks_SetHTTPRequestRequiresVerifiedCertificate(Handle hHandle, bool bRequireVerifiedCertificate);
/**
* Sets an absolute timeout, in milliseconds, on the request. Unlike the network-activity
* timeout, this is a total time limit that does not reset as data arrives.
*
* @param hHandle HTTP request handle.
* @param unMilliseconds Total timeout in milliseconds.
* @return True on success, false on an invalid handle.
*/
native bool SteamWorks_SetHTTPRequestAbsoluteTimeoutMS(Handle hHandle, int unMilliseconds); native bool SteamWorks_SetHTTPRequestAbsoluteTimeoutMS(Handle hHandle, int unMilliseconds);
/**
* Called when an HTTP request has completed (or failed). The number of trailing context
* parameters matches how many values were passed to SteamWorks_SetHTTPRequestContextValue.
*
* @param hRequest HTTP request handle.
* @param bFailure True if the request failed due to an internal or network
* error (no response from the server).
* @param bRequestSuccessful True if any response was received from the server (even an
* error response).
* @param eStatusCode HTTP status code returned by the server.
* @param data1 First context value, if one was set.
* @param data2 Second context value, if one was set.
*/
typeset SteamWorksHTTPRequestCompleted typeset SteamWorksHTTPRequestCompleted
{ {
function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode); function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode);
@@ -302,6 +593,16 @@ typeset SteamWorksHTTPRequestCompleted
function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, any data1, any data2); function void (Handle hRequest, bool bFailure, bool bRequestSuccessful, EHTTPStatusCode eStatusCode, any data1, any data2);
}; };
/**
* Called when the response headers for a streaming request have been received. The number
* of trailing context parameters matches the context values set on the request.
*
* @param hRequest HTTP request handle.
* @param bFailure Always false; headers-received is a success-only notification. A
* failed request is reported through SteamWorksHTTPRequestCompleted.
* @param data1 First context value, if one was set.
* @param data2 Second context value, if one was set.
*/
typeset SteamWorksHTTPHeadersReceived typeset SteamWorksHTTPHeadersReceived
{ {
function void (Handle hRequest, bool bFailure); function void (Handle hRequest, bool bFailure);
@@ -309,6 +610,19 @@ typeset SteamWorksHTTPHeadersReceived
function void (Handle hRequest, bool bFailure, any data1, any data2); function void (Handle hRequest, bool bFailure, any data1, any data2);
}; };
/**
* Called when a chunk of data for a streaming request has been received. Pass the offset
* and byte count to SteamWorks_GetHTTPStreamingResponseBodyData to read the chunk. The
* number of trailing context parameters matches the context values set on the request.
*
* @param hRequest HTTP request handle.
* @param bFailure Always false; data-received is a success-only notification. A
* failed request is reported through SteamWorksHTTPRequestCompleted.
* @param offset Offset of this chunk within the response body.
* @param bytesreceived Number of bytes in this chunk.
* @param data1 First context value, if one was set.
* @param data2 Second context value, if one was set.
*/
typeset SteamWorksHTTPDataReceived typeset SteamWorksHTTPDataReceived
{ {
function void (Handle hRequest, bool bFailure, int offset, int bytesreceived); function void (Handle hRequest, bool bFailure, int offset, int bytesreceived);
@@ -316,6 +630,15 @@ typeset SteamWorksHTTPDataReceived
function void (Handle hRequest, bool bFailure, int offset, int bytesreceived, any data1, any data2); function void (Handle hRequest, bool bFailure, int offset, int bytesreceived, any data1, any data2);
}; };
/**
* Called by SteamWorks_GetHTTPResponseBodyCallback with the response body. Use the string
* overload for text bodies or the int[] overload for binary bodies.
*
* @param sData Response body as a string (text overload).
* @param data Response body as a byte array (binary overload).
* @param value The context value passed to SteamWorks_GetHTTPResponseBodyCallback.
* @param datalen Length of the body, in bytes (binary overload).
*/
typeset SteamWorksHTTPBodyCallback typeset SteamWorksHTTPBodyCallback
{ {
function void (const char[] sData); function void (const char[] sData);
@@ -323,39 +646,541 @@ typeset SteamWorksHTTPBodyCallback
function void (const int[] data, any value, int datalen); function void (const int[] data, any value, int datalen);
}; };
/**
* Sets the callbacks fired for a request. Must be called before sending the request.
* The completion callback is used by both regular and streaming requests; the headers and
* data callbacks are only fired for streaming requests.
*
* @param hHandle HTTP request handle.
* @param fCompleted Callback fired when the request completes, or INVALID_FUNCTION.
* @param fHeaders Callback fired when streaming headers arrive, or INVALID_FUNCTION.
* @param fData Callback fired when a streaming data chunk arrives, or INVALID_FUNCTION.
* @param hCalling Handle of the plugin that owns the callbacks, or INVALID_HANDLE for
* the calling plugin.
* @return True on success, false on an invalid handle.
* @error Invalid plugin handle or invalid function.
*/
native bool SteamWorks_SetHTTPCallbacks(Handle hHandle, SteamWorksHTTPRequestCompleted fCompleted = INVALID_FUNCTION, SteamWorksHTTPHeadersReceived fHeaders = INVALID_FUNCTION, SteamWorksHTTPDataReceived fData = INVALID_FUNCTION, Handle hCalling = INVALID_HANDLE); native bool SteamWorks_SetHTTPCallbacks(Handle hHandle, SteamWorksHTTPRequestCompleted fCompleted = INVALID_FUNCTION, SteamWorksHTTPHeadersReceived fHeaders = INVALID_FUNCTION, SteamWorksHTTPDataReceived fData = INVALID_FUNCTION, Handle hCalling = INVALID_HANDLE);
/**
* Sends an HTTP request. The result is delivered asynchronously to the completion callback
* set with SteamWorks_SetHTTPCallbacks.
*
* @param hRequest HTTP request handle.
* @return True if the request was sent, false on an invalid handle.
*/
native bool SteamWorks_SendHTTPRequest(Handle hRequest); native bool SteamWorks_SendHTTPRequest(Handle hRequest);
/**
* Sends an HTTP request and streams the response. Headers and data are delivered
* asynchronously to the callbacks set with SteamWorks_SetHTTPCallbacks.
*
* @param hRequest HTTP request handle.
* @return True if the request was sent, false on an invalid handle.
*/
native bool SteamWorks_SendHTTPRequestAndStreamResponse(Handle hRequest); native bool SteamWorks_SendHTTPRequestAndStreamResponse(Handle hRequest);
/**
* Moves an already-sent request to the tail of the client's request queue.
*
* @param hRequest HTTP request handle.
* @return True on success, false on an invalid handle or if the request has
* not been sent.
*/
native bool SteamWorks_DeferHTTPRequest(Handle hRequest); native bool SteamWorks_DeferHTTPRequest(Handle hRequest);
/**
* Moves an already-sent request to the head of the client's request queue.
*
* @param hRequest HTTP request handle.
* @return True on success, false on an invalid handle or if the request has
* not been sent.
*/
native bool SteamWorks_PrioritizeHTTPRequest(Handle hRequest); native bool SteamWorks_PrioritizeHTTPRequest(Handle hRequest);
/**
* Checks whether a response header is present and retrieves the size of its value, so a
* correctly-sized buffer can be allocated for SteamWorks_GetHTTPResponseHeaderValue.
* Call from the completion callback.
*
* @param hRequest HTTP request handle.
* @param sHeader Header name.
* @param size Variable to store the header value size in.
* @return True if the header is present, false otherwise.
*/
native bool SteamWorks_GetHTTPResponseHeaderSize(Handle hRequest, const char[] sHeader, int &size); native bool SteamWorks_GetHTTPResponseHeaderSize(Handle hRequest, const char[] sHeader, int &size);
/**
* Retrieves a response header value. Call from the completion callback. Use
* SteamWorks_GetHTTPResponseHeaderSize first to size the buffer.
*
* @param hRequest HTTP request handle.
* @param sHeader Header name.
* @param sValue Buffer to store the header value in.
* @param size Maximum length of the buffer.
* @return True on success, false if the header is not present or the buffer
* is too small.
*/
native bool SteamWorks_GetHTTPResponseHeaderValue(Handle hRequest, const char[] sHeader, char[] sValue, int size); native bool SteamWorks_GetHTTPResponseHeaderValue(Handle hRequest, const char[] sHeader, char[] sValue, int size);
/**
* Retrieves the size of the response body. Call from the completion callback.
*
* @param hRequest HTTP request handle.
* @param size Variable to store the body size in.
* @return True on success, false on an invalid handle.
*/
native bool SteamWorks_GetHTTPResponseBodySize(Handle hRequest, int &size); native bool SteamWorks_GetHTTPResponseBodySize(Handle hRequest, int &size);
/**
* Retrieves the response body. Call from the completion callback. Use
* SteamWorks_GetHTTPResponseBodySize first to size the buffer. Not valid for streaming
* responses.
*
* @param hRequest HTTP request handle.
* @param sBody Buffer to store the body in.
* @param length Length of the buffer, which must match the body size.
* @return True on success, false on an invalid handle, a streaming response,
* or an incorrectly-sized buffer.
*/
native bool SteamWorks_GetHTTPResponseBodyData(Handle hRequest, char[] sBody, int length); native bool SteamWorks_GetHTTPResponseBodyData(Handle hRequest, char[] sBody, int length);
/**
* Retrieves a chunk of a streaming response body. Call from the data-received callback,
* passing the offset and length reported by that callback.
*
* @param hRequest HTTP request handle.
* @param cOffset Offset of the chunk, as provided by the data-received callback.
* @param sBody Buffer to store the chunk in.
* @param length Length of the chunk, as provided by the data-received callback.
* @return True on success, false on an invalid handle, a non-streaming
* response, or a mismatched offset/length.
*/
native bool SteamWorks_GetHTTPStreamingResponseBodyData(Handle hRequest, int cOffset, char[] sBody, int length); native bool SteamWorks_GetHTTPStreamingResponseBodyData(Handle hRequest, int cOffset, char[] sBody, int length);
/**
* Retrieves download progress for the request. This is zero until a response header with a
* content-length has been received; for responses with no content-length it stays zero.
*
* @param hRequest HTTP request handle.
* @param percent Variable to store the progress percentage in.
* @return True on success, false on an invalid handle.
*/
native bool SteamWorks_GetHTTPDownloadProgressPct(Handle hRequest, float &percent); native bool SteamWorks_GetHTTPDownloadProgressPct(Handle hRequest, float &percent);
/**
* Checks whether the request failed because it timed out (rather than a harder failure).
*
* @param hRequest HTTP request handle.
* @param bWasTimedOut Variable to store the result in.
* @return True on success, false on an invalid handle.
*/
native bool SteamWorks_GetHTTPRequestWasTimedOut(Handle hRequest, bool &bWasTimedOut); native bool SteamWorks_GetHTTPRequestWasTimedOut(Handle hRequest, bool &bWasTimedOut);
/**
* Sets a raw body for a POST request. Fails on a GET request or if GET/POST parameters
* were already set. This makes the raw body the entire contents of the POST.
*
* @param hRequest HTTP request handle.
* @param sContentType Value for the Content-Type header.
* @param sBody Raw body data.
* @param bodylen Length of the body, in bytes.
* @return True on success, false on failure.
*/
native bool SteamWorks_SetHTTPRequestRawPostBody(Handle hRequest, const char[] sContentType, const char[] sBody, int bodylen); native bool SteamWorks_SetHTTPRequestRawPostBody(Handle hRequest, const char[] sContentType, const char[] sBody, int bodylen);
/**
* Sets a raw POST body read from a file (relative to the game directory). Same constraints
* as SteamWorks_SetHTTPRequestRawPostBody.
*
* @param hRequest HTTP request handle.
* @param sContentType Value for the Content-Type header.
* @param sFileName Path to the file, relative to the game directory.
* @return True on success, false on failure (e.g. an empty file).
* @error Unable to open the file for reading.
*/
native bool SteamWorks_SetHTTPRequestRawPostBodyFromFile(Handle hRequest, const char[] sContentType, const char[] sFileName); native bool SteamWorks_SetHTTPRequestRawPostBodyFromFile(Handle hRequest, const char[] sContentType, const char[] sFileName);
/**
* Retrieves the full response body and passes it to a callback. Useful for bodies larger
* than a single fixed buffer. Call from the completion callback.
*
* @param hRequest HTTP request handle.
* @param fCallback Callback that receives the body.
* @param data Context value passed through to the callback.
* @param hPlugin Handle of the plugin that owns the callback, or INVALID_HANDLE for
* the calling plugin.
* @return True on success, false on an invalid handle or if the body could not
* be retrieved.
* @error Invalid plugin handle or invalid function.
*/
native bool SteamWorks_GetHTTPResponseBodyCallback(Handle hRequest, SteamWorksHTTPBodyCallback fCallback, any data = 0, Handle hPlugin = INVALID_HANDLE); native bool SteamWorks_GetHTTPResponseBodyCallback(Handle hRequest, SteamWorksHTTPBodyCallback fCallback, any data = 0, Handle hPlugin = INVALID_HANDLE);
/**
* Writes the full response body to a file (relative to the game directory). Call from the
* completion callback.
*
* @param hRequest HTTP request handle.
* @param sFileName Path to the output file, relative to the game directory.
* @return True on success, false on an invalid handle or if the body could not
* be retrieved.
* @error Unable to open the file for writing.
*/
native bool SteamWorks_WriteHTTPResponseBodyToFile(Handle hRequest, const char[] sFileName); native bool SteamWorks_WriteHTTPResponseBodyToFile(Handle hRequest, const char[] sFileName);
methodmap SteamWorksHTTPRequest < Handle
{
/**
* Creates a new HTTP request.
*
* @param method HTTP method to use.
* @param sURL Absolute URL for the request.
* @return A new request handle, or INVALID_HANDLE on failure (including when
* not connected to Steam).
*/
public native SteamWorksHTTPRequest(EHTTPMethod method, const char[] sURL);
/**
* Sets one or two context values that will be passed back to the request's callbacks.
* These let you associate arbitrary data with a request.
*
* @param data1 First context value.
* @param data2 Second context value.
* @return True on success, false on an invalid handle or if the request was
* already sent.
*/
public native bool SetContextValue(any data1, any data2 = 0);
/**
* Sets a network-activity timeout, in seconds, for the request. Must be called before
* sending. The default is 60 seconds. The timer resets whenever more data is received.
*
* @param timeout Timeout in seconds.
* @return True on success, false on an invalid handle or if the request was
* already sent.
*/
public native bool SetNetworkActivityTimeout(int timeout);
/**
* Sets a request header value. Must be called before sending the request.
*
* @param sName Header name.
* @param sValue Header value.
* @return True on success, false on an invalid handle or if the request was
* already sent.
*/
public native bool SetHeaderValue(const char[] sName, const char[] sValue);
/**
* Sets a GET or POST parameter on the request (which is used depends on the request
* method). Must be called before sending the request.
*
* @param sName Parameter name.
* @param sValue Parameter value.
* @return True on success, false on an invalid handle or if the request was
* already sent.
*/
public native bool SetGetOrPostParameter(const char[] sName, const char[] sValue);
/**
* Appends extra user-agent info to the request. This does not clobber the normal user
* agent; it is added to the end.
*
* @param sUserAgentInfo Extra user-agent info string.
* @return True on success, false on an invalid handle.
*/
public native bool SetUserAgentInfo(const char[] sUserAgentInfo);
/**
* Enables or disables verification of SSL/TLS certificates. By default, certificates
* are verified for all HTTPS requests.
*
* @param bRequireVerifiedCertificate True to require a verified certificate, false to disable.
* @return True on success, false on an invalid handle.
*/
public native bool SetRequiresVerifiedCertificate(bool bRequireVerifiedCertificate);
/**
* Sets an absolute timeout, in milliseconds, on the request. Unlike the network-activity
* timeout, this is a total time limit that does not reset as data arrives.
*
* @param unMilliseconds Total timeout in milliseconds.
* @return True on success, false on an invalid handle.
*/
public native bool SetAbsoluteTimeoutMS(int unMilliseconds);
/**
* Sets the callbacks fired for a request. Must be called before sending the request.
* The completion callback is used by both regular and streaming requests; the headers
* and data callbacks are only fired for streaming requests.
*
* @param fCompleted Callback fired when the request completes, or INVALID_FUNCTION.
* @param fHeaders Callback fired when streaming headers arrive, or INVALID_FUNCTION.
* @param fData Callback fired when a streaming data chunk arrives, or INVALID_FUNCTION.
* @param hCalling Handle of the plugin that owns the callbacks, or INVALID_HANDLE for
* the calling plugin.
* @return True on success, false on an invalid handle.
* @error Invalid plugin handle or invalid function.
*/
public native bool SetCallbacks(SteamWorksHTTPRequestCompleted fCompleted = INVALID_FUNCTION, SteamWorksHTTPHeadersReceived fHeaders = INVALID_FUNCTION, SteamWorksHTTPDataReceived fData = INVALID_FUNCTION, Handle hCalling = INVALID_HANDLE);
/**
* Sends an HTTP request. The result is delivered asynchronously to the completion
* callback set with SetCallbacks.
*
* @return True if the request was sent, false on an invalid handle.
*/
public native bool Send();
/**
* Sends an HTTP request and streams the response. Headers and data are delivered
* asynchronously to the callbacks set with SetCallbacks.
*
* @return True if the request was sent, false on an invalid handle.
*/
public native bool SendAndStreamResponse();
/**
* Moves an already-sent request to the tail of the client's request queue.
*
* @return True on success, false on an invalid handle or if the request has
* not been sent.
*/
public native bool Defer();
/**
* Moves an already-sent request to the head of the client's request queue.
*
* @return True on success, false on an invalid handle or if the request has
* not been sent.
*/
public native bool Prioritize();
/**
* Checks whether a response header is present and retrieves the size of its value, so a
* correctly-sized buffer can be allocated for GetResponseHeaderValue. Call from the
* completion callback.
*
* @param sHeader Header name.
* @param size Variable to store the header value size in.
* @return True if the header is present, false otherwise.
*/
public native bool GetResponseHeaderSize(const char[] sHeader, int &size);
/**
* Retrieves a response header value. Call from the completion callback. Use
* GetResponseHeaderSize first to size the buffer.
*
* @param sHeader Header name.
* @param sValue Buffer to store the header value in.
* @param size Maximum length of the buffer.
* @return True on success, false if the header is not present or the buffer
* is too small.
*/
public native bool GetResponseHeaderValue(const char[] sHeader, char[] sValue, int size);
/**
* Retrieves the size of the response body. Call from the completion callback.
*
* @param size Variable to store the body size in.
* @return True on success, false on an invalid handle.
*/
public native bool GetResponseBodySize(int &size);
/**
* Retrieves the response body. Call from the completion callback. Use GetResponseBodySize
* first to size the buffer. Not valid for streaming responses.
*
* @param sBody Buffer to store the body in.
* @param length Length of the buffer, which must match the body size.
* @return True on success, false on an invalid handle, a streaming response,
* or an incorrectly-sized buffer.
*/
public native bool GetResponseBodyData(char[] sBody, int length);
/**
* Retrieves a chunk of a streaming response body. Call from the data-received callback,
* passing the offset and length reported by that callback.
*
* @param cOffset Offset of the chunk, as provided by the data-received callback.
* @param sBody Buffer to store the chunk in.
* @param length Length of the chunk, as provided by the data-received callback.
* @return True on success, false on an invalid handle, a non-streaming
* response, or a mismatched offset/length.
*/
public native bool GetStreamingResponseBodyData(int cOffset, char[] sBody, int length);
/**
* Retrieves download progress for the request. This is zero until a response header with
* a content-length has been received; for responses with no content-length it stays zero.
*
* @param percent Variable to store the progress percentage in.
* @return True on success, false on an invalid handle.
*/
public native bool GetDownloadProgressPct(float &percent);
/**
* Checks whether the request failed because it timed out (rather than a harder failure).
*
* @param bWasTimedOut Variable to store the result in.
* @return True on success, false on an invalid handle.
*/
public native bool GetWasTimedOut(bool &bWasTimedOut);
/**
* Sets a raw body for a POST request. Fails on a GET request or if GET/POST parameters
* were already set. This makes the raw body the entire contents of the POST.
*
* @param sContentType Value for the Content-Type header.
* @param sBody Raw body data.
* @param bodylen Length of the body, in bytes.
* @return True on success, false on failure.
*/
public native bool SetRawPostBody(const char[] sContentType, const char[] sBody, int bodylen);
/**
* Sets a raw POST body read from a file (relative to the game directory). Same constraints
* as SetRawPostBody.
*
* @param sContentType Value for the Content-Type header.
* @param sFileName Path to the file, relative to the game directory.
* @return True on success, false on failure (e.g. an empty file).
* @error Unable to open the file for reading.
*/
public native bool SetRawPostBodyFromFile(const char[] sContentType, const char[] sFileName);
/**
* Retrieves the full response body and passes it to a callback. Useful for bodies larger
* than a single fixed buffer. Call from the completion callback.
*
* @param fCallback Callback that receives the body.
* @param data Context value passed through to the callback.
* @param hPlugin Handle of the plugin that owns the callback, or INVALID_HANDLE for
* the calling plugin.
* @return True on success, false on an invalid handle or if the body could not
* be retrieved.
* @error Invalid plugin handle or invalid function.
*/
public native bool GetResponseBodyCallback(SteamWorksHTTPBodyCallback fCallback, any data = 0, Handle hPlugin = INVALID_HANDLE);
/**
* Writes the full response body to a file (relative to the game directory). Call from the
* completion callback.
*
* @param sFileName Path to the output file, relative to the game directory.
* @return True on success, false on an invalid handle or if the body could not
* be retrieved.
* @error Unable to open the file for writing.
*/
public native bool WriteResponseBodyToFile(const char[] sFileName);
};
/**
* Deprecated alias for SteamWorks_OnValidateClient, kept for backwards compatibility.
* Use SteamWorks_OnValidateClient in new code.
*
* @param ownerauthid 32-bit account ID of the account that owns the game license.
* @param authid 32-bit account ID of the validated client.
*/
forward void SW_OnValidateClient(int ownerauthid, int authid); forward void SW_OnValidateClient(int ownerauthid, int authid);
/**
* Called when a client has been validated by Steam. For clients playing on a borrowed
* (Family Sharing) license, the owner and client account IDs differ.
*
* @param ownerauthid 32-bit account ID of the account that owns the game license.
* @param authid 32-bit account ID of the validated client.
*/
forward void SteamWorks_OnValidateClient(int ownerauthid, int authid); forward void SteamWorks_OnValidateClient(int ownerauthid, int authid);
/**
* Called when the server successfully connects (logs on) to Steam.
*/
forward void SteamWorks_SteamServersConnected(); forward void SteamWorks_SteamServersConnected();
/**
* Called when the server fails to connect to Steam.
*
* @param result Result code describing the failure.
*/
forward void SteamWorks_SteamServersConnectFailure(EResult result); forward void SteamWorks_SteamServersConnectFailure(EResult result);
/**
* Called when the server is disconnected from Steam.
*
* @param result Result code describing the disconnection.
*/
forward void SteamWorks_SteamServersDisconnected(EResult result); forward void SteamWorks_SteamServersDisconnected(EResult result);
/**
* Called when the Steam master server has requested that the server restart. Return
* Plugin_Handled or higher to indicate the restart request has been handled.
*
* @return Plugin_Handled or higher to signal the restart was handled,
* Plugin_Continue otherwise.
*/
forward Action SteamWorks_RestartRequested(); forward Action SteamWorks_RestartRequested();
/**
* Called when the server is about to log on anonymously, giving a plugin the chance to
* supply a Game Server Login Token (GSLT) instead. Write the token into sToken.
*
* @param sToken Buffer to write the login token into.
* @param maxlen Maximum length of the buffer.
*/
forward void SteamWorks_TokenRequested(char[] sToken, int maxlen); forward void SteamWorks_TokenRequested(char[] sToken, int maxlen);
/**
* Called with the result of a SteamWorks_GetUserGroupStatus /
* SteamWorks_GetUserGroupStatusAuthID request.
*
* @param authid 32-bit account ID of the user.
* @param groupid 32-bit account ID of the group.
* @param isMember True if the user is a member of the group.
* @param isOfficer True if the user is an officer of the group.
*/
forward void SteamWorks_OnClientGroupStatus(int authid, int groupid, bool isMember, bool isOfficer); forward void SteamWorks_OnClientGroupStatus(int authid, int groupid, bool isMember, bool isOfficer);
/**
* Called when the game code sends a message to the Game Coordinator, letting a plugin
* observe or override it. Return a non-OK EGCResults value to supersede the send, or
* k_EGCResultOK to let it proceed.
*
* @param unMsgType Message type.
* @param pubData Message payload.
* @param cubData Size of the payload, in bytes.
* @return An EGCResults value to override the send, or k_EGCResultOK to allow it.
*/
forward EGCResults SteamWorks_GCSendMessage(int unMsgType, const char[] pubData, int cubData); forward EGCResults SteamWorks_GCSendMessage(int unMsgType, const char[] pubData, int cubData);
/**
* Called when a message from the Game Coordinator is available to be retrieved.
*
* @param cubData Size of the available message, in bytes.
*/
forward void SteamWorks_GCMsgAvailable(int cubData); forward void SteamWorks_GCMsgAvailable(int cubData);
/**
* Called when the game code retrieves a message from the Game Coordinator, letting a plugin
* observe or override it. Return a non-OK EGCResults value to supersede the retrieval.
*
* @param punMsgType Message type.
* @param pubDest Message payload.
* @param cubDest Size of the destination buffer, in bytes.
* @param pcubMsgSize Size of the message, in bytes.
* @return An EGCResults value to override the retrieval, or k_EGCResultOK to
* allow it.
*/
forward EGCResults SteamWorks_GCRetrieveMessage(int punMsgType, const char[] pubDest, int cubDest, int pcubMsgSize); forward EGCResults SteamWorks_GCRetrieveMessage(int punMsgType, const char[] pubDest, int cubDest, int pcubMsgSize);
/**
* Sends a message to the Game Coordinator.
*
* @param unMsgType Message type.
* @param pubData Message payload.
* @param cubData Size of the payload, in bytes.
* @return An EGCResults value; k_EGCResultNotLoggedOn if not connected to Steam.
*/
native EGCResults SteamWorks_SendMessageToGC(int unMsgType, const char[] pubData, int cubData); native EGCResults SteamWorks_SendMessageToGC(int unMsgType, const char[] pubData, int cubData);
public Extension __ext_SteamWorks = public Extension __ext_SteamWorks =
@@ -386,6 +1211,7 @@ public void __ext_SteamWorks_SetNTVOptional()
MarkNativeAsOptional("SteamWorks_IsConnected"); MarkNativeAsOptional("SteamWorks_IsConnected");
MarkNativeAsOptional("SteamWorks_SetRule"); MarkNativeAsOptional("SteamWorks_SetRule");
MarkNativeAsOptional("SteamWorks_ClearRules"); MarkNativeAsOptional("SteamWorks_ClearRules");
MarkNativeAsOptional("SteamWorks_SetAdvertiseServerActive");
MarkNativeAsOptional("SteamWorks_ForceHeartbeat"); MarkNativeAsOptional("SteamWorks_ForceHeartbeat");
MarkNativeAsOptional("SteamWorks_GetUserGroupStatus"); MarkNativeAsOptional("SteamWorks_GetUserGroupStatus");
MarkNativeAsOptional("SteamWorks_GetUserGroupStatusAuthID"); MarkNativeAsOptional("SteamWorks_GetUserGroupStatusAuthID");
@@ -425,5 +1251,30 @@ public void __ext_SteamWorks_SetNTVOptional()
MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodyCallback"); MarkNativeAsOptional("SteamWorks_GetHTTPResponseBodyCallback");
MarkNativeAsOptional("SteamWorks_WriteHTTPResponseBodyToFile"); MarkNativeAsOptional("SteamWorks_WriteHTTPResponseBodyToFile");
MarkNativeAsOptional("SteamWorksHTTPRequest.SteamWorksHTTPRequest");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetContextValue");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetNetworkActivityTimeout");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetHeaderValue");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetGetOrPostParameter");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetUserAgentInfo");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetRequiresVerifiedCertificate");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetAbsoluteTimeoutMS");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetCallbacks");
MarkNativeAsOptional("SteamWorksHTTPRequest.Send");
MarkNativeAsOptional("SteamWorksHTTPRequest.SendAndStreamResponse");
MarkNativeAsOptional("SteamWorksHTTPRequest.Defer");
MarkNativeAsOptional("SteamWorksHTTPRequest.Prioritize");
MarkNativeAsOptional("SteamWorksHTTPRequest.GetResponseHeaderSize");
MarkNativeAsOptional("SteamWorksHTTPRequest.GetResponseHeaderValue");
MarkNativeAsOptional("SteamWorksHTTPRequest.GetResponseBodySize");
MarkNativeAsOptional("SteamWorksHTTPRequest.GetResponseBodyData");
MarkNativeAsOptional("SteamWorksHTTPRequest.GetStreamingResponseBodyData");
MarkNativeAsOptional("SteamWorksHTTPRequest.GetDownloadProgressPct");
MarkNativeAsOptional("SteamWorksHTTPRequest.GetWasTimedOut");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetRawPostBody");
MarkNativeAsOptional("SteamWorksHTTPRequest.SetRawPostBodyFromFile");
MarkNativeAsOptional("SteamWorksHTTPRequest.GetResponseBodyCallback");
MarkNativeAsOptional("SteamWorksHTTPRequest.WriteResponseBodyToFile");
} }
#endif #endif
+2
View File
@@ -30,4 +30,6 @@ run.options.add_argument('--enable-debug', action='store_const', const='1', dest
run.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt', run.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt',
help='Enable optimization') help='Enable optimization')
run.options.add_argument('--target', default=None, help='Override the default build target') run.options.add_argument('--target', default=None, help='Override the default build target')
run.options.add_argument('--version', type=str, dest='version', default=None,
help='Override the version string baked into the binary (defaults to the literal in smsdk_config.h)')
run.Configure() run.Configure()