Modernize build/CI, support SourceMod 1.13, deprecate ForceHeartbeat

Rework the build and CI: swap to SourceMod's safetyhook-based CDetour and
drop the vendored CDetour/asm sources, the old Makefile, Travis config, and
buildbot perl scripts. Add GitHub Actions building and releasing x86 and
x86_64 against SM 1.12 and 1.13, plus dependabot. Split the Windows and Linux
packages and tidy naming.

Gate IPluginManager::FindPluginByContext on the extension API version so the
extension builds against both SM 1.12 (API 8) and 1.13 (API 9), and shim
DETOUR_CREATE_STATIC_FIXED over the address overload safetyhook exposes.

Deprecate SteamWorks_ForceHeartbeat: newer Steamworks SDKs removed
ISteamGameServer::ForceHeartbeat, so make the native a no-op and mark it
deprecated in the include.
This commit is contained in:
Nicholas Hastings
2026-07-12 10:56:36 -04:00
parent f0c1b62dff
commit 39fcfa564e
21 changed files with 332 additions and 1842 deletions
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
-52
View File
@@ -1,52 +0,0 @@
name: SteamWorks.ext Build
on:
push:
branches: [ master, windows98 ]
pull_request:
branches: [ master, windows98 ]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
python-version: [2.7, 3.3, 3.8]
os: [ubuntu-18.04, macos-latest, windows-2019]
exclude:
- os: macos-latest
python-version: 3.3
- os: windows-2019
python-version: 3.3
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install Deps
if: runner.os == 'Linux'
run: |
sudo dpkg --add-architecture i386
sudo apt-get install lib32stdc++-7-dev lib32z1-dev libc6-dev-i386
sudo apt-get install g++-multilib
- name: install AMBuild
run: |
mkdir assets
cd assets
git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b fix-deps https://github.com/alliedmodders/ambuild.git
pip install ./ambuild
- name: Clone Dependencies
run: |
git clone --depth 1 --recurse-submodules -j8 --shallow-submodules https://[email protected]/SteamDatabase/SteamworksSDK.git SteamworksSDK
git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b sdk2013 https://github.com/alliedmodders/hl2sdk.git hl2sdk-sdk2013
git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b 1.10-dev https://github.com/alliedmodders/metamod-source.git mmsource-central
git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b 1.7-dev https://github.com/alliedmodders/sourcemod.git sourcemod-central
- name: Run Build
run: |
mkdir build
cd build
cp ../AMBuildScript ../../
python ../configure.py -s sdk2013 --hl2sdk-root ../assets --sm-path ../assets/sourcemod-central --mms-path ../assets/mmsource-central --steamworks-path ../assets/SteamworksSD
ambuild
+161
View File
@@ -0,0 +1,161 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
name: sm${{ matrix.sm.label }}-${{ matrix.target.os_name }}-${{ matrix.target.arch }}
runs-on: ${{ matrix.target.os }}
container: ${{ matrix.target.container }}
strategy:
fail-fast: false
matrix:
sm:
- label: "1.12"
branch: "1.12-dev"
- label: "1.13"
branch: "master"
target:
- os: ubuntu-latest
os_name: linux
arch: x86
container: ghcr.io/alliedmodders/build-containers/debian11-clang22:latest
- os: ubuntu-latest
os_name: linux
arch: x86_64
container: ghcr.io/alliedmodders/build-containers/debian11-clang22:latest
- os: windows-latest
os_name: windows
arch: x86
msvc_arch: x86
- os: windows-latest
os_name: windows
arch: x86_64
msvc_arch: amd64
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup Python (Windows)
if: matrix.target.os_name == 'windows'
uses: actions/setup-python@v6
with:
python-version: '3.12'
- name: Setup MSVC (Windows)
if: matrix.target.os_name == 'windows'
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.target.msvc_arch }}
- name: Install AMBuild
if: matrix.target.os_name == 'windows'
shell: bash
run: python -m pip install --upgrade git+https://github.com/alliedmodders/ambuild.git
- name: Clone dependencies
shell: bash
run: |
git config --global --add safe.directory '*'
git clone --depth 1 --recurse-submodules -j8 --shallow-submodules https://github.com/rlabrecque/SteamworksSDK.git SteamworksSDK
git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b 1.12-dev https://github.com/alliedmodders/metamod-source.git mmsource
git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b ${{ matrix.sm.branch }} https://github.com/alliedmodders/sourcemod.git sourcemod
- name: Build (Linux)
if: matrix.target.os_name == 'linux'
env:
CC: clang-22
CXX: clang++-22
run: |
mkdir build && cd build
python3 ../configure.py \
--sm-path ../sourcemod \
--mms-path ../mmsource \
--steamworks-path ../SteamworksSDK \
--target ${{ matrix.target.arch }} \
--enable-optimize
ambuild
- name: Build (Windows)
if: matrix.target.os_name == 'windows'
shell: bash
run: |
mkdir build && cd build
python ../configure.py \
--sm-path ../sourcemod \
--mms-path ../mmsource \
--steamworks-path ../SteamworksSDK \
--target ${{ matrix.target.arch }} \
--enable-optimize
ambuild
- name: Upload package artifact
uses: actions/upload-artifact@v7
with:
name: pkg-sm${{ matrix.sm.label }}-${{ matrix.target.os_name }}-${{ matrix.target.arch }}
path: build/package/addons
if-no-files-found: error
release:
name: Release
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v8
with:
path: artifacts
- name: Assemble packages
id: package
run: |
base_version=$(grep -oP 'SMEXT_CONF_VERSION\s+"\K[^"]+' Extension/sdk/smsdk_config.h)
build_number=$(git rev-list --count HEAD)
version="${base_version}-git${build_number}"
echo "version=${version}" >> "$GITHUB_OUTPUT"
# One package per SourceMod version per OS: Windows as .zip, Linux as
# .tar.gz. Each merges that combination's per-arch slices (the include
# file rides along in every slice).
assets=""
for label in 1.12 1.13; do
for os_name in windows linux; do
dest="package-sm${label}-${os_name}/addons"
mkdir -p "${dest}"
for dir in artifacts/pkg-sm${label}-${os_name}-*/; do
cp -a "${dir}." "${dest}/"
done
if [ "${os_name}" = "windows" ]; then
asset="SteamWorks-${version}-sm${label}-windows.zip"
(cd "package-sm${label}-${os_name}" && zip -r "../${asset}" addons)
else
asset="SteamWorks-${version}-sm${label}-linux.tar.gz"
tar -czf "${asset}" -C "package-sm${label}-${os_name}" addons
fi
assets="${assets} ${asset}"
done
done
echo "assets=${assets# }" >> "$GITHUB_OUTPUT"
- name: Create release
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "v${{ steps.package.outputs.version }}" \
${{ steps.package.outputs.assets }} \
--target "${GITHUB_SHA}" \
--title "SteamWorks ${{ steps.package.outputs.version }}" \
--notes "Automated release built from ${GITHUB_SHA}."
+4
View File
@@ -26,3 +26,7 @@
[Rr]elease - */
[Dd]ebug/
[Rr]elease/
# ambuild output directories
/build/
/build-*/
-67
View File
@@ -1,67 +0,0 @@
git:
depth: 1
env:
global:
- secure: "VsvGz6WqBVbT+RpnaWwYb16mVvQHQMvzfRxLlUEnYBVkKCWBgyECDXRL/ShBwGW+aMYW25ZPt/aJNk7rN/wvTrgGU2N9X6CrfVyGPp94HPSYPzEbZSXRoCGex30HkVVITYUBDd06CWuMMIOgS7At/XdJIR1ZjZpOr91Oze3YbGA="
matrix:
fast_finish: true
include:
- os: linux
dist: trusty
language: cpp
compiler: gcc
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
env:
- AMB="install --user"
- PATH="~/.local/bin:$PATH"
- RELEASE_PKG_FILE="package-lin.tgz"
# - os: windows
# language: cpp
# env:
# - AMB="install"
# - PATH="$PATH:/C/ProgramData/chocolatey/bin:/C/ProgramData/chocolatey/lib/mingw/tools/install/mingw64/opt/bin"
# - RELEASE_PKG_FILE="package-win.tgz"
- os: mac
osx_image: xcode7.2
language: cpp
compiler: clang
env:
- AMB="install"
- PATH="~/.local/bin:$PATH"
- RELEASE_PKG_FILE="package-mac.tgz"
before_script:
- mkdir assets && cd assets
- git clone https://github.com/alliedmodders/ambuild.git
- cd ambuild
- python setup.py build
- python setup.py $AMB
- cd ..
- git clone --depth 1 --recurse-submodules -j8 --shallow-submodules https://[email protected]/SteamDatabase/SteamworksSDK.git SteamworksSDK
- git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b sdk2013 https://github.com/alliedmodders/hl2sdk.git hl2sdk-sdk2013
- git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b 1.10-dev https://github.com/alliedmodders/metamod-source.git mmsource-central
- git clone --depth 1 --recurse-submodules -j8 --shallow-submodules -b 1.7-dev https://github.com/alliedmodders/sourcemod.git sourcemod-central
- cd ..
script:
- mkdir build
- cd build
- cp ../AMBuildScript ../../
- python2 ../configure.py -s sdk2013 --hl2sdk-root ../assets --sm-path ../assets/sourcemod-central --mms-path ../assets/mmsource-central --steamworks-path ../assets/SteamworksSDK
- ambuild
- tar czvf ${RELEASE_PKG_FILE} package
deploy:
provider: releases
api_key:
secure: "Px60/dTgw3w6ZvxzyuilYaHHWFHWQ1rONhpbWJbxzz5+dfkmiqVyYLszlBrbS6tbyOv/oBMqcaOXsB7mv4OOlvKQPOjc8siS8ux1Ows8WL+yvRR/rGS0j28pP6HKN11hBerxOps3sqiCyNa2gNJ+3vX987SIekpIb5nqzuqg+yQ="
file_glob: true
file: "${RELEASE_PKG_FILE}"
skip_cleanup: true
on:
tags: true
+28 -90
View File
@@ -1,24 +1,5 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os, sys
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 = {
'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, 'sdk2013'),
}
import os
def ResolveEnvPath(env, folder):
if env in os.environ:
@@ -43,7 +24,6 @@ def Normalize(path):
class SteamWorksConfig(object):
def __init__(self):
self.sdks = {}
self.binaries = []
self.mms_root = None
self.sm_root = None
@@ -62,29 +42,7 @@ class SteamWorksConfig(object):
return 'Debug'
return 'Release'
def detectSDKs(self):
sdk_list = builder.options.sdks.split(',')
use_all = sdk_list[0] == 'all'
use_present = sdk_list[0] == 'present'
for sdk_name in PossibleSDKs:
sdk = PossibleSDKs[sdk_name]
if builder.cxx.target.platform in sdk.platform:
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.')
def detectDeps(self):
#METAMOD:SOURCE
if builder.options.mms_path:
self.mms_root = builder.options.mms_path
@@ -153,15 +111,22 @@ class SteamWorksConfig(object):
'-Wno-format',
'-Wno-format-security',
'-Wno-array-bounds',
'-msse',
'-m32',
]
cxx.cxxflags += [
'-std=c++11',
'-std=c++17',
]
have_gcc = cxx.vendor == 'gcc'
have_clang = cxx.vendor == 'clang'
if cxx.target.arch == 'x86':
cxx.cflags += ['-msse', '-m32']
cxx.linkflags += ['-m32']
if cxx.family == 'gcc':
cxx.cflags += ['-mfpmath=sse']
elif cxx.target.arch == 'x86_64':
cxx.cflags += ['-m64']
cxx.linkflags += ['-m64']
have_gcc = cxx.family == 'gcc'
have_clang = cxx.family == 'clang'
if have_clang or (have_gcc and cxx.version >= '4'):
cxx.cflags += ['-fvisibility=hidden']
cxx.cxxflags += ['-fvisibility-inlines-hidden']
@@ -179,17 +144,13 @@ class SteamWorksConfig(object):
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']
cxx.linkflags += ['-m32']
cxx.cxxflags += [
'-fno-exceptions',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual',
]
if have_gcc:
cxx.cflags += ['-mfpmath=sse']
elif cxx.vendor == 'msvc':
elif cxx.like('msvc'):
if builder.options.debug == '1':
cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
@@ -208,9 +169,10 @@ class SteamWorksConfig(object):
'/EHsc',
'/GR-',
'/TP',
'/std:c++17',
]
cxx.linkflags += [
'/MACHINE:X86',
'/MACHINE:X64' if cxx.target.arch == 'x86_64' else '/MACHINE:X86',
'/SUBSYSTEM:WINDOWS',
'kernel32.lib',
'user32.lib',
@@ -244,27 +206,17 @@ class SteamWorksConfig(object):
cxx.cflags += ['/d2Zi+']
# This needs to be after our optimization flags which could otherwise disable it.
if cxx.vendor == 'msvc':
if cxx.like('msvc'):
# Don't omit the frame pointer.
cxx.cflags += ['/Oy-']
# Platform-specifics
if cxx.target.platform == 'linux':
cxx.defines += ['_LINUX', 'POSIX']
if cxx.vendor == 'gcc':
if cxx.family == 'gcc':
cxx.linkflags += ['-static-libgcc']
elif cxx.vendor == 'clang':
elif cxx.family == 'clang':
cxx.linkflags += ['-lgcc_eh']
elif cxx.target.platform == 'mac':
cxx.defines += ['OSX', '_OSX', 'POSIX']
cxx.cflags += ['-mmacosx-version-min=10.5']
cxx.linkflags += [
'-mmacosx-version-min=10.5',
'-arch', 'i386',
'-static',
'-stdlib=libc++'
]
cxx.cxxflags += ['-stdlib=libstdc++']
elif cxx.target.platform == 'windows':
cxx.defines += ['WIN32', '_WINDOWS']
@@ -274,16 +226,15 @@ class SteamWorksConfig(object):
os.path.join(context.currentSourcePath, 'sdk'),
os.path.join(self.sm_root, 'public'),
os.path.join(self.sm_root, 'public', 'extensions'),
os.path.join(self.sm_root, 'public', 'sourcepawn'),
os.path.join(self.sm_root, 'sourcepawn', 'include'),
os.path.join(self.sm_root, 'public', 'amtl', 'amtl'),
os.path.join(self.sm_root, 'public', 'amtl'),
]
return compiler
def ConfigureForHL2(self, binary, sdk):
def ConfigureForHL2(self, binary):
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 += [
@@ -291,32 +242,19 @@ class SteamWorksConfig(object):
os.path.join(mms_path, 'sourcehook'),
]
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
compiler.defines += defines
if compiler.like('msvc'):
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
else:
compiler.defines += ['COMPILER_GCC']
return binary
def HL2Library(self, context, name, sdk):
binary = context.compiler.Library(name)
self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(binary, sdk)
def HL2Project(self, context, name):
project = context.LibraryProject(name)
self.ConfigureForExtension(context, context.cxx)
return project
def HL2Config(self, project, cxx, name, sdk):
binary = project.Configure(cxx, name, '{0} - {1}'.format(self.tag, sdk.name))
return self.ConfigureForHL2(binary, sdk)
def HL2Config(self, project, cxx, name):
binary = project.Configure(cxx, name, '{0}'.format(self.tag))
return self.ConfigureForHL2(binary)
SteamWorks = SteamWorksConfig()
SteamWorks.detectSDKs()
SteamWorks.detectDeps()
SteamWorks.configure()
BuildScripts = ['Extension/AMBuilder']
+69 -13
View File
@@ -1,6 +1,51 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
# --- SafetyHook -----------------------------------------------------------------
# The extension's detours use SourceMod's safetyhook-based CDetour, which handles
# both x86 and x86_64, replacing the old x86-only asm trampolines. Build safetyhook
# as a static library straight out of the SourceMod tree.
sh_root = os.path.join(SteamWorks.sm_root, 'public', 'safetyhook')
libsafetyhook = builder.StaticLibraryProject('safetyhook')
libsafetyhook.sources += [
os.path.join(sh_root, 'src', 'allocator.cpp'),
os.path.join(sh_root, 'src', 'easy.cpp'),
os.path.join(sh_root, 'src', 'inline_hook.cpp'),
os.path.join(sh_root, 'src', 'mid_hook.cpp'),
os.path.join(sh_root, 'src', 'utility.cpp'),
os.path.join(sh_root, 'src', 'vmt_hook.cpp'),
os.path.join(sh_root, 'zydis', 'Zydis.c'),
]
sh_binary = libsafetyhook.Configure(builder.cxx, 'safetyhook',
'Release - {0}'.format(builder.cxx.target.arch))
sh_cxx = sh_binary.compiler
# safetyhook is third-party; compile it with its own flag set.
sh_cxx.cxxflags = []
sh_cxx.cflags = []
sh_cxx.defines = []
sh_cxx.includes = []
sh_cxx.cxxincludes = []
if builder.options.debug != '1':
sh_cxx.defines += ['NDEBUG']
if sh_cxx.target.platform == 'windows':
sh_cxx.cflags += ['/W4']
sh_cxx.cflags += ['/MTd' if builder.options.debug == '1' else '/MT']
sh_cxx.cxxflags += ['/EHsc', '/permissive-', '/std:c++17']
sh_binary.sources += [os.path.join(sh_root, 'src', 'os.windows.cpp')]
elif sh_cxx.target.platform == 'linux':
sh_cxx.cflags += ['-fPIC', '-Wall', '-Wno-unused-function', '-Wno-unused-const-variable']
sh_cxx.cflags += ['-m64' if sh_cxx.target.arch == 'x86_64' else '-m32']
sh_cxx.cxxflags += ['-std=c++17', '-Wno-format']
sh_binary.sources += [os.path.join(sh_root, 'src', 'os.linux.cpp')]
sh_cxx.includes += [os.path.join(sh_root, 'include'), os.path.join(sh_root, 'zydis')]
safetyhook_tasks = builder.Add(libsafetyhook)
# --- SteamWorks extension -------------------------------------------------------
project = SteamWorks.HL2Project(builder, 'SteamWorks.ext')
project.sources += [
'extension.cpp',
@@ -16,25 +61,36 @@ project.sources += [
'swhttprequest.cpp',
'swgchooks.cpp',
'sdk/smsdk_ext.cpp',
'CDetour/detours.cpp',
'asm/asm.c'
os.path.join(SteamWorks.sm_root, 'public', 'CDetour', 'detours.cpp'),
]
for sdk_name in SteamWorks.sdks:
sdk = SteamWorks.sdks[sdk_name]
binary = SteamWorks.HL2Config(project, builder.cxx, 'SteamWorks.ext')
binary = SteamWorks.HL2Config(project, builder.cxx, 'SteamWorks.ext', sdk)
# The Steam API headers all come from the SteamWorks SDK; the extension is built
# with META_NO_HL2SDK, so no HL2SDK is required.
binary.compiler.defines += ['META_NO_HL2SDK', 'SOURCEMOD_BUILD', 'VERSION_SAFE_STEAM_API_INTERFACES']
binary.compiler.cxxincludes += [os.path.join(SteamWorks.steamworks_root, 'public', 'steam')]
binary.compiler.cxxincludes += [os.path.join(SteamWorks.sm_root, 'public', 'safetyhook', 'include')]
binary.compiler.defines += ['META_NO_HL2SDK', 'SOURCEMOD_BUILD', 'VERSION_SAFE_STEAM_API_INTERFACES']
binary.compiler.cxxincludes += [os.path.join(SteamWorks.steamworks_root, 'public', 'steam'), os.path.join(sdk.path, 'public', 'steam')];
# Link the matching-arch safetyhook static library.
for task in safetyhook_tasks:
if task.target.arch == binary.compiler.target.arch:
binary.compiler.linkflags += [task.binary]
break
if binary.compiler.target.platform == 'linux':
binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'linux32', 'libsteam_api.so'),;
steamworks_bin = os.path.join(SteamWorks.steamworks_root, 'redistributable_bin')
arch = binary.compiler.target.arch
if binary.compiler.target.platform == 'windows':
binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'steam_api.lib'),;
if binary.compiler.target.platform == 'linux':
if arch == 'x86_64':
binary.compiler.postlink += [os.path.join(steamworks_bin, 'linux64', 'libsteam_api.so')]
else:
binary.compiler.postlink += [os.path.join(steamworks_bin, 'linux32', 'libsteam_api.so')]
if binary.compiler.target.platform == 'mac':
binary.compiler.postlink += os.path.join(SteamWorks.steamworks_root, 'redistributable_bin', 'osx', 'libsteam_api.dylib'),;
if binary.compiler.target.platform == 'windows':
if arch == 'x86_64':
binary.compiler.postlink += [os.path.join(steamworks_bin, 'win64', 'steam_api64.lib')]
else:
binary.compiler.postlink += [os.path.join(steamworks_bin, 'steam_api.lib')]
SteamWorks.extensions += builder.Add(project)
-100
View File
@@ -1,100 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id: detourhelpers.h 248 2008-08-27 00:56:22Z pred $
*/
#ifndef _INCLUDE_SOURCEMOD_DETOURHELPERS_H_
#define _INCLUDE_SOURCEMOD_DETOURHELPERS_H_
#if defined PLATFORM_POSIX
#include <sys/mman.h>
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#define ALIGN(ar) ((long)ar & ~(PAGE_SIZE-1))
#define PAGE_EXECUTE_READWRITE PROT_READ|PROT_WRITE|PROT_EXEC
#endif
struct patch_t
{
patch_t()
{
patch[0] = 0;
bytes = 0;
}
unsigned char patch[20];
size_t bytes;
};
inline void ProtectMemory(void *addr, int length, int prot)
{
#if defined PLATFORM_POSIX
void *addr2 = (void *)ALIGN(addr);
mprotect(addr2, sysconf(_SC_PAGESIZE), prot);
#elif defined PLATFORM_WINDOWS
DWORD old_prot;
VirtualProtect(addr, length, prot, &old_prot);
#endif
}
inline void SetMemPatchable(void *address, size_t size)
{
ProtectMemory(address, (int)size, PAGE_EXECUTE_READWRITE);
}
inline void DoGatePatch(unsigned char *target, void *callback)
{
SetMemPatchable(target, 20);
target[0] = 0xFF; /* JMP */
target[1] = 0x25; /* MEM32 */
*(void **)(&target[2]) = callback;
}
inline void ApplyPatch(void *address, int offset, const patch_t *patch, patch_t *restore)
{
ProtectMemory(address, 20, PAGE_EXECUTE_READWRITE);
unsigned char *addr = (unsigned char *)address + offset;
if (restore)
{
for (size_t i=0; i<patch->bytes; i++)
{
restore->patch[i] = addr[i];
}
restore->bytes = patch->bytes;
}
for (size_t i=0; i<patch->bytes; i++)
{
addr[i] = patch->patch[i];
}
}
#endif //_INCLUDE_SOURCEMOD_DETOURHELPERS_H_
-228
View File
@@ -1,228 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id: detours.cpp 248 2008-08-27 00:56:22Z pred $
*/
#include "detours.h"
#include <asm/asm.h>
ISourcePawnEngine *CDetourManager::spengine = NULL;
IGameConfig *CDetourManager::gameconf = NULL;
void CDetourManager::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
{
CDetourManager::spengine = spengine;
CDetourManager::gameconf = gameconf;
}
CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, const char *signame)
{
CDetour *detour = new CDetour(callbackfunction, trampoline, signame);
if (detour)
{
if (!detour->Init(spengine, gameconf))
{
delete detour;
return NULL;
}
return detour;
}
return NULL;
}
CDetour *CDetourManager::CreateDetour(void *callbackfunction, void **trampoline, void *address)
{
CDetour *detour = new CDetour(callbackfunction, trampoline, address);
if (detour)
{
if (!detour->Init(spengine, gameconf))
{
delete detour;
return NULL;
}
return detour;
}
return NULL;
}
CDetour::CDetour(void *callbackfunction, void **trampoline, const char *signame)
{
enabled = false;
detoured = false;
detour_address = NULL;
detour_trampoline = NULL;
this->signame = signame;
this->address = NULL;
this->detour_callback = callbackfunction;
spengine = NULL;
gameconf = NULL;
this->trampoline = trampoline;
}
CDetour::CDetour(void *callbackfunction, void **trampoline, void *pAddress)
{
enabled = false;
detoured = false;
detour_address = NULL;
detour_trampoline = NULL;
this->signame = NULL;
this->address = pAddress;
this->detour_callback = callbackfunction;
spengine = NULL;
gameconf = NULL;
this->trampoline = trampoline;
}
bool CDetour::Init(ISourcePawnEngine *spengine, IGameConfig *gameconf)
{
this->spengine = spengine;
this->gameconf = gameconf;
if (!CreateDetour())
{
enabled = false;
return enabled;
}
enabled = true;
return enabled;
}
void CDetour::Destroy()
{
DeleteDetour();
delete this;
}
bool CDetour::IsEnabled()
{
return enabled;
}
bool CDetour::CreateDetour()
{
if (signame != NULL && !gameconf->GetMemSig(signame, &detour_address))
{
g_pSM->LogError(myself, "Could not locate %s - Disabling detour", signame);
return false;
}
else if (address != NULL)
{
detour_address = address;
}
if (!detour_address)
{
g_pSM->LogError(myself, "Sigscan for %s failed - Disabling detour to prevent crashes", signame);
return false;
}
detour_restore.bytes = copy_bytes((unsigned char *)detour_address, NULL, OP_JMP_SIZE+1);
/* First, save restore bits */
for (size_t i=0; i<detour_restore.bytes; i++)
{
detour_restore.patch[i] = ((unsigned char *)detour_address)[i];
}
JitWriter wr;
JitWriter *jit = &wr;
jit_uint32_t CodeSize = 0;
wr.outbase = NULL;
wr.outptr = NULL;
jit_rewind:
/* Patch old bytes in */
if (wr.outbase != NULL)
{
copy_bytes((unsigned char *)detour_address, (unsigned char*)wr.outptr, detour_restore.bytes);
}
wr.outptr += detour_restore.bytes;
/* Return to the original function */
jitoffs_t call = IA32_Jump_Imm32(jit, 0);
IA32_Write_Jump32_Abs(jit, call, (unsigned char *)detour_address + detour_restore.bytes);
if (wr.outbase == NULL)
{
CodeSize = wr.get_outputpos();
wr.outbase = (jitcode_t)spengine->AllocatePageMemory(CodeSize);
spengine->SetReadWrite(wr.outbase);
wr.outptr = wr.outbase;
detour_trampoline = wr.outbase;
goto jit_rewind;
}
spengine->SetReadExecute(wr.outbase);
*trampoline = detour_trampoline;
return true;
}
void CDetour::DeleteDetour()
{
if (detoured)
{
DisableDetour();
}
if (detour_trampoline)
{
/* Free the allocated trampoline memory */
spengine->FreePageMemory(detour_trampoline);
detour_trampoline = NULL;
}
}
void CDetour::EnableDetour()
{
if (!detoured)
{
DoGatePatch((unsigned char *)detour_address, &detour_callback);
detoured = true;
}
}
void CDetour::DisableDetour()
{
if (detoured)
{
/* Remove the patch */
ApplyPatch(detour_address, 0, &detour_restore, NULL);
detoured = false;
}
}
-249
View File
@@ -1,249 +0,0 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id: detours.h 257 2008-09-23 03:12:13Z pred $
*/
#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_
#define _INCLUDE_SOURCEMOD_DETOURS_H_
#include "smsdk_ext.h"
#include <jit/jit_helpers.h>
#include <jit/x86/x86_macros.h>
#include "detourhelpers.h"
/**
* CDetours class for SourceMod Extensions by pRED*
* detourhelpers.h entirely stolen from CSS:DM and were written by BAILOPAN (I assume).
* asm.h/c from devmaster.net (thanks cybermind) edited by pRED* to handle gcc -fPIC thunks correctly
* Concept by Nephyrin Zey (http://www.doublezen.net/) and Windows Detour Library (http://research.microsoft.com/sn/detours/)
* Member function pointer ideas by Don Clugston (http://www.codeproject.com/cpp/FastDelegate.asp)
*/
#define DETOUR_MEMBER_CALL(name) (this->*name##_Actual)
#define DETOUR_STATIC_CALL(name) (name##_Actual)
#define DETOUR_DECL_STATIC0(name, ret) \
ret (*name##_Actual)(void) = NULL; \
ret name(void)
#define DETOUR_DECL_STATIC1(name, ret, p1type, p1name) \
ret (*name##_Actual)(p1type) = NULL; \
ret name(p1type p1name)
#define DETOUR_DECL_STATIC4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \
ret (*name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name)
#define DETOUR_DECL_STATIC6(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name) \
ret (*name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type) = NULL; \
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name)
#define DETOUR_DECL_MEMBER0(name, ret) \
class name##Class \
{ \
public: \
ret name(); \
static ret (name##Class::* name##_Actual)(void); \
}; \
ret (name##Class::* name##Class::name##_Actual)(void) = NULL; \
ret name##Class::name()
#define DETOUR_DECL_MEMBER1(name, ret, p1type, p1name) \
class name##Class \
{ \
public: \
ret name(p1type p1name); \
static ret (name##Class::* name##_Actual)(p1type); \
}; \
ret (name##Class::* name##Class::name##_Actual)(p1type) = NULL; \
ret name##Class::name(p1type p1name)
#define DETOUR_DECL_MEMBER2(name, ret, p1type, p1name, p2type, p2name) \
class name##Class \
{ \
public: \
ret name(p1type p1name, p2type p2name); \
static ret (name##Class::* name##_Actual)(p1type, p2type); \
}; \
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type) = NULL; \
ret name##Class::name(p1type p1name, p2type p2name)
#define DETOUR_DECL_MEMBER3(name, ret, p1type, p1name, p2type, p2name, p3type, p3name) \
class name##Class \
{ \
public: \
ret name(p1type p1name, p2type p2name, p3type p3name); \
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type); \
}; \
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type) = NULL; \
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name)
#define DETOUR_DECL_MEMBER4(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name) \
class name##Class \
{ \
public: \
ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name); \
static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type); \
}; \
ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type) = NULL; \
ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name)
#define GET_MEMBER_CALLBACK(name) (void *)GetCodeAddress(&name##Class::name)
#define GET_MEMBER_TRAMPOLINE(name) (void **)(&name##Class::name##_Actual)
#define GET_STATIC_CALLBACK(name) (void *)&name
#define GET_STATIC_TRAMPOLINE(name) (void **)&name##_Actual
#define DETOUR_CREATE_MEMBER(name, gamedata) CDetourManager::CreateDetour(GET_MEMBER_CALLBACK(name), GET_MEMBER_TRAMPOLINE(name), gamedata);
#define DETOUR_CREATE_STATIC(name, gamedata) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), gamedata);
#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address);
class GenericClass {};
typedef void (GenericClass::*VoidFunc)();
inline void *GetCodeAddr(VoidFunc mfp)
{
return *(void **)&mfp;
}
/**
* Converts a member function pointer to a void pointer.
* This relies on the assumption that the code address lies at mfp+0
* This is the case for both g++ and later MSVC versions on non virtual functions but may be different for other compilers
* Based on research by Don Clugston : http://www.codeproject.com/cpp/FastDelegate.asp
*/
#define GetCodeAddress(mfp) GetCodeAddr(reinterpret_cast<VoidFunc>(mfp))
class CDetourManager;
class CDetour
{
public:
bool IsEnabled();
/**
* These would be somewhat self-explanatory I hope
*/
void EnableDetour();
void DisableDetour();
void Destroy();
friend class CDetourManager;
protected:
CDetour(void *callbackfunction, void **trampoline, const char *signame);
CDetour(void *callbackfunction, void **trampoline, void *address);
bool Init(ISourcePawnEngine *spengine, IGameConfig *gameconf);
private:
/* These create/delete the allocated memory */
bool CreateDetour();
void DeleteDetour();
bool enabled;
bool detoured;
patch_t detour_restore;
/* Address of the detoured function */
void *detour_address;
/* Address of the allocated trampoline function */
void *detour_trampoline;
/* Address of the callback handler */
void *detour_callback;
/* The function pointer used to call our trampoline */
void **trampoline;
const char *signame;
void *address;
ISourcePawnEngine *spengine;
IGameConfig *gameconf;
};
class CDetourManager
{
public:
static void Init(ISourcePawnEngine *spengine, IGameConfig *gameconf);
/**
* Creates a new detour
*
* @param callbackfunction Void pointer to your detour callback function.
* @param trampoline Address of the trampoline pointer
* @param signame Section name containing a signature to fetch from the gamedata file.
* @return A new CDetour pointer to control your detour.
*
* Example:
*
* CBaseServer::ConnectClient(netadr_s &, int, int, int, char const*, char const*, char const*, int)
*
* Define a new class with the required function and a member function pointer to the same type:
*
* class CBaseServerDetour
* {
* public:
* bool ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int);
* static bool (CBaseServerDetour::* ConnectClient_Actual)(void *netaddr_s, int, int, int, char const*, char const*, char const*, int);
* }
*
* void *callbackfunc = GetCodeAddress(&CBaseServerDetour::ConnectClient);
* void **trampoline = (void **)(&CBaseServerDetour::ConnectClient_Actual);
*
* Creation:
* CDetourManager::CreateDetour(callbackfunc, trampoline, "ConnectClient");
*
* Usage:
*
* CBaseServerDetour::ConnectClient(void *netaddr_s, int, int, int, char const*, char const*, char const*, int)
* {
* //pre hook code
* bool result = (this->*ConnectClient_Actual)(netaddr_s, rest of params);
* //post hook code
* return result;
* }
*
* Note we changed the netadr_s reference into a void* to avoid needing to define the type
*/
static CDetour *CreateDetour(void *callbackfunction, void **trampoline, const char *signame);
static CDetour *CreateDetour(void *callbackfunction, void **trampoline, void *address);
friend class CBlocker;
friend class CDetour;
private:
static ISourcePawnEngine *spengine;
static IGameConfig *gameconf;
};
#endif // _INCLUDE_SOURCEMOD_DETOURS_H_
-252
View File
@@ -1,252 +0,0 @@
# (C)2004-2010 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
###########################################
### EDIT THESE PATHS FOR YOUR OWN SETUP ###
###########################################
SMSDK = ../..
HL2SDK_ORIG = ../../../hl2sdk
HL2SDK_OB = ../../../hl2sdk-ob
HL2SDK_CSS = ../../../hl2sdk-css
HL2SDK_OB_VALVE = ../../../hl2sdk-2013
HL2SDK_L4D = ../../../hl2sdk-l4d
HL2SDK_L4D2 = ../../../hl2sdk-l4d2
HL2SDK_CSGO = ../../../hl2sdk-csgo
MMSOURCE19 = ../../../mmsource-1.9
STEAMWORKS = ../../../opensteamworks
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
PROJECT = SteamWorks
#Uncomment for Metamod: Source enabled extension
#USEMETA = true
USESH = true
USECD = true
OBJECTS = sdk/smsdk_ext.cpp extension.cpp swgameserver.cpp swgamedata.cpp swforwards.cpp gsnatives.cpp swgshooks.cpp swgsdetours.cpp ssnatives.cpp swhttp.cpp swhttprequest.cpp
ifeq "$(USECD)" "true"
OBJECTS += CDetour/detours.cpp asm/asm.c
endif
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc
CPP_OSX = clang
##########################
### SDK CONFIGURATIONS ###
##########################
override ENGSET = false
# Check for valid list of engines
ifneq (,$(filter original orangebox orangeboxvalve css left4dead left4dead2 csgo,$(ENGINE)))
override ENGSET = true
endif
ifeq "$(ENGINE)" "original"
HL2SDK = $(HL2SDK_ORIG)
CFLAGS += -DSOURCE_ENGINE=1
endif
ifeq "$(ENGINE)" "orangebox"
HL2SDK = $(HL2SDK_OB)
CFLAGS += -DSOURCE_ENGINE=3
endif
ifeq "$(ENGINE)" "css"
HL2SDK = $(HL2SDK_CSS)
CFLAGS += -DSOURCE_ENGINE=6
endif
ifeq "$(ENGINE)" "orangeboxvalve"
HL2SDK = $(HL2SDK_OB_VALVE)
CFLAGS += -DSOURCE_ENGINE=7
endif
ifeq "$(ENGINE)" "left4dead"
HL2SDK = $(HL2SDK_L4D)
CFLAGS += -DSOURCE_ENGINE=8
endif
ifeq "$(ENGINE)" "left4dead2"
HL2SDK = $(HL2SDK_L4D2)
CFLAGS += -DSOURCE_ENGINE=9
endif
ifeq "$(ENGINE)" "csgo"
HL2SDK = $(HL2SDK_CSGO)
CFLAGS += -DSOURCE_ENGINE=12
endif
HL2PUB = $(HL2SDK)/public
ifeq "$(ENGINE)" "original"
INCLUDE += -I$(HL2SDK)/public/dlls
METAMOD = $(MMSOURCE19)/core-legacy
else
INCLUDE += -I$(HL2SDK)/public/game/server
METAMOD = $(MMSOURCE19)/core
endif
OS := $(shell uname -s)
ifeq "$(OS)" "Darwin"
LIB_EXT = dylib
HL2LIB = $(HL2SDK)/lib/mac
else
LIB_EXT = so
ifeq "$(ENGINE)" "original"
HL2LIB = $(HL2SDK)/linux_sdk
else
HL2LIB = $(HL2SDK)/lib/linux
endif
endif
# if ENGINE is original or OB
ifneq (,$(filter original orangebox,$(ENGINE)))
LIB_SUFFIX = _i486.$(LIB_EXT)
else
LIB_PREFIX = lib
LIB_SUFFIX = .$(LIB_EXT)
endif
INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
ifeq "$(USEMETA)" "true"
LINK_HL2 = $(HL2LIB)/tier1_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX)
ifeq "$(ENGINE)" "csgo"
LINK_HL2 += $(HL2LIB)/interfaces_i486.a
endif
LINK += $(LINK_HL2)
INCLUDE += -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) \
-I$(METAMOD)/sourcehook
CFLAGS += -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
endif
ifeq "$(USESH)" "true"
INCLUDE += -I$(METAMOD) -I$(METAMOD)/sourcehook
CFLAGS += -DMETA_NO_HL2SDK
endif
LINK += -m32 -lm -ldl
LINK += $(STEAMWORKS)/redistributable_bin/linux32/libsteam_api.so
CFLAGS += -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -DCOMPILER_GCC -Wall -Werror \
-Wno-overloaded-virtual -Wno-switch -Wno-unused -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -m32
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
INCLUDE += -I$(STEAMWORKS)/public/steam
INCLUDE += -I$(HL2SDK)/public/steam
CFLAGS += -DVERSION_SAFE_STEAM_API_INTERFACES
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
BINARY = $(PROJECT).ext.$(LIB_EXT)
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS += $(C_OPT_FLAGS)
endif
ifeq "$(USEMETA)" "true"
BIN_DIR := $(BIN_DIR).$(ENGINE)
endif
ifeq "$(OS)" "Darwin"
CPP = $(CPP_OSX)
LIB_EXT = dylib
CFLAGS += -DOSX -D_OSX
LINK += -dynamiclib -lstdc++ -mmacosx-version-min=10.5
else
LIB_EXT = so
CFLAGS += -D_LINUX
LINK += -shared
endif
IS_CLANG := $(shell $(CPP) --version | head -1 | grep clang > /dev/null && echo "1" || echo "0")
ifeq "$(IS_CLANG)" "1"
CPP_MAJOR := $(shell $(CPP) --version | grep clang | sed "s/.*version \([0-9]\)*\.[0-9]*.*/\1/")
CPP_MINOR := $(shell $(CPP) --version | grep clang | sed "s/.*version [0-9]*\.\([0-9]\)*.*/\1/")
else
CPP_MAJOR := $(shell $(CPP) -dumpversion >&1 | cut -b1)
CPP_MINOR := $(shell $(CPP) -dumpversion >&1 | cut -b3)
endif
# If not clang
ifeq "$(IS_CLANG)" "0"
CFLAGS += -mfpmath=sse
endif
# Clang || GCC >= 4
ifeq "$(shell expr $(IS_CLANG) \| $(CPP_MAJOR) \>= 4)" "1"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
# Clang >= 3 || GCC >= 4.7
ifeq "$(shell expr $(IS_CLANG) \& $(CPP_MAJOR) \>= 3 \| $(CPP_MAJOR) \>= 4 \& $(CPP_MINOR) \>= 7)" "1"
CFLAGS += -Wno-delete-non-virtual-dtor
endif
# OS is Linux and not using clang
ifeq "$(shell expr $(OS) \= Linux \& $(IS_CLANG) \= 0)" "1"
LINK += -static-libgcc
endif
OBJ_BIN := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
# This will break if we include other Makefiles, but is fine for now. It allows
# us to make a copy of this file that uses altered paths (ie. Makefile.mine)
# or other changes without mucking up the original.
MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
all: check
mkdir -p $(BIN_DIR)/sdk
mkdir -p $(BIN_DIR)/CDetour
if [ "$(USEMETA)" = "true" ]; then \
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX); \
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX); \
fi
$(MAKE) -f $(MAKEFILE_NAME) extension
check:
if [ "$(USEMETA)" = "true" ] && [ "$(ENGSET)" = "false" ]; then \
echo "You must supply one of the following values for ENGINE:"; \
echo "csgo, left4dead2, left4dead, css, orangeboxvalve, orangebox, or original"; \
exit 1; \
fi
extension: check $(OBJ_BIN)
$(CPP) $(INCLUDE) $(OBJ_BIN) $(LINK) -o $(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f $(MAKEFILE_NAME) all DEBUG=true
default: all
clean: check
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/sdk/*.o
rm -rf $(BIN_DIR)/$(BINARY)
-418
View File
@@ -1,418 +0,0 @@
#include "asm.h"
#ifndef WIN32
#define _GNU_SOURCE
#include <dlfcn.h>
#include <string.h>
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define IA32_MOV_REG_IMM 0xB8 // encoding is +r <imm32>
#endif
/**
* Checks if a call to a fpic thunk has just been written into dest.
* If found replaces it with a direct mov that sets the required register to the value of pc.
*
* @param dest Destination buffer where a call opcode + addr (5 bytes) has just been written.
* @param pc The program counter value that needs to be set (usually the next address from the source).
* @noreturn
*/
void check_thunks(unsigned char *dest, unsigned char *pc)
{
#if defined WIN32
return;
#else
/* Step write address back 4 to the start of the function address */
unsigned char *writeaddr = dest - 4;
unsigned char *calloffset = *(unsigned char **)writeaddr;
unsigned char *calladdr = (unsigned char *)(dest + (unsigned int)calloffset);
/* Lookup name of function being called */
if ((*calladdr == 0x8B) && (*(calladdr+2) == 0x24) && (*(calladdr+3) == 0xC3))
{
//a thunk maybe?
char movByte = IA32_MOV_REG_IMM;
/* Calculate the correct mov opcode */
switch (*(calladdr+1))
{
case 0x04:
{
movByte += REG_EAX;
break;
}
case 0x1C:
{
movByte += REG_EBX;
break;
}
case 0x0C:
{
movByte += REG_ECX;
break;
}
case 0x14:
{
movByte += REG_EDX;
break;
}
default:
{
break;
}
}
/* Move our write address back one to where the call opcode was */
writeaddr--;
/* Write our mov */
*writeaddr = movByte;
writeaddr++;
/* Write the value - The provided program counter value */
*(void **)writeaddr = (void *)pc;
writeaddr += 4;
}
return;
#endif
}
//if dest is NULL, returns minimum number of bytes needed to be copied
//if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs
//http://www.devmaster.net/forums/showthread.php?t=2311
int copy_bytes(unsigned char *func, unsigned char* dest, int required_len) {
int bytecount = 0;
while(bytecount < required_len && *func != 0xCC)
{
// prefixes F0h, F2h, F3h, 66h, 67h, D8h-DFh, 2Eh, 36h, 3Eh, 26h, 64h and 65h
int operandSize = 4;
int FPU = 0;
int twoByte = 0;
unsigned char opcode = 0x90;
unsigned char modRM = 0xFF;
while(*func == 0xF0 ||
*func == 0xF2 ||
*func == 0xF3 ||
(*func & 0xFC) == 0x64 ||
(*func & 0xF8) == 0xD8 ||
(*func & 0x7E) == 0x62)
{
if(*func == 0x66)
{
operandSize = 2;
}
else if((*func & 0xF8) == 0xD8)
{
FPU = *func;
if (dest)
*dest++ = *func++;
else
func++;
bytecount++;
break;
}
if (dest)
*dest++ = *func++;
else
func++;
bytecount++;
}
// two-byte opcode byte
if(*func == 0x0F)
{
twoByte = 1;
if (dest)
*dest++ = *func++;
else
func++;
bytecount++;
}
// opcode byte
opcode = *func++;
if (dest) *dest++ = opcode;
bytecount++;
// mod R/M byte
modRM = 0xFF;
if(FPU)
{
if((opcode & 0xC0) != 0xC0)
{
modRM = opcode;
}
}
else if(!twoByte)
{
if((opcode & 0xC4) == 0x00 ||
((opcode & 0xF4) == 0x60 && ((opcode & 0x0A) == 0x02 || (opcode & 0x09) == 0x09)) ||
(opcode & 0xF0) == 0x80 ||
((opcode & 0xF8) == 0xC0 && (opcode & 0x0E) != 0x02) ||
(opcode & 0xFC) == 0xD0 ||
(opcode & 0xF6) == 0xF6)
{
modRM = *func++;
if (dest) *dest++ = modRM;
bytecount++;
}
}
else
{
if(((opcode & 0xF0) == 0x00 && (opcode & 0x0F) >= 0x04 && (opcode & 0x0D) != 0x0D) ||
(opcode & 0xF0) == 0x30 ||
opcode == 0x77 ||
(opcode & 0xF0) == 0x80 ||
((opcode & 0xF0) == 0xA0 && (opcode & 0x07) <= 0x02) ||
(opcode & 0xF8) == 0xC8)
{
// No mod R/M byte
}
else
{
modRM = *func++;
if (dest) *dest++ = modRM;
bytecount++;
}
}
// SIB
if((modRM & 0x07) == 0x04 &&
(modRM & 0xC0) != 0xC0)
{
if (dest)
*dest++ = *func++; //SIB
else
func++;
bytecount++;
}
// mod R/M displacement
// Dword displacement, no base
if((modRM & 0xC5) == 0x05) {
if (dest) {
*(unsigned int*)dest = *(unsigned int*)func;
dest += 4;
}
func += 4;
bytecount += 4;
}
// Byte displacement
if((modRM & 0xC0) == 0x40) {
if (dest)
*dest++ = *func++;
else
func++;
bytecount++;
}
// Dword displacement
if((modRM & 0xC0) == 0x80) {
if (dest) {
*(unsigned int*)dest = *(unsigned int*)func;
dest += 4;
}
func += 4;
bytecount += 4;
}
// immediate
if(FPU)
{
// Can't have immediate operand
}
else if(!twoByte)
{
if((opcode & 0xC7) == 0x04 ||
(opcode & 0xFE) == 0x6A || // PUSH/POP/IMUL
(opcode & 0xF0) == 0x70 || // Jcc
opcode == 0x80 ||
opcode == 0x83 ||
(opcode & 0xFD) == 0xA0 || // MOV
opcode == 0xA8 || // TEST
(opcode & 0xF8) == 0xB0 || // MOV
(opcode & 0xFE) == 0xC0 || // RCL
opcode == 0xC6 || // MOV
opcode == 0xCD || // INT
(opcode & 0xFE) == 0xD4 || // AAD/AAM
(opcode & 0xF8) == 0xE0 || // LOOP/JCXZ
opcode == 0xEB ||
(opcode == 0xF6 && (modRM & 0x30) == 0x00)) // TEST
{
if (dest)
*dest++ = *func++;
else
func++;
bytecount++;
}
else if((opcode & 0xF7) == 0xC2) // RET
{
if (dest) {
*(unsigned short*)dest = *(unsigned short*)func;
dest += 2;
}
func += 2;
bytecount += 2;
}
else if((opcode & 0xFC) == 0x80 ||
(opcode & 0xC7) == 0x05 ||
(opcode & 0xF8) == 0xB8 ||
(opcode & 0xFE) == 0xE8 || // CALL/Jcc
(opcode & 0xFE) == 0x68 ||
(opcode & 0xFC) == 0xA0 ||
(opcode & 0xEE) == 0xA8 ||
opcode == 0xC7 ||
(opcode == 0xF7 && (modRM & 0x30) == 0x00))
{
if (dest) {
//Fix CALL/JMP offset
if ((opcode & 0xFE) == 0xE8) {
if (operandSize == 4)
{
*(long*)dest = ((func + *(long*)func) - dest);
//pRED* edit. func is the current address of the call address, +4 is the next instruction, so the value of $pc
check_thunks(dest+4, func+4);
}
else
*(short*)dest = ((func + *(short*)func) - dest);
} else {
if (operandSize == 4)
*(unsigned long*)dest = *(unsigned long*)func;
else
*(unsigned short*)dest = *(unsigned short*)func;
}
dest += operandSize;
}
func += operandSize;
bytecount += operandSize;
}
}
else
{
if(opcode == 0xBA || // BT
opcode == 0x0F || // 3DNow!
(opcode & 0xFC) == 0x70 || // PSLLW
(opcode & 0xF7) == 0xA4 || // SHLD
opcode == 0xC2 ||
opcode == 0xC4 ||
opcode == 0xC5 ||
opcode == 0xC6)
{
if (dest)
*dest++ = *func++;
else
func++;
}
else if((opcode & 0xF0) == 0x80) // Jcc -i
{
if (dest) {
if (operandSize == 4)
*(unsigned long*)dest = *(unsigned long*)func;
else
*(unsigned short*)dest = *(unsigned short*)func;
dest += operandSize;
}
func += operandSize;
bytecount += operandSize;
}
}
}
return bytecount;
}
//insert a specific JMP instruction at the given location
void inject_jmp(void* src, void* dest) {
*(unsigned char*)src = OP_JMP;
*(long*)((unsigned char*)src+1) = (long)((unsigned char*)dest - ((unsigned char*)src + OP_JMP_SIZE));
}
//fill a given block with NOPs
void fill_nop(void* src, unsigned int len) {
unsigned char* src2 = (unsigned char*)src;
while (len) {
*src2++ = OP_NOP;
--len;
}
}
void* eval_jump(void* src) {
unsigned char* addr = (unsigned char*)src;
if (!addr) return 0;
//import table jump
if (addr[0] == OP_PREFIX && addr[1] == OP_JMP_SEG) {
addr += 2;
addr = *(unsigned char**)addr;
//TODO: if addr points into the IAT
return *(void**)addr;
}
//8bit offset
else if (addr[0] == OP_JMP_BYTE) {
addr = &addr[OP_JMP_BYTE_SIZE] + *(char*)&addr[1];
//mangled 32bit jump?
if (addr[0] == OP_JMP) {
addr = addr + *(int*)&addr[1];
}
return addr;
}
/*
//32bit offset
else if (addr[0] == OP_JMP) {
addr = &addr[OP_JMP_SIZE] + *(int*)&addr[1];
}
*/
return addr;
}
/*
from ms detours package
static bool detour_is_imported(PBYTE pbCode, PBYTE pbAddress)
{
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery((PVOID)pbCode, &mbi, sizeof(mbi));
__try {
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
return false;
}
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
pDosHeader->e_lfanew);
if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
return false;
}
if (pbAddress >= ((PBYTE)pDosHeader +
pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) &&
pbAddress < ((PBYTE)pDosHeader +
pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress +
pNtHeader->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size)) {
return true;
}
return false;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
return false;
}
}
*/
-40
View File
@@ -1,40 +0,0 @@
#ifndef __ASM_H__
#define __ASM_H__
#define OP_JMP 0xE9
#define OP_JMP_SIZE 5
#define OP_NOP 0x90
#define OP_NOP_SIZE 1
#define OP_PREFIX 0xFF
#define OP_JMP_SEG 0x25
#define OP_JMP_BYTE 0xEB
#define OP_JMP_BYTE_SIZE 2
#ifdef __cplusplus
extern "C" {
#endif
void check_thunks(unsigned char *dest, unsigned char *pc);
//if dest is NULL, returns minimum number of bytes needed to be copied
//if dest is not NULL, it will copy the bytes to dest as well as fix CALLs and JMPs
//http://www.devmaster.net/forums/showthread.php?t=2311
int copy_bytes(unsigned char *func, unsigned char* dest, int required_len);
//insert a specific JMP instruction at the given location
void inject_jmp(void* src, void* dest);
//fill a given block with NOPs
void fill_nop(void* src, unsigned int len);
//evaluate a JMP at the target
void* eval_jump(void* src);
#ifdef __cplusplus
}
#endif
#endif //__ASM_H__
+2 -8
View File
@@ -192,15 +192,9 @@ static cell_t sm_ClearRules(IPluginContext *pContext, const cell_t *params)
static cell_t sm_ForceHeartbeat(IPluginContext *pContext, const cell_t *params)
{
ISteamGameServer *pServer = GetGSPointer();
if (pServer == NULL)
{
/* Deprecated no-op: newer Steamworks SDKs removed ISteamGameServer::ForceHeartbeat();
server list heartbeats are now sent implicitly by Steam. */
return 0;
}
pServer->ForceHeartbeat();
return 1;
}
static cell_t sm_UserHasLicenseForApp(IPluginContext *pContext, const cell_t *params)
+6
View File
@@ -21,6 +21,12 @@
#include "steam_gameserver.h"
#include "CDetour/detours.h"
/* SourceMod's safetyhook-based CDetour doesn't ship the "fixed address" helper the
old vendored copy had, so define it in terms of the address overload it does expose. */
#ifndef DETOUR_CREATE_STATIC_FIXED
#define DETOUR_CREATE_STATIC_FIXED(name, address) CDetourManager::CreateDetour(GET_STATIC_CALLBACK(name), GET_STATIC_TRAMPOLINE(name), address);
#endif
class SteamWorksGSDetours
{
public:
+11 -2
View File
@@ -20,6 +20,15 @@
#include <cstdio>
/* SourceMod 1.13 (extension API 9) changed IPluginManager::FindPluginByContext()
to take an IPluginContext* directly; older SM (API 8) takes the low-level
sp_context_t* from IPluginContext::GetContext(). */
#if SMINTERFACE_EXTENSIONAPI_VERSION >= 9
#define SW_PLUGIN_CTX(ctx) (ctx)
#else
#define SW_PLUGIN_CTX(ctx) ((ctx)->GetContext())
#endif
static ISteamHTTP *GetHTTPPointer(void)
{
return g_SteamWorks.pSWGameServer->GetHTTP();
@@ -220,7 +229,7 @@ static cell_t sm_SetCallbacks(IPluginContext *pContext, const cell_t *params)
IPlugin *pPlugin;
if (params[5] == BAD_HANDLE)
{
pPlugin = plsys->FindPluginByContext(pContext->GetContext());
pPlugin = plsys->FindPluginByContext(SW_PLUGIN_CTX(pContext));
} else {
HandleError err;
pPlugin = plsys->PluginFromHandle(params[5], &err);
@@ -518,7 +527,7 @@ static cell_t sm_GetHTTPResponseBodyCallback(IPluginContext *pContext, const cel
IPlugin *pPlugin;
if (params[4] == BAD_HANDLE)
{
pPlugin = plsys->FindPluginByContext(pContext->GetContext());
pPlugin = plsys->FindPluginByContext(SW_PLUGIN_CTX(pContext));
} else {
HandleError err;
pPlugin = plsys->PluginFromHandle(params[4], &err);
+1
View File
@@ -222,6 +222,7 @@ native bool:SteamWorks_SetMapName(const String:sMapName[]);
native bool:SteamWorks_IsConnected();
native bool:SteamWorks_SetRule(const String:sKey[], const String:sValue[]);
native bool:SteamWorks_ClearRules();
#pragma deprecated This function is deprecated in the SDK and no longer does anything in this extension
native bool:SteamWorks_ForceHeartbeat();
native bool:SteamWorks_GetUserGroupStatus(client, groupid);
native bool:SteamWorks_GetUserGroupStatusAuthID(authid, groupid);
+10 -4
View File
@@ -3,9 +3,16 @@ import os
builder.SetBuildFolder('package')
# 64-bit extensions live under an x64/ subfolder; 32-bit sit directly in
# extensions/. Only one architecture is built per configure, so pick the
# matching destination here.
if builder.cxx.target.arch == 'x86_64':
ext_folder = 'addons/sourcemod/extensions/x64'
else:
ext_folder = 'addons/sourcemod/extensions'
folder_list = [
'addons/sourcemod/extensions',
'addons/sourcemod/scripting',
ext_folder,
'addons/sourcemod/scripting/include',
]
@@ -16,7 +23,7 @@ for folder in folder_list:
folder_map[folder] = builder.AddFolder(norm_folder)
for extension in SteamWorks.extensions:
builder.AddCopy(extension.binary, folder_map['addons/sourcemod/extensions'])
builder.AddCopy(extension.binary, folder_map[ext_folder])
# Do all straight-up file copies from the source tree.
def CopyFiles(src, dest, files):
@@ -27,5 +34,4 @@ def CopyFiles(src, dest, files):
source_path = os.path.join(builder.sourcePath, src, source_file)
builder.AddCopy(source_path, dest_entry)
CopyFiles('Pawn', 'addons/sourcemod/scripting', ['swag.sp'])
CopyFiles('Pawn/includes', 'addons/sourcemod/scripting/include', ['SteamWorks.inc'])
-174
View File
@@ -1,174 +0,0 @@
#!/usr/bin/perl
use strict;
use Cwd;
package Build;
our $SVN = "/usr/bin/svn";
our $SVN_USER = 'dvander';
our $SVN_ARGS = '';
sub GitRevNum
{
my ($path) = (@_);
my ($cd, $text, $rev);
$cd = Cwd::cwd();
chdir($path);
$text = `git rev-list --count HEAD`;
chdir($cd);
chomp $text;
if ($text =~ /^(\d+)/) {
return $1;
}
return 0;
}
sub HgRevNum
{
my ($path) = (@_);
my ($cd, $text, $rev);
$cd = Cwd::cwd();
chdir($path);
$text = `hg identify -n`;
chdir($cd);
chomp $text;
if ($text =~ /^(\d+)/)
{
return $1;
}
return 0;
}
sub SvnRevNum
{
my ($str)=(@_);
my $data = Command('svnversion -c ' . $str);
if ($data =~ /(\d+):(\d+)/)
{
return $2;
} elsif ($data =~ /(\d+)/) {
return $1;
} else {
return 0;
}
}
sub ProductVersion
{
my ($file) = (@_);
my ($version);
open(FILE, $file) or die "Could not open $file: $!\n";
$version = <FILE>;
close(FILE);
chomp $version;
return $version;
}
sub Delete
{
my ($str)=(@_);
if ($^O =~ /MSWin/)
{
Command("del /S /F /Q \"$str\"");
Command("rmdir /S /Q \"$str\"");
} else {
Command("rm -rf $str");
}
return !(-e $str);
}
sub Copy
{
my ($src,$dest)=(@_);
if ($^O =~ /MSWin/)
{
Command("copy \"$src\" \"$dest\" /y");
} else {
Command("cp \"$src\" \"$dest\"");
}
return (-e $dest);
}
sub Move
{
my ($src,$dest)=(@_);
if ($^O =~ /MSWin/)
{
Command("move \"$src\" \"$dest\"");
} else {
Command("mv \"$src\" \"$dest\"");
}
return (-e $dest);
}
sub Command
{
my($cmd)=(@_);
print "$cmd\n";
return `$cmd`;
}
sub PathFormat
{
my ($str)=(@_);
if ($^O =~ /MSWin/)
{
$str =~ s#/#\\#g;
} else {
$str =~ s#\\#/#g;
}
return $str;
}
sub SVN_Remove
{
my ($file)=(@_);
my ($path, $name);
if ($^O =~ /MSWin/)
{
($path, $name) = ($file =~ /(.+)\/([^\/]+)$/);
} else {
($path, $name) = ($file =~ /(.+)\\([^\\]+)$/);
}
my $dir = Cwd::cwd();
chdir($path);
Command($SVN . ' ' . $SVN_ARGS . ' delete ' . $name);
chdir($dir);
}
sub SVN_Add
{
my ($file)=(@_);
my ($path, $name);
if ($^O =~ /MSWin/)
{
($path, $name) = ($file =~ /(.+)\/([^\/]+)$/);
} else {
($path, $name) = ($file =~ /(.+)\\([^\\]+)$/);
}
my $dir = Cwd::cwd();
chdir($path);
Command($SVN . ' ' . $SVN_ARGS . ' add ' . $name);
chdir($dir);
}
sub GetBuildType
{
my ($file)=(@_);
my ($type);
open(TYPE, $file) or die("Could not open file: $!\n");
$type = <TYPE>;
close(TYPE);
chomp $type;
return $type;
}
return 1;
-106
View File
@@ -1,106 +0,0 @@
# Pastebin eziGmKtQ
#!/usr/bin/perl
use strict;
use Cwd;
use File::Basename;
use File::Copy;
use File::Path;
use Net::FTP;
my ($ftp_file, $ftp_host, $ftp_user, $ftp_pass, $ftp_path, $tag);
$ftp_file = shift;
$tag = shift;
open(FTP, $ftp_file) or die "Unable to read FTP config file $ftp_file: $!\n";
$ftp_host = <FTP>;
$ftp_user = <FTP>;
$ftp_pass = <FTP>;
$ftp_path = <FTP>;
close(FTP);
chomp $ftp_host;
chomp $ftp_user;
chomp $ftp_pass;
chomp $ftp_path;
my ($myself, $path) = fileparse($0);
chdir($path);
require 'helpers.pm';
my ($version, $ext);
$version .= '-git' . Build::GitRevNum('.');
# Append OS to package version
if ($^O eq "darwin")
{
$ext = ".dylib";
$version .= '-mac';
}
elsif ($^O =~ /MSWin/)
{
$ext = ".dll";
$version .= '-windows';
}
elsif ($^O eq "linux")
{
$ext = ".so";
$version .= '-linux';
}
else
{
$version .= '-' . $^O;
}
#Switch to the output folder.
chdir(Build::PathFormat('../build/package'));
my ($dirlist, $filename, $cmd);
$dirlist = "addons";
$filename = 'SteamWorks' . $version;
if ($^O eq "linux")
{
$filename .= '.tar.gz';
$cmd = "tar zcvf $filename $dirlist";
}
else
{
$filename .= '.zip';
$cmd = "zip -r $filename $dirlist";
}
print "$cmd\n";
system($cmd);
$ftp_path .= "/SteamWorks";
my ($ftp);
$ftp = Net::FTP->new($ftp_host, Debug => 0, Passive => 1)
or die "Cannot connect to host $ftp_host: $@";
$ftp->login($ftp_user, $ftp_pass)
or die "Cannot connect to host $ftp_host as $ftp_user: " . $ftp->message . "\n";
if ($ftp_path ne '')
{
# YOU LEAVE ME NO CHOICE
$ftp->mkdir($ftp_path, 1);
$ftp->cwd($ftp_path)
or die "Cannot change to folder $ftp_path: " . $ftp->message . "\n";
}
$ftp->binary();
$ftp->put($filename)
or die "Cannot drop file $filename ($ftp_path): " . $ftp->message . "\n";
$ftp->close();
print "File sent to drop site as $filename -- build succeeded.\n";
exit(0);
-5
View File
@@ -19,8 +19,6 @@ if ambuild_version.startswith('2.1'):
sys.exit(1)
run = run.BuildParser(sourcePath=sys.path[0], api='2.2')
run.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
help='Root search folder for HL2SDKs')
run.options.add_argument('--mms-path', type=str, dest='mms_path', default=None,
help='Path to Metamod:Source')
run.options.add_argument('--sm-path', type=str, dest='sm_path', default=None,
@@ -31,8 +29,5 @@ run.options.add_argument('--enable-debug', action='store_const', const='1', dest
help='Enable debugging symbols')
run.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt',
help='Enable optimization')
run.options.add_argument('-s', '--sdks', default='all', dest='sdks',
help='Build against specified SDKs; valid args are "all", "present", or '
'comma-delimited list of engine names')
run.options.add_argument('--target', default=None, help='Override the default build target')
run.Configure()