diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d58068a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,165 @@ +name: Extension builder + +on: + push: + branches: [ action, master ] + pull_request: + branches: [ action, master ] + + +jobs: + build: + strategy: + matrix: + os: [ubuntu-20.04, windows-2019, ubuntu-latest, windows-latest] + include: + - os: ubuntu-20.04 + cc: clang-10 + cxx: clang++-10 + - os: windows-2019 + cc: msvc + - os: ubuntu-latest + cc: clang + cxx: clang++ + - os: windows-latest + cc: msvc + fail-fast: false + + + name: ${{ matrix.os }} - ${{ matrix.cc }} + runs-on: ${{ matrix.os }} + + env: + PROJECT: 'connect' + SDKS: 'css hl2dm dods tf2' + MMSOURCE_VERSION: '1.10' + SOURCEMOD_VERSION: '1.11' + CACHE_PATH: ${{ github.workspace }}/cache + steps: + - name: Concatenate SDK Names + shell: bash + run: | + # Paranoia + SDKS_VAR="${{env.SDKS}}" + # This will be used in our cache key + echo "SDKS_KEY=${SDKS_VAR//[[:blank:]]/}" >> $GITHUB_ENV + + - name: Linux dependencies + 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 }} + + - uses: actions/setup-python@v4 + name: Setup Python 3.9 + 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 + + - uses: actions/cache@v3 + name: Cache dependencies + env: + cache-name: connect-cache + with: + path: ${{ env.CACHE_PATH }} + key: ${{ runner.os }}-build-${{ env.cache-name }}-sm${{ env.SOURCEMOD_VERSION }}-mmsource${{ env.MMSOURCE_VERSION }}-${{ env.SDKS_KEY }} + + - shell: bash + name: Install dependencies + run: | + 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" + # But maybe others aren't (also probably unnecessary because git actions but paranoia) + git config --global advice.detachedHead true + + - name: Setup AMBuild + shell: bash + run: | + 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 + shell: bash + working-directory: extension + run: | + mkdir build + cd build + python ../configure.py --enable-auto-versioning --enable-optimize --sdks="${{ env.SDKS }}" --mms-path="${{ env.CACHE_PATH }}/metamod-source" --hl2sdk-root="${{ env.CACHE_PATH }}" --sm-path="${{ env.CACHE_PATH }}/sourcemod" + ambuild + + PLATFORM="${{ runner.os }}" + FILENAME="$(cat ./includes/filename_versioning.txt)" + ZIP_FILENAME="${{ env.PROJECT }}-${FILENAME}-${PLATFORM,}.zip" + + echo "ZIP_FILENAME=${ZIP_FILENAME}" >> $GITHUB_ENV + + - name: Package release - Windows + if: github.event_name == 'push' && github.ref == 'refs/heads/action' && startsWith(matrix.os, 'windows-latest') + working-directory: extension/build/package + run: Compress-Archive -Path * -Destination ${{ env.ZIP_FILENAME }} + + - name: Package release + if: github.event_name == 'push' && github.ref == 'refs/heads/action' && startsWith(matrix.os, 'ubuntu-latest') + working-directory: extension/build/package + run: zip -r "${{ env.ZIP_FILENAME }}" . + + - name: Upload release + if: github.event_name == 'push' && github.ref == 'refs/heads/action' && (startsWith(matrix.os, 'ubuntu-latest') || startsWith(matrix.os, 'windows-latest')) + shell: bash + working-directory: extension/build/package + run: | + echo "Begin upload..." + AUTHORIZATION="$(echo -n '${{ secrets.USERNAME }}:${{ secrets.PASSWORD }}' | base64)" + echo "::add-mask::${AUTHORIZATION}" + + HTTP_CODE=$(curl -XPOST -H "Authorization: Basic ${AUTHORIZATION}" -H "Content-Type: application/zip" --output /dev/null --silent --write-out "%{http_code}" --data-binary "@${{ env.ZIP_FILENAME }}" "https://builds.limetech.io/upload.php?project=${{ env.PROJECT }}&branch=action&filename=${{ env.ZIP_FILENAME }}") + if test ${HTTP_CODE} -ne 200; then + exit ${HTTP_CODE} + fi + echo "Upload successful!" \ No newline at end of file diff --git a/AMBuildScript b/AMBuildScript index 40aa0ef..813dbd7 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -1,425 +1,581 @@ -# vim: set ts=2 sw=2 tw=99 noet ft=python: -import os -import sys -from ambuild.command import Command -from ambuild.command import ShellCommand -from ambuild.command import SymlinkCommand +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os, sys -class ExtractDebugInfoCommand(Command): - def __init__(self, binary, outfile): - Command.__init__(self) - self.binary = binary - self.outfile = outfile +# Simple extensions do not need to modify this file. - def run(self, runner, job): - if not self.binary.NeedsRelink(self.outfile): - return +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 + self.platformSpec = platform - if AMBuild.target['platform'] == 'linux': - job.AddCommand(ShellCommand('objcopy --only-keep-debug ' + self.outfile + ' ' + self.outfile + '.dbg')) - job.AddCommand(ShellCommand('objcopy --strip-debug ' + self.outfile)) - job.AddCommand(ShellCommand('objcopy --add-gnu-debuglink=' + os.path.basename(self.outfile) + '.dbg ' + self.outfile)) - elif AMBuild.target['platform'] == 'darwin': - job.AddCommand(ShellCommand('dsymutil ' + self.outfile)) - job.AddCommand(ShellCommand('strip -S ' + self.outfile)) + # By default, nothing supports x64. + if type(platform) is list: + self.platformSpec = {p: ['x86'] for p in platform} + else: + self.platformSpec = platform -class SM: - def __init__(self): - self.compiler = Cpp.Compiler() + def shouldBuild(self, targets): + for cxx in targets: + if cxx.target.platform in self.platformSpec: + if cxx.target.arch in self.platformSpec[cxx.target.platform]: + return True + return False - #Build SDK info - self.possibleSdks = { } - self.possibleSdks['ep1'] = {'sdk': 'HL2SDK', 'ext': '1.ep1', 'def': '1', - 'name': 'EPISODEONE', 'platform': []} - self.possibleSdks['ep2'] = {'sdk': 'HL2SDKOB', 'ext': '2.ep2', 'def': '3', - 'name': 'ORANGEBOX', 'platform': []} - self.possibleSdks['css'] = {'sdk': 'HL2SDKCSS', 'ext': '2.css', 'def': '6', - 'name': 'CSS', 'platform': []} - self.possibleSdks['ep2v'] = {'sdk': 'HL2SDKOBVALVE', 'ext': '2.ep2v', 'def': '7', - 'name': 'ORANGEBOXVALVE', 'platform': ['windows', 'linux', 'darwin']} - self.possibleSdks['l4d'] = {'sdk': 'HL2SDKL4D', 'ext': '2.l4d', 'def': '8', - 'name': 'LEFT4DEAD', 'platform': []} - self.possibleSdks['l4d2'] = {'sdk': 'HL2SDKL4D2', 'ext': '2.l4d2', 'def': '9', - 'name': 'LEFT4DEAD2', 'platform': []} - self.possibleSdks['darkm'] = {'sdk': 'HL2SDK-DARKM', 'ext': '2.darkm', 'def': '2', - 'name': 'DARKMESSIAH', 'platform': []} - self.possibleSdks['swarm'] = {'sdk': 'HL2SDK-SWARM', 'ext': '2.swarm', 'def': '10', - 'name': 'ALIENSWARM', 'platform': []} - self.possibleSdks['bgt'] = {'sdk': 'HL2SDK-BGT', 'ext': '2.bgt', 'def': '4', - 'name': 'BLOODYGOODTIME', 'platform': []} - self.possibleSdks['eye'] = {'sdk': 'HL2SDK-EYE', 'ext': '2.eye', 'def': '5', - 'name': 'EYE', 'platform': []} - self.possibleSdks['csgo'] = {'sdk': 'HL2SDKCSGO', 'ext': '2.csgo', 'def': '12', - 'name': 'CSGO', 'platform': []} - - self.sdkInfo = { } - - if AMBuild.mode == 'config': - #Detect compilers - self.compiler.DetectAll(AMBuild) - - #Detect variables - envvars = { 'MMSOURCE19': 'mmsource-1.9', - 'SOURCEMOD14': 'sourcemod-1.7', - 'HL2SDKCSS': 'hl2sdk-css', - 'HL2SDKOBVALVE': 'hl2sdk-ob-valve', - 'HL2SDKL4D': 'hl2sdk-l4d', - 'HL2SDKL4D2': 'hl2sdk-l4d2', - 'HL2SDKCSGO': 'hl2sdk-csgo' - } - - if AMBuild.target['platform'] != 'darwin': - envvars['HL2SDK'] = 'hl2sdk' - envvars['HL2SDKOB'] = 'hl2sdk-ob' - - if AMBuild.target['platform'] == 'windows': - envvars['HL2SDK-DARKM'] = 'hl2sdk-darkm' - envvars['HL2SDK-SWARM'] = 'hl2sdk-swarm' - envvars['HL2SDK-BGT'] = 'hl2sdk-bgt' - envvars['HL2SDK-EYE'] = 'hl2sdk-eye' - - # Finds if a dict with `key` set to `value` is present on the dict of dicts `dictionary` - def findDictByKey(dictionary, key, value): - for index in dictionary: - elem = dictionary[index] - if elem[key] == value: - return (elem, index) - return None - - for i in envvars: - if i in os.environ: - path = os.environ[i] - if not os.path.isdir(path): - raise Exception('Path for {0} was not found: {1}'.format(i, path)) - elif i.startswith('HL2SDK'): - (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i) - self.sdkInfo[sdk] = info - else: - head = os.getcwd() - oldhead = None - while head != None and head != oldhead: - path = os.path.join(head, envvars[i]) - if os.path.isdir(path): - break - oldhead = head - head, tail = os.path.split(head) - if i.startswith('HL2SDK'): - if head != None and head != oldhead: - (info, sdk) = findDictByKey(self.possibleSdks, 'sdk', i) - self.sdkInfo[sdk] = info - elif head == None or head == oldhead: - raise Exception('Could not find a valid path for {0}'.format(i)) - AMBuild.cache.CacheVariable(i, path) - - if len(self.sdkInfo) < 1: - raise Exception('At least one SDK must be available.') - - AMBuild.cache.CacheVariable('sdkInfo', self.sdkInfo) - - #Set up defines - cxx = self.compiler.cxx - if isinstance(cxx, Cpp.CompatGCC): - if isinstance(cxx, Cpp.GCC): - self.vendor = 'gcc' - elif isinstance(cxx, Cpp.Clang): - self.vendor = 'clang' - self.compiler.AddToListVar('CDEFINES', 'stricmp=strcasecmp') - self.compiler.AddToListVar('CDEFINES', '_stricmp=strcasecmp') - self.compiler.AddToListVar('CDEFINES', '_snprintf=snprintf') - self.compiler.AddToListVar('CDEFINES', '_vsnprintf=vsnprintf') - self.compiler.AddToListVar('CFLAGS', '-pipe') - self.compiler.AddToListVar('CFLAGS', '-fno-strict-aliasing') - if (self.vendor == 'gcc' and cxx.majorVersion >= 4) or self.vendor == 'clang': - self.compiler.AddToListVar('CFLAGS', '-fvisibility=hidden') - self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden') - self.compiler.AddToListVar('CFLAGS', '-Wall') - self.compiler.AddToListVar('CFLAGS', '-Werror') - self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized') - self.compiler.AddToListVar('CFLAGS', '-Wno-unused') - self.compiler.AddToListVar('CFLAGS', '-Wno-switch') - self.compiler.AddToListVar('CFLAGS', '-msse') - self.compiler.AddToListVar('CFLAGS', '-g3') - self.compiler.AddToListVar('CFLAGS', '-m32') - self.compiler.AddToListVar('POSTLINKFLAGS', '-m32') - self.compiler.AddToListVar('CXXFLAGS', '-fno-exceptions') - self.compiler.AddToListVar('CXXFLAGS', '-fno-threadsafe-statics') - self.compiler.AddToListVar('CXXFLAGS', '-Wno-non-virtual-dtor') - self.compiler.AddToListVar('CXXFLAGS', '-Wno-overloaded-virtual') - if (self.vendor == 'gcc' and cxx.majorVersion >= 4 and cxx.minorVersion >= 3) or \ - (self.vendor == 'clang' and cxx.majorVersion >= 3): - self.compiler.AddToListVar('CXXFLAGS', '-Wno-delete-non-virtual-dtor') - self.compiler.AddToListVar('CDEFINES', 'HAVE_STDINT_H') - self.compiler.AddToListVar('CDEFINES', 'GNUC') - if self.vendor == 'gcc': - self.compiler.AddToListVar('CFLAGS', '-mfpmath=sse') - elif isinstance(cxx, Cpp.MSVC): - self.vendor = 'msvc' - if AMBuild.options.debug == '1': - self.compiler.AddToListVar('CFLAGS', '/MTd') - self.compiler.AddToListVar('POSTLINKFLAGS', '/NODEFAULTLIB:libcmt') - else: - self.compiler.AddToListVar('CFLAGS', '/MT') - self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_DEPRECATE') - self.compiler.AddToListVar('CDEFINES', '_CRT_SECURE_NO_WARNINGS') - self.compiler.AddToListVar('CDEFINES', '_CRT_NONSTDC_NO_DEPRECATE') - self.compiler.AddToListVar('CXXFLAGS', '/EHsc') - self.compiler.AddToListVar('CFLAGS', '/W3') - self.compiler.AddToListVar('CFLAGS', '/nologo') - self.compiler.AddToListVar('CFLAGS', '/Zi') - self.compiler.AddToListVar('CXXFLAGS', '/TP') - self.compiler.AddToListVar('POSTLINKFLAGS', '/DEBUG') - self.compiler.AddToListVar('POSTLINKFLAGS', '/MACHINE:X86') - self.compiler.AddToListVar('POSTLINKFLAGS', '/SUBSYSTEM:WINDOWS') - self.compiler.AddToListVar('POSTLINKFLAGS', 'kernel32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'user32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'gdi32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'winspool.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'comdlg32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'advapi32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'shell32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'ole32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'oleaut32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'uuid.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'odbc32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'odbccp32.lib') - self.compiler.AddToListVar('POSTLINKFLAGS', 'legacy_stdio_definitions.lib') - - #Optimization - if AMBuild.options.opt == '1': - self.compiler.AddToListVar('CDEFINES', 'NDEBUG') - if self.vendor == 'gcc' or self.vendor == 'clang': - self.compiler.AddToListVar('CFLAGS', '-O3') - elif self.vendor == 'msvc': - self.compiler.AddToListVar('CFLAGS', '/Ox') - self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:ICF') - self.compiler.AddToListVar('POSTLINKFLAGS', '/OPT:REF') - - #Debugging - if AMBuild.options.debug == '1': - self.compiler.AddToListVar('CDEFINES', 'DEBUG') - self.compiler.AddToListVar('CDEFINES', '_DEBUG') - if self.vendor == 'msvc': - self.compiler.AddToListVar('CFLAGS', '/Od') - self.compiler.AddToListVar('CFLAGS', '/RTC1') - - #Platform-specifics - if AMBuild.target['platform'] == 'linux': - self.compiler.AddToListVar('CDEFINES', 'POSIX') - self.compiler.AddToListVar('CDEFINES', '_LINUX') - if self.vendor == 'gcc': - self.compiler.AddToListVar('POSTLINKFLAGS', '-static-libgcc') - if self.vendor == 'clang': - self.compiler.AddToListVar('POSTLINKFLAGS', '-lgcc_eh') - elif AMBuild.target['platform'] == 'darwin': - self.compiler.AddToListVar('CDEFINES', 'OSX') - self.compiler.AddToListVar('CDEFINES', '_OSX') - self.compiler.AddToListVar('POSTLINKFLAGS', '-mmacosx-version-min=10.5') - self.compiler.AddToListVar('POSTLINKFLAGS', ['-arch', 'i386']) - self.compiler.AddToListVar('POSTLINKFLAGS', '-lstdc++') - - # For OS X dylib versioning - import re - productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r') - productContents = productFile.read() - productFile.close() - m = re.match('(\d+)\.(\d+)\.(\d+).*', productContents) - if m == None: - self.version = '1.0.0' - else: - major, minor, release = m.groups() - self.version = '{0}.{1}.{2}'.format(major, minor, release) - AMBuild.cache.CacheVariable('version', self.version) - elif AMBuild.target['platform'] == 'windows': - self.compiler.AddToListVar('CDEFINES', 'WIN32') - self.compiler.AddToListVar('CDEFINES', '_WINDOWS') - - #Finish up - self.compiler.AddToListVar('CDEFINES', 'SOURCEMOD_BUILD') - self.compiler.AddToListVar('CDEFINES', 'SM_GENERATED_BUILD') - self.compiler.AddToListVar('CINCLUDES', - os.path.join(AMBuild.outputFolder, 'includes')) - self.compiler.ToConfig(AMBuild, 'compiler') - AMBuild.cache.CacheVariable('vendor', self.vendor) - self.targetMap = { } - AMBuild.cache.CacheVariable('targetMap', self.targetMap) - else: - self.sdkInfo = AMBuild.cache['sdkInfo'] - self.compiler.FromConfig(AMBuild, 'compiler') - self.targetMap = AMBuild.cache['targetMap'] - - if AMBuild.target['platform'] == 'windows': - self.compiler.AddToListVar('RCINCLUDES', os.path.join(AMBuild.sourceFolder, 'extension')) - self.mmsPath = AMBuild.cache['MMSOURCE19'] - - def DefaultCompiler(self): - return self.compiler.Clone() - - def JobMatters(self, jobname): - file = sys._getframe().f_code.co_filename - if AMBuild.mode == 'config': - self.targetMap[jobname] = file - return True - if len(AMBuild.args) == 0: - return True - if not jobname in AMBuild.args: - return False - - def AutoVersion(self, folder, binary): - if AMBuild.target['platform'] == 'windows': - env = {'RCDEFINES': ['BINARY_NAME="' + binary.binaryFile + '"', 'SM_GENERATED_BUILD']} - binary.AddResourceFile(os.path.join(folder, 'version.rc' ), env) - elif AMBuild.target['platform'] == 'darwin' and isinstance(binary, Cpp.LibraryBuilder): - binary.compiler['POSTLINKFLAGS'].extend(['-compatibility_version', '1.0.0']) - binary.compiler['POSTLINKFLAGS'].extend(['-current_version', AMBuild.cache['version']]) - else: - return - - def ExtractDebugInfo(self, job, binary): - src = os.path.join('..', AMBuild.outputFolder, job.workFolder, binary.binaryFile) - job.AddCommand(ExtractDebugInfoCommand(binary, src)) - - def PreSetupHL2Job(self, job, builder, sdk): - info = self.sdkInfo[sdk] - sdkPath = AMBuild.cache[info['sdk']] - if AMBuild.target['platform'] == 'linux': - if sdk == 'ep1': - staticLibs = os.path.join(sdkPath, 'linux_sdk') - else: - staticLibs = os.path.join(sdkPath, 'lib', 'linux') - workFolder = os.path.join(AMBuild.outputFolder, job.workFolder) - if sdk in ['ep2v', 'css']: - libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib_srv.so', 'libtier0_srv.so'] - for lib in libs: - link = os.path.join(workFolder, lib) - target = os.path.join(staticLibs, lib) - try: - os.lstat(link) - except: - job.AddCommand(SymlinkCommand(link, target)) - elif sdk in ['l4d', 'l4d2', 'csgo']: - libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.so', 'libtier0.so'] - if sdk == 'csgo': - libs.append('interfaces_i486.a') - for lib in libs: - link = os.path.join(workFolder, lib) - target = os.path.join(staticLibs, lib) - try: - os.lstat(link) - except: - job.AddCommand(SymlinkCommand(link, target)) - else: - libs = ['tier1_i486.a', 'mathlib_i486.a', 'vstdlib_i486.so', 'tier0_i486.so'] - for lib in libs: - link = os.path.join(workFolder, lib) - target = os.path.join(staticLibs, lib) - try: - os.lstat(link) - except: - job.AddCommand(SymlinkCommand(link, target)) - elif AMBuild.target['platform'] == 'darwin': - staticLibs = os.path.join(sdkPath, 'lib', 'mac') - workFolder = os.path.join(AMBuild.outputFolder, job.workFolder) - libs = ['tier1_i486.a', 'mathlib_i486.a', 'libvstdlib.dylib', 'libtier0.dylib'] - if sdk == 'csgo': - libs.append('interfaces_i486.a') - for lib in libs: - link = os.path.join(workFolder, lib) - target = os.path.join(staticLibs, lib) - try: - os.lstat(link) - except: - job.AddCommand(SymlinkCommand(link, target)) - elif AMBuild.target['platform'] == 'windows': - libs = ['tier0', 'tier1', 'vstdlib', 'mathlib'] - if sdk in ['swarm', 'csgo']: - libs.append('interfaces') - for lib in libs: - libPath = os.path.join(sdkPath, 'lib', 'public', lib) + '.lib' - builder.RebuildIfNewer(libPath) - builder['POSTLINKFLAGS'].append(libPath) - - def PostSetupHL2Job(self, job, builder, sdk): - if AMBuild.target['platform'] in ['linux', 'darwin']: - builder.AddObjectFiles(['tier1_i486.a', 'mathlib_i486.a']) - if sdk == 'csgo': - builder.AddObjectFiles(['interfaces_i486.a']) - - def DefaultHL2Compiler(self, path, sdk, noLink = False, oldMms = '-legacy'): - compiler = self.DefaultCompiler() - - mms = 'core' - if sdk == 'ep1': - mms += oldMms - - compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms)) - compiler['CXXINCLUDES'].append(os.path.join(self.mmsPath, mms, 'sourcehook')) - - info = self.possibleSdks - compiler['CDEFINES'].extend(['SE_' + info[i]['name'] + '=' + info[i]['def'] for i in info]) - - paths = [['public'], ['public', 'engine'], ['public', 'mathlib'], ['public', 'vstdlib'], ['public', 'tier0'], ['public', 'tier1']] - if sdk == 'ep1' or sdk == 'darkm': - paths.append(['public', 'dlls']) - paths.append(['game_shared']) - else: - paths.append(['public', 'game', 'server']) - paths.append(['public', 'toolframework']) - paths.append(['game', 'shared']) - paths.append(['common']) - - info = self.sdkInfo[sdk] - sdkPath = AMBuild.cache[info['sdk']] - - compiler['CDEFINES'].append('SOURCE_ENGINE=' + info['def']) - - if sdk in ['swarm','csgo']: - if AMBuild.target['platform'] == 'windows': - compiler['CDEFINES'].extend(['COMPILER_MSVC', 'COMPILER_MSVC32']) - else: - compiler['CDEFINES'].extend(['COMPILER_GCC', 'POSIX']) - - if sdk == 'ep1': - if AMBuild.target['platform'] == 'linux': - staticLibs = os.path.join(sdkPath, 'linux_sdk') - else: - if AMBuild.target['platform'] == 'linux': - staticLibs = os.path.join(sdkPath, 'lib', 'linux') - elif AMBuild.target['platform'] == 'darwin': - staticLibs = os.path.join(sdkPath, 'lib', 'mac') - - for i in paths: - compiler['CXXINCLUDES'].append(os.path.join(sdkPath, *i)) - - if not noLink: - if AMBuild.target['platform'] == 'linux': - compiler['POSTLINKFLAGS'][0:0] = ['-lm'] - if sdk in ['ep2v', 'css']: - compiler['POSTLINKFLAGS'][0:0] = ['libtier0_srv.so'] - compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib_srv.so'] - elif sdk in ['l4d', 'l4d2', 'csgo']: - compiler['POSTLINKFLAGS'][0:0] = ['libtier0.so'] - compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.so'] - else: - compiler['POSTLINKFLAGS'][0:0] = ['tier0_i486.so'] - compiler['POSTLINKFLAGS'][0:0] = ['vstdlib_i486.so'] - elif AMBuild.target['platform'] == 'darwin': - compiler['POSTLINKFLAGS'][0:0] = ['libtier0.dylib'] - compiler['POSTLINKFLAGS'][0:0] = ['libvstdlib.dylib'] - - return compiler - -sm = SM() -globals = { - 'SM': sm +WinLinux = ['windows', 'linux'] +TF2 = { + 'windows': ['x86', 'x86_64'], + 'linux': ['x86', 'x86_64'] +} +CSGO = { + 'windows': ['x86'], + 'linux': ['x86', 'x86_64'] } -AMBuild.Include(os.path.join('buildbot', 'Versioning'), globals) +PossibleSDKs = { +# 'episode1': SDK('HL2SDK', '1.ep1', '1', 'EPISODEONE', WinLinux, 'episode1'), +# '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', WinLinux, 'css'), + 'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', WinLinux, 'hl2dm'), + 'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', WinLinux, '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'), +} -FileList = [ - ['extension', 'AMBuilder'], - ['buildbot', 'PackageScript'], - ['buildbot', 'BreakpadSymbols'] - ] +def ResolveEnvPath(env, folder): + if env in os.environ: + path = os.environ[env] + if os.path.isdir(path): + return path + return None -for parts in FileList: - AMBuild.Include(os.path.join(*parts), globals) + head = os.getcwd() + oldhead = None + while head != None and head != oldhead: + path = os.path.join(head, folder) + if os.path.isdir(path): + return path + oldhead = head + head, tail = os.path.split(head) + + return None + +def Normalize(path): + return os.path.abspath(os.path.normpath(path)) + +def SetArchFlags(compiler): + if compiler.behavior == 'gcc': + if compiler.target.arch == 'x86_64': + compiler.cflags += ['-fPIC'] + elif compiler.like('msvc'): + if compiler.target.arch == 'x86_64': + compiler.defines += ['WIN64'] + +class ExtensionConfig(object): + def __init__(self): + self.sdks = {} + self.binaries = [] + self.extensions = [] + self.generated_headers = None + self.productVersion = None + self.mms_root = None + self.sm_root = None + self.all_targets = [] + self.target_archs = set() + + if builder.options.targets: + target_archs = builder.options.targets.split(',') + else: + target_archs = ['x86', 'x86_64'] + + for arch in target_archs: + try: + cxx = builder.DetectCxx(target_arch = arch) + self.target_archs.add(cxx.target.arch) + except Exception as e: + # Error if archs were manually overridden. + if builder.options.targets: + raise + print('Skipping target {}: {}'.format(arch, e)) + continue + self.all_targets.append(cxx) + + if not self.all_targets: + raise Exception('No suitable C/C++ compiler was found.') + + def use_auto_versioning(self): + return not getattr(builder.options, 'disable_auto_versioning', False) + + 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 + def tag(self): + if builder.options.debug == '1': + return 'Debug' + return 'Release' + + def detectProductVersion(self): + builder.AddConfigureFile('product.version') + + # For OS X dylib versioning + import re + with open(os.path.join(builder.sourcePath, 'product.version'), 'r') as fp: + productContents = fp.read() + m = re.match('(\\d+)\.(\\d+)\.(\\d+).*', productContents) + if m == None: + self.productVersion = '1.0.0' + else: + major, minor, release = m.groups() + self.productVersion = '{0}.{1}.{2}'.format(major, minor, 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 sdk.shouldBuild(self.all_targets): + if builder.options.hl2sdk_root: + sdk_path = os.path.join(os.path.realpath(builder.options.hl2sdk_root), sdk.folder) + else: + sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder) + if sdk_path is None or not os.path.isdir(sdk_path): + if use_all or sdk_name in sdk_list: + raise Exception('Could not find a valid path for {0}'.format(sdk.envvar)) + continue + if use_all or use_present or sdk_name in sdk_list: + sdk.path = Normalize(sdk_path) + self.sdks[sdk_name] = sdk + + if len(self.sdks) < 1: + raise Exception('At least one SDK must be available.') + + if builder.options.sm_path: + self.sm_root = os.path.realpath(builder.options.sm_path) + else: + 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): + raise Exception('Could not find a source copy of SourceMod') + self.sm_root = Normalize(self.sm_root) + + if builder.options.mms_path: + self.mms_root = builder.options.mms_path + else: + self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10') + if not self.mms_root: + self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source') + if not self.mms_root: + self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central') + + if not self.mms_root or not os.path.isdir(self.mms_root): + raise Exception('Could not find a source copy of Metamod:Source') + self.mms_root = Normalize(self.mms_root) + + def configure(self): + + if not set(self.target_archs).issubset(['x86', 'x86_64']): + raise Exception('Unknown target architecture: {0}'.format(self.target_archs)) + + for cxx in self.all_targets: + self.configure_cxx(cxx) + + def configure_cxx(self, cxx): + if cxx.family == 'msvc': + if cxx.version < 1900: + raise Exception('Only MSVC 2015 and later are supported, c++14 support is required.') + if cxx.family == 'gcc': + if cxx.version < 'gcc-4.9': + raise Exception('Only GCC versions 4.9 or greater are supported, c++14 support is required.') + if cxx.family == 'clang': + if cxx.version < 'clang-3.4': + raise Exception('Only clang versions 3.4 or greater are supported, c++14 support is required.') + + if cxx.like('gcc'): + self.configure_gcc(cxx) + elif cxx.family == 'msvc': + self.configure_msvc(cxx) + cxx.defines += ['HAVE_STRING_H'] + + # Optimizaiton + if builder.options.opt == '1': + cxx.defines += ['NDEBUG'] + + # Debugging + if builder.options.debug == '1': + cxx.defines += ['DEBUG', '_DEBUG'] + + # Platform-specifics + if cxx.target.platform == 'linux': + self.configure_linux(cxx) + elif cxx.target.platform == 'mac': + self.configure_mac(cxx) + elif cxx.target.platform == 'windows': + self.configure_windows(cxx) + + cxx.includes += [ + 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): + cxx.defines += [ + 'stricmp=strcasecmp', + '_stricmp=strcasecmp', + '_snprintf=snprintf', + '_vsnprintf=vsnprintf', + 'typeof=__typeof__', + 'HAVE_STDINT_H', + 'GNUC', + ] + cxx.cflags += [ + '-pipe', + '-fno-strict-aliasing', + '-Wall', + '-Wno-unused', + '-Wno-switch', + '-Wno-array-bounds', + '-msse', + '-fvisibility=hidden', + ] + cxx.cxxflags += [ + '-std=c++14', + '-fno-threadsafe-statics', + '-Wno-non-virtual-dtor', + '-Wno-overloaded-virtual', + '-fvisibility-inlines-hidden', + '-fpermissive' + ] + + have_gcc = cxx.vendor == 'gcc' + have_clang = cxx.vendor == 'clang' + if cxx.version >= 'clang-3.9' or cxx.version == 'clang-3.4' or cxx.version > 'apple-clang-6.0': + cxx.cxxflags += ['-Wno-expansion-to-defined'] + if cxx.version == 'clang-3.9' or cxx.version == 'apple-clang-8.0': + cxx.cflags += ['-Wno-varargs'] + if cxx.version >= 'clang-3.4' or cxx.version >= 'apple-clang-7.0': + cxx.cxxflags += ['-Wno-inconsistent-missing-override'] + if cxx.version >= 'clang-2.9' or cxx.version >= 'apple-clang-3.0': + cxx.cxxflags += ['-Wno-null-dereference'] + if have_clang or (cxx.version >= 'gcc-4.6'): + cxx.cflags += ['-Wno-narrowing'] + if have_clang or (cxx.version >= 'gcc-4.7'): + cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] + if cxx.version >= 'gcc-4.8': + cxx.cflags += ['-Wno-unused-result'] + if cxx.version >= 'gcc-9.0': + cxx.cxxflags += ['-Wno-class-memaccess', '-Wno-packed-not-aligned'] + + if have_clang: + cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] + if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4': + cxx.cxxflags += ['-Wno-deprecated-register'] + else: + cxx.cxxflags += ['-Wno-deprecated'] + cxx.cflags += ['-Wno-sometimes-uninitialized'] + + # Work around SDK warnings. + if cxx.version >= 'clang-10.0': + cxx.cflags += ['-Wno-implicit-int-float-conversion', '-Wno-tautological-overlap-compare'] + + if have_gcc: + cxx.cflags += ['-mfpmath=sse'] + + if builder.options.opt == '1': + cxx.cflags += ['-O3'] + + def configure_msvc(self, cxx): + if builder.options.debug == '1': + cxx.cflags += ['/MTd'] + cxx.linkflags += ['/NODEFAULTLIB:libcmt'] + else: + cxx.cflags += ['/MT'] + cxx.defines += [ + '_CRT_SECURE_NO_DEPRECATE', + '_CRT_SECURE_NO_WARNINGS', + '_CRT_NONSTDC_NO_DEPRECATE', + '_ITERATOR_DEBUG_LEVEL=0', + ] + cxx.cflags += [ + '/W3', + ] + cxx.cxxflags += [ + '/EHsc', + '/TP', + ] + cxx.linkflags += [ + '/MACHINE:X86', + 'kernel32.lib', + 'user32.lib', + 'gdi32.lib', + 'winspool.lib', + 'comdlg32.lib', + 'advapi32.lib', + 'shell32.lib', + 'ole32.lib', + 'oleaut32.lib', + 'uuid.lib', + 'odbc32.lib', + 'odbccp32.lib', + ] + + if builder.options.opt == '1': + cxx.cflags += ['/Ox', '/Zo'] + cxx.linkflags += ['/OPT:ICF', '/OPT:REF'] + + if builder.options.debug == '1': + cxx.cflags += ['/Od', '/RTC1'] + + # This needs to be after our optimization flags which could otherwise disable it. + # Don't omit the frame pointer. + cxx.cflags += ['/Oy-'] + + def configure_linux(self, cxx): + cxx.defines += ['_LINUX', 'POSIX'] + cxx.linkflags += ['-Wl,--exclude-libs,ALL', '-lm'] + if cxx.vendor == 'gcc': + cxx.linkflags += ['-static-libgcc'] + elif cxx.vendor == 'clang': + cxx.linkflags += ['-lgcc_eh'] + cxx.linkflags += ['-static-libstdc++'] + + def configure_mac(self, cxx): + cxx.defines += ['OSX', '_OSX', 'POSIX'] + cxx.cflags += ['-mmacosx-version-min=10.7'] + cxx.linkflags += [ + '-mmacosx-version-min=10.7', + '-arch', 'i386', + '-lstdc++', + '-stdlib=libstdc++', + ] + cxx.cxxflags += ['-stdlib=libstdc++'] + + def configure_windows(self, cxx): + cxx.defines += ['WIN32', '_WINDOWS'] + + def ConfigureForExtension(self, context, compiler): + compiler.cxxincludes += [ + os.path.join(context.currentSourcePath), + 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, 'sourcepawn', 'include'), + os.path.join(self.sm_root, 'public', 'amtl', 'amtl'), + os.path.join(self.sm_root, 'public', 'amtl'), + ] + return compiler + + def ConfigureForHL2(self, context, binary, sdk): + compiler = binary.compiler + SetArchFlags(compiler) + + compiler.cxxincludes += [ + os.path.join(self.mms_root, 'core'), + os.path.join(self.mms_root, 'core', 'sourcehook'), + ] + + defines = ['RAD_TELEMETRY_DISABLED'] + defines += ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs] + compiler.defines += defines + + paths = [ + ['public'], + ['public', 'engine'], + ['public', 'mathlib'], + ['public', 'vstdlib'], + ['public', 'tier0'], + ['public', 'tier1'] + ] + if sdk.name == 'episode1' or sdk.name == 'darkm': + paths.append(['public', 'dlls']) + paths.append(['game_shared']) + else: + paths.append(['public', 'game', 'server']) + paths.append(['public', 'toolframework']) + paths.append(['game', 'shared']) + paths.append(['common']) + + compiler.defines += ['SOURCE_ENGINE=' + sdk.code] + + if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'): + # The 2013 SDK already has these in public/tier0/basetypes.h + compiler.defines.remove('stricmp=strcasecmp') + compiler.defines.remove('_stricmp=strcasecmp') + compiler.defines.remove('_snprintf=snprintf') + compiler.defines.remove('_vsnprintf=vsnprintf') + + if compiler.like('msvc'): + compiler.defines += ['COMPILER_MSVC'] + if compiler.target.arch == 'x86': + compiler.defines += ['COMPILER_MSVC32'] + elif compiler.target.arch == 'x86_64': + compiler.defines += ['COMPILER_MSVC64'] + compiler.linkflags += ['legacy_stdio_definitions.lib'] + else: + compiler.defines += ['COMPILER_GCC'] + + if compiler.target.arch == 'x86_64': + compiler.defines += ['X64BITS', 'PLATFORM_64BITS'] + + # For everything after Swarm, this needs to be defined for entity networking + # to work properly with sendprop value changes. + if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']: + compiler.defines += ['NETWORK_VARS_ENABLED'] + + if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2']: + if compiler.target.platform in ['linux', 'mac']: + compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE'] + + if compiler.target.platform == 'linux': + if sdk.name in ['csgo', 'blade']: + compiler.linkflags.remove('-static-libstdc++') + compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0'] + + for path in paths: + compiler.cxxincludes += [os.path.join(sdk.path, *path)] + + if compiler.target.platform == 'linux': + if sdk.name == 'episode1': + lib_folder = os.path.join(sdk.path, 'linux_sdk') + elif sdk.name in ['sdk2013', 'bms']: + lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32') + elif compiler.target.arch == 'x86_64': + lib_folder = os.path.join(sdk.path, 'lib', 'linux64') + else: + lib_folder = os.path.join(sdk.path, 'lib', 'linux') + elif compiler.target.platform == 'mac': + if sdk.name in ['sdk2013', 'bms']: + lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32') + elif compiler.target.arch == 'x86_64': + lib_folder = os.path.join(sdk.path, 'lib', 'osx64') + else: + lib_folder = os.path.join(sdk.path, 'lib', 'mac') + + if compiler.target.platform in ['linux', 'mac']: + if sdk.name in ['sdk2013', 'bms'] or compiler.target.arch == 'x86_64': + compiler.postlink += [ + os.path.join(lib_folder, 'tier1.a'), + os.path.join(lib_folder, 'mathlib.a') + ] + else: + compiler.postlink += [ + os.path.join(lib_folder, 'tier1_i486.a'), + os.path.join(lib_folder, 'mathlib_i486.a') + ] + + if sdk.name in ['blade', 'insurgency', 'doi', 'csgo']: + if compiler.target.arch == 'x86_64': + compiler.postlink += [os.path.join(lib_folder, 'interfaces.a')] + else: + compiler.postlink += [os.path.join(lib_folder, 'interfaces_i486.a')] + + dynamic_libs = [] + if compiler.target.platform == 'linux': + if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2', 'insurgency', 'doi']: + dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so'] + elif compiler.target.arch == 'x86_64' and sdk.name in ['csgo', 'mock']: + dynamic_libs = ['libtier0_client.so', 'libvstdlib_client.so'] + elif sdk.name in ['l4d', 'blade', 'insurgency', 'doi', 'csgo']: + dynamic_libs = ['libtier0.so', 'libvstdlib.so'] + else: + dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so'] + elif compiler.target.platform == 'mac': + compiler.linkflags.append('-liconv') + dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib'] + elif compiler.target.platform == 'windows': + libs = ['tier0', 'tier1', 'vstdlib', 'mathlib'] + if sdk.name in ['swarm', 'blade', 'insurgency', 'doi', 'csgo']: + libs.append('interfaces') + for lib in libs: + if compiler.target.arch == 'x86': + lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib' + elif compiler.target.arch == 'x86_64': + lib_path = os.path.join(sdk.path, 'lib', 'public', 'win64', lib) + '.lib' + compiler.linkflags.append(lib_path) + + for library in dynamic_libs: + source_path = os.path.join(lib_folder, library) + output_path = os.path.join(binary.localFolder, library) + + # Ensure the output path exists. + context.AddFolder(binary.localFolder) + output = context.AddSymlink(source_path, output_path) + + compiler.weaklinkdeps += [output] + compiler.linkflags[0:0] = [library] + + return binary + + def HL2Config(self, project, context, compiler, name, sdk): + binary = project.Configure(compiler, name, + '{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch)) + self.AddVersioning(binary) + return self.ConfigureForHL2(context, binary, sdk) + + def HL2ExtConfig(self, project, context, compiler, name, sdk): + binary = project.Configure(compiler, name, + '{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch)) + self.AddVersioning(binary) + self.ConfigureForHL2(context, binary, sdk) + self.ConfigureForExtension(context, binary.compiler) + return binary + +Extension = ExtensionConfig() +Extension.detectProductVersion() +Extension.detectSDKs() +Extension.configure() + +if Extension.use_auto_versioning(): + Extension.generated_headers = builder.Build('buildbot/Versioning') + +builder.targets = builder.CloneableList(Extension.all_targets) +# Add additional buildscripts here +BuildScripts = [ + 'extension/AMBuilder', + 'buildbot/PackageScript', + 'buildbot/BreakpadSymbols' +] + +builder.Build(BuildScripts, {'Extension': Extension}) \ No newline at end of file diff --git a/buildbot/BreakpadSymbols b/buildbot/BreakpadSymbols index 7d40e8e..a85f0bf 100644 --- a/buildbot/BreakpadSymbols +++ b/buildbot/BreakpadSymbols @@ -1,41 +1,39 @@ # vim: set ts=2 sw=2 tw=99 noet ft=python: -import os -import urllib.request -from ambuild.command import Command -from ambuild.command import ShellCommand +import os, sys -class IterateDebugInfoCommand(Command): - def run(self, master, job): - pdblog = open(os.path.join(AMBuild.outputFolder, 'pdblog.txt'), 'rt') - for debug_info in pdblog: - debug_info = os.path.join(AMBuild.outputFolder, debug_info.strip()) - job.AddCommand(SymbolCommand(debug_info, symbolServer)) - pdblog.close() - -class SymbolCommand(ShellCommand): - def __init__(self, debugFile, symbolServer): - self.serverResponse = None - self.symbolServer = symbolServer - if AMBuild.target['platform'] == 'linux': - cmdstring = "dump_syms {0} {1}".format(debugFile, os.path.dirname(debugFile)) - elif AMBuild.target['platform'] == 'darwin': - cmdstring = "dump_syms {0}".format(debugFile) - elif AMBuild.target['platform'] == 'windows': - cmdstring = "dump_syms.exe {0}".format(debugFile) - ShellCommand.__init__(self, cmdstring) - def run(self, master, job): - ShellCommand.run(self, master, job) - if self.stdout != None and len(self.stdout) > 0: - request = urllib.request.Request(symbolServer, self.stdout.encode('utf-8')) - request.add_header("Content-Type", "text/plain") - self.serverResponse = urllib.request.urlopen(request).read().decode('utf-8') - def spew(self, runner): - if self.stderr != None and len(self.stderr) > 0: - runner.PrintOut(self.stderr) - if self.serverResponse != None and len(self.serverResponse) > 0: - runner.PrintOut(self.serverResponse) +UPLOAD_SCRIPT = os.path.join(Extension.sm_root, 'tools', 'buildbot', 'upload_symbols.py') if 'BREAKPAD_SYMBOL_SERVER' in os.environ: - symbolServer = os.environ['BREAKPAD_SYMBOL_SERVER'] - job = AMBuild.AddJob('breakpad-symbols') - job.AddCommand(IterateDebugInfoCommand()) + symbolServer = os.environ['BREAKPAD_SYMBOL_SERVER'] + builder.SetBuildFolder('breakpad-symbols') + + for cxx_task in Extension.extensions: + if cxx_task.target.platform in ['windows']: + debug_entry = cxx_task.debug + else: + debug_entry = cxx_task.binary + + debug_file = os.path.join(builder.buildPath, debug_entry.path) + if cxx_task.target.platform == 'linux': + argv = ['dump_syms', debug_file, os.path.dirname(debug_file)] + elif cxx_task.target.platform == 'mac': + # Required once dump_syms is updated on the slaves. + #argv = ['dump_syms', '-g', debug_file + '.dSYM', debug_file] + argv = ['dump_syms', debug_file + '.dSYM'] + elif cxx_task.target.platform == 'windows': + argv = ['dump_syms.exe', debug_file] + + plat_dir = os.path.dirname(debug_file) + bin_dir = os.path.split(plat_dir)[0] + + symbol_file = '{}-{}-{}.breakpad'.format( + os.path.split(bin_dir)[1], + cxx_task.target.platform, + cxx_task.target.arch) + + argv = [sys.executable, UPLOAD_SCRIPT, symbol_file] + argv + builder.AddCommand( + inputs = [UPLOAD_SCRIPT, debug_entry], + argv = argv, + outputs = [symbol_file] + ) \ No newline at end of file diff --git a/buildbot/PackageScript b/buildbot/PackageScript index f5d06bf..014a2f1 100644 --- a/buildbot/PackageScript +++ b/buildbot/PackageScript @@ -4,112 +4,44 @@ import shutil import ambuild.osutil as osutil from ambuild.command import Command -job = AMBuild.AddJob('package') +builder.SetBuildFolder('package') -class DestroyPath(Command): - def __init__(self, folder): - Command.__init__(self) - self.folder = folder +def CreateFolders(folders): + dict = {} + for folder in folders: + path = os.path.normpath(folder) + dict[folder] = builder.AddFolder(path) + return dict - def destroy(self, path): - entries = os.listdir(path) - for entry in entries: - newpath = os.path.join(path, entry) - if os.path.isdir(newpath): - self.destroy(newpath) - os.rmdir(newpath) - elif os.path.isfile(newpath): - os.remove(newpath) - - def run(self, runner, job): - runner.PrintOut('rm -rf {0}/*'.format(self.folder)) - self.destroy(self.folder) - -class CreateFolders(Command): - def __init__(self, folders): - Command.__init__(self) - self.folders = folders - - def run(self, runner, job): - for folder in self.folders: - path = os.path.join(*folder) - runner.PrintOut('mkdir {0}'.format(path)) - os.makedirs(path) - -#Shallow folder copy -class CopyFolder(Command): - def __init__(self, fromList, toList, excludes = []): - Command.__init__(self) - self.fromPath = os.path.join(AMBuild.sourceFolder, *fromList) - self.toPath = os.path.join(*toList) - self.excludes = excludes - - def run(self, runner, job): - entries = os.listdir(self.fromPath) - for entry in entries: - if entry in self.excludes: - continue - path = os.path.join(self.fromPath, entry) - if not os.path.isfile(path): - continue - runner.PrintOut('copy {0} to {1}'.format(path, self.toPath)) - shutil.copy(path, self.toPath) - -#Single file copy -class CopyFile(Command): - def __init__(self, fromFile, toPath): - Command.__init__(self) - self.fromFile = fromFile - self.toPath = toPath - - def run(self, runner, job): - runner.PrintOut('copy {0} to {1}'.format(self.fromFile, self.toPath)) - shutil.copy(self.fromFile, self.toPath) +def CopyFiles(src, dest, filter_ext=None): + source_path = os.path.join(builder.sourcePath, src) + 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) -folders = [['addons', 'sourcemod', 'extensions'], ['addons', 'sourcemod', 'gamedata'], ['addons', 'sourcemod', 'scripting', 'include']] +folders = CreateFolders(['addons/sourcemod/extensions', 'addons/sourcemod/extensions/x64', 'addons/sourcemod/gamedata', 'addons/sourcemod/scripting', 'addons/sourcemod/scripting/include']) -#Setup -job.AddCommand(DestroyPath(os.path.join(AMBuild.outputFolder, 'package'))) -job.AddCommand(CreateFolders(folders)) - -#Copy Files -job.AddCommand(CopyFile(os.path.join(AMBuild.sourceFolder, 'connect.games.txt'), - os.path.join('addons', 'sourcemod', 'gamedata'))) -job.AddCommand(CopyFile(os.path.join(AMBuild.sourceFolder, 'connect.inc'), - os.path.join('addons', 'sourcemod', 'scripting', 'include'))) -job.AddCommand(CopyFile(os.path.join(AMBuild.sourceFolder, 'connect.sp'), - os.path.join('addons', 'sourcemod', 'scripting'))) - -bincopies = [] - -def AddNormalLibrary(name, dest): - dest = os.path.join('addons', 'sourcemod', dest) - bincopies.append(CopyFile(os.path.join('..', name, name + osutil.SharedLibSuffix()), dest)) - - # Each platform's version of dump_syms needs the path in a different format. - if AMBuild.target['platform'] == 'linux': - debug_info.append(name + '/' + name + '.so') - elif AMBuild.target['platform'] == 'darwin': - debug_info.append(name + '/' + name + '.dylib.dSYM') - elif AMBuild.target['platform'] == 'windows': - debug_info.append(name + '\\' + name + '.pdb') - -def AddHL2Library(name, dest): - for i in SM.sdkInfo: - sdk = SM.sdkInfo[i] - if AMBuild.target['platform'] not in sdk['platform']: - continue - AddNormalLibrary(name + '.ext.' + sdk['ext'], dest) - -debug_info = [] - -AddHL2Library('connect', 'extensions') - -job.AddCommandGroup(bincopies) - -pdblog = open(os.path.join(AMBuild.outputFolder, 'pdblog.txt'), 'wt') -for pdb in debug_info: - pdblog.write(pdb + '\n') +pdblog = open(os.path.join(builder.buildPath, 'pdblog.txt'), 'wt') +for cxx_task in Extension.extensions: + if cxx_task.target.arch == 'x86_64': + builder.AddCopy(cxx_task.binary, folders['addons/sourcemod/extensions/x64']) + else: + builder.AddCopy(cxx_task.binary, folders['addons/sourcemod/extensions']) + pdblog.write(cxx_task.debug.path + '\n') pdblog.close() +CopyFiles('connect.games.txt', folders['addons/sourcemod/gamedata']) +CopyFiles('connect.inc', folders['addons/sourcemod/scripting/include']) +CopyFiles('connect.sp', folders['addons/sourcemod/scripting']) + +debug_info = [] \ No newline at end of file diff --git a/buildbot/Versioning b/buildbot/Versioning index c5c731b..e3647da 100644 --- a/buildbot/Versioning +++ b/buildbot/Versioning @@ -1,55 +1,50 @@ -# vim: set ts=2 sw=2 tw=99 noet ft=python: -import os +# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: +import os, sys import re -import subprocess -from ambuild.cache import Cache -import ambuild.command as command -#Quickly try to ascertain the current repository revision -def GetVersion(): - args = ['hg', 'parent', '-R', AMBuild.sourceFolder] - p = command.RunDirectCommand(AMBuild, args) - m = re.match('changeset:\s+(\d+):(.+)', p.stdoutText) - if m == None: - raise Exception('Could not determine repository version') - return m.groups() +builder.SetBuildFolder('/') +includes = builder.AddFolder('includes') -def PerformReversioning(): - rev, cset = GetVersion() - cacheFile = os.path.join(AMBuild.outputFolder, '.ambuild', 'hgcache') - cache = Cache(cacheFile) - if os.path.isfile(cacheFile): - cache.LoadCache() - if cache.HasVariable('cset') and cache['cset'] == cset: - return False - cache.CacheVariable('cset', cset) +argv = [ + sys.executable, + os.path.join(builder.sourcePath, 'buildbot', 'generate_header.py'), + os.path.join(builder.sourcePath), + os.path.join(builder.buildPath, 'includes'), +] - productFile = open(os.path.join(AMBuild.sourceFolder, 'product.version'), 'r') - productContents = productFile.read() - productFile.close() - m = re.match('(\d+)\.(\d+)\.(\d+)(.*)', productContents) - if m == None: - raise Exception('Could not detremine product version') - major, minor, release, tag = m.groups() +outputs = [ + os.path.join(builder.buildFolder, 'includes', 'version_auto.h') +] - incFolder = os.path.join(AMBuild.sourceFolder, 'extension') - incFile = open(os.path.join(incFolder, 'version_auto.h'), 'w') - incFile.write(""" -#ifndef _AUTO_VERSION_INFORMATION_H_ -#define _AUTO_VERSION_INFORMATION_H_ +repo_head_path = os.path.join(builder.sourcePath, 'product.version') +if os.path.exists(os.path.join(builder.sourcePath, '.git')): + with open(os.path.join(builder.sourcePath, '.git', 'HEAD')) as fp: + head_contents = fp.read().strip() + if re.search('^[a-fA-F0-9]{40}$', head_contents): + repo_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') + else: + git_state = head_contents.split(':')[1].strip() + repo_head_path = os.path.join(builder.sourcePath, '.git', git_state) + if not os.path.exists(repo_head_path): + repo_head_path = os.path.join(builder.sourcePath, '.git', 'HEAD') -#define SM_BUILD_TAG \"{0}\" -#define SM_BUILD_UNIQUEID \"{1}:{2}\" SM_BUILD_TAG -#define SM_VERSION \"{3}.{4}.{5}\" -#define SM_FULL_VERSION SM_VERSION SM_BUILD_TAG -#define SM_FILE_VERSION {6},{7},{8},0 +sources = [ + os.path.join(builder.sourcePath, 'product.version'), + repo_head_path, + argv[1] +] -#endif /* _AUTO_VERSION_INFORMATION_H_ */ - -""".format(tag, rev, cset, major, minor, release, major, minor, release)) - incFile.close() - cache.WriteCache() - -PerformReversioning() +for source in sources: + if not os.path.exists(source): + print(source) +for source in sources: + if not os.path.exists(source): + print(source) +output_nodes = builder.AddCommand( + inputs=sources, + argv=argv, + outputs=outputs +) +rvalue = output_nodes \ No newline at end of file diff --git a/buildbot/generate_header.py b/buildbot/generate_header.py new file mode 100644 index 0000000..eeb508b --- /dev/null +++ b/buildbot/generate_header.py @@ -0,0 +1,61 @@ +# vim: set ts=2 sw=2 tw=99 noet ft=python: +import os, sys +import re +import subprocess + +argv = sys.argv[1:] +if len(argv) < 2: + sys.stderr.write('Usage: generate_header.py \n') + sys.exit(1) + +SourceFolder = os.path.abspath(os.path.normpath(argv[0])) +OutputFolder = os.path.normpath(argv[1]) + +def run_and_return(argv): + text = subprocess.check_output(argv) + if str != bytes: + text = str(text, 'utf-8') + return text.strip() + +def GetGHVersion(): + p = run_and_return(['hg', 'parent', '-R', SourceFolder]) + m = re.match('changeset:\s+(\d+):(.+)', p.stdoutText) + if m == None: + raise Exception('Could not determine repository version') + return m.groups() + +def GetGitVersion(): + revision_count = run_and_return(['git', 'rev-list', '--count', 'HEAD']) + revision_hash = run_and_return(['git', 'log', '--pretty=format:%h:%H', '-n', '1']) + shorthash, longhash = revision_hash.split(':') + + return revision_count, shorthash + +rev = None +cset = None +rev, cset = GetGitVersion() + +productFile = open(os.path.join(SourceFolder, 'product.version'), 'r') +productContents = productFile.read() +productFile.close() +m = re.match('(\d+)\.(\d+)\.(\d+)(.*)', productContents) +if m == None: + raise Exception('Could not detremine product version') +major, minor, release, tag = m.groups() + +incFile = open(os.path.join(OutputFolder, 'version_auto.h'), 'w') +incFile.write(""" +#ifndef _AUTO_VERSION_INFORMATION_H_ +#define _AUTO_VERSION_INFORMATION_H_ +#define SM_BUILD_TAG \"{0}\" +#define SM_BUILD_UNIQUEID \"{1}:{2}\" SM_BUILD_TAG +#define SM_VERSION \"{3}.{4}.{5}\" +#define SM_FULL_VERSION SM_VERSION SM_BUILD_TAG +#define SM_FILE_VERSION {6},{7},{8},0 +#endif /* _AUTO_VERSION_INFORMATION_H_ */ +""".format(tag, rev, cset, major, minor, release, major, minor, release)) +incFile.close() + +filename_versioning = open(os.path.join(OutputFolder, 'filename_versioning.txt'), 'w') +filename_versioning.write("{0}.{1}.{2}-git{3}-{4}".format(major, minor, release, rev, cset)) +filename_versioning.close() \ No newline at end of file diff --git a/configure.py b/configure.py index f0f2aa0..394c114 100644 --- a/configure.py +++ b/configure.py @@ -1,10 +1,26 @@ -# vim: set ts=2 sw=2 tw=99 noet: +# vim: set sts=2 ts=8 sw=2 tw=99 et: import sys -import ambuild.runner as runner +from ambuild2 import run -run = runner.Runner() -run.options.add_option('--enable-debug', action='store_const', const='1', dest='debug', +# Simple extensions do not need to modify this file. + +parser = run.BuildParser(sourcePath = sys.path[0], api='2.2') + +parser.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None, + help='Root search folder for HL2SDKs') +parser.options.add_argument('--mms-path', type=str, dest='mms_path', default=None, + help='Path to Metamod:Source') +parser.options.add_argument('--sm-path', type=str, dest='sm_path', default=None, + help='Path to SourceMod') +parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug', help='Enable debugging symbols') -run.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt', +parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt', help='Enable optimization') -run.Configure(sys.path[0]) +parser.options.add_argument('--enable-auto-versioning', action='store_false', dest='disable_auto_versioning', + default=True, help='Enables the auto versioning script') +parser.options.add_argument('-s', '--sdks', default='all', dest='sdks', + help='Build against specified SDKs; valid args are "all", "present", or ' + 'space-delimited list of engine names (default: %default)') +parser.options.add_argument('--targets', type=str, dest='targets', default=None, + help="Override the target architecture (use commas to separate multiple targets).") +parser.Configure() \ No newline at end of file diff --git a/connect.games.txt b/connect.games.txt index 843de8b..ff73948 100644 --- a/connect.games.txt +++ b/connect.games.txt @@ -15,14 +15,14 @@ "ISteamGameServer__BeginAuthSession" { "linux" "29" - "mac" "29" + "linux64" "29" "windows" "29" } "ISteamGameServer__EndAuthSession" { "linux" "30" - "mac" "30" + "linux64" "30" "windows" "30" } } @@ -39,7 +39,7 @@ { "library" "engine" "linux" "@_Z12Steam3Serverv" - "mac" "@_Z12Steam3Serverv" + "linux64" "@_Z12Steam3Serverv" } } } @@ -102,7 +102,7 @@ { "library" "engine" "linux" "@_ZN11CBaseServer13ConnectClientER8netadr_siiiiPKcS3_S3_i" - "mac" "@_ZN11CBaseServer13ConnectClientER8netadr_siiiiPKcS3_S3_i" + "linux64" "@_ZN11CBaseServer13ConnectClientER8netadr_siiiiPKcS3_S3_i" "windows" "\x55\x8B\xEC\x81\xEC\x24\x05\x00\x00" } @@ -110,7 +110,7 @@ { "library" "engine" "linux" "@_ZN11CBaseServer16RejectConnectionERK8netadr_siPKc" - "mac" "@_ZN11CBaseServer16RejectConnectionERK8netadr_siPKc" + "linux64" "@_ZN11CBaseServer16RejectConnectionERK8netadr_siPKc" "windows" "\x55\x8B\xEC\x81\xEC\x04\x05\x00\x00\x57" } @@ -118,7 +118,7 @@ { "library" "engine" "linux" "@_ZN11CBaseClient10SetSteamIDERK8CSteamID" - "mac" "@_ZN11CBaseClient10SetSteamIDERK8CSteamID" + "linux64" "@_ZN11CBaseClient10SetSteamIDERK8CSteamID" "windows" "\x55\x8B\xEC\x56\x57\x8B\x7D\x08\x8B\xF1\x8D\x4E\x04" } @@ -126,7 +126,7 @@ { "library" "engine" "linux" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii" - "mac" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii" + "linux64" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii" "windows" "\x55\x8B\xEC\x83\xEC\x14\x53\x8B\x5D\x14" } } diff --git a/extension/AMBuilder b/extension/AMBuilder index 86ef252..e711315 100644 --- a/extension/AMBuilder +++ b/extension/AMBuilder @@ -1,38 +1,29 @@ -# vim: set ts=2 sw=2 tw=99 noet ft=python: -import os +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os, sys -for i in SM.sdkInfo: - sdk = SM.sdkInfo[i] - if AMBuild.target['platform'] not in sdk['platform']: - continue +projectname = 'connect' - compiler = SM.DefaultHL2Compiler('extension', i) +project = builder.LibraryProject(projectname + '.ext') +project.sources = [ + 'extension.cpp', + os.path.join(Extension.sm_root, 'public', 'smsdk_ext.cpp'), + os.path.join(Extension.sm_root, 'public', 'CDetour', 'detours.cpp'), + os.path.join(Extension.sm_root, 'public', 'asm', 'asm.c'), + os.path.join(Extension.sm_root, 'public', 'libudis86', 'decode.c'), + os.path.join(Extension.sm_root, 'public', 'libudis86', 'itab.c'), + os.path.join(Extension.sm_root, 'public', 'libudis86', 'syn-att.c'), + os.path.join(Extension.sm_root, 'public', 'libudis86', 'syn-intel.c'), + os.path.join(Extension.sm_root, 'public', 'libudis86', 'syn.c'), + os.path.join(Extension.sm_root, 'public', 'libudis86', 'udis86.c') +] - compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'extension')) - compiler['CXXINCLUDES'].append(os.path.join(AMBuild.sourceFolder, 'extension', 'sdk')) - - compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache['SOURCEMOD14'], 'public')) - compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache['SOURCEMOD14'], 'extensions')) - compiler['CXXINCLUDES'].append(os.path.join(AMBuild.cache['SOURCEMOD14'], 'public', 'sourcepawn')) +for sdk_name in Extension.sdks: + sdk = Extension.sdks[sdk_name] - if compiler.cc.name == 'gcc': - compiler['CFLAGS'].append('-Wno-parentheses') - - if i != 'ep1': - compiler['CDEFINES'].append('HOOKING_ENABLED') - - name = 'connect.ext.' + sdk['ext'] - extension = AMBuild.AddJob(name) - binary = Cpp.LibraryBuilder(name, AMBuild, extension, compiler) - SM.PreSetupHL2Job(extension, binary, i) - binary.AddSourceFiles('extension', [ - 'extension.cpp', - 'asm/asm.c', - 'CDetour/detours.cpp', - 'sdk/smsdk_ext.cpp' - ]) - SM.PostSetupHL2Job(extension, binary, i) - SM.AutoVersion('extension', binary) - SM.ExtractDebugInfo(extension, binary) - binary.SendToJob() + for cxx in builder.targets: + if not cxx.target.arch in sdk.platformSpec[cxx.target.platform]: + continue + + binary = Extension.HL2ExtConfig(project, builder, cxx, projectname + '.ext.' + sdk.ext, sdk) +Extension.extensions = builder.Add(project) \ No newline at end of file diff --git a/extension/CDetour/detourhelpers.h b/extension/CDetour/detourhelpers.h deleted file mode 100644 index 85cda0e..0000000 --- a/extension/CDetour/detourhelpers.h +++ /dev/null @@ -1,98 +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 . - * - * 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 . - * - * 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 -#define PAGE_SIZE 4096 -#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; ibytes; i++) - { - restore->patch[i] = addr[i]; - } - restore->bytes = patch->bytes; - } - - for (size_t i=0; ibytes; i++) - { - addr[i] = patch->patch[i]; - } -} - -#endif //_INCLUDE_SOURCEMOD_DETOURHELPERS_H_ diff --git a/extension/CDetour/detours.cpp b/extension/CDetour/detours.cpp deleted file mode 100644 index 71aba44..0000000 --- a/extension/CDetour/detours.cpp +++ /dev/null @@ -1,192 +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 . -* -* 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 . -* -* Version: $Id: detours.cpp 248 2008-08-27 00:56:22Z pred $ -*/ - -#include "detours.h" -#include - -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::CDetour(void *callbackfunction, void **trampoline, const char *signame) -{ - enabled = false; - detoured = false; - detour_address = NULL; - detour_trampoline = NULL; - this->signame = signame; - 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 (!gameconf->GetMemSig(signame, &detour_address)) - { - g_pSM->LogError(myself, "Could not locate %s - Disabling detour", signame); - return false; - } - - 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; iAllocatePageMemory(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; - } -} diff --git a/extension/CDetour/detours.h b/extension/CDetour/detours.h deleted file mode 100644 index 289e2b3..0000000 --- a/extension/CDetour/detours.h +++ /dev/null @@ -1,300 +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 . -* -* 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 . -* -* Version: $Id: detours.h 257 2008-09-23 03:12:13Z pred $ -*/ - -#ifndef _INCLUDE_SOURCEMOD_DETOURS_H_ -#define _INCLUDE_SOURCEMOD_DETOURS_H_ - -#include "extension.hpp" -#include -#include -#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_STATIC2(name, ret, p1type, p1name, p2type, p2name) \ - ret (*name##_Actual)(p1type, p2type) = NULL; \ - ret name(p1type p1name, p2type p2name) - -#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_MEMBER5(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name) - -#define DETOUR_DECL_MEMBER7(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name) - -#define DETOUR_DECL_MEMBER8(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name) - -#define DETOUR_DECL_MEMBER9(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name) - -#define DETOUR_DECL_MEMBER10(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name, p10type, p10name) \ -class name##Class \ -{ \ -public: \ - ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name, p10type p10name); \ - static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type, p10type); \ -}; \ -ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type, p10type) = NULL; \ -ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name, p10type p10name) - -#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); - - -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(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); - - 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; - 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); - - friend class CBlocker; - friend class CDetour; - -private: - static ISourcePawnEngine *spengine; - static IGameConfig *gameconf; -}; - -#define DECL_DETOUR(name) \ - CDetour *name##_Detour = NULL; - -#define CREATE_DETOUR(name) \ - name##_Detour = DETOUR_CREATE_MEMBER(name, #name); \ - if (name##_Detour != NULL) \ - { \ - name##_Detour->EnableDetour(); \ - } else { \ - snprintf(error, maxlen, "Failed to create " #name " detour, check error log.\n"); \ - return false; \ - } - -#define DESTROY_DETOUR(name) \ - if (name##_Detour != NULL) \ -{ \ - name##_Detour->Destroy(); \ - name##_Detour = NULL; \ -} - -#endif // _INCLUDE_SOURCEMOD_DETOURS_H_ diff --git a/extension/asm/asm.c b/extension/asm/asm.c deleted file mode 100644 index 2facf8d..0000000 --- a/extension/asm/asm.c +++ /dev/null @@ -1,421 +0,0 @@ -#include "asm.h" - -#ifndef WIN32 -#define _GNU_SOURCE -#include -#include - -#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 -#endif - -extern void Msg( const char *, ... ); - -/** -* 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: - { - Msg("Unknown thunk: %c\n", *(calladdr+1)); - 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; - } -} -*/ diff --git a/extension/asm/asm.h b/extension/asm/asm.h deleted file mode 100644 index 6086232..0000000 --- a/extension/asm/asm.h +++ /dev/null @@ -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__ diff --git a/extension/extension.cpp b/extension/extension.cpp index 459ba31..22e54f9 100644 --- a/extension/extension.cpp +++ b/extension/extension.cpp @@ -17,7 +17,7 @@ * this program. If not, see . */ -#include "extension.hpp" +#include "extension.h" #include "CDetour/detours.h" #include "steam/steamclientpublic.h" @@ -44,6 +44,7 @@ typedef enum EAuthProtocol k_EAuthProtocolSteam = 3, } EAuthProtocol; +#if SOURCE_ENGINE < SE_SDK2013 || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_LEFT4DEAD || SOURCE_ENGINE == SE_LEFT4DEAD2 typedef enum EBeginAuthSessionResult { k_EBeginAuthSessionResultOK = 0, // Ticket is valid for this game and this steamID. @@ -53,6 +54,7 @@ typedef enum EBeginAuthSessionResult k_EBeginAuthSessionResultGameMismatch = 4, // Ticket is not for this game k_EBeginAuthSessionResultExpiredTicket = 5, // Ticket has expired } EBeginAuthSessionResult; +#endif typedef struct netadr_s { @@ -74,7 +76,11 @@ public: const char *CSteamID::Render() const { static char szSteamID[64]; +#if SOURCE_ENGINE < SE_SDK2013 || SOURCE_ENGINE == SE_TF2 || SOURCE_ENGINE == SE_LEFT4DEAD || SOURCE_ENGINE == SE_LEFT4DEAD2 V_snprintf(szSteamID, sizeof(szSteamID), "STEAM_0:%u:%u", (m_unAccountID % 2) ? 1 : 0, (int32)m_unAccountID/2); +#else + V_snprintf(szSteamID, sizeof(szSteamID), "STEAM_0:%u:%u", (m_steamid.m_comp.m_unAccountID % 2) ? 1 : 0, (int32)m_steamid.m_comp.m_unAccountID/2); +#endif return szSteamID; } @@ -211,9 +217,9 @@ void EndAuthSession(CSteamID steamID) return (void)(reinterpret_cast(this_ptr)->*u.mfpnew)(steamID); } -DECL_DETOUR(CBaseServer__ConnectClient); -DECL_DETOUR(CBaseServer__RejectConnection) -DECL_DETOUR(CBaseServer__CheckChallengeType); +CDetour* detourCBaseServer__ConnectClient = nullptr; +CDetour* detourCBaseServer__RejectConnection = nullptr; +CDetour* detourCBaseServer__CheckChallengeType = nullptr; bool g_bEndAuthSessionOnRejectConnection = false; CSteamID g_lastClientSteamID; @@ -221,7 +227,18 @@ CSteamID g_lastClientSteamID; bool g_bSuppressCheckChallengeType = false; char passwordBuffer[255]; -DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient *, netadr_t &, address, int, nProtocol, int, iChallenge, int, iClientChallenge, int, nAuthProtocol, const char *, pchName, const char *, pchPassword, const char *, pCookie, int, cbCookie) + +#define DETOUR_DECL_MEMBER9(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name) \ +class name##Class \ +{ \ +public: \ + ret name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name); \ + static ret (name##Class::* name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type); \ +}; \ +ret (name##Class::* name##Class::name##_Actual)(p1type, p2type, p3type, p4type, p5type, p6type, p7type, p8type, p9type) = NULL; \ +ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name, p5type p5name, p6type p6name, p7type p7name, p8type p8name, p9type p9name) + +DETOUR_DECL_MEMBER9(CBaseServer__ConnectClient, IClient*, netadr_t&, address, int, nProtocol, int, iChallenge, int, iClientChallenge, int, nAuthProtocol, const char *, pchName, const char *, pchPassword, const char *, pCookie, int, cbCookie) { if (nAuthProtocol != k_EAuthProtocolSteam) { @@ -379,9 +396,9 @@ bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late) CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf); - CREATE_DETOUR(CBaseServer__ConnectClient); - CREATE_DETOUR(CBaseServer__RejectConnection); - CREATE_DETOUR(CBaseServer__CheckChallengeType); + detourCBaseServer__ConnectClient = DETOUR_CREATE_MEMBER(CBaseServer__ConnectClient, "CBaseServer__ConnectClient"); + detourCBaseServer__RejectConnection = DETOUR_CREATE_MEMBER(CBaseServer__RejectConnection, "CBaseServer__RejectConnection"); + detourCBaseServer__CheckChallengeType = DETOUR_CREATE_MEMBER(CBaseServer__CheckChallengeType, "CBaseServer__CheckChallengeType"); g_pConnectForward = g_pForwards->CreateForward("OnClientPreConnectEx", ET_LowEvent, 5, NULL, Param_String, Param_String, Param_String, Param_String, Param_String); @@ -406,9 +423,21 @@ void Connect::SDK_OnUnload() bool Connect::SDK_OnMetamodUnload(char *error, size_t maxlen) { - DESTROY_DETOUR(CBaseServer__ConnectClient); - DESTROY_DETOUR(CBaseServer__RejectConnection); - DESTROY_DETOUR(CBaseServer__CheckChallengeType); + if (detourCBaseServer__ConnectClient) + { + detourCBaseServer__ConnectClient->DisableDetour(); + delete detourCBaseServer__ConnectClient; + } + if (detourCBaseServer__RejectConnection) + { + detourCBaseServer__RejectConnection->DisableDetour(); + delete detourCBaseServer__RejectConnection; + } + if (detourCBaseServer__CheckChallengeType) + { + detourCBaseServer__CheckChallengeType->DisableDetour(); + delete detourCBaseServer__CheckChallengeType; + } return true; } diff --git a/extension/extension.hpp b/extension/extension.h similarity index 96% rename from extension/extension.hpp rename to extension/extension.h index 72a84f5..5d6fdd3 100644 --- a/extension/extension.hpp +++ b/extension/extension.h @@ -1,103 +1,103 @@ -/** - * ============================================================================= - * TF2 Items Extension - * Copyright (C) 2009-2010 AzuiSleet, Asher Baker (asherkin). 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 . - * - */ - -#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ -#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ - -/** - * @file extension.hpp - * @brief Connect extension code header. - */ - -#include "smsdk_ext.hpp" - -/** - * @brief Sample implementation of the SDK Extension. - * Note: Uncomment one of the pre-defined virtual functions in order to use it. - */ -class Connect : public SDKExtension, public IConCommandBaseAccessor -{ -public: - /** - * @brief This is called after the initial loading sequence has been processed. - * - * @param error Error message buffer. - * @param maxlength Size of error message buffer. - * @param late Whether or not the module was loaded after map load. - * @return True to succeed loading, false to fail. - */ - virtual bool SDK_OnLoad(char *error, size_t maxlen, bool late); - - /** - * @brief This is called right before the extension is unloaded. - */ - virtual void SDK_OnUnload(); - - /** - * @brief Called when the pause state is changed. - */ - //virtual void SDK_OnPauseChange(bool paused); - - /** - * @brief this is called when Core wants to know if your extension is working. - * - * @param error Error message buffer. - * @param maxlength Size of error message buffer. - * @return True if working, false otherwise. - */ - //virtual bool QueryRunning(char *error, size_t maxlen); -public: -#if defined SMEXT_CONF_METAMOD - /** - * @brief Called when Metamod is attached, before the extension version is called. - * - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @param late Whether or not Metamod considers this a late load. - * @return True to succeed, false to fail. - */ - virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late); - - /** - * @brief Called when Metamod is detaching, after the extension version is called. - * NOTE: By default this is blocked unless sent from SourceMod. - * - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @return True to succeed, false to fail. - */ - virtual bool SDK_OnMetamodUnload(char *error, size_t maxlen); - - /** - * @brief Called when Metamod's pause state is changing. - * NOTE: By default this is blocked unless sent from SourceMod. - * - * @param paused Pause state being set. - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @return True to succeed, false to fail. - */ - //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlen); -#endif -public: //IConCommandBaseAccessor - bool RegisterConCommandBase(ConCommandBase *pCommand); -}; - -#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ +/** + * ============================================================================= + * TF2 Items Extension + * Copyright (C) 2009-2010 AzuiSleet, Asher Baker (asherkin). 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 . + * + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ + +/** + * @file extension.hpp + * @brief Connect extension code header. + */ + +#include "smsdk_ext.h" + +/** + * @brief Sample implementation of the SDK Extension. + * Note: Uncomment one of the pre-defined virtual functions in order to use it. + */ +class Connect : public SDKExtension, public IConCommandBaseAccessor +{ +public: + /** + * @brief This is called after the initial loading sequence has been processed. + * + * @param error Error message buffer. + * @param maxlength Size of error message buffer. + * @param late Whether or not the module was loaded after map load. + * @return True to succeed loading, false to fail. + */ + virtual bool SDK_OnLoad(char *error, size_t maxlen, bool late); + + /** + * @brief This is called right before the extension is unloaded. + */ + virtual void SDK_OnUnload(); + + /** + * @brief Called when the pause state is changed. + */ + //virtual void SDK_OnPauseChange(bool paused); + + /** + * @brief this is called when Core wants to know if your extension is working. + * + * @param error Error message buffer. + * @param maxlength Size of error message buffer. + * @return True if working, false otherwise. + */ + //virtual bool QueryRunning(char *error, size_t maxlen); +public: +#if defined SMEXT_CONF_METAMOD + /** + * @brief Called when Metamod is attached, before the extension version is called. + * + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @param late Whether or not Metamod considers this a late load. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late); + + /** + * @brief Called when Metamod is detaching, after the extension version is called. + * NOTE: By default this is blocked unless sent from SourceMod. + * + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodUnload(char *error, size_t maxlen); + + /** + * @brief Called when Metamod's pause state is changing. + * NOTE: By default this is blocked unless sent from SourceMod. + * + * @param paused Pause state being set. + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlen); +#endif +public: //IConCommandBaseAccessor + bool RegisterConCommandBase(ConCommandBase *pCommand); +}; + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extension/sdk/smsdk_ext.cpp b/extension/sdk/smsdk_ext.cpp deleted file mode 100644 index de7c400..0000000 --- a/extension/sdk/smsdk_ext.cpp +++ /dev/null @@ -1,475 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Base Extension Code - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - * - * 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 . - * - * Version: $Id$ - */ - -#include -#include -#include "smsdk_ext.hpp" - -/** - * @file smsdk_ext.cpp - * @brief Contains wrappers for making Extensions easier to write. - */ - -IExtension *myself = NULL; /**< Ourself */ -IShareSys *g_pShareSys = NULL; /**< Share system */ -IShareSys *sharesys = NULL; /**< Share system */ -ISourceMod *g_pSM = NULL; /**< SourceMod helpers */ -ISourceMod *smutils = NULL; /**< SourceMod helpers */ - -#if defined SMEXT_ENABLE_FORWARDSYS -IForwardManager *g_pForwards = NULL; /**< Forward system */ -IForwardManager *forwards = NULL; /**< Forward system */ -#endif -#if defined SMEXT_ENABLE_HANDLESYS -IHandleSys *g_pHandleSys = NULL; /**< Handle system */ -IHandleSys *handlesys = NULL; /**< Handle system */ -#endif -#if defined SMEXT_ENABLE_PLAYERHELPERS -IPlayerManager *playerhelpers = NULL; /**< Player helpers */ -#endif //SMEXT_ENABLE_PLAYERHELPERS -#if defined SMEXT_ENABLE_DBMANAGER -IDBManager *dbi = NULL; /**< DB Manager */ -#endif //SMEXT_ENABLE_DBMANAGER -#if defined SMEXT_ENABLE_GAMECONF -IGameConfigManager *gameconfs = NULL; /**< Game config manager */ -#endif //SMEXT_ENABLE_DBMANAGER -#if defined SMEXT_ENABLE_MEMUTILS -IMemoryUtils *memutils = NULL; -#endif //SMEXT_ENABLE_DBMANAGER -#if defined SMEXT_ENABLE_GAMEHELPERS -IGameHelpers *gamehelpers = NULL; -#endif -#if defined SMEXT_ENABLE_TIMERSYS -ITimerSystem *timersys = NULL; -#endif -#if defined SMEXT_ENABLE_ADTFACTORY -IADTFactory *adtfactory = NULL; -#endif -#if defined SMEXT_ENABLE_THREADER -IThreader *threader = NULL; -#endif -#if defined SMEXT_ENABLE_LIBSYS -ILibrarySys *libsys = NULL; -#endif -#if defined SMEXT_ENABLE_PLUGINSYS -SourceMod::IPluginManager *plsys; -#endif -#if defined SMEXT_ENABLE_MENUS -IMenuManager *menus = NULL; -#endif -#if defined SMEXT_ENABLE_ADMINSYS -IAdminSystem *adminsys = NULL; -#endif -#if defined SMEXT_ENABLE_TEXTPARSERS -ITextParsers *textparsers = NULL; -#endif -#if defined SMEXT_ENABLE_USERMSGS -IUserMessages *usermsgs = NULL; -#endif -#if defined SMEXT_ENABLE_TRANSLATOR -ITranslator *translator = NULL; -#endif -#if defined SMEXT_ENABLE_NINVOKE -INativeInterface *ninvoke = NULL; -#endif - -/** Exports the main interface */ -PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI() -{ - return g_pExtensionIface; -} - -SDKExtension::SDKExtension() -{ -#if defined SMEXT_CONF_METAMOD - m_SourceMMLoaded = false; - m_WeAreUnloaded = false; - m_WeGotPauseChange = false; -#endif -} - -bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late) -{ - g_pShareSys = sharesys = sys; - myself = me; - -#if defined SMEXT_CONF_METAMOD - m_WeAreUnloaded = true; - - if (!m_SourceMMLoaded) - { - if (error) - { - snprintf(error, maxlength, "Metamod attach failed"); - } - return false; - } -#endif - SM_GET_IFACE(SOURCEMOD, g_pSM); - smutils = g_pSM; -#if defined SMEXT_ENABLE_HANDLESYS - SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys); - handlesys = g_pHandleSys; -#endif -#if defined SMEXT_ENABLE_FORWARDSYS - SM_GET_IFACE(FORWARDMANAGER, g_pForwards); - forwards = g_pForwards; -#endif -#if defined SMEXT_ENABLE_PLAYERHELPERS - SM_GET_IFACE(PLAYERMANAGER, playerhelpers); -#endif -#if defined SMEXT_ENABLE_DBMANAGER - SM_GET_IFACE(DBI, dbi); -#endif -#if defined SMEXT_ENABLE_GAMECONF - SM_GET_IFACE(GAMECONFIG, gameconfs); -#endif -#if defined SMEXT_ENABLE_MEMUTILS - SM_GET_IFACE(MEMORYUTILS, memutils); -#endif -#if defined SMEXT_ENABLE_GAMEHELPERS - SM_GET_IFACE(GAMEHELPERS, gamehelpers); -#endif -#if defined SMEXT_ENABLE_TIMERSYS - SM_GET_IFACE(TIMERSYS, timersys); -#endif -#if defined SMEXT_ENABLE_ADTFACTORY - SM_GET_IFACE(ADTFACTORY, adtfactory); -#endif -#if defined SMEXT_ENABLE_THREADER - SM_GET_IFACE(THREADER, threader); -#endif -#if defined SMEXT_ENABLE_LIBSYS - SM_GET_IFACE(LIBRARYSYS, libsys); -#endif -#if defined SMEXT_ENABLE_PLUGINSYS - SM_GET_IFACE(PLUGINSYSTEM, plsys); -#endif -#if defined SMEXT_ENABLE_MENUS - SM_GET_IFACE(MENUMANAGER, menus); -#endif -#if defined SMEXT_ENABLE_ADMINSYS - SM_GET_IFACE(ADMINSYS, adminsys); -#endif -#if defined SMEXT_ENABLE_TEXTPARSERS - SM_GET_IFACE(TEXTPARSERS, textparsers); -#endif -#if defined SMEXT_ENABLE_USERMSGS - SM_GET_IFACE(USERMSGS, usermsgs); -#endif -#if defined SMEXT_ENABLE_TRANSLATOR - SM_GET_IFACE(TRANSLATOR, translator); -#endif - - if (SDK_OnLoad(error, maxlength, late)) - { -#if defined SMEXT_CONF_METAMOD - m_WeAreUnloaded = true; -#endif - return true; - } - - return false; -} - -bool SDKExtension::IsMetamodExtension() -{ -#if defined SMEXT_CONF_METAMOD - return true; -#else - return false; -#endif -} - -void SDKExtension::OnExtensionPauseChange(bool state) -{ -#if defined SMEXT_CONF_METAMOD - m_WeGotPauseChange = true; -#endif - SDK_OnPauseChange(state); -} - -void SDKExtension::OnExtensionsAllLoaded() -{ - SDK_OnAllLoaded(); -} - -void SDKExtension::OnExtensionUnload() -{ -#if defined SMEXT_CONF_METAMOD - m_WeAreUnloaded = true; -#endif - SDK_OnUnload(); -} - -const char *SDKExtension::GetExtensionAuthor() -{ - return SMEXT_CONF_AUTHOR; -} - -const char *SDKExtension::GetExtensionDateString() -{ - return SMEXT_CONF_DATESTRING; -} - -const char *SDKExtension::GetExtensionDescription() -{ - return SMEXT_CONF_DESCRIPTION; -} - -const char *SDKExtension::GetExtensionVerString() -{ - return SMEXT_CONF_VERSION; -} - -const char *SDKExtension::GetExtensionName() -{ - return SMEXT_CONF_NAME; -} - -const char *SDKExtension::GetExtensionTag() -{ - return SMEXT_CONF_LOGTAG; -} - -const char *SDKExtension::GetExtensionURL() -{ - return SMEXT_CONF_URL; -} - -bool SDKExtension::SDK_OnLoad(char *error, size_t maxlength, bool late) -{ - return true; -} - -void SDKExtension::SDK_OnUnload() -{ -} - -void SDKExtension::SDK_OnPauseChange(bool paused) -{ -} - -void SDKExtension::SDK_OnAllLoaded() -{ -} - -#if defined SMEXT_CONF_METAMOD - -PluginId g_PLID = 0; /**< Metamod plugin ID */ -ISmmPlugin *g_PLAPI = NULL; /**< Metamod plugin API */ -SourceHook::ISourceHook *g_SHPtr = NULL; /**< SourceHook pointer */ -ISmmAPI *g_SMAPI = NULL; /**< SourceMM API pointer */ - -IVEngineServer *engine = NULL; /**< IVEngineServer pointer */ -IServerGameDLL *gamedll = NULL; /**< IServerGameDLL pointer */ - -/** Exposes the extension to Metamod */ -SMM_API void *PL_EXPOSURE(const char *name, int *code) -{ -#if defined METAMOD_PLAPI_VERSION - if (name && !strcmp(name, METAMOD_PLAPI_NAME)) -#else - if (name && !strcmp(name, PLAPI_NAME)) -#endif - { - if (code) - { - *code = IFACE_OK; - } - return static_cast(g_pExtensionIface); - } - - if (code) - { - *code = IFACE_FAILED; - } - - return NULL; -} - -bool SDKExtension::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) -{ - PLUGIN_SAVEVARS(); - -#if !defined METAMOD_PLAPI_VERSION - GET_V_IFACE_ANY(serverFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); - GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); -#else - GET_V_IFACE_ANY(GetServerFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); - GET_V_IFACE_CURRENT(GetEngineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); -#endif - - m_SourceMMLoaded = true; - - return SDK_OnMetamodLoad(ismm, error, maxlen, late); -} - -bool SDKExtension::Unload(char *error, size_t maxlen) -{ - if (!m_WeAreUnloaded) - { - if (error) - { - snprintf(error, maxlen, "This extension must be unloaded by SourceMod."); - } - return false; - } - - return SDK_OnMetamodUnload(error, maxlen); -} - -bool SDKExtension::Pause(char *error, size_t maxlen) -{ - if (!m_WeGotPauseChange) - { - if (error) - { - snprintf(error, maxlen, "This extension must be paused by SourceMod."); - } - return false; - } - - m_WeGotPauseChange = false; - - return SDK_OnMetamodPauseChange(true, error, maxlen); -} - -bool SDKExtension::Unpause(char *error, size_t maxlen) -{ - if (!m_WeGotPauseChange) - { - if (error) - { - snprintf(error, maxlen, "This extension must be unpaused by SourceMod."); - } - return false; - } - - m_WeGotPauseChange = false; - - return SDK_OnMetamodPauseChange(false, error, maxlen); -} - -const char *SDKExtension::GetAuthor() -{ - return GetExtensionAuthor(); -} - -const char *SDKExtension::GetDate() -{ - return GetExtensionDateString(); -} - -const char *SDKExtension::GetDescription() -{ - return GetExtensionDescription(); -} - -const char *SDKExtension::GetLicense() -{ - return SMEXT_CONF_LICENSE; -} - -const char *SDKExtension::GetLogTag() -{ - return GetExtensionTag(); -} - -const char *SDKExtension::GetName() -{ - return GetExtensionName(); -} - -const char *SDKExtension::GetURL() -{ - return GetExtensionURL(); -} - -const char *SDKExtension::GetVersion() -{ - return GetExtensionVerString(); -} - -bool SDKExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late) -{ - return true; -} - -bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t maxlength) -{ - return true; -} - -bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength) -{ - return true; -} - -#endif - -/* Overload a few things to prevent libstdc++ linking */ -#if defined __linux__ || defined __APPLE__ -extern "C" void __cxa_pure_virtual(void) -{ -} - -void *operator new(size_t size) -{ - return malloc(size); -} - -void *operator new[](size_t size) -{ - return malloc(size); -} - -void operator delete(void *ptr) -{ - free(ptr); -} - -void operator delete[](void * ptr) -{ - free(ptr); -} - -void operator delete(void *ptr, size_t size) -{ - free(ptr); -} - -void operator delete[](void * ptr, size_t size) -{ - free(ptr); -} -#endif - diff --git a/extension/sdk/smsdk_ext.hpp b/extension/sdk/smsdk_ext.hpp deleted file mode 100644 index a3de9b3..0000000 --- a/extension/sdk/smsdk_ext.hpp +++ /dev/null @@ -1,339 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Base Extension Code - * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. - * ============================================================================= - * - * This program is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, version 3.0, as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - * - * 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 . - * - * Version: $Id$ - */ - -#ifndef _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ -#define _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ - -/** - * @file smsdk_ext.hpp - * @brief Contains wrappers for making Extensions easier to write. - */ - -#include "smsdk_config.hpp" -#include -#include -#include -#include -#include -#if defined SMEXT_ENABLE_FORWARDSYS -#include -#endif //SMEXT_ENABLE_FORWARDSYS -#if defined SMEXT_ENABLE_PLAYERHELPERS -#include -#endif //SMEXT_ENABLE_PlAYERHELPERS -#if defined SMEXT_ENABLE_DBMANAGER -#include -#endif //SMEXT_ENABLE_DBMANAGER -#if defined SMEXT_ENABLE_GAMECONF -#include -#endif -#if defined SMEXT_ENABLE_MEMUTILS -#include -#endif -#if defined SMEXT_ENABLE_GAMEHELPERS -#include -#endif -#if defined SMEXT_ENABLE_TIMERSYS -#include -#endif -#if defined SMEXT_ENABLE_ADTFACTORY -#include -#endif -#if defined SMEXT_ENABLE_THREADER -#include -#endif -#if defined SMEXT_ENABLE_LIBSYS -#include -#endif -#if defined SMEXT_ENABLE_PLUGINSYS -#include -#endif -#if defined SMEXT_ENABLE_MENUS -#include -#endif -#if defined SMEXT_ENABLE_ADMINSYS -#include -#endif -#if defined SMEXT_ENABLE_TEXTPARSERS -#include -#endif -#if defined SMEXT_ENABLE_USERMSGS -#include -#endif -#if defined SMEXT_ENABLE_TRANSLATOR -#include -#endif -#if defined SMEXT_ENABLE_NINVOKE -#include -#endif - -#if defined SMEXT_CONF_METAMOD -#include -#include -#endif - -using namespace SourceMod; -using namespace SourcePawn; - -class SDKExtension : -#if defined SMEXT_CONF_METAMOD - public ISmmPlugin, -#endif - public IExtensionInterface -{ -public: - /** Constructor */ - SDKExtension(); -public: - /** - * @brief This is called after the initial loading sequence has been processed. - * - * @param error Error message buffer. - * @param maxlength Size of error message buffer. - * @param late Whether or not the module was loaded after map load. - * @return True to succeed loading, false to fail. - */ - virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late); - - /** - * @brief This is called right before the extension is unloaded. - */ - virtual void SDK_OnUnload(); - - /** - * @brief This is called once all known extensions have been loaded. - */ - virtual void SDK_OnAllLoaded(); - - /** - * @brief Called when the pause state is changed. - */ - virtual void SDK_OnPauseChange(bool paused); - -#if defined SMEXT_CONF_METAMOD - /** - * @brief Called when Metamod is attached, before the extension version is called. - * - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @param late Whether or not Metamod considers this a late load. - * @return True to succeed, false to fail. - */ - virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late); - - /** - * @brief Called when Metamod is detaching, after the extension version is called. - * NOTE: By default this is blocked unless sent from SourceMod. - * - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @return True to succeed, false to fail. - */ - virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength); - - /** - * @brief Called when Metamod's pause state is changing. - * NOTE: By default this is blocked unless sent from SourceMod. - * - * @param paused Pause state being set. - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @return True to succeed, false to fail. - */ - virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); -#endif - -public: //IExtensionInterface - virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late); - virtual void OnExtensionUnload(); - virtual void OnExtensionsAllLoaded(); - - /** Returns whether or not this is a Metamod-based extension */ - virtual bool IsMetamodExtension(); - - /** - * @brief Called when the pause state changes. - * - * @param state True if being paused, false if being unpaused. - */ - virtual void OnExtensionPauseChange(bool state); - - /** Returns name */ - virtual const char *GetExtensionName(); - /** Returns URL */ - virtual const char *GetExtensionURL(); - /** Returns log tag */ - virtual const char *GetExtensionTag(); - /** Returns author */ - virtual const char *GetExtensionAuthor(); - /** Returns version string */ - virtual const char *GetExtensionVerString(); - /** Returns description string */ - virtual const char *GetExtensionDescription(); - /** Returns date string */ - virtual const char *GetExtensionDateString(); -#if defined SMEXT_CONF_METAMOD -public: //ISmmPlugin - /** Called when the extension is attached to Metamod. */ - virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late); - /** Returns the author to MM */ - virtual const char *GetAuthor(); - /** Returns the name to MM */ - virtual const char *GetName(); - /** Returns the description to MM */ - virtual const char *GetDescription(); - /** Returns the URL to MM */ - virtual const char *GetURL(); - /** Returns the license to MM */ - virtual const char *GetLicense(); - /** Returns the version string to MM */ - virtual const char *GetVersion(); - /** Returns the date string to MM */ - virtual const char *GetDate(); - /** Returns the logtag to MM */ - virtual const char *GetLogTag(); - /** Called on unload */ - virtual bool Unload(char *error, size_t maxlength); - /** Called on pause */ - virtual bool Pause(char *error, size_t maxlength); - /** Called on unpause */ - virtual bool Unpause(char *error, size_t maxlength); -private: - bool m_SourceMMLoaded; - bool m_WeAreUnloaded; - bool m_WeGotPauseChange; -#endif -}; - -extern SDKExtension *g_pExtensionIface; -extern IExtension *myself; - -extern IShareSys *g_pShareSys; -extern IShareSys *sharesys; /* Note: Newer name */ -extern ISourceMod *g_pSM; -extern ISourceMod *smutils; /* Note: Newer name */ - -/* Optional interfaces are below */ -#if defined SMEXT_ENABLE_FORWARDSYS -extern IForwardManager *g_pForwards; -extern IForwardManager *forwards; /* Note: Newer name */ -#endif //SMEXT_ENABLE_FORWARDSYS -#if defined SMEXT_ENABLE_HANDLESYS -extern IHandleSys *g_pHandleSys; -extern IHandleSys *handlesys; /* Note: Newer name */ -#endif //SMEXT_ENABLE_HANDLESYS -#if defined SMEXT_ENABLE_PLAYERHELPERS -extern IPlayerManager *playerhelpers; -#endif //SMEXT_ENABLE_PLAYERHELPERS -#if defined SMEXT_ENABLE_DBMANAGER -extern IDBManager *dbi; -#endif //SMEXT_ENABLE_DBMANAGER -#if defined SMEXT_ENABLE_GAMECONF -extern IGameConfigManager *gameconfs; -#endif //SMEXT_ENABLE_DBMANAGER -#if defined SMEXT_ENABLE_MEMUTILS -extern IMemoryUtils *memutils; -#endif -#if defined SMEXT_ENABLE_GAMEHELPERS -extern IGameHelpers *gamehelpers; -#endif -#if defined SMEXT_ENABLE_TIMERSYS -extern ITimerSystem *timersys; -#endif -#if defined SMEXT_ENABLE_ADTFACTORY -extern IADTFactory *adtfactory; -#endif -#if defined SMEXT_ENABLE_THREADER -extern IThreader *threader; -#endif -#if defined SMEXT_ENABLE_LIBSYS -extern ILibrarySys *libsys; -#endif -#if defined SMEXT_ENABLE_PLUGINSYS -extern SourceMod::IPluginManager *plsys; -#endif -#if defined SMEXT_ENABLE_MENUS -extern IMenuManager *menus; -#endif -#if defined SMEXT_ENABLE_ADMINSYS -extern IAdminSystem *adminsys; -#endif -#if defined SMEXT_ENABLE_USERMSGS -extern IUserMessages *usermsgs; -#endif -#if defined SMEXT_ENABLE_TRANSLATOR -extern ITranslator *translator; -#endif -#if defined SMEXT_ENABLE_NINVOKE -extern INativeInterface *ninvoke; -#endif - -#if defined SMEXT_CONF_METAMOD -PLUGIN_GLOBALVARS(); -extern IVEngineServer *engine; -extern IServerGameDLL *gamedll; -#endif - -/** Creates a SourceMod interface macro pair */ -#define SM_MKIFACE(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION -/** Automates retrieving SourceMod interfaces */ -#define SM_GET_IFACE(prefix, addr) \ - if (!g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)) \ - { \ - if (error != NULL && maxlength) \ - { \ - size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \ - if (len >= maxlength) \ - { \ - error[maxlength - 1] = '\0'; \ - } \ - } \ - return false; \ - } -/** Automates retrieving SourceMod interfaces when needed outside of SDK_OnLoad() */ -#define SM_GET_LATE_IFACE(prefix, addr) \ - g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr) -/** Validates a SourceMod interface pointer */ -#define SM_CHECK_IFACE(prefix, addr) \ - if (!addr) \ - { \ - if (error != NULL && maxlength) \ - { \ - size_t len = snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \ - if (len >= maxlength) \ - { \ - error[maxlength - 1] = '\0'; \ - } \ - } \ - return false; \ - } - -#endif // _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ diff --git a/extension/sdk/smsdk_config.hpp b/extension/smsdk_config.h similarity index 97% rename from extension/sdk/smsdk_config.hpp rename to extension/smsdk_config.h index db37f02..6951814 100644 --- a/extension/sdk/smsdk_config.hpp +++ b/extension/smsdk_config.h @@ -1,80 +1,80 @@ -/** - * ============================================================================= - * connect Extension - * Copyright (C) 2011 Asher Baker (asherkin). 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 . - * - * 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 . - */ - -#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ -#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ - -/** - * @file smsdk_config.hpp - * @brief Contains macros for configuring basic extension information. - */ - - #include "version.h" // SM_FULL_VERSION - -/* Basic information exposed publicly */ -#define SMEXT_CONF_NAME "Connect" -#define SMEXT_CONF_DESCRIPTION "Forward for early connection" -#define SMEXT_CONF_VERSION SM_FULL_VERSION -#define SMEXT_CONF_AUTHOR "Asher \"asherkin\" Baker" -#define SMEXT_CONF_URL "http://limetech.org/" -#define SMEXT_CONF_LOGTAG "CONNECT" -#define SMEXT_CONF_LICENSE "GPL" -#define SMEXT_CONF_DATESTRING __DATE__ - -/** - * @brief Exposes plugin's main interface. - */ -#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name; - -/** - * @brief Sets whether or not this plugin required Metamod. - * NOTE: Uncomment to enable, comment to disable. - */ -#define SMEXT_CONF_METAMOD - -/** Enable interfaces you want to use here by uncommenting lines */ -#define SMEXT_ENABLE_FORWARDSYS -//#define SMEXT_ENABLE_HANDLESYS -//#define SMEXT_ENABLE_PLAYERHELPERS -//#define SMEXT_ENABLE_DBMANAGER -#define SMEXT_ENABLE_GAMECONF -//#define SMEXT_ENABLE_MEMUTILS -//#define SMEXT_ENABLE_GAMEHELPERS -//#define SMEXT_ENABLE_TIMERSYS -//#define SMEXT_ENABLE_THREADER -//#define SMEXT_ENABLE_LIBSYS -//#define SMEXT_ENABLE_MENUS -//#define SMEXT_ENABLE_ADTFACTORY -//#define SMEXT_ENABLE_PLUGINSYS -//#define SMEXT_ENABLE_ADMINSYS -//#define SMEXT_ENABLE_TEXTPARSERS -//#define SMEXT_ENABLE_USERMSGS -//#define SMEXT_ENABLE_TRANSLATOR -//#define SMEXT_ENABLE_NINVOKE - -#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +/** + * ============================================================================= + * connect Extension + * Copyright (C) 2011 Asher Baker (asherkin). 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 . + * + * 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 . + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ + +/** + * @file smsdk_config.hpp + * @brief Contains macros for configuring basic extension information. + */ + + #include "version.h" // SM_FULL_VERSION + +/* Basic information exposed publicly */ +#define SMEXT_CONF_NAME "Connect" +#define SMEXT_CONF_DESCRIPTION "Forward for early connection" +#define SMEXT_CONF_VERSION SM_FULL_VERSION +#define SMEXT_CONF_AUTHOR "Asher \"asherkin\" Baker" +#define SMEXT_CONF_URL "http://limetech.org/" +#define SMEXT_CONF_LOGTAG "CONNECT" +#define SMEXT_CONF_LICENSE "GPL" +#define SMEXT_CONF_DATESTRING __DATE__ + +/** + * @brief Exposes plugin's main interface. + */ +#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name; + +/** + * @brief Sets whether or not this plugin required Metamod. + * NOTE: Uncomment to enable, comment to disable. + */ +#define SMEXT_CONF_METAMOD + +/** Enable interfaces you want to use here by uncommenting lines */ +#define SMEXT_ENABLE_FORWARDSYS +//#define SMEXT_ENABLE_HANDLESYS +//#define SMEXT_ENABLE_PLAYERHELPERS +//#define SMEXT_ENABLE_DBMANAGER +#define SMEXT_ENABLE_GAMECONF +//#define SMEXT_ENABLE_MEMUTILS +//#define SMEXT_ENABLE_GAMEHELPERS +//#define SMEXT_ENABLE_TIMERSYS +//#define SMEXT_ENABLE_THREADER +//#define SMEXT_ENABLE_LIBSYS +//#define SMEXT_ENABLE_MENUS +//#define SMEXT_ENABLE_ADTFACTORY +//#define SMEXT_ENABLE_PLUGINSYS +//#define SMEXT_ENABLE_ADMINSYS +//#define SMEXT_ENABLE_TEXTPARSERS +//#define SMEXT_ENABLE_USERMSGS +//#define SMEXT_ENABLE_TRANSLATOR +//#define SMEXT_ENABLE_NINVOKE + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ diff --git a/product.version b/product.version index 6085e94..f0bb29e 100644 --- a/product.version +++ b/product.version @@ -1 +1 @@ -1.2.1 +1.3.0