Author SHA1 Message Date
Maxime Leroy 25286e2f04 feat: update sdks, builders, ci, proper secure data (#10) 2025-02-21 00:47:09 +01:00
9 changed files with 460 additions and 270 deletions
+113 -47
View File
@@ -1,81 +1,147 @@
name: CI name: Extension builder
on: [push, pull_request, workflow_dispatch] on:
push:
branches:
- master
tags:
- "*"
pull_request:
branches:
- master
jobs: jobs:
build: build:
name: Build
runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false
matrix: matrix:
os: [ubuntu-20.04] os: [ubuntu-20.04]
sourcemod-version: [1.11-dev]
include: include:
- os: ubuntu-20.04 - os: ubuntu-20.04
target-archs: x86,x86_64 cc: clang-10
sdks: sdk2013,csgo cxx: clang++-10
fail-fast: false
name: ${{ matrix.os }} - ${{ matrix.cc }}
runs-on: ${{ matrix.os }}
env:
PROJECT: 'a2sqcache'
SDKS: 'css'
MMSOURCE_VERSION: '1.12'
SOURCEMOD_VERSION: '1.12'
CACHE_PATH: ${{ github.workspace }}/cache
steps: steps:
- name: Install Linux packages - name: Concatenate SDK Names
if: runner.os == 'Linux' shell: bash
run: | run: |
sudo apt update # Paranoia
sudo apt install -yq --no-install-recommends g++-multilib SDKS_VAR="${{env.SDKS}}"
# This will be used in our cache key
echo "SDKS_KEY=${SDKS_VAR//[[:blank:]]/}" >> $GITHUB_ENV
- name: Set up Python - name: Linux dependencies
uses: actions/setup-python@v5 if: startsWith(runner.os, 'Linux')
run: |
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
gcc-multilib g++-multilib libstdc++6 lib32stdc++6 \
libc6-dev libc6-dev-i386 linux-libc-dev \
linux-libc-dev:i386 lib32z1-dev ${{ matrix.cc }}
- name: Checkout - uses: actions/setup-python@v4
uses: actions/checkout@v4 name: Setup Python 3.9
with: with:
python-version: 3.9
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
- uses: actions/checkout@v3
name: Repository checkout
with:
fetch-depth: 0
path: extension path: extension
- name: Checkout SourceMod - uses: actions/cache@v3
uses: actions/checkout@v4 name: Cache dependencies
if: ${{ ! startsWith(github.ref, 'refs/tags/') }}
env:
cache-name: cache
with: with:
repository: alliedmodders/sourcemod path: ${{ env.CACHE_PATH }}
ref: ${{ matrix.sourcemod-version }} key: ${{ runner.os }}-build-${{ env.cache-name }}-sm${{ env.SOURCEMOD_VERSION }}-mmsource${{ env.MMSOURCE_VERSION }}-${{ env.SDKS_KEY }}
path: sourcemod
submodules: recursive
- name: Checkout AMBuild - shell: bash
uses: actions/checkout@v4 name: Install dependencies
with:
repository: alliedmodders/ambuild
path: ambuild
- name: Checkout sm-ext-common
uses: actions/checkout@v4
with:
repository: srcdslab/sm-ext-common
path: sourcemod/extensions/sm-ext-common
- name: Install sourcemod dependencies
run: | run: |
bash sourcemod/tools/checkout-deps.sh -m -s ${{ matrix.sdks }} mkdir -p "${{ env.CACHE_PATH }}"
cd "${{ env.CACHE_PATH }}"
shallow_checkout () {
# Param 1 is origin
# Param 2 is branch
# Param 3 is name
if [ ! -d "$3" ]; then
git clone "$1" --depth 1 --branch "$2" "$3"
fi
cd "$3"
git remote set-url origin "$1"
git fetch --depth 1 origin "$2"
git checkout --force --recurse-submodules FETCH_HEAD
git submodule init
git submodule update --depth 1
cd ..
}
# We are aware of what we are doing!
git config --global advice.detachedHead false
# Verify github cache, and see if we don't have the sdks already cloned and update them
for sdk in ${{ env.SDKS }}
do
shallow_checkout "https://github.com/alliedmodders/hl2sdk" "${sdk}" "hl2sdk-${sdk}"
done
shallow_checkout "https://github.com/alliedmodders/ambuild" "master" "ambuild"
shallow_checkout "https://github.com/alliedmodders/sourcemod" "${{env.SOURCEMOD_VERSION}}-dev" "sourcemod"
shallow_checkout "https://github.com/alliedmodders/metamod-source/" "${{env.MMSOURCE_VERSION}}-dev" "metamod-source"
shallow_checkout "https://github.com/srcdslab/sm-ext-common" "master" "sourcemod/public/sm-ext-common"
# But maybe others aren't (also probably unnecessary because git actions but paranoia)
git config --global advice.detachedHead true
- name: Install AMBuild - name: Setup AMBuild
uses: BSFishy/pip-action@v1 shell: bash
with: run: |
packages: ./ambuild cd "${{ env.CACHE_PATH }}"
python -m pip install ./ambuild
- name: Select clang compiler
if: startsWith(runner.os, 'Linux')
run: |
echo "CC=${{ matrix.cc }}" >> $GITHUB_ENV
echo "CXX=${{ matrix.cxx }}" >> $GITHUB_ENV
${{ matrix.cc }} --version
${{ matrix.cxx }} --version
- name: Build - name: Build
working-directory: extension
shell: bash shell: bash
env: working-directory: extension
BREAKPAD_SYMBOL_SERVER: ${{ secrets.BREAKPAD_SYMBOL_SERVER }}
run: | run: |
mkdir build && cd build mkdir build
python ../configure.py --enable-optimize --targets=${{ matrix.target-archs }} --sdks=${{ matrix.sdks }} cd build
python ../configure.py --enable-optimize --sdks="${{ env.SDKS }}" --mms-path="${{ env.CACHE_PATH }}/metamod-source" --hl2sdk-root="${{ env.CACHE_PATH }}" --sm-path="${{ env.CACHE_PATH }}/sourcemod" --targets=x86,x86_64
ambuild ambuild
- name: Upload artifact - name: Upload a Build Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
# Artifact name
name: ${{ runner.os }} name: ${{ runner.os }}
# optional, default is artifact
# A file, directory or wildcard pattern that describes what to upload
path: extension/build/package path: extension/build/package
# The desired behavior if no files are found using the provided path.
if-no-files-found: error
# Duration after which artifact will expire in days. 0 means using default retention.
retention-days: 14
release: release:
name: Release name: Release
+4
View File
@@ -0,0 +1,4 @@
build
Containerfile
.venv
safetyhook
+172 -113
View File
@@ -1,6 +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
import traceback
class SDK(object): class SDK(object):
def __init__(self, sdk, ext, aDef, name, platform, dir): def __init__(self, sdk, ext, aDef, name, platform, dir):
@@ -27,13 +26,49 @@ class SDK(object):
return True return True
return False return False
WinOnly = ['windows']
WinLinux = ['windows', 'linux'] WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac'] CSS = {
'windows': ['x86', 'x86_64'],
'linux': ['x86', 'x86_64']
}
HL2DM = {
'windows': ['x86', 'x86_64'],
'linux': ['x86', 'x86_64']
}
DODS = {
'windows': ['x86', 'x86_64'],
'linux': ['x86', 'x86_64']
}
TF2 = {
'windows': ['x86', 'x86_64'],
'linux': ['x86', 'x86_64']
}
CSGO = {
'windows': ['x86'],
'linux': ['x86', 'x86_64']
}
PossibleSDKs = { PossibleSDKs = {
'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinuxMac, 'sdk2013'), # 'episode1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', WinLinuxMac, 'csgo'), # 'darkm': SDK('HL2SDK-DARKM', '2.darkm', '2', 'DARKMESSIAH', WinOnly, 'darkm'),
# 'orangebox': SDK('HL2SDKOB', '2.ep2', '3', 'ORANGEBOX', WinLinux, 'orangebox'),
# 'bgt': SDK('HL2SDK-BGT', '2.bgt', '4', 'BLOODYGOODTIME', WinOnly, 'bgt'),
# 'eye': SDK('HL2SDK-EYE', '2.eye', '5', 'EYE', WinOnly, 'eye'),
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', CSS, 'css'),
# 'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', HL2DM, 'hl2dm'),
# 'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', DODS, 'dods'),
# 'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinux, 'sdk2013'),
# 'bms': SDK('HL2SDKBMS', '2.bms', '11', 'BMS', WinLinux, 'bms'),
# 'tf2': SDK('HL2SDKTF2', '2.tf2', '12', 'TF2', TF2, 'tf2'),
# 'l4d': SDK('HL2SDKL4D', '2.l4d', '13', 'LEFT4DEAD', WinLinux, 'l4d'),
# 'nucleardawn': SDK('HL2SDKND', '2.nd', '14', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'),
# 'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '15', 'CONTAGION', WinOnly, 'contagion'),
# 'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '16', 'LEFT4DEAD2', WinLinux, 'l4d2'),
# 'swarm': SDK('HL2SDK-SWARM', '2.swarm', '17', 'ALIENSWARM', WinOnly, 'swarm'),
# 'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '18', 'PORTAL2', [], 'portal2'),
# 'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'),
# 'blade': SDK('HL2SDKBLADE', '2.blade', '21', 'BLADE', WinLinux, 'blade'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '23', 'CSGO', CSGO, 'csgo'),
} }
def ResolveEnvPath(env, folder): def ResolveEnvPath(env, folder):
@@ -69,19 +104,13 @@ class ExtensionConfig(object):
def __init__(self): def __init__(self):
self.sdks = {} self.sdks = {}
self.binaries = [] self.binaries = []
self.spvm = []
self.extensions = [] self.extensions = []
self.generated_headers = None self.generated_headers = None
self.sm_root = None
self.mms_root = None self.mms_root = None
self.mysql_root = {} self.sm_root = None
self.spcomp = None
self.spcomp_bins = None
self.smx_files = {}
self.versionlib = None
self.all_targets = [] self.all_targets = []
self.target_archs = set() self.target_archs = set()
self.libsafetyhook = {}
if builder.options.targets: if builder.options.targets:
target_archs = builder.options.targets.split(',') target_archs = builder.options.targets.split(',')
@@ -105,6 +134,26 @@ class ExtensionConfig(object):
if not self.all_targets: if not self.all_targets:
raise Exception('No suitable C/C++ compiler was found.') raise Exception('No suitable C/C++ compiler was found.')
def use_auto_versioning(self):
return not getattr(builder.options, 'disable_auto_versioning', True)
def AddVersioning(self, binary):
if binary.compiler.target.platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'RC_COMPILE',
]
elif binary.compiler.target.platform == 'mac':
if binary.type == 'library':
binary.compiler.postlink += [
'-compatibility_version', '1.0.0',
'-current_version', self.productVersion
]
if self.use_auto_versioning():
binary.compiler.sourcedeps += self.generated_headers
return binary
@property @property
def tag(self): def tag(self):
if builder.options.debug == '1': if builder.options.debug == '1':
@@ -118,7 +167,7 @@ class ExtensionConfig(object):
import re import re
with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp: with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp:
productContents = fp.read() productContents = fp.read()
m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents) m = re.match('(\\d+)\.(\\d+)\.(\\d+).*', productContents)
if m == None: if m == None:
self.productVersion = '1.0.0' self.productVersion = '1.0.0'
else: else:
@@ -126,7 +175,7 @@ class ExtensionConfig(object):
self.productVersion = '{0}.{1}.{2}'.format(major, minor, release) self.productVersion = '{0}.{1}.{2}'.format(major, minor, release)
def detectSDKs(self): def detectSDKs(self):
sdk_list = builder.options.sdks.split(',') sdk_list = builder.options.sdks.split(' ')
use_none = sdk_list[0] == 'none' use_none = sdk_list[0] == 'none'
use_all = sdk_list[0] == 'all' use_all = sdk_list[0] == 'all'
use_present = sdk_list[0] == 'present' use_present = sdk_list[0] == 'present'
@@ -152,28 +201,24 @@ class ExtensionConfig(object):
if builder.options.sm_path: if builder.options.sm_path:
self.sm_root = builder.options.sm_path self.sm_root = builder.options.sm_path
else: else:
self.sm_root = ResolveEnvPath('SOURCEMOD18', 'sourcemod-1.10') self.sm_root = ResolveEnvPath('SOURCEMOD112', 'sourcemod-1.12')
if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod-source')
if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD_DEV', 'sourcemod-central')
if not self.sm_root: if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod') self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod')
if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD_DEV', 'sourcemod-central')
if not self.sm_root or not os.path.isdir(self.sm_root): if not self.sm_root or not os.path.isdir(self.sm_root):
raise Exception('Could not find a source copy of Sourcemod') raise Exception('Could not find a source copy of SourceMod')
self.sm_root = Normalize(self.sm_root) self.sm_root = Normalize(self.sm_root)
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('MMSOURCE112', 'mmsource-1.12')
if not self.mms_root: if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source') 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')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod')
if not self.mms_root or not os.path.isdir(self.mms_root): if not self.mms_root or not os.path.isdir(self.mms_root):
raise Exception('Could not find a source copy of Metamod:Source') raise Exception('Could not find a source copy of Metamod:Source')
@@ -188,14 +233,14 @@ class ExtensionConfig(object):
def configure_cxx(self, cxx): def configure_cxx(self, cxx):
if cxx.family == 'msvc': if cxx.family == 'msvc':
if cxx.version < 1900: if cxx.version < 1914 and builder.options.generator != 'vs':
raise Exception('Only MSVC 2015 and later are supported, c++14 support is required.') raise Exception(f'Only MSVC 2017 15.7 and later are supported, full C++17 support is required. ({str(cxx.version)} < 1914)')
if cxx.family == 'gcc': elif cxx.family == 'gcc':
if cxx.version < 'gcc-4.9': if cxx.version < 'gcc-9':
raise Exception('Only GCC versions 4.9 or greater are supported, c++14 support is required.') raise Exception('Only GCC versions 9 or later are supported, full C++17 support is required.')
if cxx.family == 'clang': elif cxx.family == 'clang':
if cxx.version < 'clang-3.4': if cxx.version < 'clang-5':
raise Exception('Only clang versions 3.4 or greater are supported, c++14 support is required.') raise Exception('Only clang versions 5 or later are supported, full C++17 support is required.')
if cxx.like('gcc'): if cxx.like('gcc'):
self.configure_gcc(cxx) self.configure_gcc(cxx)
@@ -223,6 +268,12 @@ class ExtensionConfig(object):
os.path.join(self.sm_root, 'public'), os.path.join(self.sm_root, 'public'),
] ]
if self.use_auto_versioning():
cxx.defines += ['SM_GENERATED_BUILD']
cxx.includes += [
os.path.join(builder.buildPath, 'includes')
]
def configure_gcc(self, cxx): def configure_gcc(self, cxx):
cxx.defines += [ cxx.defines += [
'stricmp=strcasecmp', 'stricmp=strcasecmp',
@@ -240,19 +291,19 @@ class ExtensionConfig(object):
'-Wno-unused', '-Wno-unused',
'-Wno-switch', '-Wno-switch',
'-Wno-array-bounds', '-Wno-array-bounds',
'-msse', '-Wno-unknown-pragmas',
'-Wno-dangling-else',
'-fvisibility=hidden', '-fvisibility=hidden',
] ]
if cxx.target.arch in ['x86', 'x86_64']:
if cxx.version == 'apple-clang-6.0' or cxx.version == 'clang-3.4': cxx.cflags += ['-msse']
cxx.cxxflags += ['-std=c++1y']
else:
cxx.cxxflags += ['-std=c++14']
cxx.cxxflags += [ cxx.cxxflags += [
'-std=c++17',
'-fno-threadsafe-statics', '-fno-threadsafe-statics',
'-Wno-non-virtual-dtor', '-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual', '-Wno-overloaded-virtual',
'-Wno-register',
'-fvisibility-inlines-hidden', '-fvisibility-inlines-hidden',
] ]
@@ -283,26 +334,18 @@ 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 have_gcc: if have_gcc:
cxx.cflags += ['-mfpmath=sse'] cxx.cflags += ['-mfpmath=sse']
cxx.cflags += ['-Wno-maybe-uninitialized'] cxx.cflags += ['-Wno-maybe-uninitialized']
if builder.options.opt == '1': if builder.options.opt == '1':
cxx.cflags += [ cxx.cflags += ['-O3']
'-O3',
'-fexperimental-new-pass-manager',
'-mllvm',
'-inline-threshold=1000',
'-mllvm',
'-vectorize-loops',
'-ftree-vectorize',
]
# Don't omit the frame pointer. # Don't omit the frame pointer.
cxx.cflags += ['-fno-omit-frame-pointer'] cxx.cflags += ['-fno-omit-frame-pointer']
@@ -326,6 +369,7 @@ class ExtensionConfig(object):
'/EHsc', '/EHsc',
'/GR-', '/GR-',
'/TP', '/TP',
'/std:c++17',
] ]
cxx.linkflags += [ cxx.linkflags += [
'kernel32.lib', 'kernel32.lib',
@@ -354,13 +398,12 @@ class ExtensionConfig(object):
cxx.cflags += ['/Oy-'] cxx.cflags += ['/Oy-']
def configure_linux(self, cxx): def configure_linux(self, cxx):
cxx.defines += ['_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64'] cxx.defines += ['LINUX', '_LINUX', 'POSIX', '_FILE_OFFSET_BITS=64']
cxx.linkflags += ['-lm'] cxx.linkflags += ['-lm']
if cxx.family == 'gcc': if cxx.family == 'gcc':
cxx.linkflags += ['-static-libgcc'] cxx.linkflags += ['-static-libgcc']
elif cxx.family == 'clang': elif cxx.family == 'clang':
cxx.linkflags += ['-lgcc_eh'] cxx.linkflags += ['-lgcc_eh']
cxx.linkflags += ['-static-libstdc++']
def configure_mac(self, cxx): def configure_mac(self, cxx):
cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL'] cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
@@ -373,43 +416,16 @@ class ExtensionConfig(object):
cxx.cxxflags += ['-stdlib=libc++'] cxx.cxxflags += ['-stdlib=libc++']
def configure_windows(self, cxx): def configure_windows(self, cxx):
cxx.defines += ['WIN32', '_WINDOWS'] cxx.defines += ['WIN32', '_WINDOWS', 'PLATFORM_WINDOWS_PC']
def add_libamtl(self):
# Add libamtl.
self.libamtl = {}
for cxx in self.all_targets:
def get_configure_fn(cxx):
return lambda builder, name: self.StaticLibrary(builder, cxx, name)
extra_vars = {'Configure': get_configure_fn(cxx)}
libamtl = builder.Build('public/amtl/amtl/AMBuilder', extra_vars)
self.libamtl[cxx.target.arch] = libamtl.binary
def AddVersioning(self, binary):
if binary.compiler.target.platform == 'windows':
binary.sources += ['version.rc']
binary.compiler.rcdefines += [
'BINARY_NAME="{0}"'.format(binary.outputFile),
'RC_COMPILE',
]
elif binary.compiler.target.platform == 'mac':
if binary.type == 'library':
binary.compiler.postlink += [
'-compatibility_version', '1.0.0',
'-current_version', self.productVersion
]
return binary
def LibraryBuilder(self, compiler, name): def LibraryBuilder(self, compiler, name):
binary = compiler.Library(name) binary = compiler.Library(name)
self.AddVersioning(binary)
if binary.compiler.like('msvc'): if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS'] binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
return binary return binary
def ProgramBuilder(self, compiler, name): def ProgramBuilder(self, compiler, name):
binary = compiler.Program(name) binary = compiler.Program(name)
self.AddVersioning(binary)
if '-static-libgcc' in binary.compiler.linkflags: if '-static-libgcc' in binary.compiler.linkflags:
binary.compiler.linkflags.remove('-static-libgcc') binary.compiler.linkflags.remove('-static-libgcc')
if '-lgcc_eh' in binary.compiler.linkflags: if '-lgcc_eh' in binary.compiler.linkflags:
@@ -444,10 +460,10 @@ class ExtensionConfig(object):
os.path.join(context.currentSourcePath, 'sdk'), os.path.join(context.currentSourcePath, 'sdk'),
os.path.join(self.sm_root, 'public'), os.path.join(self.sm_root, 'public'),
os.path.join(self.sm_root, 'public', 'extensions'), os.path.join(self.sm_root, 'public', 'extensions'),
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', 'amtl'),
os.path.join(self.sm_root, 'public', 'amtl'), os.path.join(self.sm_root, 'public', 'amtl'),
os.path.join(self.sm_root, 'extensions', 'sm-ext-common', 'include'), os.path.join(self.sm_root, 'sourcepawn', 'include'),
os.path.join(self.sm_root, 'public', 'sm-ext-common', 'include'),
] ]
return compiler return compiler
@@ -466,7 +482,8 @@ class ExtensionConfig(object):
os.path.join(self.mms_root, 'core', 'sourcehook'), os.path.join(self.mms_root, 'core', 'sourcehook'),
] ]
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs] defines = ['RAD_TELEMETRY_DISABLED']
defines += ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
compiler.defines += defines compiler.defines += defines
paths = [ paths = [
@@ -475,8 +492,7 @@ class ExtensionConfig(object):
['public', 'mathlib'], ['public', 'mathlib'],
['public', 'vstdlib'], ['public', 'vstdlib'],
['public', 'tier0'], ['public', 'tier0'],
['public', 'tier1'], ['public', 'tier1']
['public', 'appframework']
] ]
if sdk.name == 'episode1' or sdk.name == 'darkm': if sdk.name == 'episode1' or sdk.name == 'darkm':
paths.append(['public', 'dlls']) paths.append(['public', 'dlls'])
@@ -489,7 +505,7 @@ class ExtensionConfig(object):
compiler.defines += ['SOURCE_ENGINE=' + sdk.code] compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'): if sdk.name in ['sdk2013', 'bms', 'css', 'tf2', 'dods', 'hl2dm'] and compiler.like('gcc'):
# The 2013 SDK already has these in public/tier0/basetypes.h # The 2013 SDK already has these in public/tier0/basetypes.h
compiler.defines.remove('stricmp=strcasecmp') compiler.defines.remove('stricmp=strcasecmp')
compiler.defines.remove('_stricmp=strcasecmp') compiler.defines.remove('_stricmp=strcasecmp')
@@ -520,7 +536,6 @@ class ExtensionConfig(object):
if compiler.target.platform == 'linux': if compiler.target.platform == 'linux':
if sdk.name in ['csgo', 'blade']: if sdk.name in ['csgo', 'blade']:
compiler.linkflags.remove('-static-libstdc++')
compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0'] compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
for path in paths: for path in paths:
@@ -532,16 +547,16 @@ class ExtensionConfig(object):
elif sdk.name in ['sdk2013', 'bms']: elif sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
elif compiler.target.arch == 'x86_64': elif compiler.target.arch == 'x86_64':
lib_folder = os.path.join(sdk.path, 'lib', 'linux64') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux64')
else: else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux')
elif compiler.target.platform == 'mac': elif compiler.target.platform == 'mac':
if sdk.name in ['sdk2013', 'bms']: if sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
elif compiler.target.arch == 'x86_64': elif compiler.target.arch == 'x86_64':
lib_folder = os.path.join(sdk.path, 'lib', 'osx64') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx64')
else: else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac') lib_folder = os.path.join(sdk.path, 'lib', 'public', 'mac')
if compiler.target.platform in ['linux', 'mac']: if compiler.target.platform in ['linux', 'mac']:
if sdk.name in ['sdk2013', 'bms'] or compiler.target.arch == 'x86_64': if sdk.name in ['sdk2013', 'bms'] or compiler.target.arch == 'x86_64':
@@ -580,9 +595,9 @@ class ExtensionConfig(object):
libs.append('interfaces') libs.append('interfaces')
for lib in libs: for lib in libs:
if compiler.target.arch == 'x86': if compiler.target.arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib' lib_path = os.path.join(sdk.path, 'lib', 'public', 'x86', lib) + '.lib'
elif compiler.target.arch == 'x86_64': elif compiler.target.arch == 'x86_64':
lib_path = os.path.join(sdk.path, 'lib', 'public', 'win64', lib) + '.lib' lib_path = os.path.join(sdk.path, 'lib', 'public', 'x64', lib) + '.lib'
compiler.linkflags.append(lib_path) compiler.linkflags.append(lib_path)
for library in dynamic_libs: for library in dynamic_libs:
@@ -598,16 +613,41 @@ class ExtensionConfig(object):
return binary return binary
def AddCDetour(self, binary):
sm_public_path = os.path.join(self.sm_root, 'public')
if os.path.exists(os.path.join(sm_public_path, 'safetyhook')):
binary.sources += [ os.path.join(sm_public_path, 'CDetour', 'detours.cpp') ]
binary.compiler.cxxincludes += [ os.path.join(builder.sourcePath, 'safetyhook', 'include') ]
for task in self.libsafetyhook:
if task.target.arch == binary.compiler.target.arch:
binary.compiler.linkflags += [task.binary]
return
raise Exception('No suitable build of safetyhook was found.')
else:
binary.sources += [
os.path.join(sm_public_path, 'CDetour', 'detours.cpp'),
os.path.join(sm_public_path, 'asm', 'asm.c'),
]
# sm1.10+
libudis_folder = os.path.join(sm_public_path, 'libudis86')
if os.path.isdir(libudis_folder):
binary.compiler.defines += ['HAVE_STRING_H']
binary.sources += [
os.path.join(libudis_folder, 'decode.c'),
os.path.join(libudis_folder, 'itab.c'),
os.path.join(libudis_folder, 'syn-att.c'),
os.path.join(libudis_folder, 'syn-intel.c'),
os.path.join(libudis_folder, 'syn.c'),
os.path.join(libudis_folder, 'udis86.c'),
]
def HL2Library(self, context, compiler, name, sdk): def HL2Library(self, context, compiler, name, sdk):
binary = self.Library(context, compiler, name) binary = self.Library(context, compiler, name)
self.ConfigureForExtension(context, binary.compiler) self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(context, binary, sdk) return self.ConfigureForHL2(context, binary, sdk)
def HL2Project(self, context, compiler, name):
project = context.LibraryProject(name)
self.ConfigureForExtension(context, compiler)
return project
def HL2Config(self, project, context, compiler, name, sdk): def HL2Config(self, project, context, compiler, name, sdk):
binary = project.Configure(compiler, name, binary = project.Configure(compiler, name,
'{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch)) '{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch))
@@ -622,24 +662,43 @@ class ExtensionConfig(object):
self.ConfigureForExtension(context, binary.compiler) self.ConfigureForExtension(context, binary.compiler)
return binary return binary
class SafetyHookShim(object):
def __init__(self):
self.all_targets = {}
self.libsafetyhook = {}
if getattr(builder, 'target', None) is not None: if getattr(builder, 'target', None) is not None:
sys.stderr.write("Your output folder was configured for AMBuild 2.1, and SourceMod is now\n") sys.stderr.write("Your output folder was configured for AMBuild 2.1.\n")
sys.stderr.write("configured to use AMBuild 2.2. Please remove your output folder and\n") sys.stderr.write("Please remove your output folder and reconfigure to continue.\n")
sys.stderr.write("reconfigure to continue.\n")
os._exit(1) os._exit(1)
SM = ExtensionConfig() Extension = ExtensionConfig()
SM.detectSDKs() Extension.detectProductVersion()
SM.configure() Extension.detectSDKs()
Extension.configure()
if os.path.exists(os.path.join(Extension.sm_root, 'public', 'safetyhook')):
# we need to pull safetyhook in locally because ambuild does not take kindly to outside relpaths
safetyhook_dest = Normalize(builder.sourcePath + '/safetyhook/')
shutil.copytree(os.path.join(Extension.sm_root, 'public', 'safetyhook'), safetyhook_dest, dirs_exist_ok=True)
SafetyHook = SafetyHookShim()
SafetyHook.all_targets = Extension.all_targets
builder.Build('safetyhook/AMBuilder', {'SafetyHook': SafetyHook })
Extension.libsafetyhook = SafetyHook.libsafetyhook
# This will clone the list and each cxx object as we recurse, preventing child # This will clone the list and each cxx object as we recurse, preventing child
# scripts from messing up global state. # scripts from messing up global state.
builder.targets = builder.CloneableList(SM.all_targets) builder.targets = builder.CloneableList(Extension.all_targets)
# Add additional buildscripts here
BuildScripts = [
'AMBuilder',
]
if builder.backend == 'amb2': if builder.backend == 'amb2':
BuildScripts = [ BuildScripts += [
'AMBuilder', 'PackageScript',
'PackageScript', ]
]
builder.Build(BuildScripts, { 'SM': SM}) builder.Build(BuildScripts, { 'Extension': Extension })
+14 -40
View File
@@ -1,48 +1,22 @@
# 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 import os, sys
projectName = 'a2sqcache' projectname = 'a2sqcache'
for cxx in builder.targets: project = builder.LibraryProject(projectname + '.ext')
for sdk_name in SM.sdks: project.sources = [
sdk = SM.sdks[sdk_name] 'extension.cpp',
os.path.join(Extension.sm_root, 'public', 'smsdk_ext.cpp'),
]
for sdk_name in Extension.sdks:
sdk = Extension.sdks[sdk_name]
for cxx in builder.targets:
if not cxx.target.arch in sdk.platformSpec[cxx.target.platform]: if not cxx.target.arch in sdk.platformSpec[cxx.target.platform]:
continue continue
sdk.ext = "." + sdk.ext binary = Extension.HL2ExtConfig(project, builder, cxx, projectname + '.ext.' + sdk.ext, sdk)
if "sdk2013" in sdk.ext: Extension.AddCDetour(binary)
sdk.ext = ""
binary = SM.HL2Library(builder, cxx, projectName + ".ext" + sdk.ext, sdk) Extension.extensions = builder.Add(project)
binary.compiler.defines += [
'HAVE_STRING_H',
]
if cxx.target.platform == 'linux':
cxx.postlink += ['-lpthread', '-lrt']
elif cxx.target.platform == 'mac':
cxx.cflags += ['-Wno-deprecated-declarations']
cxx.postlink += ['-framework', 'CoreServices']
if cxx.family == 'gcc' or cxx.family == 'clang':
cxx.cxxflags += ['-fno-rtti']
elif cxx.family == 'msvc':
cxx.cxxflags += ['/GR-']
binary.sources += [
'extension.cpp',
os.path.join(SM.sm_root, 'extensions', 'sm-ext-common', 'mathstubs.c'),
os.path.join(SM.sm_root, 'public', 'smsdk_ext.cpp'),
os.path.join(SM.sm_root, 'public', 'CDetour', 'detours.cpp'),
os.path.join(SM.sm_root, 'public', 'asm', 'asm.c'),
os.path.join(SM.sm_root, 'public', 'libudis86', 'decode.c'),
os.path.join(SM.sm_root, 'public', 'libudis86', 'itab.c'),
os.path.join(SM.sm_root, 'public', 'libudis86', 'syn-att.c'),
os.path.join(SM.sm_root, 'public', 'libudis86', 'syn-intel.c'),
os.path.join(SM.sm_root, 'public', 'libudis86', 'syn.c'),
os.path.join(SM.sm_root, 'public', 'libudis86', 'udis86.c'),
]
SM.extensions += [builder.Add(binary)]
+36 -46
View File
@@ -1,57 +1,47 @@
# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: # vim: set ts=2 sw=2 tw=99 noet ft=python:
import os import os
import shutil
import ambuild.osutil as osutil
from ambuild.command import Command
# This is where the files will be output to
# package is the default
builder.SetBuildFolder('package') builder.SetBuildFolder('package')
# Add any folders you need to this list def CreateFolders(folders):
folder_list = [ dict = {}
'addons/sourcemod/extensions', for folder in folders:
'addons/sourcemod/scripting/include', path = os.path.normpath(folder)
'addons/sourcemod/gamedata' dict[folder] = builder.AddFolder(path)
] return dict
if 'x86_64' in SM.target_archs: def CopyFiles(src, dest, filter_ext=None):
folder_list.extend([ source_path = os.path.join(builder.sourcePath, src)
'addons/sourcemod/extensions/x64', if os.path.isfile(source_path):
]) builder.AddCopy(source_path, dest)
return
for entry in os.listdir(source_path):
entry_path = os.path.join(source_path, entry)
if not os.path.isfile(entry_path):
continue
if filter_ext:
_, ext = os.path.splitext(entry)
if filter_ext != ext:
continue
builder.AddCopy(entry_path, dest)
# Create the distribution folder hierarchy.
folder_map = {}
for folder in folder_list:
norm_folder = os.path.normpath(folder)
folder_map[folder] = builder.AddFolder(norm_folder)
# Copy binaries. folders = CreateFolders(['addons/sourcemod/extensions', 'addons/sourcemod/extensions/x64', 'addons/sourcemod/gamedata', 'addons/sourcemod/scripting', 'addons/sourcemod/scripting/include'])
for cxx_task in SM.extensions:
pdblog = open(os.path.join(builder.buildPath, 'pdblog.txt'), 'wt')
for cxx_task in Extension.extensions:
if cxx_task.target.arch == 'x86_64': if cxx_task.target.arch == 'x86_64':
builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions/x64']) builder.AddCopy(cxx_task.binary, folders['addons/sourcemod/extensions/x64'])
else: else:
builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions']) builder.AddCopy(cxx_task.binary, folders['addons/sourcemod/extensions'])
pdblog.write(cxx_task.debug.path + '\n')
pdblog.close()
# Do all straight-up file copies from the source tree. CopyFiles('addons/sourcemod/gamedata/a2sqcache.games.txt', folders['addons/sourcemod/gamedata'])
def CopyFiles(src, dest, files): CopyFiles('addons/sourcemod/scripting/include/a2sqcache.inc', folders['addons/sourcemod/scripting/include'])
if not dest: CopyFiles('addons/sourcemod/extensions/a2sqcache.autoload', folders['addons/sourcemod/extensions'])
dest = src
dest_entry = folder_map[dest]
for source_file in files:
source_path = os.path.join(builder.sourcePath, src, source_file)
dest_path = os.path.join(dest_entry.path, source_file)
if not os.path.isfile(str(dest_path)):
builder.AddCopy(source_path, dest_entry)
# Gamedata (custom so updater doesn't replace it) debug_info = []
CopyFiles('addons/sourcemod/gamedata', 'addons/sourcemod/gamedata',
[ 'a2sqcache.games.txt' ]
)
# Include file
CopyFiles('addons/sourcemod/scripting/include', 'addons/sourcemod/scripting/include',
[ 'a2sqcache.inc' ]
)
# Autoload extension
CopyFiles('addons/sourcemod/extensions', 'addons/sourcemod/extensions',
[ 'a2sqcache.autoload' ]
)
@@ -37,6 +37,19 @@
"Signatures" "Signatures"
{ {
"Steam3Server"
{
"library" "engine"
"linux" "@_Z12Steam3Serverv"
"linux64" "@_Z12Steam3Serverv"
}
"CBaseServer__CheckMasterServerRequestRestart"
{
"library" "engine"
"windows" "\xE8\x2A\x2A\x2A\x2A\x83\x78\x04\x00\x74\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x48\x04\x8B\x01\x8B\x40\x2C\xFF\xD0\x84\xC0\x74\x2A\x56"
}
"net_sockets" "net_sockets"
{ {
"library" "engine" "library" "engine"
@@ -75,6 +88,11 @@
"windows" "1" "windows" "1"
"linux" "2" "linux" "2"
} }
"CheckMasterServerRequestRestart_Steam3ServerFuncOffset"
{
"windows" "1"
}
} }
} }
+87 -9
View File
@@ -52,6 +52,19 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
enum
{
NS_CLIENT = 0, // client socket
NS_SERVER, // server socket
NS_HLTV,
NS_MATCHMAKING,
NS_SYSTEMLINK,
#ifdef LINUX
NS_SVLAN, // LAN udp port for Linux. See NET_OpenSockets for info.
#endif
MAX_SOCKETS
};
size_t size_t
strlcpy(char *dst, const char *src, size_t dsize) strlcpy(char *dst, const char *src, size_t dsize)
{ {
@@ -156,6 +169,32 @@ typedef struct
#endif #endif
} netsocket_t; } netsocket_t;
class CSteam3Server
{
public:
void *m_pSteamClient;
ISteamGameServer *m_pSteamGameServer;
void *m_pSteamGameServerUtils;
void *m_pSteamGameServerNetworking;
void *m_pSteamGameServerStats;
void *m_pSteamHTTP;
void *m_pSteamInventory;
void *m_pSteamUGC;
void *m_pSteamApps;
} *g_pSteam3Server;
typedef CSteam3Server *(*Steam3ServerFunc)();
Steam3ServerFunc g_pSteam3ServerFunc = NULL;
CSteam3Server *Steam3Server()
{
if (!g_pSteam3ServerFunc)
return NULL;
return g_pSteam3ServerFunc();
}
CUtlVector<netsocket_t> *net_sockets; CUtlVector<netsocket_t> *net_sockets;
int g_ServerUDPSocket = 0; int g_ServerUDPSocket = 0;
@@ -256,7 +295,7 @@ void UpdateQueryCache()
#endif #endif
info.nPassword = iserver->GetPassword() ? 1 : 0; info.nPassword = iserver->GetPassword() ? 1 : 0;
info.bIsSecure = true; info.bIsSecure = g_pSteam3Server->m_pSteamGameServer->BSecure() ? 1 : 0;
if(!(info.nNewFlags & S2A_EXTRA_DATA_HAS_STEAMID) && engine->GetGameServerSteamID()) if(!(info.nNewFlags & S2A_EXTRA_DATA_HAS_STEAMID) && engine->GetGameServerSteamID())
{ {
@@ -276,7 +315,7 @@ void UpdateQueryCache()
IServer *ihltvserver = hltv->GetBaseServer(); IServer *ihltvserver = hltv->GetBaseServer();
if(ihltvserver) if(ihltvserver)
{ {
info.iHLTVUDPPort = ihltvserver->GetUDPPort(); info.iHLTVUDPPort = ihltvserver->GetLocalUDPPort();
info.aHLTVNameLen = strlcpy(info.aHLTVName, ihltvserver->GetName(), sizeof(info.aHLTVName)); info.aHLTVNameLen = strlcpy(info.aHLTVName, ihltvserver->GetName(), sizeof(info.aHLTVName));
info.nNewFlags |= S2A_EXTRA_DATA_HAS_SPECTATOR_DATA; info.nNewFlags |= S2A_EXTRA_DATA_HAS_SPECTATOR_DATA;
} }
@@ -416,10 +455,8 @@ void SendA2S_Info(netpacket_t * packet)
// Password? // Password?
buf.PutUnsignedChar( iserver->GetPassword() ? 1 : 0 ); buf.PutUnsignedChar( iserver->GetPassword() ? 1 : 0 );
// buf.PutUnsignedChar( Steam3Server().BSecure() ? 1 : 0 );
// Secure? // Secure?
buf.PutUnsignedChar( 1 ); buf.PutUnsignedChar( g_pSteam3Server->m_pSteamGameServer->BSecure() ? 1 : 0 );
buf.PutString( g_QueryCache.info.aVersion ); buf.PutString( g_QueryCache.info.aVersion );
@@ -432,7 +469,7 @@ void SendA2S_Info(netpacket_t * packet)
// Write the rest of the data. // Write the rest of the data.
if ( g_QueryCache.info.nNewFlags & S2A_EXTRA_DATA_HAS_GAME_PORT ) if ( g_QueryCache.info.nNewFlags & S2A_EXTRA_DATA_HAS_GAME_PORT )
{ {
buf.PutShort( LittleWord( iserver->GetUDPPort() ) ); buf.PutShort( LittleWord( iserver->GetLocalUDPPort() ) );
} }
#if SOURCE_ENGINE <= SE_CSGO #if SOURCE_ENGINE <= SE_CSGO
@@ -604,6 +641,48 @@ bool A2SQCache::SDK_OnLoad(char *error, size_t maxlen, bool late)
} }
#endif #endif
#ifndef WIN32
if (!g_pGameConf->GetMemSig("Steam3Server", (void **)(&g_pSteam3ServerFunc)) || !g_pSteam3ServerFunc)
{
snprintf(error, maxlen, "Failed to find Steam3Server function.\n");
return false;
}
#else
void *address;
if (!g_pGameConf->GetMemSig("CBaseServer__CheckMasterServerRequestRestart", &address) || !address)
{
snprintf(error, maxlen, "Failed to find CBaseServer__CheckMasterServerRequestRestart function.\n");
return false;
}
int steam3ServerFuncOffset = 0;
if (!g_pGameConf->GetOffset("CheckMasterServerRequestRestart_Steam3ServerFuncOffset", &steam3ServerFuncOffset) || steam3ServerFuncOffset == 0)
{
snprintf(error, maxlen, "Failed to find CheckMasterServerRequestRestart_Steam3ServerFuncOffset offset.\n");
return false;
}
//META_CONPRINTF("CheckMasterServerRequestRestart: %p\n", address);
address = (void *)((intptr_t)address + steam3ServerFuncOffset);
intptr_t offset = (intptr_t)(*(void **)address); // Get offset
g_pSteam3ServerFunc = (Steam3ServerFunc)((intptr_t)address + offset + sizeof(intptr_t));
//META_CONPRINTF("Steam3Server: %p\n", g_pSteam3ServerFunc);
#endif
g_pSteam3Server = Steam3Server();
if (!g_pSteam3Server)
{
snprintf(error, maxlen, "Unable to get Steam3Server singleton.\n");
return false;
}
if (!g_pSteam3Server->m_pSteamGameServer)
{
snprintf(error, maxlen, "Unable to get Steam Game Server.\n");
return false;
}
CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf); CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
g_Detour_CBaseServer__InactivateClients = DETOUR_CREATE_MEMBER(CBaseServer__InactivateClients, "CBaseServer__InactivateClients"); g_Detour_CBaseServer__InactivateClients = DETOUR_CREATE_MEMBER(CBaseServer__InactivateClients, "CBaseServer__InactivateClients");
@@ -680,8 +759,7 @@ void A2SQCache::SDK_OnAllLoaded()
return; return;
} }
int socknum = 1; // NS_SERVER g_ServerUDPSocket = (*net_sockets)[NS_SERVER].hUDP;
g_ServerUDPSocket = (*net_sockets)[socknum].hUDP;
if(!g_ServerUDPSocket) if(!g_ServerUDPSocket)
{ {
@@ -715,7 +793,7 @@ void A2SQCache::SDK_OnAllLoaded()
info.aVersionLen = snprintf(info.aVersion, sizeof(info.aVersion), "%d", engine->GetServerVersion()); info.aVersionLen = snprintf(info.aVersion, sizeof(info.aVersion), "%d", engine->GetServerVersion());
#endif #endif
info.iUDPPort = iserver->GetUDPPort(); info.iUDPPort = iserver->GetLocalUDPPort();
info.nNewFlags |= S2A_EXTRA_DATA_HAS_GAME_PORT; info.nNewFlags |= S2A_EXTRA_DATA_HAS_GAME_PORT;
info.iGameID = info.iSteamAppID; info.iGameID = info.iSteamAppID;
+1
View File
@@ -0,0 +1 @@
1.1.1
+1 -1
View File
@@ -40,7 +40,7 @@
/* Basic information exposed publicly */ /* Basic information exposed publicly */
#define SMEXT_CONF_NAME "A2SQCache" #define SMEXT_CONF_NAME "A2SQCache"
#define SMEXT_CONF_DESCRIPTION "A2S_INFO + A2S_PLAYER cache" #define SMEXT_CONF_DESCRIPTION "A2S_INFO + A2S_PLAYER cache"
#define SMEXT_CONF_VERSION "1.1" #define SMEXT_CONF_VERSION "1.1.1"
#define SMEXT_CONF_AUTHOR "BotoX, maxime1907" #define SMEXT_CONF_AUTHOR "BotoX, maxime1907"
#define SMEXT_CONF_URL "https://git.botox.bz/CSSZombieEscape/sm-ext-A2SQCache" #define SMEXT_CONF_URL "https://git.botox.bz/CSSZombieEscape/sm-ext-A2SQCache"
#define SMEXT_CONF_LOGTAG "A2SQCACHE" #define SMEXT_CONF_LOGTAG "A2SQCACHE"