mirror of
https://github.com/accelerator74/l4dtoolz.git
synced 2025-07-19 01:48:39 +08:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
aa143fb0e0 | |||
44ee0e7a02 | |||
11ab6e1e54 | |||
e235106c86 | |||
763fbf3b96 | |||
3295b7aeae | |||
c510965a8a | |||
e5e9bac1c0 | |||
e1a6182665 | |||
679b6f54c0 | |||
a7e01138c7 | |||
5b19701a0e | |||
c7ee545ce9 |
@ -1,6 +1,7 @@
|
|||||||
name: l4d2-build
|
name: build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
@ -29,18 +30,22 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
os:
|
os:
|
||||||
- ubuntu-latest
|
- ubuntu-latest
|
||||||
|
- ubuntu-22.04
|
||||||
- windows-latest
|
- windows-latest
|
||||||
|
|
||||||
mm_version:
|
mm_version:
|
||||||
- "master"
|
- "1.12"
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- mm_version: "master"
|
- mm_version: "1.12"
|
||||||
mm_branch: "master"
|
mm_branch: "1.12-dev"
|
||||||
|
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
os_short: linux
|
os_short: linux
|
||||||
|
|
||||||
|
- os: ubuntu-22.04
|
||||||
|
os_short: oldlinux
|
||||||
|
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
os_short: win
|
os_short: win
|
||||||
|
|
||||||
@ -93,6 +98,13 @@ jobs:
|
|||||||
python -m pip install wheel
|
python -m pip install wheel
|
||||||
pip install git+https://github.com/accelerator74/ambuild
|
pip install git+https://github.com/accelerator74/ambuild
|
||||||
|
|
||||||
|
- name: Checking out hl2sdk-l4d
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: alliedmodders/hl2sdk
|
||||||
|
ref: l4d
|
||||||
|
path: hl2sdk-l4d
|
||||||
|
|
||||||
- name: Checking out hl2sdk-l4d2
|
- name: Checking out hl2sdk-l4d2
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@ -105,16 +117,61 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: src
|
path: src
|
||||||
|
|
||||||
- name: Compiling ${{ github.event.repository.name }} files
|
- name: Compiling ${{ github.event.repository.name }}-l4d files
|
||||||
working-directory: src
|
working-directory: src
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build_l4d
|
||||||
cd build
|
cd build_l4d
|
||||||
|
python ../configure.py --enable-optimize --sdks="l4d" --mms-path="${{ github.workspace }}/metamod-${{ matrix.mm_version }}"
|
||||||
|
ambuild
|
||||||
|
|
||||||
|
- name: Compiling ${{ github.event.repository.name }}-l4d2 files
|
||||||
|
working-directory: src
|
||||||
|
run: |
|
||||||
|
mkdir build_l4d2
|
||||||
|
cd build_l4d2
|
||||||
python ../configure.py --enable-optimize --sdks="l4d2" --mms-path="${{ github.workspace }}/metamod-${{ matrix.mm_version }}"
|
python ../configure.py --enable-optimize --sdks="l4d2" --mms-path="${{ github.workspace }}/metamod-${{ matrix.mm_version }}"
|
||||||
ambuild
|
ambuild
|
||||||
|
|
||||||
- name: Uploading package
|
- name: Uploading l4d package
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ github.event.repository.name }}-l4d-${{ matrix.os_short }}-${{ env.GITHUB_SHA_SHORT }}
|
||||||
|
path: src/build_l4d/package
|
||||||
|
|
||||||
|
- name: Uploading l4d2 package
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ github.event.repository.name }}-l4d2-${{ matrix.os_short }}-${{ env.GITHUB_SHA_SHORT }}
|
name: ${{ github.event.repository.name }}-l4d2-${{ matrix.os_short }}-${{ env.GITHUB_SHA_SHORT }}
|
||||||
path: src/build/package
|
path: src/build_l4d2/package
|
||||||
|
|
||||||
|
release:
|
||||||
|
name: Release
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Package
|
||||||
|
run: |
|
||||||
|
version=`echo $GITHUB_REF | sed "s/refs\/tags\///"`
|
||||||
|
ls -Rall
|
||||||
|
for folder in ${{ github.event.repository.name }}*; do
|
||||||
|
if [ -d "$folder" ]; then
|
||||||
|
echo "Processing folder: $folder"
|
||||||
|
cd $folder
|
||||||
|
tar -czf ../$folder.tar.gz -T <(\ls -1)
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
uses: svenstaro/upload-release-action@v2
|
||||||
|
with:
|
||||||
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
file: '*.tar.gz'
|
||||||
|
tag: ${{ github.ref }}
|
||||||
|
file_glob: true
|
120
.github/workflows/l4d_build.yml
vendored
120
.github/workflows/l4d_build.yml
vendored
@ -1,120 +0,0 @@
|
|||||||
name: l4d-build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- master
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
paths-ignore:
|
|
||||||
- LICENSE
|
|
||||||
- README.md
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- master
|
|
||||||
paths-ignore:
|
|
||||||
- LICENSE
|
|
||||||
- README.md
|
|
||||||
schedule:
|
|
||||||
- cron: '30 03 01 */3 *' # Artifacts expire every 3 months
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: build with mms${{ matrix.mm_version }} on ${{ matrix.os_short }}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
os:
|
|
||||||
- ubuntu-latest
|
|
||||||
- windows-latest
|
|
||||||
|
|
||||||
mm_version:
|
|
||||||
- "master"
|
|
||||||
|
|
||||||
include:
|
|
||||||
- mm_version: "master"
|
|
||||||
mm_branch: "master"
|
|
||||||
|
|
||||||
- os: ubuntu-latest
|
|
||||||
os_short: linux
|
|
||||||
|
|
||||||
- os: windows-latest
|
|
||||||
os_short: win
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Prepare env
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "GITHUB_SHA_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Install (Linux)
|
|
||||||
if: startsWith(runner.os, 'Linux')
|
|
||||||
run: |
|
|
||||||
sudo dpkg --add-architecture i386
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y clang g++-multilib
|
|
||||||
echo "CC=clang" >> $GITHUB_ENV
|
|
||||||
echo "CXX=clang++" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Add msbuild to PATH (Windows)
|
|
||||||
if: startsWith(runner.os, 'Windows')
|
|
||||||
uses: microsoft/setup-msbuild@v2
|
|
||||||
|
|
||||||
- name: Install (Windows)
|
|
||||||
if: startsWith(runner.os, 'Windows')
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
:: See https://github.com/microsoft/vswhere/wiki/Find-VC
|
|
||||||
for /f "usebackq delims=*" %%i in (`vswhere -latest -property installationPath`) do (
|
|
||||||
call "%%i"\Common7\Tools\vsdevcmd.bat -arch=x86 -host_arch=x64
|
|
||||||
)
|
|
||||||
:: Loop over all environment variables and make them global.
|
|
||||||
for /f "delims== tokens=1,2" %%a in ('set') do (
|
|
||||||
echo>>"%GITHUB_ENV%" %%a=%%b
|
|
||||||
)
|
|
||||||
|
|
||||||
- name: Checking out MM:Source
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: alliedmodders/metamod-source
|
|
||||||
ref: ${{ matrix.mm_branch }}
|
|
||||||
path: metamod-${{ matrix.mm_version }}
|
|
||||||
|
|
||||||
- name: Setting up Python
|
|
||||||
uses: actions/setup-python@v5
|
|
||||||
with:
|
|
||||||
python-version: '3.11'
|
|
||||||
|
|
||||||
- name: Setting up ambuild
|
|
||||||
run: |
|
|
||||||
python -m pip install wheel
|
|
||||||
pip install git+https://github.com/accelerator74/ambuild
|
|
||||||
|
|
||||||
- name: Checking out hl2sdk-l4d
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: alliedmodders/hl2sdk
|
|
||||||
ref: l4d
|
|
||||||
path: hl2sdk-l4d
|
|
||||||
|
|
||||||
- name: Checking out own repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
path: src
|
|
||||||
|
|
||||||
- name: Compiling ${{ github.event.repository.name }} files
|
|
||||||
working-directory: src
|
|
||||||
run: |
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
python ../configure.py --enable-optimize --sdks="l4d" --mms-path="${{ github.workspace }}/metamod-${{ matrix.mm_version }}"
|
|
||||||
ambuild
|
|
||||||
|
|
||||||
- name: Uploading package
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ github.event.repository.name }}-l4d-${{ matrix.os_short }}-${{ env.GITHUB_SHA_SHORT }}
|
|
||||||
path: src/build/package
|
|
265
baseserver.h
Normal file
265
baseserver.h
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
// CBaseServer vtable for l4d1 and l4d2 games
|
||||||
|
// Header file created by - A1m`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vim: set ts=4 :
|
||||||
|
* =============================================================================
|
||||||
|
* Left 4 Downtown SourceMod Extension
|
||||||
|
* Copyright (C) 2021-2023 A1m`;
|
||||||
|
* =============================================================================
|
||||||
|
*
|
||||||
|
* 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 BASESERVER_H
|
||||||
|
#define BASESERVER_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <iserver.h>
|
||||||
|
#include <netadr.h>
|
||||||
|
#include <irecipientfilter.h>
|
||||||
|
#include <bitbuf.h>
|
||||||
|
#include <utlvector.h>
|
||||||
|
#include <checksum_crc.h>
|
||||||
|
|
||||||
|
class IClient;
|
||||||
|
class CBaseClient;
|
||||||
|
class CClientFrame;
|
||||||
|
class CFrameSnapshot;
|
||||||
|
class CLC_SplitPlayerConnect;
|
||||||
|
class CNetworkStringTableContainer;
|
||||||
|
class INetworkStringTable;
|
||||||
|
|
||||||
|
enum server_state_t
|
||||||
|
{
|
||||||
|
ss_dead = 0, // Dead
|
||||||
|
ss_loading, // Spawning
|
||||||
|
ss_active, // Running
|
||||||
|
ss_paused, // Running, but paused
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
netadr_t adr; // Address where challenge value was sent to.
|
||||||
|
int challenge; // To connect, adr IP address must respond with this #
|
||||||
|
float time; // # is valid for only a short duration.
|
||||||
|
} challenge_t;
|
||||||
|
|
||||||
|
class CBaseServer :
|
||||||
|
public IServer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~CBaseServer() = 0;
|
||||||
|
|
||||||
|
public: // IConnectionlessPacketHandler implementation
|
||||||
|
|
||||||
|
virtual bool ProcessConnectionlessPacket( netpacket_t *packet ) = 0;
|
||||||
|
|
||||||
|
public: // IServer implementation
|
||||||
|
|
||||||
|
virtual int GetNumClients( void ) const = 0;
|
||||||
|
virtual int GetNumProxies( void ) const = 0;
|
||||||
|
virtual int GetNumFakeClients( void ) const = 0;
|
||||||
|
virtual int GetMaxClients( void ) const = 0;
|
||||||
|
virtual IClient* GetClient( int index ) = 0;
|
||||||
|
virtual int GetClientCount( void ) const = 0;
|
||||||
|
virtual int GetUDPPort( void ) const = 0;
|
||||||
|
virtual float GetTime( void ) const = 0;
|
||||||
|
virtual int GetTick( void ) const = 0;
|
||||||
|
virtual float GetTickInterval( void ) const = 0;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_LEFT4DEAD2
|
||||||
|
virtual float GetTimescale( void ) const = 0; // l4d2 only
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual const char* GetName( void ) const = 0;
|
||||||
|
virtual const char* GetMapName( void ) const = 0;
|
||||||
|
virtual int GetSpawnCount( void ) const = 0;
|
||||||
|
virtual int GetNumClasses( void ) const = 0;
|
||||||
|
virtual int GetClassBits( void ) const = 0;
|
||||||
|
virtual void GetNetStats( float &avgIn, float &avgOut ) = 0;
|
||||||
|
virtual int GetNumPlayers( void ) = 0;
|
||||||
|
virtual bool GetPlayerInfo( int nClientIndex, player_info_t *pinfo ) = 0;
|
||||||
|
virtual bool IsActive( void ) const = 0;
|
||||||
|
virtual bool IsLoading( void ) const = 0;
|
||||||
|
virtual bool IsDedicated( void ) const = 0;
|
||||||
|
virtual bool IsPaused( void ) const = 0;
|
||||||
|
virtual bool IsMultiplayer( void ) const = 0;
|
||||||
|
virtual bool IsPausable( void ) const = 0;
|
||||||
|
virtual bool IsHLTV( void ) const = 0;
|
||||||
|
virtual const char* GetPassword( void ) const = 0;
|
||||||
|
virtual void SetPaused( bool paused ) = 0;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_LEFT4DEAD2
|
||||||
|
virtual void SetTimescale( float flTimescale ) = 0; // l4d2 only
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual void SetPassword( const char *password ) = 0;
|
||||||
|
virtual void BroadcastMessage( INetMessage &msg, bool onlyActive = false, bool reliable = false ) = 0;
|
||||||
|
virtual void BroadcastMessage( INetMessage &msg, IRecipientFilter &filter ) = 0;
|
||||||
|
virtual void DisconnectClient( IClient *client, const char *reason ) = 0;
|
||||||
|
virtual float GetCPUUsage( void ) = 0;
|
||||||
|
|
||||||
|
public: // Other
|
||||||
|
|
||||||
|
virtual void BroadcastPrintf( const char *fmt, ... ) = 0;
|
||||||
|
virtual void SetMaxClients( int number ) = 0;
|
||||||
|
virtual void WriteDeltaEntities( CBaseClient *client, CClientFrame *to, CClientFrame *from, bf_write &pBuf ) = 0;
|
||||||
|
virtual void WriteTempEntities( CBaseClient *client, CFrameSnapshot *to, CFrameSnapshot *from, bf_write &pBuf, int nMaxEnts ) = 0;
|
||||||
|
virtual void Init( bool isDedicated ) = 0;
|
||||||
|
virtual void Clear( void ) = 0;
|
||||||
|
virtual void Shutdown( void ) = 0;
|
||||||
|
virtual CBaseClient* CreateFakeClient( const char *name ) = 0;
|
||||||
|
virtual void RemoveClientFromGame( CBaseClient* client ) = 0;
|
||||||
|
virtual void SendClientMessages( bool bSendSnapshots ) = 0;
|
||||||
|
virtual void FillServerInfo( SVC_ServerInfo &serverinfo ) = 0;
|
||||||
|
virtual void UserInfoChanged( int nClientIndex ) = 0;
|
||||||
|
virtual void RejectConnection( const netadr_t &adr, char *fmt, ... ) = 0;
|
||||||
|
virtual bool CheckIPRestrictions( const netadr_t &adr, int nAuthProtocol ) = 0;
|
||||||
|
|
||||||
|
virtual IClient* ConnectClient( netadr_t &adr, int protocol, int challenge, int authProtocol,
|
||||||
|
const char *name, const char *password, const char *hashedCDkey, int cdKeyLen,
|
||||||
|
CUtlVector< CLC_SplitPlayerConnect * > &splitScreenClients, bool isClientLowViolence ) = 0;
|
||||||
|
|
||||||
|
virtual CBaseClient* CreateNewClient( int slot ) = 0;
|
||||||
|
virtual bool FinishCertificateCheck( netadr_t &adr, int nAuthProtocol, const char *szRawCertificate ) = 0;
|
||||||
|
virtual int GetChallengeNr( netadr_t &adr ) = 0;
|
||||||
|
virtual int GetChallengeType( netadr_t &adr ) = 0;
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_LEFT4DEAD2
|
||||||
|
virtual bool CheckHostVersion( netadr_t &adr, int checkVersion ) = 0; // l4d2 only
|
||||||
|
#else
|
||||||
|
virtual bool CheckProtocol( netadr_t& adr, int nProtocol ) = 0; // l4d1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual bool CheckChallengeNr( netadr_t &adr, int nChallengeValue ) = 0;
|
||||||
|
virtual bool CheckChallengeType( CBaseClient *client, int nNewUserID, netadr_t &adr, int nAuthProtocol, const char *pchLogonCookie, int cbCookie ) = 0;
|
||||||
|
virtual bool CheckPassword(netadr_t &adr, const char *password, const char *name ) = 0;
|
||||||
|
virtual void ReplyChallenge(netadr_t &adr, bf_read &msg ) = 0;
|
||||||
|
virtual void ReplyServerChallenge( netadr_t &adr ) = 0;
|
||||||
|
virtual void ReplyReservationRequest( netadr_t &adr, bf_read &msg ) = 0;
|
||||||
|
virtual void CalculateCPUUsage( void ) = 0;
|
||||||
|
virtual bool ShouldUpdateMasterServer( void ) = 0;
|
||||||
|
virtual void UpdateMasterServerPlayers( void ) = 0;
|
||||||
|
|
||||||
|
// vtable offset - 0
|
||||||
|
server_state_t m_State; // 4, some actions are only valid during load (CBaseServer::IsActive)
|
||||||
|
int m_Socket; // 8, network socket (CBaseServer::GetUDPPort)
|
||||||
|
int m_nTickCount; // 12, current server tick (CBaseServer::GetTick)
|
||||||
|
char m_szMapname[64]; // 16, map name without path and extension (CBaseServer::Clear)
|
||||||
|
char m_szSkyname[64]; // 80, skybox name (CBaseServer::Clear)
|
||||||
|
char m_Password[32]; // 144, server password (CBaseServer::SetPassword)
|
||||||
|
|
||||||
|
CRC32_t worldmapCRC; // 176, For detecting that client has a hacked local copy of map, the client will be dropped if this occurs. (CGameServer::SpawnServer)
|
||||||
|
CRC32_t clientDllCRC; // 180, The dll that this server is expecting clients to be using. (CGameServer::SpawnServer)
|
||||||
|
CRC32_t stringTableCRC; // 184, (CGameServer::SpawnServer)
|
||||||
|
|
||||||
|
CNetworkStringTableContainer* m_StringTables; // 188, newtork string table container (CBaseServer::GetUserInfoTable)
|
||||||
|
|
||||||
|
INetworkStringTable* m_pInstanceBaselineTable; // 192, (CBaseServer::GetInstanceBaselineTable)
|
||||||
|
INetworkStringTable* m_pLightStyleTable; // 196, (CBaseServer::GetLightStyleTable)
|
||||||
|
INetworkStringTable* m_pUserInfoTable; // 200, (CBaseServer::GetUserInfoTable)
|
||||||
|
INetworkStringTable* m_pServerStartupTable; // 204, (CGameServer::SetQueryPortFromSteamServer)
|
||||||
|
INetworkStringTable* m_pDownloadableFileTable; // 208, (CGameServer::CreateEngineStringTables)
|
||||||
|
|
||||||
|
bf_write m_Signon; // 212, (24 byte) (CBaseServer::Clear)
|
||||||
|
CUtlMemory<byte> m_SignonBuffer; // 236, (12 byte) (CBaseServer::Clear)
|
||||||
|
|
||||||
|
int serverclasses; // 248, number of unique server classes (CBaseServer::Clear)
|
||||||
|
int serverclassbits; // 252, log2 of serverclasses (CBaseServer::Clear)
|
||||||
|
|
||||||
|
int m_nUserid; // 256, increases by one with every new client (CBaseServer::GetNextUserID)
|
||||||
|
|
||||||
|
int m_nMaxclients; // 260, Current max # (CBaseServer::SetMaxClients)
|
||||||
|
int m_nSpawnCount; // 264, Number of servers spawned since start, used to check late spawns (e.g., when d/l'ing lots of data) (CBaseServer::GetSpawnCount)
|
||||||
|
|
||||||
|
float m_flTickInterval; // 268, time for 1 tick in seconds (CBaseServer::GetTickInterval)
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_LEFT4DEAD2
|
||||||
|
float m_flTimescale; // 272, the game time scale (multiplied in conjunction with host_timescale) (CBaseServer::GetTimescale)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CUtlVector<CBaseClient*> m_Clients; // l4d2 - 276 (20 byte), l4d1 - 272, array of up to [maxclients] client slots. (CBaseServer::GetClient)
|
||||||
|
|
||||||
|
bool m_bIsDedicated; // l4d2 - 296, l4d1 - 292, (CBaseServer::IsDedicated)
|
||||||
|
// 3 byte alignment
|
||||||
|
|
||||||
|
CUtlVector<challenge_t> m_ServerQueryChallenges; // l4d2 - 300 (20 byte), l4d1 - 296, prevent spoofed IP's from server queries/connecting (CBaseServer::GetChallengeNr)
|
||||||
|
|
||||||
|
float m_fCPUPercent; // l4d2 - 320, l4d1 - 316, (CBaseServer::GetCPUUsage)
|
||||||
|
float m_fStartTime; // l4d2 - 324, l4d1 - 320, (CBaseServer::CalculateCPUUsage)
|
||||||
|
float m_fLastCPUCheckTime; // l4d2 - 328, l4d1 - 324, (CBaseServer::CalculateCPUUsage)
|
||||||
|
|
||||||
|
// This is only used for Steam's master server updater to refer to this server uniquely.
|
||||||
|
bool m_bRestartOnLevelChange; // l4d2 - 332, l4d1 - 328, (CBaseServer::CheckMasterServerRequestRestart)
|
||||||
|
bool m_bMasterServerRulesDirty; // l4d2 - 333, l4d1 - 329, (CBaseServer::UpdateMasterServerRules)
|
||||||
|
|
||||||
|
// 3 byte alignment
|
||||||
|
double m_flLastMasterServerUpdateTime; // l4d2 - 336 (8 byte), l4d1 - 332, (CBaseServer::UpdateMasterServer)
|
||||||
|
|
||||||
|
struct SplitDisconnect_t
|
||||||
|
{
|
||||||
|
CBaseClient* m_pUser;
|
||||||
|
CBaseClient* m_pSplit;
|
||||||
|
};
|
||||||
|
|
||||||
|
CUtlVector< SplitDisconnect_t > m_QueuedForDisconnect; // l4d2 - 344 (20 byte), l4d1 - 340, (CBaseServer::QueueSplitScreenDisconnect)
|
||||||
|
|
||||||
|
uint64 m_nReservationCookie; // l4d2 - 364 (8 byte), l4d1 - 360, if this server has been reserved, cookie that connecting clients must present (CBaseServer::GetReservationCookie)
|
||||||
|
float m_flReservationExpiryTime; // l4d2 - 372, l4d1 - 368, time at which reservation expires (CBaseServer::UpdateReservedState)
|
||||||
|
float m_flTimeLastClientLeft; // l4d2 - 376, l4d1 - 372, time when last client left server (CGameServer::UpdateHibernationState)
|
||||||
|
int m_numGameSlots; // l4d2 - 380, l4d1 - 376, number of game slots allocated (CBaseServer::ConnectClient)
|
||||||
|
CUtlString m_GameType; // l4d2 - 384 (16 byte ?), l4d1 - 380, (CBaseServer::ClearTagStrings)
|
||||||
|
|
||||||
|
CUtlVector<char> m_GameData; // l4d2 - 400 (20 byte), l4d1 - 396, (CBaseServer::GetGameData)
|
||||||
|
int m_GameDataVersion; // l4d2 - 420, l4d1 - 416, (CBaseServer::GetGameDataVersion)
|
||||||
|
|
||||||
|
#if SOURCE_ENGINE == SE_LEFT4DEAD // l4d1
|
||||||
|
bool m_bSteamMasterHeartbeatsEnabled; // l4d1 - 420 (CBaseServer::UpdateMasterServer)
|
||||||
|
// 3 byte alignment
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float m_flTimeReservationGraceStarted; // l4d2 - 424, l4d1 - 424, time when client attempted to connect and was granted a reservation grace period (CBaseServer::CanAcceptChallengesFrom)
|
||||||
|
netadr_t m_adrReservationGraceStarted; // l4d2 - 428 (12 byte), l4d1 - 428, netadr of the client for whom reservation grace has been given (CBaseServer::CanAcceptChallengesFrom)
|
||||||
|
|
||||||
|
struct ReservationStatus_t
|
||||||
|
{
|
||||||
|
ReservationStatus_t() : m_bActive(false), m_bSuccess(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_bActive;
|
||||||
|
bool m_bSuccess;
|
||||||
|
// 2 byte alignment
|
||||||
|
netadr_t m_Remote;
|
||||||
|
};
|
||||||
|
|
||||||
|
ReservationStatus_t m_ReservationStatus; // l4d2 - 440 (16 byte?), l4d1 - 440, (CBaseServer::ClearReservationStatus)
|
||||||
|
};
|
||||||
|
// size 456 l4d2 and l4d1
|
||||||
|
|
||||||
|
#endif // BASESERVER_H
|
@ -14,7 +14,7 @@ builder.options.add_option('--enable-debug', action='store_const', const='1', de
|
|||||||
help='Enable debugging symbols')
|
help='Enable debugging symbols')
|
||||||
builder.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
|
builder.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
|
||||||
help='Enable optimization')
|
help='Enable optimization')
|
||||||
builder.options.add_option('-s', '--sdks', default='all', dest='sdks',
|
builder.options.add_option('-s', '--sdks', default='present', dest='sdks',
|
||||||
help='Build against specified SDKs; valid args are "all", "present", or '
|
help='Build against specified SDKs; valid args are "all", "present", or '
|
||||||
'comma-delimited list of engine names (default: %default)')
|
'comma-delimited list of engine names (default: %default)')
|
||||||
|
|
||||||
|
@ -2,19 +2,23 @@
|
|||||||
#define _INCLUDE_GAME_OFFSETS_
|
#define _INCLUDE_GAME_OFFSETS_
|
||||||
|
|
||||||
#if SH_SYS == SH_SYS_WIN32
|
#if SH_SYS == SH_SYS_WIN32
|
||||||
int maxplayers_offs = 138; // m_nMaxClientsLimit (in CGameServer::SetMaxClients)
|
const int maxplayers_offs = 0x228; // m_nMaxClientsLimit (in CGameServer::SetMaxClients)
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||||
#include "l4d1_offsets_win32.h"
|
const int sv_offs = 6; // IServer pointer (in IVEngineServer::CreateFakeClient)
|
||||||
|
const int maxhuman_idx = 131; // CTerrorGameRules::GetMaxHumanPlayers vtable
|
||||||
|
#else
|
||||||
|
const int sv_offs = 8; // IServer pointer (in IVEngineServer::CreateFakeClient)
|
||||||
|
const int maxhuman_idx = 136; // CTerrorGameRules::GetMaxHumanPlayers vtable
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#include "l4d2_offsets_win32.h"
|
const int maxplayers_offs = 0x220; // m_nMaxClientsLimit (in CGameServer::SetMaxClients)
|
||||||
#endif
|
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
||||||
#else
|
const char* engine_dll = "engine.so";
|
||||||
int maxplayers_offs = 136; // m_nMaxClientsLimit (in CGameServer::SetMaxClients)
|
const int maxhuman_idx = 132; // CTerrorGameRules::GetMaxHumanPlayers vtable
|
||||||
#if SOURCE_ENGINE == SE_LEFT4DEAD
|
#else
|
||||||
#include "l4d1_offsets_linux.h"
|
const char* engine_dll = "engine_srv.so";
|
||||||
#else
|
const int maxhuman_idx = 137; // CTerrorGameRules::GetMaxHumanPlayers vtable
|
||||||
#include "l4d2_offsets_linux.h"
|
#endif
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //_INCLUDE_GAME_OFFSETS_
|
#endif //_INCLUDE_GAME_OFFSETS_
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef _INCLUDE_L4D1_OFFSETS_LINUX_
|
|
||||||
#define _INCLUDE_L4D1_OFFSETS_LINUX_
|
|
||||||
|
|
||||||
const char* engine_dll = "engine.so";
|
|
||||||
int slots_offs = 94; // m_numGameSlots (in CGameServer::ExecGameTypeCfg)
|
|
||||||
int reservation_idx = 60; // CBaseServer::ReplyReservationRequest(netadr_s&, bf_read&) vtable
|
|
||||||
int maxhuman_idx = 132; // CTerrorGameRules::GetMaxHumanPlayers vtable
|
|
||||||
|
|
||||||
#endif //_INCLUDE_L4D1_OFFSETS_LINUX_
|
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef _INCLUDE_L4D1_OFFSETS_WIN32_
|
|
||||||
#define _INCLUDE_L4D1_OFFSETS_WIN32_
|
|
||||||
|
|
||||||
int sv_offs = 6; // IServer pointer (in IVEngineServer::CreateFakeClient)
|
|
||||||
int slots_offs = 96; // m_numGameSlots (in CGameServer::ExecGameTypeCfg)
|
|
||||||
int reservation_idx = 59; // CBaseServer::ReplyReservationRequest(netadr_s&, bf_read&) vtable
|
|
||||||
int maxhuman_idx = 131; // CTerrorGameRules::GetMaxHumanPlayers vtable
|
|
||||||
|
|
||||||
#endif //_INCLUDE_L4D1_OFFSETS_WIN32_
|
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef _INCLUDE_L4D2_OFFSETS_LINUX_
|
|
||||||
#define _INCLUDE_L4D2_OFFSETS_LINUX_
|
|
||||||
|
|
||||||
const char* engine_dll = "engine_srv.so";
|
|
||||||
int slots_offs = 95; // m_numGameSlots (in CGameServer::ExecGameTypeCfg)
|
|
||||||
int reservation_idx = 62; // CBaseServer::ReplyReservationRequest(netadr_s&, bf_read&) vtable
|
|
||||||
int maxhuman_idx = 137; // CTerrorGameRules::GetMaxHumanPlayers vtable
|
|
||||||
|
|
||||||
#endif //_INCLUDE_L4D2_OFFSETS_LINUX_
|
|
@ -1,9 +0,0 @@
|
|||||||
#ifndef _INCLUDE_L4D2_OFFSETS_WIN32_
|
|
||||||
#define _INCLUDE_L4D2_OFFSETS_WIN32_
|
|
||||||
|
|
||||||
int sv_offs = 8; // IServer pointer (in IVEngineServer::CreateFakeClient)
|
|
||||||
int slots_offs = 96; // m_numGameSlots (in CGameServer::ExecGameTypeCfg)
|
|
||||||
int reservation_idx = 61; // CBaseServer::ReplyReservationRequest(netadr_s&, bf_read&) vtable
|
|
||||||
int maxhuman_idx = 136; // CTerrorGameRules::GetMaxHumanPlayers vtable
|
|
||||||
|
|
||||||
#endif //_INCLUDE_L4D2_OFFSETS_WIN32_
|
|
@ -1,5 +1,6 @@
|
|||||||
#include "l4dtoolz_mm.h"
|
#include "l4dtoolz_mm.h"
|
||||||
#include "game_offsets.h"
|
#include "game_offsets.h"
|
||||||
|
#include "baseserver.h"
|
||||||
#include "memutils.h"
|
#include "memutils.h"
|
||||||
#include "icommandline.h"
|
#include "icommandline.h"
|
||||||
#include "server_class.h"
|
#include "server_class.h"
|
||||||
@ -12,16 +13,16 @@ IServerGameClients* gameclients = NULL;
|
|||||||
IVEngineServer* engine = NULL;
|
IVEngineServer* engine = NULL;
|
||||||
IMatchFramework* g_pMatchFramework = NULL;
|
IMatchFramework* g_pMatchFramework = NULL;
|
||||||
ICvar* g_pCVar = NULL;
|
ICvar* g_pCVar = NULL;
|
||||||
IServer* g_pGameIServer = NULL;
|
CBaseServer* g_pGameIServer = NULL;
|
||||||
void* g_pGameRules = nullptr;
|
void* g_pGameRules = nullptr;
|
||||||
int m_numGameSlots = -1;
|
int g_nGameSlots = -1;
|
||||||
|
|
||||||
SH_DECL_HOOK1_void(IServerGameDLL, ApplyGameSettings, SH_NOATTRIB, 0, KeyValues*);
|
SH_DECL_HOOK1_void(IServerGameDLL, ApplyGameSettings, SH_NOATTRIB, 0, KeyValues*);
|
||||||
SH_DECL_HOOK0(IMatchTitle, GetTotalNumPlayersSupported, SH_NOATTRIB, 0, int);
|
SH_DECL_HOOK0(IMatchTitle, GetTotalNumPlayersSupported, SH_NOATTRIB, 0, int);
|
||||||
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, char const *, char const *, char const *, char const *, bool, bool);
|
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, 0, bool, char const *, char const *, char const *, char const *, bool, bool);
|
||||||
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0);
|
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, 0);
|
||||||
SH_DECL_MANUALHOOK0(CTerrorGameRules_GetMaxHumanPlayers, maxhuman_idx, 0, 0, int);
|
SH_DECL_MANUALHOOK0(CTerrorGameRules_GetMaxHumanPlayers, maxhuman_idx, 0, 0, int);
|
||||||
SH_DECL_MANUALHOOK2_void(CBaseServer_ReplyReservationRequest, reservation_idx, 0, 0, netadr_s&, CBitRead&);
|
SH_DECL_HOOK2_void(CBaseServer, ReplyReservationRequest, SH_NOATTRIB, 0, netadr_t&, bf_read&);
|
||||||
|
|
||||||
ConVar sv_maxplayers("sv_maxplayers", "-1", FCVAR_SPONLY|FCVAR_NOTIFY, "Max Human Players", true, -1, true, 32, l4dtoolz::OnChangeMaxplayers);
|
ConVar sv_maxplayers("sv_maxplayers", "-1", FCVAR_SPONLY|FCVAR_NOTIFY, "Max Human Players", true, -1, true, 32, l4dtoolz::OnChangeMaxplayers);
|
||||||
ConVar sv_force_unreserved("sv_force_unreserved", "0", FCVAR_SPONLY|FCVAR_NOTIFY, "Disallow lobby reservation cookie", true, 0, true, 1, l4dtoolz::OnChangeUnreserved);
|
ConVar sv_force_unreserved("sv_force_unreserved", "0", FCVAR_SPONLY|FCVAR_NOTIFY, "Disallow lobby reservation cookie", true, 0, true, 1, l4dtoolz::OnChangeUnreserved);
|
||||||
@ -36,10 +37,10 @@ void l4dtoolz::OnChangeMaxplayers ( IConVar *var, const char *pOldValue, float f
|
|||||||
}
|
}
|
||||||
if(new_value != old_value) {
|
if(new_value != old_value) {
|
||||||
if(new_value >= 0) {
|
if(new_value >= 0) {
|
||||||
m_numGameSlots = new_value;
|
g_nGameSlots = new_value;
|
||||||
*(int*)(((uint**)g_pGameIServer)+slots_offs) = m_numGameSlots;
|
g_pGameIServer->m_numGameSlots = g_nGameSlots;
|
||||||
} else {
|
} else {
|
||||||
m_numGameSlots = -1;
|
g_nGameSlots = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +55,7 @@ void l4dtoolz::OnChangeUnreserved ( IConVar *var, const char *pOldValue, float f
|
|||||||
}
|
}
|
||||||
if(new_value != old_value) {
|
if(new_value != old_value) {
|
||||||
if(new_value == 1) {
|
if(new_value == 1) {
|
||||||
engine->ServerCommand("sv_allow_lobby_connect_only 0\n");
|
g_pCVar->FindVar("sv_allow_lobby_connect_only")->SetValue(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,16 +65,20 @@ void Hook_ApplyGameSettings(KeyValues *pKV)
|
|||||||
if (!pKV) {
|
if (!pKV) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_numGameSlots = sv_maxplayers.GetInt();
|
g_nGameSlots = sv_maxplayers.GetInt();
|
||||||
if (m_numGameSlots == -1) {
|
if (g_nGameSlots == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pKV->SetInt("members/numSlots", m_numGameSlots);
|
pKV->SetInt("members/numSlots", g_nGameSlots);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hook_ReplyReservationRequest(netadr_s& adr, CBitRead& inmsg)
|
void Hook_ReplyReservationRequest(netadr_t& adr, bf_read& inmsg)
|
||||||
{
|
{
|
||||||
if (sv_force_unreserved.GetInt()) {
|
if (sv_force_unreserved.GetInt()) {
|
||||||
|
if (g_pGameIServer != NULL) {
|
||||||
|
if (g_pGameIServer->m_nReservationCookie != 0)
|
||||||
|
RETURN_META(MRES_IGNORED);
|
||||||
|
}
|
||||||
RETURN_META(MRES_SUPERCEDE);
|
RETURN_META(MRES_SUPERCEDE);
|
||||||
}
|
}
|
||||||
RETURN_META(MRES_IGNORED);
|
RETURN_META(MRES_IGNORED);
|
||||||
@ -81,10 +86,10 @@ void Hook_ReplyReservationRequest(netadr_s& adr, CBitRead& inmsg)
|
|||||||
|
|
||||||
int Hook_GetMaxHumanPlayers()
|
int Hook_GetMaxHumanPlayers()
|
||||||
{
|
{
|
||||||
if (m_numGameSlots > 0) {
|
if (g_nGameSlots > 0) {
|
||||||
RETURN_META_VALUE(MRES_SUPERCEDE, m_numGameSlots);
|
RETURN_META_VALUE(MRES_SUPERCEDE, g_nGameSlots);
|
||||||
}
|
}
|
||||||
RETURN_META_VALUE(MRES_IGNORED, m_numGameSlots);
|
RETURN_META_VALUE(MRES_IGNORED, g_nGameSlots);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLUGIN_EXPOSE(l4dtoolz, g_l4dtoolz);
|
PLUGIN_EXPOSE(l4dtoolz, g_l4dtoolz);
|
||||||
@ -104,20 +109,22 @@ bool l4dtoolz::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool
|
|||||||
if (!(handle=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient))) {
|
if (!(handle=SH_GET_ORIG_VFNPTR_ENTRY(engine, &IVEngineServer::CreateFakeClient))) {
|
||||||
Warning("Failed to get address 'IVEngineServer::CreateFakeClient'\n");
|
Warning("Failed to get address 'IVEngineServer::CreateFakeClient'\n");
|
||||||
} else {
|
} else {
|
||||||
g_pGameIServer = *reinterpret_cast<IServer **>(reinterpret_cast<unsigned char *>(handle)+sv_offs);
|
g_pGameIServer = *reinterpret_cast<CBaseServer **>(reinterpret_cast<unsigned char *>(handle)+sv_offs);
|
||||||
#else
|
#else
|
||||||
if (!(handle=dlopen(engine_dll, RTLD_LAZY))) {
|
if (!(handle=dlopen(engine_dll, RTLD_LAZY))) {
|
||||||
Warning("Could't open library '%s'\n", engine_dll);
|
Warning("Could't open library '%s'\n", engine_dll);
|
||||||
} else {
|
} else {
|
||||||
g_pGameIServer = (IServer *)g_MemUtils.ResolveSymbol(handle, "sv");
|
g_pGameIServer = (CBaseServer *)g_MemUtils.ResolveSymbol(handle, "sv");
|
||||||
dlclose(handle);
|
dlclose(handle);
|
||||||
#endif
|
#endif
|
||||||
int* m_nMaxClientsLimit = (int*)(((uint**)g_pGameIServer)+maxplayers_offs);
|
int* m_nMaxClientsLimit = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(g_pGameIServer)+maxplayers_offs);
|
||||||
if (*m_nMaxClientsLimit != 0x12) {
|
if (*m_nMaxClientsLimit != 18) {
|
||||||
Warning("Couldn't patch maxplayers\n");
|
Warning("Couldn't patch maxplayers\n");
|
||||||
g_pGameIServer = NULL;
|
if (!late) {
|
||||||
|
g_pGameIServer = NULL;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*m_nMaxClientsLimit = 0x20;
|
*m_nMaxClientsLimit = 32;
|
||||||
const char *pszCmdLineMax;
|
const char *pszCmdLineMax;
|
||||||
if(CommandLine()->CheckParm("-maxplayers", &pszCmdLineMax) || CommandLine()->CheckParm("+maxplayers", &pszCmdLineMax)) {
|
if(CommandLine()->CheckParm("-maxplayers", &pszCmdLineMax) || CommandLine()->CheckParm("+maxplayers", &pszCmdLineMax)) {
|
||||||
char command[32];
|
char command[32];
|
||||||
@ -136,7 +143,7 @@ bool l4dtoolz::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool
|
|||||||
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &l4dtoolz::LevelShutdown, false);
|
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &l4dtoolz::LevelShutdown, false);
|
||||||
|
|
||||||
if (g_pGameIServer) {
|
if (g_pGameIServer) {
|
||||||
SH_ADD_MANUALHOOK(CBaseServer_ReplyReservationRequest, g_pGameIServer, SH_STATIC(Hook_ReplyReservationRequest), false);
|
SH_ADD_HOOK(CBaseServer, ReplyReservationRequest, g_pGameIServer, SH_STATIC(Hook_ReplyReservationRequest), false);
|
||||||
} else {
|
} else {
|
||||||
Warning("g_pGameIServer pointer is not available\n");
|
Warning("g_pGameIServer pointer is not available\n");
|
||||||
}
|
}
|
||||||
@ -154,7 +161,7 @@ bool l4dtoolz::Unload(char *error, size_t maxlen)
|
|||||||
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &l4dtoolz::LevelShutdown, false);
|
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &l4dtoolz::LevelShutdown, false);
|
||||||
|
|
||||||
if (g_pGameIServer) {
|
if (g_pGameIServer) {
|
||||||
SH_REMOVE_MANUALHOOK(CBaseServer_ReplyReservationRequest, g_pGameIServer, SH_STATIC(Hook_ReplyReservationRequest), false);
|
SH_REMOVE_HOOK(CBaseServer, ReplyReservationRequest, g_pGameIServer, SH_STATIC(Hook_ReplyReservationRequest), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
LevelShutdown();
|
LevelShutdown();
|
||||||
@ -235,7 +242,7 @@ const char *l4dtoolz::GetLicense()
|
|||||||
|
|
||||||
const char *l4dtoolz::GetVersion()
|
const char *l4dtoolz::GetVersion()
|
||||||
{
|
{
|
||||||
return "2.0.0";
|
return "2.1.0";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *l4dtoolz::GetDate()
|
const char *l4dtoolz::GetDate()
|
||||||
|
Reference in New Issue
Block a user