31 Commits

Author SHA1 Message Date
Accelerator 9c43e4c4a2 Fix win build 2026-09-09 23:03:04 +03:00
Accelerator 62d17722f4 Add submodule 2026-09-09 22:54:57 +03:00
Accelerator a011e38962 Replace SourceHook with KHook 2026-09-09 22:53:01 +03:00
Accelerator 07535e118f Update AMBuildScript
build / build with mms1.12 on oldlinux (push) Failing after 19s
build / build with mms1.12 on linux (push) Failing after 54s
build / build with mms1.12 on win (push) Has been cancelled
build / Release (push) Has been cancelled
2026-09-03 20:44:42 +03:00
Accelerator dedf217b61 Update AMBuildScript
build / build with mms1.12 on oldlinux (push) Failing after 17s
build / build with mms1.12 on linux (push) Failing after 13s
build / build with mms1.12 on win (push) Has been cancelled
build / Release (push) Has been cancelled
2026-07-23 17:49:34 +03:00
Accelerator 178640b3e7 Update build scripts 2026-07-23 17:37:11 +03:00
Accelerator ae7d3d5c2b Update build.yml
build / build with mms1.12 on oldlinux (push) Failing after 19s
build / build with mms1.12 on linux (push) Failing after 26s
build / build with mms1.12 on win (push) Has been cancelled
build / Release (push) Has been cancelled
2026-07-23 13:40:06 +03:00
Accelerator 63c9b19e9a hl2sdk-manifests 2026-07-23 13:35:54 +03:00
Accelerator 6590795d4f Update AMBuildScript 2026-07-23 09:09:18 +03:00
Accelerator 3041183422 Update build.yml
build / build with mms1.12 on oldlinux (push) Failing after 25s
build / build with mms1.12 on linux (push) Failing after 7s
build / build with mms1.12 on win (push) Has been cancelled
build / Release (push) Has been cancelled
2025-11-26 15:06:18 +03:00
Accelerator c895db9e78 Update build.yml 2025-11-26 14:51:52 +03:00
Accelerator ef2a8df7e0 2.2.0
build / build with mms1.12 on oldlinux (push) Has been cancelled
build / build with mms1.12 on linux (push) Has been cancelled
build / build with mms1.12 on win (push) Has been cancelled
build / Release (push) Has been cancelled
New method for changing the MaxClients limit. Thanks to @A1mDev
2025-11-18 18:57:20 +03:00
Accelerator aa143fb0e0 Bump version
build / build with mms1.12 on oldlinux (push) Failing after 2m21s
build / build with mms1.12 on linux (push) Failing after 35s
build / build with mms1.12 on win (push) Has been cancelled
build / Release (push) Has been cancelled
2025-07-12 20:24:28 +03:00
Accelerator 44ee0e7a02 Fix build
build / build with mms1.12 on oldlinux (push) Failing after 2m18s
build / build with mms1.12 on linux (push) Failing after 2m56s
build / build with mms1.12 on win (push) Has been cancelled
build / Release (push) Has been cancelled
2025-07-12 17:19:33 +03:00
Accelerator 11ab6e1e54 Safe Memory Patching
Using `baseserver.h` (https://github.com/L4D-Community/Left4Downtown2/blob/master/extension/l4d2sdk/baseserver.h) instead of hardcoded offsets. Thanks @A1mDev
2025-07-12 17:08:37 +03:00
Accelerator e235106c86 Update build.yml
build / build with mms1.12 on oldlinux (push) Failing after 2m17s
build / build with mms1.12 on linux (push) Failing after 1m49s
build / build with mms1.12 on win (push) Has been cancelled
build / Release (push) Has been cancelled
2025-07-01 18:38:29 +03:00
Accelerator 763fbf3b96 Update l4d1_offsets_linux.h
build / build with mms${{ matrix.mm_version }} on ${{ matrix.os_short }} (master, master, ubuntu-20.04, oldlinux) (push) Has been cancelled
build / build with mms${{ matrix.mm_version }} on ${{ matrix.os_short }} (master, master, ubuntu-latest, linux) (push) Has been cancelled
build / build with mms${{ matrix.mm_version }} on ${{ matrix.os_short }} (master, master, windows-latest, win) (push) Has been cancelled
build / build with mmsmaster on oldlinux (push) Failing after 2m30s
build / build with mmsmaster on linux (push) Failing after 2m24s
build / build with mmsmaster on win (push) Has been cancelled
build / Release (push) Has been cancelled
2024-07-04 15:26:38 +03:00
Accelerator 3295b7aeae Fix m_nReservationCookie on Win 2024-07-04 12:40:06 +03:00
Accelerator c510965a8a Update build.yml
build / build with mms${{ matrix.mm_version }} on ${{ matrix.os_short }} (master, master, ubuntu-20.04, oldlinux) (push) Failing after 2m50s
build / build with mms${{ matrix.mm_version }} on ${{ matrix.os_short }} (master, master, ubuntu-latest, linux) (push) Failing after 15m59s
build / build with mms${{ matrix.mm_version }} on ${{ matrix.os_short }} (master, master, windows-latest, win) (push) Has been cancelled
build / Release (push) Has been cancelled
2024-06-17 17:00:44 +03:00
Accelerator e5e9bac1c0 Update l4dtoolz_mm.cpp 2024-05-15 05:19:40 +03:00
Accelerator e1a6182665 Update l4dtoolz_mm.cpp 2024-05-08 18:27:12 +03:00
Accelerator 679b6f54c0 Update l4dtoolz_mm.cpp 2024-05-08 10:17:02 +03:00
Accelerator a7e01138c7 Fix windows build 2024-05-07 23:02:47 +03:00
Accelerator 5b19701a0e Update workflow 2024-05-07 22:55:15 +03:00
Accelerator c7ee545ce9 2.0.1
Always reply to a lobby request if the server is already reserved.
2024-05-07 20:08:42 +03:00
Accelerator 93ae32eea5 Fix l4d1 reservation offsets 2024-05-06 09:38:45 +03:00
Accelerator 057e6ce671 Fix l4d1 windows crash 2024-05-06 09:08:53 +03:00
Accelerator f665622521 Update l4dtoolz_mm.cpp 2024-05-05 15:05:40 +03:00
Accelerator f77ced2d2d Fix windows build 2024-05-05 14:13:16 +03:00
Accelerator 3f6694b148 Update README.md 2024-05-05 14:09:22 +03:00
Accelerator a5ebdd6e82 v2.0.0 2024-05-05 14:08:27 +03:00
25 changed files with 1592 additions and 1277 deletions
+168
View File
@@ -0,0 +1,168 @@
name: build
on:
workflow_dispatch:
push:
branches:
- main
- master
- dev
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
- ubuntu-22.04
- windows-latest
mm_version:
- "master"
include:
- mm_version: "master"
mm_branch: "master"
- os: ubuntu-latest
os_short: linux
- os: ubuntu-22.04
os_short: oldlinux
- 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: Checking out MM:Source
uses: actions/checkout@v7
with:
repository: alliedmodders/metamod-source
ref: ${{ matrix.mm_branch }}
path: metamod-${{ matrix.mm_version }}
- name: Setting up Python
uses: actions/setup-python@v7
with:
python-version: '3.12'
- name: Setting up ambuild
run: |
python -m pip install wheel
pip install git+https://github.com/accelerator74/ambuild@nog3
- name: Checking out hl2sdk-l4d
uses: actions/checkout@v7
with:
repository: alliedmodders/hl2sdk
ref: l4d
path: hl2sdk-l4d
- name: Checking out hl2sdk-l4d2
uses: actions/checkout@v7
with:
repository: alliedmodders/hl2sdk
ref: l4d2
path: hl2sdk-l4d2
- name: Checking out hl2sdk-manifests
uses: actions/checkout@v7
with:
repository: alliedmodders/hl2sdk-manifests
path: hl2sdk-manifests
- name: Checking out own repository
uses: actions/checkout@v7
with:
path: src
submodules: recursive
- name: Compiling ${{ github.event.repository.name }}-l4d files
working-directory: src
run: |
mkdir build_l4d
cd build_l4d
python ../configure.py --enable-optimize --sdks="l4d" --hl2sdk-manifest-path="${{ github.workspace }}/hl2sdk-manifests" --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" --hl2sdk-manifest-path="${{ github.workspace }}/hl2sdk-manifests" --mms-path="${{ github.workspace }}/metamod-${{ matrix.mm_version }}"
ambuild
- name: Uploading l4d package
uses: actions/upload-artifact@v7
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@v7
with:
name: ${{ github.event.repository.name }}-l4d2-${{ matrix.os_short }}-${{ env.GITHUB_SHA_SHORT }}
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@v8
- 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
View File
@@ -1,120 +0,0 @@
name: l4d2-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-l4d2
uses: actions/checkout@v4
with:
repository: alliedmodders/hl2sdk
ref: l4d2
path: hl2sdk-l4d2
- 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="l4d2" --mms-path="${{ github.workspace }}/metamod-${{ matrix.mm_version }}"
ambuild
- name: Uploading package
uses: actions/upload-artifact@v4
with:
name: ${{ github.event.repository.name }}-l4d2-${{ matrix.os_short }}-${{ env.GITHUB_SHA_SHORT }}
path: src/build/package
-120
View File
@@ -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
+3
View File
@@ -0,0 +1,3 @@
[submodule "khook"]
path = khook
url = https://github.com/Kenzzer/KHook
+201 -208
View File
@@ -1,27 +1,5 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os, sys import os, sys, shutil
# Simple extensions do not need to modify this file.
class SDK(object):
def __init__(self, sdk, ext, aDef, name, platform, dir):
self.folder = 'hl2sdk-' + dir
self.envvar = sdk
self.ext = ext
self.code = aDef
self.define = name
self.platform = platform
self.name = dir
self.path = None # Actual path
WinOnly = ['windows']
WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac']
PossibleSDKs = {
'l4d': SDK('HL2SDKL4D', '_mm', '12', 'LEFT4DEAD', WinLinuxMac, 'l4d'),
'l4d2': SDK('HL2SDKL4D2', '_mm', '15', 'LEFT4DEAD2', WinLinuxMac, 'l4d2'),
}
def ResolveEnvPath(env, folder): def ResolveEnvPath(env, folder):
if env in os.environ: if env in os.environ:
@@ -44,13 +22,59 @@ def ResolveEnvPath(env, folder):
def Normalize(path): def Normalize(path):
return os.path.abspath(os.path.normpath(path)) return os.path.abspath(os.path.normpath(path))
hl2sdk_manifests_path = None
# First we check if the manifest exists in the current path
hl2sdk_manifests_path = os.path.join(builder.sourcePath, 'hl2sdk-manifests/SdkHelpers.ambuild')
if not os.path.exists(hl2sdk_manifests_path):
# manifests does not exists in the project file, use the path from --hl2sdk-manifest-path
if not builder.options.hl2sdk_manifest:
raise Exception('HL2SDK Manifest root path not set! (--hl2sdk-manifest-path)')
else:
hl2sdk_manifests_path = os.path.join(builder.options.hl2sdk_manifest, 'SdkHelpers.ambuild')
if not os.path.exists(hl2sdk_manifests_path):
raise Exception('Could not find SdkHelpers.ambuild in the given HL2SDK Manifest path!')
SdkHelpers = builder.Eval(hl2sdk_manifests_path, {
'Project': 'l4dtoolz'
})
class ExtensionConfig(object): class ExtensionConfig(object):
def __init__(self): def __init__(self):
self.sdk_manifests = []
self.sdks = {} self.sdks = {}
self.sdk_targets = []
self.binaries = [] self.binaries = []
self.extensions = [] self.extensions = []
self.generated_headers = None self.generated_headers = None
self.mms_root = None self.mms_root = None
self.all_targets = []
self.target_archs = set()
self.libsafetyhook = {}
self.libkhook = {}
if builder.options.targets:
target_archs = builder.options.targets.split(',')
else:
target_archs = ['x86', 'x86_64']
for arch in target_archs:
try:
cxx = builder.DetectCxx(target_arch = arch)
self.target_archs.add(cxx.target.arch)
except Exception as e:
# Error if archs were manually overridden.
if builder.options.targets:
raise
print('Skipping target {}: {}'.format(arch, e))
continue
self.all_targets.append(cxx)
if not self.all_targets:
raise Exception('No suitable C/C++ compiler was found.')
@property @property
def tag(self): def tag(self):
@@ -58,35 +82,35 @@ class ExtensionConfig(object):
return 'Debug' return 'Debug'
return 'Release' return 'Release'
def findSdkPath(self, sdk_name):
dir_name = 'hl2sdk-{}'.format(sdk_name)
if builder.options.hl2sdk_root:
sdk_path = os.path.join(builder.options.hl2sdk_root, dir_name)
if os.path.exists(sdk_path):
return sdk_path
return ResolveEnvPath('HL2SDK{}'.format(sdk_name.upper()), dir_name)
def shouldIncludeSdk(self, sdk):
return not sdk.get('source2', False)
def detectSDKs(self): def detectSDKs(self):
sdk_list = builder.options.sdks.split(',') sdk_list = [s for s in builder.options.sdks.split(',') if s]
use_all = sdk_list[0] == 'all' SdkHelpers.sdk_filter = self.shouldIncludeSdk
use_present = sdk_list[0] == 'present' SdkHelpers.find_sdk_path = self.findSdkPath
SdkHelpers.findSdks(builder, self.all_targets, sdk_list)
for sdk_name in PossibleSDKs: self.sdks = SdkHelpers.sdks
sdk = PossibleSDKs[sdk_name] self.sdk_manifests = SdkHelpers.sdk_manifests
if builder.target_platform in sdk.platform: self.sdk_targets = SdkHelpers.sdk_targets
if builder.options.hl2sdk_root:
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
else:
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
if sdk_path is None or not os.path.isdir(sdk_path):
if use_all or sdk_name in sdk_list:
raise Exception('Could not find a valid path for {0}'.format(sdk.envvar))
continue
if use_all or use_present or sdk_name in sdk_list:
sdk.path = Normalize(sdk_path)
self.sdks[sdk_name] = sdk
if len(self.sdks) < 1:
raise Exception('At least one SDK must be available.')
if builder.options.mms_path: if builder.options.mms_path:
self.mms_root = builder.options.mms_path self.mms_root = builder.options.mms_path
else: else:
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10') self.mms_root = ResolveEnvPath('MMSOURCE20', 'mmsource-2.0')
if not self.mms_root: if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source') self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source')
if not self.mms_root: if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central') self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
@@ -95,14 +119,32 @@ class ExtensionConfig(object):
self.mms_root = Normalize(self.mms_root) self.mms_root = Normalize(self.mms_root)
def configure(self): def configure(self):
cxx = builder.DetectCompilers()
allowed_archs = ['x86','x86_64']
if not set(self.target_archs).issubset(allowed_archs):
raise Exception('Unknown target architecture: {0}'.format(self.target_archs))
for cxx in self.all_targets:
self.configure_cxx(cxx)
def configure_cxx(self, cxx):
if cxx.family == 'msvc':
if cxx.version < 1928 and builder.options.generator != 'vs':
raise Exception(f'Only MSVC 2022 and later are supported, full C++20 support is required. ({str(cxx.version)} < 1928)')
elif cxx.family == 'gcc':
if cxx.version < 'gcc-11':
raise Exception('Only GCC versions 11 or later are supported, full C++20 support is required.')
elif cxx.family == 'clang':
if cxx.version < 'clang-14':
raise Exception('Only clang versions 14 or later are supported, full C++20 support is required.')
if cxx.like('gcc'): if cxx.like('gcc'):
self.configure_gcc(cxx) self.configure_gcc(cxx)
elif cxx.vendor == 'msvc': elif cxx.family == 'msvc':
self.configure_msvc(cxx) self.configure_msvc(cxx)
# Optimizaiton # Optimization
if builder.options.opt == '1': if builder.options.opt == '1':
cxx.defines += ['NDEBUG'] cxx.defines += ['NDEBUG']
@@ -111,11 +153,11 @@ class ExtensionConfig(object):
cxx.defines += ['DEBUG', '_DEBUG'] cxx.defines += ['DEBUG', '_DEBUG']
# Platform-specifics # Platform-specifics
if builder.target_platform == 'linux': if cxx.target.platform == 'linux':
self.configure_linux(cxx) self.configure_linux(cxx)
elif builder.target_platform == 'mac': elif cxx.target.platform == 'mac':
self.configure_mac(cxx) self.configure_mac(cxx)
elif builder.target_platform == 'windows': elif cxx.target.platform == 'windows':
self.configure_windows(cxx) self.configure_windows(cxx)
def configure_gcc(self, cxx): def configure_gcc(self, cxx):
@@ -135,34 +177,41 @@ class ExtensionConfig(object):
'-Wno-unused', '-Wno-unused',
'-Wno-switch', '-Wno-switch',
'-Wno-array-bounds', '-Wno-array-bounds',
'-msse', '-Wno-unknown-pragmas',
'-m32', '-Wno-dangling-else',
'-fvisibility=hidden', '-fvisibility=hidden',
'-msse',
'-fPIC',
] ]
cxx.cxxflags += [ cxx.cxxflags += [
'-std=c++17', '-fno-rtti',
'-fno-exceptions',
'-fno-threadsafe-statics', '-fno-threadsafe-statics',
'-Wno-non-virtual-dtor', '-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual', '-Wno-overloaded-virtual',
'-Wno-register', '-Wno-register',
'-fvisibility-inlines-hidden', '-fvisibility-inlines-hidden',
'-std=c++20',
] ]
cxx.linkflags += ['-m32']
have_gcc = cxx.vendor == 'gcc' have_gcc = cxx.family == 'gcc'
have_clang = cxx.vendor == 'clang' have_clang = cxx.family == 'clang'
if cxx.version >= 'clang-3.9' or cxx.version >= 'apple-clang-10.0': if cxx.version >= 'clang-3.9' or cxx.version == 'clang-3.4' or cxx.version > 'apple-clang-6.0':
cxx.cxxflags += ['-Wno-expansion-to-defined'] cxx.cxxflags += ['-Wno-expansion-to-defined']
if cxx.version >= 'clang-3.6': if cxx.version == 'clang-3.9' or cxx.version == 'apple-clang-8.0':
cxx.cflags += ['-Wno-varargs']
if cxx.version >= 'clang-3.4' or cxx.version >= 'apple-clang-7.0':
cxx.cxxflags += ['-Wno-inconsistent-missing-override'] cxx.cxxflags += ['-Wno-inconsistent-missing-override']
if cxx.version >= 'clang-2.9' or cxx.version >= 'apple-clang-3.0':
cxx.cxxflags += ['-Wno-null-dereference']
if have_clang or (cxx.version >= 'gcc-4.6'): if have_clang or (cxx.version >= 'gcc-4.6'):
cxx.cflags += ['-Wno-narrowing'] cxx.cflags += ['-Wno-narrowing']
if have_clang or (cxx.version >= 'gcc-4.7'): if have_clang or (cxx.version >= 'gcc-4.7'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if cxx.version >= 'gcc-4.8': if cxx.version >= 'gcc-4.8':
cxx.cflags += ['-Wno-unused-result'] cxx.cflags += ['-Wno-unused-result']
if cxx.version >= 'gcc-9.0':
cxx.cxxflags += ['-Wno-class-memaccess', '-Wno-packed-not-aligned']
if have_clang: if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4': if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
@@ -172,14 +221,24 @@ class ExtensionConfig(object):
cxx.cflags += ['-Wno-sometimes-uninitialized'] cxx.cflags += ['-Wno-sometimes-uninitialized']
# Work around SDK warnings. # Work around SDK warnings.
if cxx.version >= 'clang-10.0': if cxx.version >= 'clang-10.0' or cxx.version >= 'apple-clang-12.0':
cxx.cflags += [ cxx.cflags += [
'-Wno-implicit-int-float-conversion', '-Wno-implicit-int-float-conversion',
'-Wno-tautological-overlap-compare', '-Wno-tautological-overlap-compare',
] ]
if cxx.version >= 'clang-21.0':
cxx.cflags += ['-Wno-uninitialized-const-pointer']
if cxx.version >= 'clang-16.0' or cxx.version >= 'apple-clang-15.0':
cxx.cxxflags += ['-Wno-deprecated-anon-enum-enum-conversion']
if cxx.version >= 'clang-12.0' or cxx.version >= 'apple-clang-13.0':
cxx.cxxflags += ['-Wno-deprecated-volatile']
if have_gcc: if have_gcc:
cxx.cflags += ['-mfpmath=sse'] cxx.cflags += ['-mfpmath=sse']
cxx.cflags += ['-Wno-maybe-uninitialized']
if builder.options.opt == '1': if builder.options.opt == '1':
cxx.cflags += ['-O3'] cxx.cflags += ['-O3']
@@ -206,10 +265,9 @@ class ExtensionConfig(object):
'/EHsc', '/EHsc',
'/GR-', '/GR-',
'/TP', '/TP',
'/std:c++17', '/std:c++20',
] ]
cxx.linkflags += [ cxx.linkflags += [
'/MACHINE:X86',
'kernel32.lib', 'kernel32.lib',
'user32.lib', 'user32.lib',
'gdi32.lib', 'gdi32.lib',
@@ -236,184 +294,119 @@ class ExtensionConfig(object):
cxx.cflags += ['/Oy-'] cxx.cflags += ['/Oy-']
def configure_linux(self, cxx): def configure_linux(self, cxx):
cxx.defines += ['_LINUX', 'POSIX'] cxx.defines += ['LINUX', '_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
cxx.linkflags += ['-lm'] cxx.linkflags += ['-lm']
if cxx.vendor == 'gcc': if cxx.family == 'gcc':
cxx.linkflags += ['-static-libgcc'] cxx.linkflags += ['-static-libgcc']
elif cxx.vendor == 'clang': elif cxx.family == 'clang':
cxx.linkflags += ['-lgcc_eh'] cxx.linkflags += ['-lgcc_eh']
cxx.linkflags += ['-Wl,--exclude-libs,ALL']
def configure_mac(self, cxx): def configure_mac(self, cxx):
cxx.defines += ['OSX', '_OSX', 'POSIX'] cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
cxx.cflags += ['-mmacosx-version-min=10.5'] cxx.cflags += ['-mmacosx-version-min=10.15']
cxx.linkflags += [ cxx.linkflags += [
'-mmacosx-version-min=10.5', '-mmacosx-version-min=10.15',
'-arch', 'i386', '-stdlib=libc++',
'-lstdc++', '-lc++',
'-stdlib=libstdc++',
] ]
cxx.cxxflags += ['-stdlib=libstdc++'] cxx.cxxflags += ['-stdlib=libc++']
def configure_windows(self, cxx): def configure_windows(self, cxx):
cxx.defines += ['WIN32', '_WINDOWS'] cxx.defines += ['WIN32', '_WINDOWS']
def LibraryBuilder(self, compiler, name):
binary = compiler.Library(name)
if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
return binary
def ProgramBuilder(self, compiler, name):
binary = compiler.Program(name)
if '-static-libgcc' in binary.compiler.linkflags:
binary.compiler.linkflags.remove('-static-libgcc')
if '-lgcc_eh' in binary.compiler.linkflags:
binary.compiler.linkflags.remove('-lgcc_eh')
if binary.compiler.like('gcc'):
binary.compiler.linkflags += ['-lstdc++', '-lpthread']
if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE']
return binary
def StaticLibraryBuilder(self, compiler, name):
return compiler.StaticLibrary(name)
def Library(self, context, compiler, name):
compiler = compiler.clone()
return self.LibraryBuilder(compiler, name)
def Program(self, context, compiler, name):
compiler = compiler.clone()
return self.ProgramBuilder(compiler, name)
def StaticLibrary(self, context, compiler, name):
compiler = compiler.clone()
return self.StaticLibraryBuilder(compiler, name)
def ConfigureForExtension(self, context, compiler): def ConfigureForExtension(self, context, compiler):
compiler.cxxincludes += [ compiler.cxxincludes += [
os.path.join(context.currentSourcePath), os.path.join(context.currentSourcePath),
os.path.join(self.sm_root, 'core', 'logic'),
] ]
return compiler return compiler
def ConfigureForHL2(self, binary, sdk): def ExtLibrary(self, context, compiler, name):
binary = self.Library(context, compiler, name)
self.ConfigureForExtension(context, binary.compiler)
return binary
def ConfigureForHL2(self, context, binary, sdk):
compiler = binary.compiler compiler = binary.compiler
if sdk.name == 'episode1':
mms_path = os.path.join(self.mms_root, 'core-legacy')
else:
mms_path = os.path.join(self.mms_root, 'core')
compiler.cxxincludes += [ compiler.cxxincludes += [
os.path.join(mms_path), os.path.join(self.mms_root, 'core'),
os.path.join(mms_path, 'sourcehook'), os.path.join(context.currentSourcePath, 'khook', 'include'),
] ]
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs] for other_sdk in self.sdk_manifests:
compiler.defines += defines compiler.defines += ['SE_{}={}'.format(other_sdk['define'], other_sdk['code'])]
paths = [ SdkHelpers.configureCxx(context, binary, sdk)
['public'],
['public', 'engine'],
['public', 'mathlib'],
['public', 'vstdlib'],
['public', 'tier0'],
['public', 'tier1']
]
if sdk.name == 'episode1' or sdk.name == 'darkm':
paths.append(['public', 'dlls'])
paths.append(['game_shared'])
else:
paths.append(['public', 'game', 'server'])
paths.append(['public', 'toolframework'])
paths.append(['game', 'shared'])
paths.append(['common'])
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'):
# The 2013 SDK already has these in public/tier0/basetypes.h
compiler.defines.remove('stricmp=strcasecmp')
compiler.defines.remove('_stricmp=strcasecmp')
compiler.defines.remove('_snprintf=snprintf')
compiler.defines.remove('_vsnprintf=vsnprintf')
if compiler.like('msvc'):
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
compiler.linkflags += ['legacy_stdio_definitions.lib']
else:
compiler.defines += ['COMPILER_GCC']
# For everything after Swarm, this needs to be defined for entity networking
# to work properly with sendprop value changes.
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.defines += ['NETWORK_VARS_ENABLED']
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']:
if builder.target_platform in ['linux', 'mac']:
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
if sdk.name == 'csgo' and builder.target_platform == 'linux':
compiler.linkflags += ['-lstdc++']
for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
if builder.target_platform == 'linux':
if sdk.name == 'episode1':
lib_folder = os.path.join(sdk.path, 'linux_sdk')
elif sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
elif builder.target_platform == 'mac':
if sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
if builder.target_platform in ['linux', 'mac']:
if sdk.name in ['sdk2013', 'bms']:
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
]
else:
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
]
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
dynamic_libs = []
if builder.target_platform == 'linux':
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency']:
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']:
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else:
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
elif builder.target_platform == 'mac':
compiler.linkflags.append('-liconv')
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
elif builder.target_platform == 'windows':
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
libs.append('interfaces')
for lib in libs:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
compiler.linkflags.append(compiler.Dep(lib_path))
for library in dynamic_libs:
source_path = os.path.join(lib_folder, library)
output_path = os.path.join(binary.localFolder, library)
def make_linker(source_path, output_path):
def link(context, binary):
cmd_node, (output,) = context.AddSymlink(source_path, output_path)
return output
return link
linker = make_linker(source_path, output_path)
compiler.linkflags[0:0] = [compiler.Dep(library, linker)]
return binary return binary
def HL2Library(self, context, name, sdk): def HL2Library(self, context, compiler, name, sdk):
binary = context.compiler.Library(name) binary = self.Library(context, compiler, name)
self.ConfigureForExtension(context, binary.compiler) self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(binary, sdk) return self.ConfigureForHL2(context, binary, sdk)
def HL2Project(self, context, name): def HL2Config(self, project, context, compiler, name, sdk):
project = context.compiler.LibraryProject(name) binary = project.Configure(compiler, name,
self.ConfigureForExtension(context, project.compiler) '{0} - {1} {2}'.format(self.tag, sdk['name'], compiler.target.arch))
return project return self.ConfigureForHL2(context, binary, sdk)
def HL2Config(self, project, name, sdk): if getattr(builder, 'target', None) is not None:
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name)) sys.stderr.write("Your output folder was configured for AMBuild 2.1.\n")
return self.ConfigureForHL2(binary, sdk) sys.stderr.write("Please remove your output folder and reconfigure to continue.\n")
os._exit(1)
Extension = ExtensionConfig() Extension = ExtensionConfig()
Extension.detectSDKs() Extension.detectSDKs()
Extension.configure() Extension.configure()
# This will clone the list and each cxx object as we recurse, preventing child
# scripts from messing up global state.
builder.targets = builder.CloneableList(Extension.all_targets)
# Add additional buildscripts here # Add additional buildscripts here
BuildScripts = [ BuildScripts = [
'AMBuilder', 'AMBuilder',
] ]
if builder.backend == 'amb2': if builder.backend == 'amb2':
BuildScripts += [ BuildScripts += [
'PackageScript', 'PackageScript',
] ]
builder.RunBuildScripts(BuildScripts, { 'Extension': Extension}) builder.Build(['khook/AMBuilder', 'khook/third_party/safetyhook/AMBuilder'], { 'KHook': Extension, 'SafetyHook': Extension })
builder.Build(BuildScripts, { 'Extension': Extension })
+22 -15
View File
@@ -1,23 +1,30 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
projectName = 'l4dtoolz' import os
# smsdk_ext.cpp will be automatically added later project = builder.LibraryProject('l4dtoolz')
sourceFiles = [ project.sources += [
'l4dtoolz_mm.cpp', 'l4dtoolz_mm.cpp',
'signature.cpp', 'memutils.cpp',
] ]
###############
# Make sure to edit PackageScript, which copies your files to their appropriate locations
# Simple extensions do not need to modify past this point.
project = Extension.HL2Project(builder, projectName)
project.sources += sourceFiles
for sdk_name in Extension.sdks: for sdk_name in Extension.sdks:
sdk = Extension.sdks[sdk_name] sdk = Extension.sdks[sdk_name]
if sdk['name'] in ['mock']:
binary = Extension.HL2Config(project, projectName + sdk.ext, sdk) continue
Extension.extensions = builder.Add(project) for cxx in builder.targets:
if not cxx.target.arch in sdk['platforms'][cxx.target.platform]:
continue
binary = Extension.HL2Config(project, builder, cxx, 'l4dtoolz_mm', sdk)
binary.compiler.cxxincludes += [os.path.join(builder.sourcePath, 'khook', 'include')]
binary.compiler.defines += ['KHOOK_STANDALONE', 'KHOOK_EXPORT']
for task in Extension.libkhook:
if task.target.arch == binary.compiler.target.arch:
binary.compiler.linkflags += [task.binary]
for task in Extension.libsafetyhook:
if task.target.arch == binary.compiler.target.arch:
binary.compiler.linkflags += [task.binary]
Extension.extensions += builder.Add(project)
-83
View File
@@ -1,83 +0,0 @@
# Makefile
HX_SDK = ../hl2sdk-l4d2
HX_METAMOD = ../mmsource
#
# l4dtoolz_mm.so
#
HX_INCLUDE = -I. \
-I$(HX_METAMOD)/core \
-I$(HX_METAMOD)/core/sourcehook \
-I$(HX_SDK)/public \
-I$(HX_SDK)/public/tier0 \
-I$(HX_SDK)/public/tier1 \
-I$(HX_SDK)/public/engine \
-I$(HX_SDK)/public/mathlib
#
HX_FLAGS = -DSOURCE_ENGINE=9
#
HX_FLAGS += -DSE_EPISODEONE=1 \
-DSE_DARKMESSIAH=2 \
-DSE_ORANGEBOX=3 \
-DSE_BLOODYGOODTIME=4 \
-DSE_EYE=5 \
-DSE_CSS=6 \
-DSE_ORANGEBOXVALVE=7 \
-DSE_LEFT4DEAD=8 \
-DSE_LEFT4DEAD2=9 \
-DSE_ALIENSWARM=10 \
-DSE_PORTAL2=11 \
-DSE_CSGO=12
#
HX_FLAGS += -DPOSIX \
-Dstricmp=strcasecmp \
-D_stricmp=strcasecmp \
-D_strnicmp=strncasecmp \
-Dstrnicmp=strncasecmp \
-D_snprintf=snprintf \
-D_vsnprintf=vsnprintf \
-D_alloca=alloca \
-Dstrcmpi=strcasecmp \
-Wall \
-Werror \
-Wno-switch \
-Wno-unused \
-msse \
-DHAVE_STDINT_H \
-m32 \
-DNDEBUG \
-O3 \
-funroll-loops \
-pipe \
-fno-strict-aliasing \
-D_LINUX \
-mfpmath=sse \
-fvisibility=hidden \
-Wno-non-virtual-dtor \
-Wno-overloaded-virtual \
-Wno-deprecated-register \
-fno-exceptions \
-fno-rtti \
-fvisibility-inlines-hidden
#
HX_LIB = Release/l4dtoolz_mm.o \
Release/signature.o \
$(HX_SDK)/lib/linux/tier1_i486.a \
libvstdlib_srv.so \
libtier0_srv.so
#
all:
mkdir -p Release
ln -sf $(HX_SDK)/lib/linux/libvstdlib_srv.so libvstdlib_srv.so;
ln -sf $(HX_SDK)/lib/linux/libtier0_srv.so libtier0_srv.so;
#
clang $(HX_INCLUDE) $(HX_FLAGS) -o Release/l4dtoolz_mm.o -c l4dtoolz_mm.cpp
clang $(HX_INCLUDE) $(HX_FLAGS) -o Release/signature.o -c signature.cpp
clang $(HX_INCLUDE) $(HX_LIB) -m32 -shared -static-libgcc -ldl -lm -o Release/l4dtoolz_mm.so
#
rm -rf Release/*.o
-83
View File
@@ -1,83 +0,0 @@
# Makefile
HX_SDK = ../hl2sdk-l4d
HX_METAMOD = ../mmsource
#
# l4dtoolz_mm.so
#
HX_INCLUDE = -I. \
-I$(HX_METAMOD)/core \
-I$(HX_METAMOD)/core/sourcehook \
-I$(HX_SDK)/public \
-I$(HX_SDK)/public/tier0 \
-I$(HX_SDK)/public/tier1 \
-I$(HX_SDK)/public/engine \
-I$(HX_SDK)/public/mathlib
#
HX_FLAGS = -DSOURCE_ENGINE=8
#
HX_FLAGS += -DSE_EPISODEONE=1 \
-DSE_DARKMESSIAH=2 \
-DSE_ORANGEBOX=3 \
-DSE_BLOODYGOODTIME=4 \
-DSE_EYE=5 \
-DSE_CSS=6 \
-DSE_ORANGEBOXVALVE=7 \
-DSE_LEFT4DEAD=8 \
-DSE_LEFT4DEAD2=9 \
-DSE_ALIENSWARM=10 \
-DSE_PORTAL2=11 \
-DSE_CSGO=12
#
HX_FLAGS += -DPOSIX \
-Dstricmp=strcasecmp \
-D_stricmp=strcasecmp \
-D_strnicmp=strncasecmp \
-Dstrnicmp=strncasecmp \
-D_snprintf=snprintf \
-D_vsnprintf=vsnprintf \
-D_alloca=alloca \
-Dstrcmpi=strcasecmp \
-Wall \
-Werror \
-Wno-switch \
-Wno-unused \
-msse \
-DHAVE_STDINT_H \
-m32 \
-DNDEBUG \
-O3 \
-funroll-loops \
-pipe \
-fno-strict-aliasing \
-D_LINUX \
-mfpmath=sse \
-fvisibility=hidden \
-Wno-non-virtual-dtor \
-Wno-overloaded-virtual \
-Wno-deprecated-register \
-fno-exceptions \
-fno-rtti \
-fvisibility-inlines-hidden
#
HX_LIB = Release/l4dtoolz_mm.o \
Release/signature.o \
$(HX_SDK)/lib/linux/tier1_i486.a \
libvstdlib.so \
libtier0.so
#
all:
mkdir -p Release
ln -sf $(HX_SDK)/lib/linux/libvstdlib.so libvstdlib.so;
ln -sf $(HX_SDK)/lib/linux/libtier0.so libtier0.so;
#
clang $(HX_INCLUDE) $(HX_FLAGS) -o Release/l4dtoolz_mm.o -c l4dtoolz_mm.cpp
clang $(HX_INCLUDE) $(HX_FLAGS) -o Release/signature.o -c signature.cpp
clang $(HX_INCLUDE) $(HX_LIB) -m32 -shared -static-libgcc -ldl -lm -o Release/l4dtoolz_mm.so
#
rm -rf Release/*.o
+1 -2
View File
@@ -1,4 +1,4 @@
# L4DToolz by ivailosp # L4DToolz
https://forums.alliedmods.net/showthread.php?t=93600 https://forums.alliedmods.net/showthread.php?t=93600
@@ -7,5 +7,4 @@ Metamod plugin to unlock the max player limit on L4D and L4D2.
# CVARS # CVARS
- sv_maxplayers - max human players that can join your server. -1 to disable and use standart check (range 0 to 32). - sv_maxplayers - max human players that can join your server. -1 to disable and use standart check (range 0 to 32).
- sv_removehumanlimit - remove kick for players (only L4D) when they are more than 8 for vs and 4 for coop(0 to disable, 1 to enable).
- sv_force_unreserved - if you set it to 1 before connection from lobby your server will stay unreserved and allow players to connect using connect command, this command sets. - sv_force_unreserved - if you set it to 1 before connection from lobby your server will stay unreserved and allow players to connect using connect command, this command sets.
+265
View 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
+30 -14
View File
@@ -1,21 +1,37 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et: # vim: set ts=2 sw=2 tw=99 noet:
import sys import sys
from ambuild2 import run try:
from ambuild2 import run, util
except:
try:
import ambuild
sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n')
sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n')
except:
sys.stderr.write('AMBuild must be installed to build this project.\n')
sys.stderr.write('http://www.alliedmods.net/ambuild\n')
sys.exit(1)
# Simple extensions do not need to modify this file. # Hack to show a decent upgrade message, which wasn't done until 2.2.
ambuild_version = getattr(run, 'CURRENT_API', '2.1')
if ambuild_version.startswith('2.1'):
sys.stderr.write("AMBuild 2.2 or higher is required; please update\n")
sys.exit(1)
builder = run.PrepareBuild(sourcePath = sys.path[0]) parser = run.BuildParser(sourcePath=sys.path[0], api='2.2')
parser.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
builder.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
help='Root search folder for HL2SDKs') help='Root search folder for HL2SDKs')
builder.options.add_option('--mms-path', type=str, dest='mms_path', default=None, parser.options.add_argument('--hl2sdk-manifest-path', type=str, dest='hl2sdk_manifest', default=None,
help='Path to HL2SDK Manifests')
parser.options.add_argument('--mms-path', type=str, dest='mms_path', default=None,
help='Path to Metamod:Source') help='Path to Metamod:Source')
builder.options.add_option('--enable-debug', action='store_const', const='1', dest='debug', parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug',
help='Enable debugging symbols') help='Enable debugging symbols')
builder.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt', parser.options.add_argument('--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', parser.options.add_argument('-s', '--sdks', default='l4d2', dest='sdks',
help='Build against specified SDKs; valid args are "all", "present", or ' help='Build against specified SDKs; valid args are "none", "all", "present",'
'comma-delimited list of engine names (default: %default)') ' or comma-delimited list of engine names')
parser.options.add_argument('--targets', type=str, dest='targets', default=None,
builder.Configure() help="Override the target architecture (use commas to separate multiple targets).")
parser.Configure()
+22
View File
@@ -0,0 +1,22 @@
#ifndef _INCLUDE_GAME_OFFSETS_
#define _INCLUDE_GAME_OFFSETS_
#if defined WIN32
#if SOURCE_ENGINE == SE_LEFT4DEAD
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
#if SOURCE_ENGINE == SE_LEFT4DEAD
const char* engine_dll = "engine.so";
const int maxhuman_idx = 132; // CTerrorGameRules::GetMaxHumanPlayers vtable
#else
const char* engine_dll = "engine_srv.so";
const int maxhuman_idx = 137; // CTerrorGameRules::GetMaxHumanPlayers vtable
#endif
#endif
#endif //_INCLUDE_GAME_OFFSETS_
-18
View File
@@ -1,18 +0,0 @@
#ifndef _INCLUDE_GAME_SIGNATURE_
#define _INCLUDE_GAME_SIGNATURE_
#ifdef WIN32
#if SOURCE_ENGINE == SE_LEFT4DEAD
#include "l4d1_signature_win32.h"
#else
#include "l4d2_signature_win32.h"
#endif
#else
#if SOURCE_ENGINE == SE_LEFT4DEAD
#include "l4d1_signature_linux.h"
#else
#include "l4d2_signature_linux.h"
#endif
#endif
#endif //_INCLUDE_GAME_SIGNATURE_
Submodule
+1
Submodule khook added at 876c66949a
-57
View File
@@ -1,57 +0,0 @@
#ifndef _INCLUDE_L4D1_SIGNATURE_LINUX_
#define _INCLUDE_L4D1_SIGNATURE_LINUX_
const char* server_dll[] = {"server.so", 0};
const char* engine_dll[] = {"engine.so", 0};
const char* matchmaking_dll[] = {"matchmaking_ds.so", "matchmaking.so", 0};
//CBaseServer::GetMaxHumanPlayers(void)const
//function is in engine.so
const char* friends_lobby = "\x0F\x53\x83\xEC\x18\xE8\xC3\xC3\xC3\xC3\x81\xC3\xB9\xB8\x23\x00";
unsigned char friends_lobby_new[] = {0x06, 0x00, 0xB8, 0x3C, 0x00, 0x00, 0x00, 0xC3};
void* friends_lobby_org = NULL;
//CBaseServer::ConnectClient(netadr_s &, int, int, int, char const*, char const*, char const*, int, CUtlVector<CLC_SplitPlayerConnect, CUtlMemory<CLC_SplitPlayerConnect, int>> &, bool)
//function is in engine.so, loc jz/jnz, above #Valve_Reject_Hidden_Game
const char* lobby_sux = "\x0A\x8B\xAE\x78\x01\x00\x00\x85\xED\x0F\x85";
const char* lobby_sux_new = "\x06\x00\xB8\x01\x00\x00\x00\x90";
void* lobby_sux_org = NULL;
//CBaseServer::ConnectClient(netadr_s &, int, int, int, char const*, char const*, char const*, int, CUtlVector<CLC_SplitPlayerConnect, CUtlMemory<CLC_SplitPlayerConnect, int>> &, bool)
//function is in engine.so, above #Valve_Reject_Server_Full
const char* max_players = "\x0F\xFF\x50\xC3\x29\xC7\x01\xFD\x3B\xC3\xC3\xC3\x00\x00\x0F\x8E";
unsigned char max_players_new[]= {0x06, 0x07, 0x83, 0xFF, 0x3C, 0x90, 0x90, 0x90};
void* max_players_org = NULL;
//CServerGameClients::GetMaxHumanPlayers(void)
//function is in server.so
const char* server_bplayers = "\x1F\x53\x83\xEC\xC3\xE8\xC3\xC3\xC3\xC3\x81\xC3\xC3\xC3\xC3\xC3\x8B\x83\xC3\xC3\xC3\xC3\x8B\x00\x85\xC0\x74\x10\x8B\x10\x89\x04";
unsigned char server_bplayers_new[] = {0x06, 0x00, 0xB8, 0x3C, 0x00, 0x00, 0x00, 0xC3};
void* server_bplayers_org = NULL;
//CTerrorGameRules::ClientConnected(edict_t *, char const*, char const*, char *, int)
//function is in server.so
const char* human_limit = "\x12\x8B\x00\xC3\xC3\x24\x40\x89\x14\xC3\xFF\x90\xC3\x02\x00\x00\x39\xF0\x7E";
const char* human_limit_new = "\x02\x11\x90\x90";
void* human_limit_org = NULL;
//CGameServer::SetMaxClients(int)
//function is in engine.so
const char* players = "\x13\x83\xBB\xC3\xC3\xC3\xC3\x01\x7F\xC3\x8B\x80\x0C\xC3\xC3\x00\x89\xC3\xC3\xE8";
const char* players_new = "\x03\x1D\x89\xC2\xEB";
void* players_org = NULL;
//CBaseServer::SetReservationCookie(unsigned long long, char const*, ...)
//function in engine.so
const char* unreserved = "\x15\x55\x57\x56\x53\x81\xEC\x3C\x01\x00\x00\xE8\xC3\xC3\xC3\xC3\x81\xC3\x33\x8E\x23\x00";
const char* unreserved_new = "\x01\x00\xC3";
void* unreserved_org = NULL;
//CMatchTitle::GetTotalNumPlayersSupported(void)
//function in matchmaking_ds.so
const char* lobby_match = "\x06\xB8\x08\x00\x00\x00\xC3";
unsigned char lobby_match_new[] = {0x01, 0x02, 0xC3};
void* lobby_match_org = NULL;
#endif //_INCLUDE_L4D1_SIGNATURE_LINUX_
-40
View File
@@ -1,40 +0,0 @@
#ifndef _INCLUDE_L4D1_SIGNATURE_WIN32_
#define _INCLUDE_L4D1_SIGNATURE_WIN32_
const char* server_dll[] = {"server.dll", 0};
const char* engine_dll[] = {"engine.dll", 0};
const char* matchmaking_dll[] = {"matchmaking_ds.dll", "matchmaking.dll", 0};
const char* friends_lobby = "\x12\x56\x8B\xF1\x8B\x0D\xC3\xC3\xC3\xC3\x85\xC9\x74\xC3\x8B\x01\x8B\x50\x48";
unsigned char friends_lobby_new[] = {0x06, 0x00, 0xB8, 0x3C, 0x00, 0x00, 0x00, 0xC3};
void* friends_lobby_org = NULL;
const char* max_players = "\x28\x83\xBE\xC3\xC3\x00\x00\x00\x74\xC3\x8B\x54\xC3\xC3\x8B\x06\x8B\x7A\xC3\x8B\x50\x10\x8B\xCE\xFF\xD2\x2B\xF8\x8B\x06\x8B\x50\x08\x8B\xCE\xFF\xD2\x03\xC7\x3B\x86";
unsigned char max_players_new[]= {0x06, 0x26, 0x83, 0xF8, 0x3C, 0x90, 0x90, 0x90};
void* max_players_org = NULL;
const char* lobby_sux_new = "\x02\x07\x90\x90";
void* lobby_sux_org = NULL;
const char* server_bplayers = "\x1D\x56\x8B\xF1\xE8\xC3\xC3\xC3\xC3\x8B\x4C\x24\x08\x89\x01\x8B\x0D\xC3\xC3\xC3\xC3\x85\xC9\x74\xC3\x8B\x11\x8B\x42\x48";
unsigned char server_bplayers_new[] = {0x05, 0x1A, 0xB8, 0x3C, 0x00, 0x00, 0x00};
void* server_bplayers_org = NULL;
const char* human_limit = "\x15\x8B\x13\x8B\x82\xC3\xC3\x00\x00\x8B\xCB\xFF\xD0\x3B\xF8\x7C\xC3\x8B\xC3\xC3\xC3\x8B";
const char* human_limit_new = "\x01\x0E\xEB";
void* human_limit_org = NULL;
const char* players = "\x10\x56\x8B\xF1\x8B\x86\xC3\x02\x00\x00\x8B\x4C\x24\x08\x3B\xC8\x7F";
const char* players_new = "\x02\x0F\x90\x90";
void* players_org = NULL;
const char* unreserved = "\x1E\x81\xEC\xC3\xC3\x00\x00\x55\x8B\xAC\xC3\xC3\xC3\x00\x00\x56\x8B\xB4\xC3\xC3\xC3\x00\x00\x57\x8B\xBC\xC3\xC3\xC3\x00\x00";
const char* unreserved_new = "\x01\x00\xC3";
void* unreserved_org = NULL;
const char* lobby_match = "\x06\xB8\x08\x00\x00\x00\xC3";
unsigned char lobby_match_new[] = {0x01, 0x01, 0xC3};
void* lobby_match_org = NULL;
#endif //_INCLUDE_L4D1_SIGNATURE_WIN32_
-33
View File
@@ -1,33 +0,0 @@
#ifndef _INCLUDE_L4D2_SIGNATURE_LINUX_
#define _INCLUDE_L4D2_SIGNATURE_LINUX_
const char* server_dll[] = {"server_srv.so", "server.so", 0};
const char* engine_dll[] = {"engine_srv.so", "engine.so", 0};
const char* matchmaking_dll[] = {"matchmaking_ds_srv.so", "matchmaking_srv.so", "matchmaking_ds.so", "matchmaking.so", 0};
const char* lobby_sux = "\x13\xFF\x50\xC3\x84\xC0\x0F\x84\xC3\xC3\xC3\xC3\x8B\x87\xC3\x01\x00\x00\x85\xC0";
const char* lobby_sux_new = "\x06\x0B\xBE\x01\x00\x00\x00\x90";
void *lobby_sux_org = NULL;
const char* max_players = "\x15\x89\xC6\x8B\x07\x89\x3C\x24\xFF\x50\xC3\x29\xC6\x01\xF3\x3B\x9F\xC3\x01\x00\x00\x0F";
unsigned char max_players_new[]= {0x06, 0x0E, 0x83, 0xFB, 0x3C, 0x90, 0x90, 0x90};
void *max_players_org = NULL;
const char* server_bplayers = "\x16\x55\x89\xE5\x83\xEC\x08\xE8\xC3\xC3\xC3\xC3\xC9\x3C\x01\x19\xC0\x83\xE0\xFC\x83\xC0\x08";
unsigned char server_bplayers_new[] = {0x06, 0x00, 0xB8, 0x3C, 0x00, 0x00, 0x00, 0xC3};
void *server_bplayers_org = NULL;
const char* players = "\x23\x55\x89\xE5\x53\x83\xEC\xC3\x8B\x5D\x08\x8B\x55\x0C\x8B\x83\xC3\xC3\x00\x00\x39\xD0\x7C\x0B\x8B\x83\xC3\xC3\x00\x00\x39\xC2\x0F\x4D\xC2\x8B";
const char* players_new = "\x03\x13\x89\xD0\xEB";
void *players_org = NULL;
const char* unreserved = "\x0F\x55\x89\xE5\x57\x56\x53\x81\xEC\x3C\x01\x00\x00\x8B\x5D\x08";
const char* unreserved_new = "\x01\x00\xC3";
void *unreserved_org = NULL;
const char* lobby_match = "\x0A\x55\xB8\x08\x00\x00\x00\x89\xE5\x5D\xC3";
unsigned char lobby_match_new[] = {0x01, 0x02, 0xC3};
void *lobby_match_org = NULL;
#endif //_INCLUDE_L4D2_SIGNATURE_LINUX_
-32
View File
@@ -1,32 +0,0 @@
#ifndef _INCLUDE_L4D2_SIGNATURE_WIN32_
#define _INCLUDE_L4D2_SIGNATURE_WIN32_
const char* server_dll[] = {"server.dll", 0};
const char* engine_dll[] = {"engine.dll", 0};
const char* matchmaking_dll[] = {"matchmaking_ds.dll", "matchmaking.dll", 0};
const char* max_players = "\x27\x83\xBE\xC3\xC3\x00\x00\x00\x74\xC3\x8B\xC3\xC3\x8B\x06\x8B\x7A\xC3\x8B\x50\x10\x8B\xCE\xFF\xD2\x2B\xF8\x8B\x06\x8B\x50\x08\x8B\xCE\xFF\xD2\x03\xC7\x3B\x86";
unsigned char max_players_new[]= {0x06, 0x25, 0x83, 0xF8, 0x3C, 0x90, 0x90, 0x90};
void* max_players_org = NULL;
const char* lobby_sux_new = "\x02\x07\x90\x90";
void* lobby_sux_org = NULL;
const char* server_bplayers = "\x36\xF7\x05\xC3\xC3\xC3\xC3\x00\x10\x00\x00\x74\x07\xB8\xC3\xC3\xC3\xC3\xEB\x11\xA1\xC3\xC3\xC3\xC3\x8B\x40\x24\x85\xC0\x75\x05\xB8\xC3\xC3\xC3\xC3\x8B\x0D\xC3\xC3\xC3\xC3\x8B\x11\x50\x8B\x42\x10\xFF\xD0\x85\xC0\x74\x17";
unsigned char server_bplayers_new[] = {0x06, 0x00, 0xB8, 0x3C, 0x00, 0x00, 0x00, 0xC3};
void* server_bplayers_org = NULL;
const char* players = "\x0F\x56\x8B\xF1\x8B\x86\xC3\x02\x00\x00\x8B\x4D\xC3\x3B\xC8\x7F";
const char* players_new = "\x02\x0E\x90\x90";
void* players_org = NULL;
const char* unreserved = "\x21\x55\x8B\xEC\x81\xEC\xC3\xC3\x00\x00\xA1\xC3\xC3\xC3\xC3\x33\xC5\x89\xC3\xC3\x53\x8B\xC3\xC3\x56\x8B\xC3\xC3\x57\x8B\xC3\xC3\x3B\xBE";
const char* unreserved_new = "\x01\x00\xC3";
void* unreserved_org = NULL;
const char* lobby_match = "\x06\xB8\x08\x00\x00\x00\xC3";
unsigned char lobby_match_new[] = {0x01, 0x01, 0xC3};
void* lobby_match_org = NULL;
#endif //_INCLUDE_L4D2_SIGNATURE_WIN32_
+155 -178
View File
@@ -1,110 +1,107 @@
#include "l4dtoolz_mm.h" #include "l4dtoolz_mm.h"
#include "signature.h" #include "game_offsets.h"
#include "game_signature.h" #include "memutils.h"
#include "icommandline.h" #include "icommandline.h"
#include "server_class.h"
#include "khook.hpp"
l4dtoolz g_l4dtoolz; l4dtoolz g_l4dtoolz;
IServerGameDLL* gamedll = NULL;
IServerGameClients* gameclients = NULL;
IVEngineServer* engine = NULL; IVEngineServer* engine = NULL;
IMatchFramework* g_pMatchFramework = NULL;
ICvar* g_pCVar = NULL; ICvar* g_pCVar = NULL;
CBaseServer* g_pGameIServer = NULL;
CGameRules* g_pGameRules = nullptr;
int g_nGameSlots = -1;
#if SOURCE_ENGINE == SE_LEFT4DEAD ConVar sv_maxplayers("sv_maxplayers", "-1", FCVAR_SPONLY|FCVAR_NOTIFY, "Max Human Players", true, -1, true, 32, l4dtoolz::OnChangeMaxplayers);
void* l4dtoolz::max_players_friend_lobby = NULL; ConVar sv_force_unreserved("sv_force_unreserved", "0", FCVAR_SPONLY|FCVAR_NOTIFY, "Disallow lobby reservation cookie", true, 0, true, 1, l4dtoolz::OnChangeUnreserved);
void* l4dtoolz::chuman_limit = NULL;
#endif
void* l4dtoolz::max_players_connect = NULL;
void* l4dtoolz::max_players_server_browser = NULL;
void* l4dtoolz::lobby_sux_ptr = NULL;
void* l4dtoolz::tmp_player = NULL;
void* l4dtoolz::unreserved_ptr = NULL;
void* l4dtoolz::lobby_match_ptr = NULL;
ConVar sv_maxplayers("sv_maxplayers", "-1", 0, "Max Human Players", true, -1, true, 32, l4dtoolz::OnChangeMaxplayers); l4dtoolz::l4dtoolz() :
#if SOURCE_ENGINE == SE_LEFT4DEAD m_ApplyGameSettings(&IServerGameDLL::ApplyGameSettings, this, nullptr, &l4dtoolz::ApplyGameSettings),
ConVar sv_removehumanlimit("sv_removehumanlimit", "0", 0, "Remove Human limit reached kick", true, 0, true, 1, l4dtoolz::OnChangeRemovehumanlimit); m_GetTotalNumPlayersSupported(&IMatchTitle::GetTotalNumPlayersSupported, this, &l4dtoolz::GetTotalNumPlayersSupported, nullptr),
#endif m_LevelInit(&IServerGameDLL::LevelInit, this, nullptr, &l4dtoolz::LevelInit),
ConVar sv_force_unreserved("sv_force_unreserved", "0", 0, "Disallow lobby reservation cookie", true, 0, true, 1, l4dtoolz::OnChangeUnreserved); m_LevelShutdown(&IServerGameDLL::LevelShutdown, this, &l4dtoolz::LevelShutdown, nullptr),
m_ReplyReservationRequest(&CBaseServer::ReplyReservationRequest, this, &l4dtoolz::ReplyReservationRequest, nullptr)
{
g_HookGetMaxHumanPlayers.Configure(maxhuman_idx);
g_HookGetMaxHumanPlayers.AddContext(this, &l4dtoolz::GetMaxHumanPlayers, nullptr);
}
void l4dtoolz::OnChangeMaxplayers ( IConVar *var, const char *pOldValue, float flOldValue ) void l4dtoolz::OnChangeMaxplayers(IConVar *var, const char *pOldValue, float flOldValue)
{ {
int new_value = ((ConVar*)var)->GetInt(); int new_value = ((ConVar*)var)->GetInt();
int old_value = atoi(pOldValue); int old_value = atoi(pOldValue);
#if SOURCE_ENGINE == SE_LEFT4DEAD if (g_pGameIServer == NULL) {
if (max_players_friend_lobby == NULL || max_players_connect == NULL || max_players_server_browser == NULL || lobby_sux_ptr == NULL) { Msg("g_pGameIServer pointer is not available\n");
#else
if (max_players_connect == NULL || max_players_server_browser == NULL || lobby_sux_ptr == NULL) {
#endif
Msg("sv_maxplayers init error\n");
return; return;
} }
if(new_value != old_value) { if (new_value != old_value) {
if(new_value >= 0) { if (new_value >= 0) {
#if SOURCE_ENGINE == SE_LEFT4DEAD g_nGameSlots = new_value;
max_players_new[4] = friends_lobby_new[3] = server_bplayers_new[3] = (unsigned char)new_value; g_pGameIServer->m_numGameSlots = g_nGameSlots;
#else
max_players_new[4] = server_bplayers_new[3] = (unsigned char)new_value;
#endif
if(lobby_match_ptr) {
lobby_match_new[2] = (unsigned char)new_value;
write_signature(lobby_match_ptr, lobby_match_new);
} else {
Msg("sv_maxplayers MS init error\n");
}
#if SOURCE_ENGINE == SE_LEFT4DEAD
write_signature(max_players_friend_lobby, friends_lobby_new);
#endif
write_signature(max_players_connect, max_players_new);
write_signature(lobby_sux_ptr, lobby_sux_new);
write_signature(max_players_server_browser, server_bplayers_new);
} else { } else {
#if SOURCE_ENGINE == SE_LEFT4DEAD g_nGameSlots = -1;
write_signature(max_players_friend_lobby, friends_lobby_org);
#endif
write_signature(max_players_connect, max_players_org);
write_signature(lobby_sux_ptr, lobby_sux_org);
write_signature(max_players_server_browser, server_bplayers_org);
if(lobby_match_ptr)
write_signature(lobby_match_ptr, lobby_match_org);
} }
} }
} }
#if SOURCE_ENGINE == SE_LEFT4DEAD void l4dtoolz::OnChangeUnreserved(IConVar *var, const char *pOldValue, float flOldValue)
void l4dtoolz::OnChangeRemovehumanlimit ( IConVar *var, const char *pOldValue, float flOldValue )
{ {
int new_value = ((ConVar*)var)->GetInt(); int new_value = ((ConVar*)var)->GetInt();
int old_value = atoi(pOldValue); int old_value = atoi(pOldValue);
if(chuman_limit == NULL) { if (g_pGameIServer == NULL) {
Msg( "sv_removehumanlimit init error\n"); Msg("g_pGameIServer pointer is not available\n");
return; return;
} }
if(new_value != old_value) { if (new_value != old_value) {
if(new_value == 1) { if (new_value == 1) {
write_signature(chuman_limit, human_limit_new); g_pCVar->FindVar("sv_allow_lobby_connect_only")->SetValue(0);
}else{
write_signature(chuman_limit, human_limit_org);
} }
} }
} }
#endif
void l4dtoolz::OnChangeUnreserved ( IConVar *var, const char *pOldValue, float flOldValue ) KHook::Return<void> l4dtoolz::ApplyGameSettings(IServerGameDLL*, KeyValues *pKV)
{ {
int new_value = ((ConVar*)var)->GetInt(); if (!pKV) {
int old_value = atoi(pOldValue); return { KHook::Action::Ignore };
if(unreserved_ptr == NULL ) {
Msg("unreserved_ptr init error\n");
return;
} }
if(new_value != old_value) { g_nGameSlots = sv_maxplayers.GetInt();
if(new_value == 1) { if (g_nGameSlots == -1) {
write_signature(unreserved_ptr, unreserved_new); return { KHook::Action::Ignore };
engine->ServerCommand("sv_allow_lobby_connect_only 0\n"); }
} else { pKV->SetInt("members/numSlots", g_nGameSlots);
write_signature(unreserved_ptr, unreserved_org); return { KHook::Action::Ignore };
}
KHook::Return<void> l4dtoolz::ReplyReservationRequest(CBaseServer*, netadr_t& adr, bf_read& inmsg)
{
if (sv_force_unreserved.GetInt()) {
if (g_pGameIServer != NULL) {
if (g_pGameIServer->m_nReservationCookie != 0)
return { KHook::Action::Ignore };
} }
return { KHook::Action::Supersede };
} }
return { KHook::Action::Ignore };
}
KHook::Return<int> l4dtoolz::GetTotalNumPlayersSupported(IMatchTitle*)
{
if (g_nGameSlots > 0) {
return { KHook::Action::Supersede, g_nGameSlots };
}
return { KHook::Action::Ignore, g_nGameSlots };
}
KHook::Return<int> l4dtoolz::GetMaxHumanPlayers(CGameRules*)
{
if (g_nGameSlots > 0) {
return { KHook::Action::Supersede, g_nGameSlots };
}
return { KHook::Action::Ignore, g_nGameSlots };
} }
PLUGIN_EXPOSE(l4dtoolz, g_l4dtoolz); PLUGIN_EXPOSE(l4dtoolz, g_l4dtoolz);
@@ -113,134 +110,114 @@ bool l4dtoolz::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool
{ {
PLUGIN_SAVEVARS(); PLUGIN_SAVEVARS();
GET_V_IFACE_CURRENT(GetServerFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
GET_V_IFACE_CURRENT(GetServerFactory, gameclients, IServerGameClients, INTERFACEVERSION_SERVERGAMECLIENTS);
GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
GET_V_IFACE_CURRENT(GetEngineFactory, g_pMatchFramework, IMatchFramework, IMATCHFRAMEWORK_VERSION_STRING);
GET_V_IFACE_CURRENT(GetEngineFactory, g_pCVar, ICvar, CVAR_INTERFACE_VERSION); GET_V_IFACE_CURRENT(GetEngineFactory, g_pCVar, ICvar, CVAR_INTERFACE_VERSION);
ConVar_Register(0, this); void* handle = NULL;
#if defined WIN32
struct base_addr_t base_addr; if (!(handle=KHook::FindOriginalVirtual(*(void***)engine, KHook::GetVtableIndex(&IVEngineServer::CreateFakeClient)))) {
base_addr.addr = NULL; Warning("Failed to get address 'IVEngineServer::CreateFakeClient'\n");
base_addr.len = 0; } else {
g_pGameIServer = *reinterpret_cast<CBaseServer **>(reinterpret_cast<unsigned char *>(handle)+sv_offs);
find_base_from_list(matchmaking_dll, &base_addr);
if(!lobby_match_ptr) {
lobby_match_ptr = find_signature(lobby_match, &base_addr, 1);
get_original_signature(lobby_match_ptr, lobby_match_new, lobby_match_org);
}
find_base_from_list(engine_dll, &base_addr);
#if SOURCE_ENGINE == SE_LEFT4DEAD
if(!max_players_friend_lobby) {
max_players_friend_lobby = find_signature(friends_lobby, &base_addr, 0);
get_original_signature(max_players_friend_lobby, friends_lobby_new, friends_lobby_org);
}
#endif
if(!max_players_connect) {
max_players_connect = find_signature(max_players, &base_addr, 0);
get_original_signature(max_players_connect, max_players_new, max_players_org);
}
if(!lobby_sux_ptr) {
#ifdef WIN32
lobby_sux_ptr = max_players_connect;
#else #else
lobby_sux_ptr = find_signature(lobby_sux, &base_addr, 0); if (!(handle=dlopen(engine_dll, RTLD_LAZY))) {
Warning("Could't open library '%s'\n", engine_dll);
} else {
g_pGameIServer = (CBaseServer *)g_MemUtils.ResolveSymbol(handle, "sv");
dlclose(handle);
#endif #endif
get_original_signature(lobby_sux_ptr, lobby_sux_new, lobby_sux_org); const char *pszCmdLineMax;
} if (CommandLine()->CheckParm("-maxplayers", &pszCmdLineMax)) {
#if SOURCE_ENGINE == SE_LEFT4DEAD g_pGameIServer->m_nMaxclients = clamp(atoi(pszCmdLineMax), 1, 32);
#ifdef WIN32 } else {
if(!max_players_server_browser) { g_pGameIServer->m_nMaxclients = 31;
max_players_server_browser = find_signature(server_bplayers, &base_addr, 0);
get_original_signature(max_players_server_browser, server_bplayers_new, server_bplayers_org);
}
#endif
#endif
if(!tmp_player) {
tmp_player = find_signature(players, &base_addr, 0);
if(tmp_player) {
get_original_signature(tmp_player, players_new, players_org);
write_signature(tmp_player, players_new);
const char *pszCmdLineMax;
if(CommandLine()->CheckParm("-maxplayers", &pszCmdLineMax) || CommandLine()->CheckParm("+maxplayers", &pszCmdLineMax)) {
char command[32];
UTIL_Format(command, sizeof(command), "maxplayers %d\n", clamp(atoi(pszCmdLineMax), 1, 32));
engine->ServerCommand(command);
} else {
engine->ServerCommand("maxplayers 31\n");
}
engine->ServerExecute();
write_signature(tmp_player, players_org);
free(players_org);
players_org = NULL;
} }
} }
if(!unreserved_ptr) {
unreserved_ptr = find_signature(unreserved, &base_addr, 0); m_ApplyGameSettings.Add(gamedll);
get_original_signature(unreserved_ptr, unreserved_new, unreserved_org); m_GetTotalNumPlayersSupported.Add(g_pMatchFramework->GetMatchTitle());
m_LevelInit.Add(gamedll);
m_LevelShutdown.Add(gamedll);
if (g_pGameIServer) {
m_ReplyReservationRequest.Add(g_pGameIServer);
} else {
Warning("g_pGameIServer pointer is not available\n");
} }
find_base_from_list(server_dll, &base_addr); ConVar_Register(0, this);
#if SOURCE_ENGINE == SE_LEFT4DEAD
if(!chuman_limit) {
chuman_limit = find_signature(human_limit, &base_addr, 0);
get_original_signature(chuman_limit, human_limit_new, human_limit_org);
}
#ifndef WIN32
if(!max_players_server_browser) {
max_players_server_browser = find_signature(server_bplayers, &base_addr, 0);
get_original_signature(max_players_server_browser, server_bplayers_new, server_bplayers_org);
}
#endif
#else
if(!max_players_server_browser) {
max_players_server_browser = find_signature(server_bplayers, &base_addr, 0);
get_original_signature(max_players_server_browser, server_bplayers_new, server_bplayers_org);
}
#endif
return true; return true;
} }
bool l4dtoolz::Unload(char *error, size_t maxlen) bool l4dtoolz::Unload(char *error, size_t maxlen)
{ {
#if SOURCE_ENGINE == SE_LEFT4DEAD m_ApplyGameSettings.Remove(gamedll);
write_signature(max_players_friend_lobby, friends_lobby_org); m_GetTotalNumPlayersSupported.Remove(g_pMatchFramework->GetMatchTitle());
write_signature(chuman_limit, human_limit_org); m_LevelInit.Remove(gamedll);
free(friends_lobby_org); m_LevelShutdown.Remove(gamedll);
free(human_limit_org);
#endif
write_signature(max_players_connect, max_players_org); if (g_pGameIServer) {
write_signature(lobby_sux_ptr, lobby_sux_org); m_ReplyReservationRequest.Remove(g_pGameIServer);
write_signature(max_players_server_browser, server_bplayers_org); }
write_signature(unreserved_ptr, unreserved_org);
write_signature(lobby_match_ptr, lobby_match_org);
free(max_players_org); LevelShutdown(gamedll);
free(lobby_sux_org); ConVar_Unregister();
free(server_bplayers_org);
free(unreserved_org);
free(lobby_match_org);
return true; return true;
} }
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) KHook::Return<bool> l4dtoolz::LevelInit(IServerGameDLL*, const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
{ {
va_list ap; g_pGameRules = nullptr;
va_start(ap, fmt); ServerClass *pServerClass = UTIL_FindServerClass("CTerrorGameRulesProxy");
size_t len = vsnprintf(buffer, maxlength, fmt, ap); if (pServerClass) {
va_end(ap); int i, iCount;
iCount = pServerClass->m_pTable->GetNumProps();
if (len >= maxlength) for (i = 0; i < iCount; i++) {
{ if (stricmp(pServerClass->m_pTable->GetProp(i)->GetName(), "terror_gamerules_data") == 0) {
len = maxlength - 1; g_pGameRules = reinterpret_cast<CGameRules*>((*pServerClass->m_pTable->GetProp(i)->GetDataTableProxyFn())(NULL, NULL, NULL, NULL, 0));
buffer[len] = '\0'; break;
}
}
} }
return len; if (g_pGameRules) {
g_HookGetMaxHumanPlayers.Add(g_pGameRules);
} else {
Warning("g_pGameRules pointer is not available\n");
}
return { KHook::Action::Ignore, true };
}
KHook::Return<void> l4dtoolz::LevelShutdown(IServerGameDLL*)
{
if (g_pGameRules) {
g_HookGetMaxHumanPlayers.Remove(g_pGameRules);
g_pGameRules = nullptr;
}
return { KHook::Action::Ignore };
}
ServerClass *UTIL_FindServerClass(const char *classname)
{
ServerClass *sc = gamedll->GetAllServerClasses();
while (sc)
{
if (strcmp(classname, sc->GetName()) == 0)
{
return sc;
}
sc = sc->m_pNext;
}
return NULL;
} }
const char *l4dtoolz::GetLicense() const char *l4dtoolz::GetLicense()
@@ -250,7 +227,7 @@ const char *l4dtoolz::GetLicense()
const char *l4dtoolz::GetVersion() const char *l4dtoolz::GetVersion()
{ {
return "1.1.0.2"; return "2.3.0";
} }
const char *l4dtoolz::GetDate() const char *l4dtoolz::GetDate()
+19 -15
View File
@@ -2,12 +2,23 @@
#define _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_ #define _INCLUDE_METAMOD_SOURCE_STUB_PLUGIN_H_
#include <ISmmPlugin.h> #include <ISmmPlugin.h>
#include "baseserver.h"
#include "matchmaking/imatchframework.h"
class CGameRules;
class l4dtoolz : public ISmmPlugin, public IConCommandBaseAccessor class l4dtoolz : public ISmmPlugin, public IConCommandBaseAccessor
{ {
public: public:
l4dtoolz();
bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late); bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late);
bool Unload(char *error, size_t maxlen); bool Unload(char *error, size_t maxlen);
KHook::Return<void> ApplyGameSettings(IServerGameDLL*, KeyValues *pKV);
KHook::Return<int> GetTotalNumPlayersSupported(IMatchTitle*);
KHook::Return<bool> LevelInit(IServerGameDLL*, const char *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
KHook::Return<void> LevelShutdown(IServerGameDLL*);
KHook::Return<void> ReplyReservationRequest(CBaseServer*, netadr_t& adr, bf_read& inmsg);
KHook::Return<int> GetMaxHumanPlayers(CGameRules*);
public: public:
const char *GetAuthor(); const char *GetAuthor();
const char *GetName(); const char *GetName();
@@ -17,28 +28,21 @@ public:
const char *GetVersion(); const char *GetVersion();
const char *GetDate(); const char *GetDate();
const char *GetLogTag(); const char *GetLogTag();
KHook::Virtual<IServerGameDLL, void, KeyValues*> m_ApplyGameSettings;
KHook::Virtual<IMatchTitle, int> m_GetTotalNumPlayersSupported;
KHook::Virtual<IServerGameDLL, bool, char const *, char const *, char const *, char const *, bool, bool> m_LevelInit;
KHook::Virtual<IServerGameDLL, void> m_LevelShutdown;
KHook::Virtual<CBaseServer, void, netadr_t&, bf_read&> m_ReplyReservationRequest;
KHook::Virtual<CGameRules, int> g_HookGetMaxHumanPlayers;
public: //IConCommandBaseAccessor public: //IConCommandBaseAccessor
bool RegisterConCommandBase(ConCommandBase *pVar); bool RegisterConCommandBase(ConCommandBase *pVar);
public: public:
static void OnChangeMaxplayers ( IConVar *var, const char *pOldValue, float flOldValue ); static void OnChangeMaxplayers ( IConVar *var, const char *pOldValue, float flOldValue );
static void OnChangeUnreserved ( IConVar *var, const char *pOldValue, float flOldValue ); static void OnChangeUnreserved ( IConVar *var, const char *pOldValue, float flOldValue );
#if SOURCE_ENGINE == SE_LEFT4DEAD
static void OnChangeRemovehumanlimit ( IConVar *var, const char *pOldValue, float flOldValue );
static void* max_players_friend_lobby;
static void* chuman_limit;
#endif
static void* max_players_connect;
static void* max_players_server_browser;
static void* lobby_sux_ptr;
static void* tmp_player;
static void* unreserved_ptr;
static void* lobby_match_ptr;
}; };
size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); ServerClass *UTIL_FindServerClass(const char *classname);
extern l4dtoolz g_l4dtoolz; extern l4dtoolz g_l4dtoolz;
+394
View File
@@ -0,0 +1,394 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* MemoryUtils
* Copyright (C) 2004-2011 AlliedModders LLC., 2011 Prodigysim
* 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, the authors give 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>.
*/
#include "memutils.h"
#include <string.h>
#if defined LINUX
#include <fcntl.h>
#include <link.h>
#include <sys/mman.h>
#include <sys/stat.h>
#define PAGE_SIZE 4096
#define PAGE_ALIGN_UP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
#define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1))
#endif
#if defined OSX
#include <AvailabilityMacros.h>
#include <mach/task.h>
#include <mach-o/dyld_images.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
/* Define things from 10.6 SDK for older SDKs */
#ifndef MAC_OS_X_VERSION_10_6
struct task_dyld_info
{
mach_vm_address_t all_image_info_addr;
mach_vm_size_t all_image_info_size;
};
typedef struct task_dyld_info task_dyld_info_data_t;
#define TASK_DYLD_INFO 17
#define TASK_DYLD_INFO_COUNT (sizeof(task_dyld_info_data_t) / sizeof(natural_t))
#endif // MAC_OS_X_VERSION_10_6
#endif // OSX
MemoryUtils g_MemUtils;
MemoryUtils::MemoryUtils()
{
#if defined OSX
Gestalt(gestaltSystemVersionMajor, &m_OSXMajor);
Gestalt(gestaltSystemVersionMinor, &m_OSXMinor);
/* Get pointer to struct that describes all loaded mach-o images in process */
if ((m_OSXMajor == 10 && m_OSXMinor >= 6) || m_OSXMajor > 10)
{
task_dyld_info_data_t dyld_info;
mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
m_ImageList = (struct dyld_all_image_infos *)dyld_info.all_image_info_addr;
}
else
{
struct nlist list[2];
memset(list, 0, sizeof(list));
list[0].n_un.n_name = (char *)"_dyld_all_image_infos";
nlist("/usr/lib/dyld", list);
m_ImageList = (struct dyld_all_image_infos *)list[0].n_value;
}
#endif
}
MemoryUtils::~MemoryUtils()
{
#if defined LINUX || defined OSX
for (size_t i = 0; i < m_SymTables.size(); i++)
{
delete m_SymTables[i];
}
m_SymTables.clear();
#endif
}
void *MemoryUtils::ResolveSymbol(void *handle, const char *symbol)
{
#if defined WIN32
return GetProcAddress((HMODULE)handle, symbol);
#elif defined LINUX
struct link_map *dlmap;
struct stat dlstat;
int dlfile;
uintptr_t map_base;
Elf32_Ehdr *file_hdr;
Elf32_Shdr *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
Elf32_Sym *symtab;
const char *shstrtab, *strtab;
uint16_t section_count;
uint32_t symbol_count;
LibSymbolTable *libtable;
SymbolTable *table;
Symbol *symbol_entry;
dlmap = (struct link_map *)handle;
symtab_hdr = NULL;
strtab_hdr = NULL;
table = NULL;
/* See if we already have a symbol table for this library */
for (size_t i = 0; i < m_SymTables.size(); i++)
{
libtable = m_SymTables[i];
if (libtable->lib_base == dlmap->l_addr)
{
table = &libtable->table;
break;
}
}
/* If we don't have a symbol table for this library, then create one */
if (table == NULL)
{
libtable = new LibSymbolTable();
libtable->table.Initialize();
libtable->lib_base = dlmap->l_addr;
libtable->last_pos = 0;
table = &libtable->table;
m_SymTables.push_back(libtable);
}
/* See if the symbol is already cached in our table */
symbol_entry = table->FindSymbol(symbol, strlen(symbol));
if (symbol_entry != NULL)
{
return symbol_entry->address;
}
/* If symbol isn't in our table, then we have open the actual library */
dlfile = open(dlmap->l_name, O_RDONLY);
if (dlfile == -1 || fstat(dlfile, &dlstat) == -1)
{
close(dlfile);
return NULL;
}
/* Map library file into memory */
file_hdr = (Elf32_Ehdr *)mmap(NULL, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
map_base = (uintptr_t)file_hdr;
if (file_hdr == MAP_FAILED)
{
close(dlfile);
return NULL;
}
close(dlfile);
if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF)
{
munmap(file_hdr, dlstat.st_size);
return NULL;
}
sections = (Elf32_Shdr *)(map_base + file_hdr->e_shoff);
section_count = file_hdr->e_shnum;
/* Get ELF section header string table */
shstrtab_hdr = &sections[file_hdr->e_shstrndx];
shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset);
/* Iterate sections while looking for ELF symbol table and string table */
for (uint16_t i = 0; i < section_count; i++)
{
Elf32_Shdr &hdr = sections[i];
const char *section_name = shstrtab + hdr.sh_name;
if (strcmp(section_name, ".symtab") == 0)
{
symtab_hdr = &hdr;
}
else if (strcmp(section_name, ".strtab") == 0)
{
strtab_hdr = &hdr;
}
}
/* Uh oh, we don't have a symbol table or a string table */
if (symtab_hdr == NULL || strtab_hdr == NULL)
{
munmap(file_hdr, dlstat.st_size);
return NULL;
}
symtab = (Elf32_Sym *)(map_base + symtab_hdr->sh_offset);
strtab = (const char *)(map_base + strtab_hdr->sh_offset);
symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
/* Iterate symbol table starting from the position we were at last time */
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
{
Elf32_Sym &sym = symtab[i];
unsigned char sym_type = ELF32_ST_TYPE(sym.st_info);
const char *sym_name = strtab + sym.st_name;
Symbol *cur_sym;
/* Skip symbols that are undefined or do not refer to functions or objects */
if (sym.st_shndx == SHN_UNDEF || (sym_type != STT_FUNC && sym_type != STT_OBJECT))
{
continue;
}
/* Caching symbols as we go along */
cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlmap->l_addr + sym.st_value));
if (strcmp(symbol, sym_name) == 0)
{
symbol_entry = cur_sym;
libtable->last_pos = ++i;
break;
}
}
munmap(file_hdr, dlstat.st_size);
return symbol_entry ? symbol_entry->address : NULL;
#elif defined OSX
uintptr_t dlbase, linkedit_addr;
uint32_t image_count;
struct mach_header *file_hdr;
struct load_command *loadcmds;
struct segment_command *linkedit_hdr;
struct symtab_command *symtab_hdr;
struct nlist *symtab;
const char *strtab;
uint32_t loadcmd_count;
uint32_t symbol_count;
LibSymbolTable *libtable;
SymbolTable *table;
Symbol *symbol_entry;
dlbase = 0;
image_count = m_ImageList->infoArrayCount;
linkedit_hdr = NULL;
symtab_hdr = NULL;
table = NULL;
/* Loop through mach-o images in process.
* We can skip index 0 since that is just the executable.
*/
for (uint32_t i = 1; i < image_count; i++)
{
const struct dyld_image_info &info = m_ImageList->infoArray[i];
/* "Load" each one until we get a matching handle */
void *h = dlopen(info.imageFilePath, RTLD_NOLOAD);
if (h == handle)
{
dlbase = (uintptr_t)info.imageLoadAddress;
dlclose(h);
break;
}
dlclose(h);
}
if (!dlbase)
{
/* Uh oh, we couldn't find a matching handle */
return NULL;
}
/* See if we already have a symbol table for this library */
for (size_t i = 0; i < m_SymTables.size(); i++)
{
libtable = m_SymTables[i];
if (libtable->lib_base == dlbase)
{
table = &libtable->table;
break;
}
}
/* If we don't have a symbol table for this library, then create one */
if (table == NULL)
{
libtable = new LibSymbolTable();
libtable->table.Initialize();
libtable->lib_base = dlbase;
libtable->last_pos = 0;
table = &libtable->table;
m_SymTables.push_back(libtable);
}
/* See if the symbol is already cached in our table */
symbol_entry = table->FindSymbol(symbol, strlen(symbol));
if (symbol_entry != NULL)
{
return symbol_entry->address;
}
/* If symbol isn't in our table, then we have to locate it in memory */
file_hdr = (struct mach_header *)dlbase;
loadcmds = (struct load_command *)(dlbase + sizeof(struct mach_header));
loadcmd_count = file_hdr->ncmds;
/* Loop through load commands until we find the ones for the symbol table */
for (uint32_t i = 0; i < loadcmd_count; i++)
{
if (loadcmds->cmd == LC_SEGMENT && !linkedit_hdr)
{
struct segment_command *seg = (struct segment_command *)loadcmds;
if (strcmp(seg->segname, "__LINKEDIT") == 0)
{
linkedit_hdr = seg;
if (symtab_hdr)
{
break;
}
}
}
else if (loadcmds->cmd == LC_SYMTAB)
{
symtab_hdr = (struct symtab_command *)loadcmds;
if (linkedit_hdr)
{
break;
}
}
/* Load commands are not of a fixed size which is why we add the size */
loadcmds = (struct load_command *)((uintptr_t)loadcmds + loadcmds->cmdsize);
}
if (!linkedit_hdr || !symtab_hdr || !symtab_hdr->symoff || !symtab_hdr->stroff)
{
/* Uh oh, no symbol table */
return NULL;
}
linkedit_addr = dlbase + linkedit_hdr->vmaddr;
symtab = (struct nlist *)(linkedit_addr + symtab_hdr->symoff - linkedit_hdr->fileoff);
strtab = (const char *)(linkedit_addr + symtab_hdr->stroff - linkedit_hdr->fileoff);
symbol_count = symtab_hdr->nsyms;
/* Iterate symbol table starting from the position we were at last time */
for (uint32_t i = libtable->last_pos; i < symbol_count; i++)
{
struct nlist &sym = symtab[i];
/* Ignore the prepended underscore on all symbols, so +1 here */
const char *sym_name = strtab + sym.n_un.n_strx + 1;
Symbol *cur_sym;
/* Skip symbols that are undefined */
if (sym.n_sect == NO_SECT)
{
continue;
}
/* Caching symbols as we go along */
cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlbase + sym.n_value));
if (strcmp(symbol, sym_name) == 0)
{
symbol_entry = cur_sym;
libtable->last_pos = ++i;
break;
}
}
return symbol_entry ? symbol_entry->address : NULL;
#endif
return NULL;
}
+79
View File
@@ -0,0 +1,79 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* MemoryUtils
* Copyright (C) 2004-2011 AlliedModders LLC., 2011 ProdigySim
* 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, the authors give 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>.
*/
#ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
#define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
#include <stdio.h>
#include <stdint.h>
#include <cstddef>
#include "khook/memory.hpp"
#include "khook.hpp"
#if defined LINUX || defined OSX
#include <vector>
#include "sm_symtable.h"
#endif
#if defined OSX
#include <CoreServices/CoreServices.h>
#endif
#if defined LINUX || defined OSX
struct LibSymbolTable
{
SymbolTable table;
uintptr_t lib_base;
uint32_t last_pos;
};
#endif
class MemoryUtils
{
public:
MemoryUtils();
~MemoryUtils();
void *ResolveSymbol(void *handle, const char *symbol);
#if defined LINUX || defined OSX
private:
std::vector<LibSymbolTable *> m_SymTables;
#if defined OSX
struct dyld_all_image_infos *m_ImageList;
SInt32 m_OSXMajor;
SInt32 m_OSXMinor;
#endif
#endif
};
extern MemoryUtils g_MemUtils;
#endif // _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
-243
View File
@@ -1,243 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "signature.h"
#ifdef WIN32
#include <windows.h>
#include <TlHelp32.h>
#else
#include <sys/mman.h>
#include <unistd.h>
#include <link.h>
#endif
#define SIGN_HEADER_LEN 2
#define SIGN_LEN_BYTE 0
#define SIGN_OFFSET_BYTE 1
static int lock_region(const void *addr, unsigned int sign_len, unsigned int sign_off, int lock)
{
#ifndef WIN32
unsigned int all_adr;
unsigned int all_size;
unsigned int p_size;
unsigned int u_addr;
p_size = sysconf(_SC_PAGESIZE);
u_addr = (unsigned int)addr;
all_adr = (u_addr + sign_off) & ~(p_size-1);
all_size = u_addr - all_adr + sign_len;
if(lock) {
mlock((void *)all_adr, all_size);
mprotect((void *)all_adr, all_size, PROT_READ|PROT_WRITE|PROT_EXEC);
} else
munlock((void *)all_adr, all_size);
#endif
return 0;
}
void *find_signature(const char* mask, struct base_addr_t *base_addr, int pure)
{
char *pBasePtr = (char *)base_addr->addr;
char *pEndPtr = pBasePtr+base_addr->len-(int)mask[SIGN_LEN_BYTE];
int i;
char* tmp;
if(base_addr->addr == NULL)
return NULL;
#ifndef WIN32
unsigned int p_size = sysconf(_SC_PAGESIZE);
char* all_adr = (char*)((unsigned int)pBasePtr & ~(p_size-1));
unsigned int size = pEndPtr - all_adr;
mlock(all_adr, size);
#endif
while(pBasePtr < pEndPtr)
{
tmp = pBasePtr;
for(i = 1; i <= mask[SIGN_LEN_BYTE]; ++i) {
if(!pure && mask[i] == '\xC3'){
tmp++;
continue;
}
if(mask[i] != *tmp ) {
break;
}
tmp++;
}
if(i-1 == mask[0]) {
#ifndef WIN32
munlock(all_adr, size);
#endif
return pBasePtr;
}
pBasePtr++;
}
#ifndef WIN32
munlock(all_adr, size);
#endif
return NULL;
}
#ifndef WIN32
struct v_data{
const char *fname;
void *baddr;
unsigned int blen;
};
static int callback(struct dl_phdr_info *info, size_t size, void *data)
{
int i;
const char* filename;
if (!info->dlpi_name || !info->dlpi_name[0])
return 0;
filename = ((struct v_data *)data)->fname;
if(strstr(info->dlpi_name, filename)) {
if(strstr( info->dlpi_name, "metamod") == NULL) {
((struct v_data *)data)->baddr = (void*)info->dlpi_addr;
((struct v_data *)data)->blen = 0;
for(i = 0; i < info->dlpi_phnum; ++i) {
((struct v_data *)data)->blen+=info->dlpi_phdr[i].p_filesz;
break;
}
return 1;
}
}
return 0;
}
#endif
int find_base(const char* name, struct base_addr_t *base_addr)
{
#ifdef WIN32
MODULEENTRY32 modent;
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
if(hModuleSnap == INVALID_HANDLE_VALUE) {
return 0;
}
modent.dwSize = sizeof(MODULEENTRY32);
if(!Module32Next(hModuleSnap, &modent)){
CloseHandle(hModuleSnap);
return 0;
}
do {
if(strstr( modent.szExePath, name)) {
if(strstr( modent.szExePath, "metamod"))
continue;
base_addr->addr = modent.modBaseAddr;
base_addr->len = modent.modBaseSize;
CloseHandle(hModuleSnap);
return 1;
}
} while(Module32Next(hModuleSnap, &modent));
CloseHandle(hModuleSnap);
#else
struct v_data vdata;
vdata.fname = name;
if(dl_iterate_phdr(callback, &vdata)){
base_addr->addr = vdata.baddr;
base_addr->len = vdata.blen;
return 1;
}
#endif
base_addr->addr = NULL;
base_addr->len = 0;
return 0;
}
int find_base_from_list(const char *name[], struct base_addr_t *base_addr)
{
int ret = 0;
int i = 0;
base_addr->addr = NULL;
base_addr->len = 0;
if (name == NULL)
return 0;
while (name[i] != NULL && !(ret = find_base(name[i], base_addr)))
i++;
return ret;
}
int write_signature(const void* addr, const void* signature)
{
if(!addr)
return 0;
unsigned int u_addr_sign;
unsigned int sign_len;
unsigned int sign_off;
unsigned int u_addr;
sign_len = ((unsigned char *)signature)[SIGN_LEN_BYTE];
sign_off = ((unsigned char *)signature)[SIGN_OFFSET_BYTE];
u_addr = (unsigned int)addr;
u_addr_sign = (unsigned int)signature;
#ifdef WIN32
HANDLE h_process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
WriteProcessMemory(h_process, (void *)(u_addr+sign_off), (void *)(u_addr_sign+SIGN_HEADER_LEN), sign_len, NULL);
CloseHandle(h_process);
#else
lock_region(addr, sign_len, sign_off, 1);
memcpy((void *)(u_addr+sign_off), (void *)(u_addr_sign+SIGN_HEADER_LEN), sign_len);
lock_region(addr, sign_len, sign_off, 0);
#endif
return 1;
}
int read_signature(const void *addr, void *signature)
{
unsigned int u_addr_sign;
unsigned int sign_len;
unsigned int sign_off;
unsigned int u_addr;
sign_len = ((unsigned char *)signature)[SIGN_LEN_BYTE];
sign_off = ((unsigned char *)signature)[SIGN_OFFSET_BYTE];
u_addr = (unsigned int)addr;
u_addr_sign = (unsigned int)signature;
#ifdef WIN32
HANDLE h_process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
ReadProcessMemory(h_process, (void *)(u_addr+sign_off), (void *)(u_addr_sign+SIGN_HEADER_LEN), sign_len, NULL);
CloseHandle(h_process);
#else
lock_region(addr, sign_len, sign_off, 1);
memcpy((void *)(u_addr_sign+SIGN_HEADER_LEN), (void *)(u_addr+sign_off), sign_len);
lock_region(addr, sign_len, sign_off, 0);
#endif
return 0;
}
int get_original_signature(const void *offset, const void *new_sig, void *&org_sig)
{
unsigned int sign_len;
if(!offset)
return 0;
sign_len = ((unsigned char *)new_sig)[SIGN_LEN_BYTE];
org_sig = malloc(sign_len + SIGN_HEADER_LEN);
memcpy(org_sig, new_sig, SIGN_HEADER_LEN);
return read_signature(offset, org_sig);
}
-16
View File
@@ -1,16 +0,0 @@
#ifndef _INCLUDE_SIGNATURE_
#define _INCLUDE_SIGNATURE_
struct base_addr_t{
void *addr;
unsigned int len;
};
void *find_signature(const char *mask, struct base_addr_t *base_addr, int pure);
int find_base(const char *name, struct base_addr_t *base_addr);
int find_base_from_list(const char *name[], struct base_addr_t *base_addr);
int write_signature(const void *addr, const void *signature);
int read_signature(const void *addr, void *signature);
int get_original_signature(const void *offset, const void *new_sig, void *&org_sig);
#endif //_INCLUDE_SIGNATURE_
+232
View File
@@ -0,0 +1,232 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2009 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>.
*/
#ifndef _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
#define _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
#define KESTRING_TABLE_START_SIZE 65536
struct Symbol
{
size_t length;
uint32_t hash;
void *address;
Symbol *tbl_next;
inline char *buffer()
{
return reinterpret_cast<char *>(this + 1);
}
};
class SymbolTable
{
public:
~SymbolTable()
{
for (uint32_t i = 0; i < nbuckets; i++)
{
Symbol *sym = buckets[i];
while (sym != NULL)
{
Symbol *next = sym->tbl_next;
free(sym);
sym = next;
}
}
free(buckets);
}
bool Initialize()
{
buckets = (Symbol **)malloc(sizeof(Symbol *) * KESTRING_TABLE_START_SIZE);
if (buckets == NULL)
{
return false;
}
memset(buckets, 0, sizeof(Symbol *) * KESTRING_TABLE_START_SIZE);
nbuckets = KESTRING_TABLE_START_SIZE;
nused = 0;
bucketmask = KESTRING_TABLE_START_SIZE - 1;
return true;
}
static inline uint32_t HashString(const char *data, size_t len)
{
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
uint32_t hash = len, tmp;
int rem;
if (len <= 0 || data == NULL)
{
return 0;
}
rem = len & 3;
len >>= 2;
/* Main loop */
for (;len > 0; len--) {
hash += get16bits (data);
tmp = (get16bits (data+2) << 11) ^ hash;
hash = (hash << 16) ^ tmp;
data += 2 * sizeof (uint16_t);
hash += hash >> 11;
}
/* Handle end cases */
switch (rem) {
case 3: hash += get16bits (data);
hash ^= hash << 16;
hash ^= data[sizeof (uint16_t)] << 18;
hash += hash >> 11;
break;
case 2: hash += get16bits (data);
hash ^= hash << 11;
hash += hash >> 17;
break;
case 1: hash += *data;
hash ^= hash << 10;
hash += hash >> 1;
}
/* Force "avalanching" of final 127 bits */
hash ^= hash << 3;
hash += hash >> 5;
hash ^= hash << 4;
hash += hash >> 17;
hash ^= hash << 25;
hash += hash >> 6;
return hash;
#undef get16bits
}
Symbol **FindSymbolBucket(const char *str, size_t len, uint32_t hash)
{
uint32_t bucket = hash & bucketmask;
Symbol **pkvs = &buckets[bucket];
Symbol *kvs = *pkvs;
while (kvs != NULL)
{
if (len == kvs->length && memcmp(str, kvs->buffer(), len * sizeof(char)) == 0)
{
return pkvs;
}
pkvs = &kvs->tbl_next;
kvs = *pkvs;
}
return pkvs;
}
void ResizeSymbolTable()
{
uint32_t xnbuckets = nbuckets * 2;
Symbol **xbuckets = (Symbol **)malloc(sizeof(Symbol *) * xnbuckets);
if (xbuckets == NULL)
{
return;
}
memset(xbuckets, 0, sizeof(Symbol *) * xnbuckets);
uint32_t xbucketmask = xnbuckets - 1;
for (uint32_t i = 0; i < nbuckets; i++)
{
Symbol *sym = buckets[i];
while (sym != NULL)
{
Symbol *next = sym->tbl_next;
uint32_t bucket = sym->hash & xbucketmask;
sym->tbl_next = xbuckets[bucket];
xbuckets[bucket] = sym;
sym = next;
}
}
free(buckets);
buckets = xbuckets;
nbuckets = xnbuckets;
bucketmask = xbucketmask;
}
Symbol *FindSymbol(const char *str, size_t len)
{
uint32_t hash = HashString(str, len);
Symbol **pkvs = FindSymbolBucket(str, len, hash);
return *pkvs;
}
Symbol *InternSymbol(const char* str, size_t len, void *address)
{
uint32_t hash = HashString(str, len);
Symbol **pkvs = FindSymbolBucket(str, len, hash);
if (*pkvs != NULL)
{
return *pkvs;
}
Symbol *kvs = (Symbol *)malloc(sizeof(Symbol) + sizeof(char) * (len + 1));
kvs->length = len;
kvs->hash = hash;
kvs->address = address;
kvs->tbl_next = NULL;
memcpy(kvs + 1, str, sizeof(char) * (len + 1));
*pkvs = kvs;
nused++;
if (nused > nbuckets && nbuckets <= INT_MAX / 2)
{
ResizeSymbolTable();
}
return kvs;
}
private:
uint32_t nbuckets;
uint32_t nused;
uint32_t bucketmask;
Symbol **buckets;
};
#endif //_INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_