diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0da502..b95f352 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,175 +1,74 @@ -name: CI +name: Build AlliedModders Extension on: push: branches: - - main - master + - main tags: - - '*' + - "*" pull_request: branches: - - main - master + - main jobs: - build: - name: Build - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-20.04] - sourcemod-version: [1.11-dev] - protobuf-version: [v2.5.0] - # Before Counter strike 2 changes - protobuf-valve-version: [02c5c94089d46fb14d8d94a4791e8cad7eef2d63] - include: - - os: ubuntu-20.04 - target-archs: x86,x86_64 - sdks: css,csgo + # install-protobuf: + # runs-on: ubuntu-20.04 + # env: + # PROTOBUF_REF: 'v2.5.0' + # # Before Counter strike 2 changes + # PROTOBUF_VALVE_REF: '02c5c94089d46fb14d8d94a4791e8cad7eef2d63' + # steps: + # - name: Checkout valve protobuf + # uses: actions/checkout@v4 + # with: + # repository: SteamDatabase/Protobufs + # ref: ${{ env.PROTOBUF_VALVE_REF }} + # path: protobuf-valve + # submodules: recursive - steps: - - name: Install Linux packages - if: runner.os == 'Linux' - run: | - sudo apt update - sudo apt install -yq --no-install-recommends g++-multilib + # - name: Checkout protobuf + # uses: actions/checkout@v4 + # with: + # repository: protocolbuffers/protobuf + # ref: ${{ env.PROTOBUF_REF }} + # path: protobuf + # submodules: recursive - - name: Set up Python - uses: actions/setup-python@v5 + # - name: Install protobuf + # shell: bash + # run: | + # export EXTENSION_ROOT_DIR=$(pwd) + # cd protobuf - - name: Checkout - uses: actions/checkout@v4 - with: - path: extension + # # sh autogen.sh - - name: Checkout SourceMod - uses: actions/checkout@v4 - with: - repository: alliedmodders/sourcemod - ref: ${{ matrix.sourcemod-version }} - path: sourcemod - submodules: recursive + # # Fix because autogen in protobuf 2.5.0 doesnt work anymore + # autoreconf -f -i -Wall,no-obsolete + # rm -rf autom4te.cache config.h.in~ - - name: Checkout AMBuild - uses: actions/checkout@v4 - with: - repository: alliedmodders/ambuild - path: ambuild + # # Make sure to compile for 32bit with old ABI for std::string compatibility + # ./configure --prefix=$EXTENSION_ROOT_DIR/protobuf --build=i686-pc-linux-gnu "CFLAGS=-m32 -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++14" "CXXFLAGS=-m32 -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++14" "LDFLAGS=-m32 -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++14" --disable-shared --enable-static + # make -j 8 + # make install - - name: Checkout sm-ext-common - uses: actions/checkout@v4 - with: - repository: srcdslab/sm-ext-common - path: sourcemod/extensions/sm-ext-common + # # Compile .proto files to c++ - - name: Checkout valve protobuf - uses: actions/checkout@v4 - with: - repository: SteamDatabase/Protobufs - ref: ${{ matrix.protobuf-valve-version }} - path: protobuf-valve - submodules: recursive + # cd ../protobuf-valve - - name: Checkout protobuf - uses: actions/checkout@v4 - with: - repository: protocolbuffers/protobuf - ref: ${{ matrix.protobuf-version }} - path: protobuf - submodules: recursive + # # Counter strike 2 ? + # # ../protobuf/bin/protoc -I=$PWD -I=$PWD/csgo $PWD/csgo/networksystem_protomessages.proto --cpp_out=$PWD + # # ../protobuf/bin/protoc -I=$PWD -I=$PWD/csgo $PWD/csgo/network_connection.proto --cpp_out=$PWD + # # ../protobuf/bin/protoc -I=$PWD -I=$PWD/csgo $PWD/csgo/networkbasetypes.proto --cpp_out=$PWD - - name: Install AMBuild - run: | - pip install --user ./ambuild + # # CSGO + # ../protobuf/bin/protoc -I=$PWD $PWD/google/protobuf/descriptor.proto --cpp_out=$PWD + # ../protobuf/bin/protoc -I=$PWD -I=$PWD/csgo $PWD/csgo/netmessages.proto --cpp_out=$PWD + # ls -all - - name: Install sourcemod dependencies - run: | - bash sourcemod/tools/checkout-deps.sh -m -s ${{ matrix.sdks }} - - - name: Install protobuf - shell: bash - run: | - export EXTENSION_ROOT_DIR=$(pwd) - cd protobuf - - # sh autogen.sh - - # Fix because autogen in protobuf 2.5.0 doesnt work anymore - autoreconf -f -i -Wall,no-obsolete - rm -rf autom4te.cache config.h.in~ - - # Make sure to compile for 32bit with old ABI for std::string compatibility - ./configure --prefix=$EXTENSION_ROOT_DIR/protobuf --build=i686-pc-linux-gnu "CFLAGS=-m32 -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++14" "CXXFLAGS=-m32 -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++14" "LDFLAGS=-m32 -D_GLIBCXX_USE_CXX11_ABI=0 -std=c++14" --disable-shared --enable-static - make -j 8 - make install - - # Compile .proto files to c++ - - cd ../protobuf-valve - - # Counter strike 2 ? - # ../protobuf/bin/protoc -I=$PWD -I=$PWD/csgo $PWD/csgo/networksystem_protomessages.proto --cpp_out=$PWD - # ../protobuf/bin/protoc -I=$PWD -I=$PWD/csgo $PWD/csgo/network_connection.proto --cpp_out=$PWD - # ../protobuf/bin/protoc -I=$PWD -I=$PWD/csgo $PWD/csgo/networkbasetypes.proto --cpp_out=$PWD - - # CSGO - ../protobuf/bin/protoc -I=$PWD $PWD/google/protobuf/descriptor.proto --cpp_out=$PWD - ../protobuf/bin/protoc -I=$PWD -I=$PWD/csgo $PWD/csgo/netmessages.proto --cpp_out=$PWD - ls -all - - - name: Build - working-directory: extension - shell: bash - env: - BREAKPAD_SYMBOL_SERVER: ${{ secrets.BREAKPAD_SYMBOL_SERVER }} - run: | - mkdir build && cd build - python ../configure.py --enable-optimize --targets=${{ matrix.target-archs }} --sdks=${{ matrix.sdks }} - ambuild - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: ${{ runner.os }} - path: extension/build/package - - - release: - name: Release - if: startsWith(github.ref, 'refs/tags/') - needs: build - runs-on: ubuntu-latest - - steps: - - name: Download artifacts - uses: actions/download-artifact@v4 - - - name: Package - run: | - version=`echo $GITHUB_REF | sed "s/refs\/tags\///"` - ls -Rall - if [ -d "./Linux/" ]; then - cd ./Linux/ - tar -czf ../${{ github.event.repository.name }}-${version}-linux.tar.gz -T <(\ls -1) - cd - - fi - if [ -d "./macOS/" ]; then - cd ./macOS/ - tar -czf ../${{ github.event.repository.name }}-${version}-mac.tar.gz -T <(\ls -1) - cd - - fi - if [ -d "./Windows/" ]; then - cd ./Windows/ - tar -czf ../${{ github.event.repository.name }}-${version}-windows.tar.gz -T <(\ls -1) - cd - - fi - - - name: Release - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: '*.tar.gz' - tag: ${{ github.ref }} - file_glob: true + build-release-extension: + uses: srcdslab/ci-workflows/.github/workflows/shared_build_release_am_extension.yml@v1 + # needs: install-protobuf + with: + sdks: "css" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d10ce5e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +build +Containerfile +.venv +safetyhook +ambuild +*.env +*.ps1 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2301518 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "sm-ext-common"] + path = sm-ext-common + url = git@github.com:srcdslab/sm-ext-common.git diff --git a/AMBuildScript b/AMBuildScript deleted file mode 100644 index 3ca79c1..0000000 --- a/AMBuildScript +++ /dev/null @@ -1,683 +0,0 @@ -# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: -import os, sys -import traceback -import subprocess - -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 - - # By default, nothing supports x64. - if type(platform) is list: - self.platformSpec = {p: ['x86'] for p in platform} - else: - self.platformSpec = platform - - 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 - -WinOnly = ['windows'] -WinLinux = ['windows', 'linux'] -WinLinuxMac = ['windows', 'linux', 'mac'] - -PossibleSDKs = { - 'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'), - 'csgo': SDK('HL2SDKCSGO', '2.csgo', '21', 'CSGO', WinLinuxMac, 'csgo'), -} - -def ResolveEnvPath(env, folder): - if env in os.environ: - path = os.environ[env] - if os.path.isdir(path): - return path - return None - - 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.spvm = [] - self.extensions = [] - self.generated_headers = None - self.sm_root = None - self.mms_root = None - self.mysql_root = {} - self.spcomp = None - self.spcomp_bins = None - self.smx_files = {} - self.versionlib = None - self.all_targets = [] - self.target_archs = set() - self.protobuf_root = None - self.protobuf_valve_root = None - - - if builder.options.targets: - target_archs = builder.options.targets.split(',') - else: - target_archs = ['x86'] - if builder.backend != 'amb2': - target_archs.append('x86_64') - - for arch in target_archs: - try: - cxx = builder.DetectCxx(target_arch = arch) - self.target_archs.add(cxx.target.arch) - except Exception as e: - # Error if archs were manually overridden. - if builder.options.targets: - raise - print('Skipping target {}: {}'.format(arch, e)) - continue - self.all_targets.append(cxx) - - if not self.all_targets: - raise Exception('No suitable C/C++ compiler was found.') - - @property - 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_none = sdk_list[0] == 'none' - 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(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 and len(sdk_list) and not use_none: - raise Exception('No applicable SDKs were found, nothing to do') - - if builder.options.sm_path: - self.sm_root = builder.options.sm_path - else: - self.sm_root = ResolveEnvPath('SOURCEMOD18', 'sourcemod-1.10') - if not self.sm_root: - self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod-source') - if not self.sm_root: - self.sm_root = ResolveEnvPath('SOURCEMOD_DEV', 'sourcemod-central') - if not self.sm_root: - self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod') - - 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_DEV', 'metamod-source') - if not self.mms_root: - self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central') - if not self.mms_root: - self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod') - - if not self.mms_root or not os.path.isdir(self.mms_root): - raise Exception('Could not find a source copy of Metamod:Source') - self.mms_root = Normalize(self.mms_root) - - if 'csgo' in sdk_list: - if builder.options.protobuf_valve_path: - self.protobuf_valve_root = builder.options.protobuf_valve_path - else: - self.protobuf_valve_root = ResolveEnvPath('PBVSOURCE110', 'protobuf-valve-2.5.0') - if not self.protobuf_valve_root: - self.protobuf_valve_root = ResolveEnvPath('PBVSOURCE_DEV', 'protobuf-valve-source') - if not self.protobuf_valve_root: - self.protobuf_valve_root = ResolveEnvPath('PBVSOURCE_DEV', 'protobuf-valve-central') - if not self.protobuf_valve_root: - self.protobuf_valve_root = ResolveEnvPath('PBVSOURCE_DEV', 'protobuf-valve') - - if not self.protobuf_valve_root or not os.path.isdir(self.protobuf_valve_root): - raise Exception('Could not find a source copy of valve Protobuf') - self.protobuf_valve_root = Normalize(self.protobuf_valve_root) - - if builder.options.protobuf_path: - self.protobuf_root = builder.options.protobuf_path - else: - self.protobuf_root = ResolveEnvPath('PBSOURCE110', 'protobuf-2.5.0') - if not self.protobuf_root: - self.protobuf_root = ResolveEnvPath('PBSOURCE_DEV', 'protobuf-source') - if not self.protobuf_root: - self.protobuf_root = ResolveEnvPath('PBSOURCE_DEV', 'protobuf-central') - if not self.protobuf_root: - self.protobuf_root = ResolveEnvPath('PBSOURCE_DEV', 'protobuf') - - if not self.protobuf_root or not os.path.isdir(self.protobuf_root): - raise Exception('Could not find a source copy of Protobuf') - self.protobuf_root = Normalize(self.protobuf_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) - - # Optimization - 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) - - # Finish up. - cxx.includes += [ - os.path.join(self.sm_root, 'public'), - ] - - def configure_gcc(self, cxx): - cxx.defines += [ - 'stricmp=strcasecmp', - '_stricmp=strcasecmp', - '_snprintf=snprintf', - '_vsnprintf=vsnprintf', - 'HAVE_STDINT_H', - 'GNUC', - ] - cxx.cflags += [ - '-pipe', - '-fno-strict-aliasing', - '-Wall', - '-Werror', - '-Wno-unused', - '-Wno-switch', - '-Wno-array-bounds', - '-msse', - '-fvisibility=hidden', - ] - - if cxx.version == 'apple-clang-6.0' or cxx.version == 'clang-3.4': - cxx.cxxflags += ['-std=c++1y'] - else: - cxx.cxxflags += ['-std=c++14'] - - cxx.cxxflags += [ - '-fno-threadsafe-statics', - '-Wno-non-virtual-dtor', - '-Wno-overloaded-virtual', - '-fvisibility-inlines-hidden', - ] - - have_gcc = cxx.family == 'gcc' - have_clang = cxx.family == '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'] - cxx.cflags += ['-Wno-maybe-uninitialized'] - - if builder.options.opt == '1': - cxx.cflags += [ - '-O3', - '-fexperimental-new-pass-manager', - '-mllvm', - '-inline-threshold=1000', - '-mllvm', - '-vectorize-loops', - '-ftree-vectorize', - ] - - # Don't omit the frame pointer. - cxx.cflags += ['-fno-omit-frame-pointer'] - - 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', - '/GR-', - '/TP', - ] - cxx.linkflags += [ - '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', '_FILE_OFFSET_BITS=64'] - cxx.linkflags += ['-lm'] - if cxx.family == 'gcc': - cxx.linkflags += ['-static-libgcc'] - elif cxx.family == 'clang': - cxx.linkflags += ['-lgcc_eh'] - cxx.linkflags += ['-static-libstdc++'] - - def configure_mac(self, cxx): - cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL'] - cxx.cflags += ['-mmacosx-version-min=10.7'] - cxx.linkflags += [ - '-mmacosx-version-min=10.7', - '-stdlib=libc++', - '-lc++', - ] - cxx.cxxflags += ['-stdlib=libc++'] - - def configure_windows(self, cxx): - cxx.defines += ['WIN32', '_WINDOWS'] - - def add_libamtl(self): - # Add libamtl. - self.libamtl = {} - for cxx in self.all_targets: - def get_configure_fn(cxx): - return lambda builder, name: self.StaticLibrary(builder, cxx, name) - extra_vars = {'Configure': get_configure_fn(cxx)} - libamtl = builder.Build('public/amtl/amtl/AMBuilder', extra_vars) - self.libamtl[cxx.target.arch] = libamtl.binary - - def AddVersioning(self, binary): - if binary.compiler.target.platform == 'windows': - binary.sources += ['version.rc'] - binary.compiler.rcdefines += [ - 'BINARY_NAME="{0}"'.format(binary.outputFile), - 'RC_COMPILE', - ] - elif binary.compiler.target.platform == 'mac': - if binary.type == 'library': - binary.compiler.postlink += [ - '-compatibility_version', '1.0.0', - '-current_version', self.productVersion - ] - return binary - - def LibraryBuilder(self, compiler, name): - binary = compiler.Library(name) - self.AddVersioning(binary) - if binary.compiler.like('msvc'): - binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS'] - return binary - - def ProgramBuilder(self, compiler, name): - binary = compiler.Program(name) - self.AddVersioning(binary) - if '-static-libgcc' in binary.compiler.linkflags: - binary.compiler.linkflags.remove('-static-libgcc') - if '-lgcc_eh' in binary.compiler.linkflags: - binary.compiler.linkflags.remove('-lgcc_eh') - if binary.compiler.like('gcc'): - binary.compiler.linkflags += ['-lstdc++', '-lpthread'] - if binary.compiler.like('msvc'): - binary.compiler.linkflags += ['/SUBSYSTEM:CONSOLE'] - return binary - - def StaticLibraryBuilder(self, compiler, name): - return compiler.StaticLibrary(name) - - def Library(self, context, compiler, name): - compiler = compiler.clone() - SetArchFlags(compiler) - return self.LibraryBuilder(compiler, name) - - def Program(self, context, compiler, name): - compiler = compiler.clone() - SetArchFlags(compiler) - return self.ProgramBuilder(compiler, name) - - def StaticLibrary(self, context, compiler, name): - compiler = compiler.clone() - SetArchFlags(compiler) - return self.StaticLibraryBuilder(compiler, name) - - 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'), - os.path.join(self.sm_root, 'extensions', 'sm-ext-common', 'include'), - ] - return compiler - - def ExtLibrary(self, context, compiler, name): - binary = self.Library(context, compiler, name) - SetArchFlags(compiler) - self.ConfigureForExtension(context, binary.compiler) - return binary - - 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 = ['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', 'blade']: - 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 ProtoBufLibrary(self, context, compiler, name, sdk): - binary = self.Library(context, compiler, name) - self.ConfigureForExtension(context, binary.compiler) - return binary - - def HL2Library(self, context, compiler, name, sdk): - binary = self.Library(context, compiler, name) - self.ConfigureForExtension(context, binary.compiler) - return self.ConfigureForHL2(context, binary, sdk) - - def HL2Project(self, context, compiler, name): - project = context.LibraryProject(name) - self.ConfigureForExtension(context, compiler) - return project - - def HL2Config(self, project, context, compiler, name, sdk): - 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 - -if getattr(builder, 'target', None) is not None: - sys.stderr.write("Your output folder was configured for AMBuild 2.1, and SourceMod is now\n") - sys.stderr.write("configured to use AMBuild 2.2. Please remove your output folder and\n") - sys.stderr.write("reconfigure to continue.\n") - os._exit(1) - -SM = ExtensionConfig() -SM.detectSDKs() -SM.configure() - -# This will clone the list and each cxx object as we recurse, preventing child -# scripts from messing up global state. -builder.targets = builder.CloneableList(SM.all_targets) - -if builder.backend == 'amb2': - BuildScripts = [ - 'AMBuilder', - 'PackageScript', - ] - -builder.Build(BuildScripts, { 'SM': SM}) diff --git a/AMBuilder b/AMBuilder deleted file mode 100644 index dd95518..0000000 --- a/AMBuilder +++ /dev/null @@ -1,62 +0,0 @@ -# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: -import os - -projectName = 'Voice' - -for cxx in builder.targets: - for sdk_name in SM.sdks: - sdk = SM.sdks[sdk_name] - - if not cxx.target.arch in sdk.platformSpec[cxx.target.platform]: - continue - - binary = SM.HL2Library(builder, cxx, projectName + '.ext.' + sdk.ext, sdk) - - binary.compiler.defines += [ - 'SOURCEMOD_BUILD', - 'HAVE_STRING_H', - ] - - if cxx.target.platform == 'linux': - binary.compiler.postlink += ['-lpthread', '-lrt'] - elif cxx.target.platform == 'mac': - binary.compiler.cflags += ['-Wno-deprecated-declarations'] - binary.compiler.postlink += ['-framework', 'CoreServices'] - - binary.sources += [ - 'extension.cpp', - 'ringbuffer.cpp', - os.path.join(SM.sm_root, 'extensions', 'sm-ext-common', 'mathstubs.c'), - os.path.join(SM.sm_root, 'public', 'smsdk_ext.cpp'), - os.path.join(SM.sm_root, 'public', 'CDetour', 'detours.cpp'), - os.path.join(SM.sm_root, 'public', 'asm', 'asm.c'), - os.path.join(SM.sm_root, 'public', 'libudis86', 'decode.c'), - os.path.join(SM.sm_root, 'public', 'libudis86', 'itab.c'), - os.path.join(SM.sm_root, 'public', 'libudis86', 'syn-att.c'), - os.path.join(SM.sm_root, 'public', 'libudis86', 'syn-intel.c'), - os.path.join(SM.sm_root, 'public', 'libudis86', 'syn.c'), - os.path.join(SM.sm_root, 'public', 'libudis86', 'udis86.c'), - ] - - if sdk.name in ['csgo']: - binary.compiler.cxxincludes += [ - os.path.join(SM.protobuf_root, 'include'), - os.path.join(SM.protobuf_valve_root), - ] - binary.compiler.postlink += [ - '-L' + os.path.join(SM.protobuf_root, 'lib'), - '-lprotobuf' - ] - - binary.sources += [ - os.path.join(SM.protobuf_valve_root, 'csgo', 'netmessages.pb.cc'), - ] - - binary.compiler.cxxincludes += [ - os.path.join(builder.sourcePath, 'celt') - ] - binary.compiler.linkflags += [ - os.path.join(builder.sourcePath, 'celt', 'libcelt0.a') - ] - - SM.extensions += [builder.Add(binary)] diff --git a/Makefile b/Makefile deleted file mode 100644 index 956b14d..0000000 --- a/Makefile +++ /dev/null @@ -1,233 +0,0 @@ -# (C)2004-2010 SourceMod Development Team -# Makefile written by David "BAILOPAN" Anderson - -########################################### -### EDIT THESE PATHS FOR YOUR OWN SETUP ### -########################################### - -SMSDK = ../.. -HL2SDK_ORIG = ../../../hl2sdk -HL2SDK_OB = ../../../hl2sdk-ob -HL2SDK_CSS = ../../../hl2sdk-css -HL2SDK_OB_VALVE = ../../../hl2sdk-ob-valve -HL2SDK_L4D = ../../../hl2sdk-l4d -HL2SDK_L4D2 = ../../../hl2sdk-l4d2 -HL2SDK_CSGO = ../../../hl2sdk-csgo -MMSOURCE19 = ../../../mmsource-1.9 - -##################################### -### EDIT BELOW FOR OTHER PROJECTS ### -##################################### - -PROJECT = sample - -#Uncomment for Metamod: Source enabled extension -#USEMETA = true - -OBJECTS = smsdk_ext.cpp extension.cpp - -############################################## -### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### -############################################## - -C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing -C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3 -C_GCC4_FLAGS = -fvisibility=hidden -CPP_GCC4_FLAGS = -fvisibility-inlines-hidden -CPP = gcc -CPP_OSX = clang - -########################## -### SDK CONFIGURATIONS ### -########################## - -override ENGSET = false - -# Check for valid list of engines -ifneq (,$(filter original orangebox orangeboxvalve css left4dead left4dead2 csgo,$(ENGINE))) - override ENGSET = true -endif - -ifeq "$(ENGINE)" "original" - HL2SDK = $(HL2SDK_ORIG) - CFLAGS += -DSOURCE_ENGINE=1 -endif -ifeq "$(ENGINE)" "orangebox" - HL2SDK = $(HL2SDK_OB) - CFLAGS += -DSOURCE_ENGINE=3 -endif -ifeq "$(ENGINE)" "css" - HL2SDK = $(HL2SDK_CSS) - CFLAGS += -DSOURCE_ENGINE=6 -endif -ifeq "$(ENGINE)" "orangeboxvalve" - HL2SDK = $(HL2SDK_OB_VALVE) - CFLAGS += -DSOURCE_ENGINE=7 -endif -ifeq "$(ENGINE)" "left4dead" - HL2SDK = $(HL2SDK_L4D) - CFLAGS += -DSOURCE_ENGINE=8 -endif -ifeq "$(ENGINE)" "left4dead2" - HL2SDK = $(HL2SDK_L4D2) - CFLAGS += -DSOURCE_ENGINE=9 -endif -ifeq "$(ENGINE)" "csgo" - HL2SDK = $(HL2SDK_CSGO) - CFLAGS += -DSOURCE_ENGINE=12 -endif - -HL2PUB = $(HL2SDK)/public - -ifeq "$(ENGINE)" "original" - INCLUDE += -I$(HL2SDK)/public/dlls - METAMOD = $(MMSOURCE19)/core-legacy -else - INCLUDE += -I$(HL2SDK)/public/game/server - METAMOD = $(MMSOURCE19)/core -endif - -OS := $(shell uname -s) - -ifeq "$(OS)" "Darwin" - LIB_EXT = dylib - HL2LIB = $(HL2SDK)/lib/mac -else - LIB_EXT = so - ifeq "$(ENGINE)" "original" - HL2LIB = $(HL2SDK)/linux_sdk - else - HL2LIB = $(HL2SDK)/lib/linux - endif -endif - -# if ENGINE is original or OB -ifneq (,$(filter original orangebox,$(ENGINE))) - LIB_SUFFIX = _i486.$(LIB_EXT) -else - LIB_PREFIX = lib - LIB_SUFFIX = .$(LIB_EXT) -endif - -INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn - -ifeq "$(USEMETA)" "true" - LINK_HL2 = $(HL2LIB)/tier1_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX) - ifeq "$(ENGINE)" "csgo" - LINK_HL2 += $(HL2LIB)/interfaces_i486.a - endif - - LINK += $(LINK_HL2) - - INCLUDE += -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) \ - -I$(METAMOD)/sourcehook - CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \ - -DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \ - -DSE_PORTAL2=11 -DSE_CSGO=12 -endif - -LINK += -m32 -lm -ldl - -CFLAGS += -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \ - -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -DCOMPILER_GCC -Wall -Werror \ - -Wno-overloaded-virtual -Wno-switch -Wno-unused -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -m32 -CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti - -################################################ -### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### -################################################ - -BINARY = $(PROJECT).ext.$(LIB_EXT) - -ifeq "$(DEBUG)" "true" - BIN_DIR = Debug - CFLAGS += $(C_DEBUG_FLAGS) -else - BIN_DIR = Release - CFLAGS += $(C_OPT_FLAGS) -endif - -ifeq "$(USEMETA)" "true" - BIN_DIR := $(BIN_DIR).$(ENGINE) -endif - -ifeq "$(OS)" "Darwin" - CPP = $(CPP_OSX) - LIB_EXT = dylib - CFLAGS += -DOSX -D_OSX - LINK += -dynamiclib -lstdc++ -mmacosx-version-min=10.5 -else - LIB_EXT = so - CFLAGS += -D_LINUX - LINK += -shared -endif - -IS_CLANG := $(shell $(CPP) --version | head -1 | grep clang > /dev/null && echo "1" || echo "0") - -ifeq "$(IS_CLANG)" "1" - CPP_MAJOR := $(shell $(CPP) --version | grep clang | sed "s/.*version \([0-9]\)*\.[0-9]*.*/\1/") - CPP_MINOR := $(shell $(CPP) --version | grep clang | sed "s/.*version [0-9]*\.\([0-9]\)*.*/\1/") -else - CPP_MAJOR := $(shell $(CPP) -dumpversion >&1 | cut -b1) - CPP_MINOR := $(shell $(CPP) -dumpversion >&1 | cut -b3) -endif - -# If not clang -ifeq "$(IS_CLANG)" "0" - CFLAGS += -mfpmath=sse -endif - -# Clang || GCC >= 4 -ifeq "$(shell expr $(IS_CLANG) \| $(CPP_MAJOR) \>= 4)" "1" - CFLAGS += $(C_GCC4_FLAGS) - CPPFLAGS += $(CPP_GCC4_FLAGS) -endif - -# Clang >= 3 || GCC >= 4.7 -ifeq "$(shell expr $(IS_CLANG) \& $(CPP_MAJOR) \>= 3 \| $(CPP_MAJOR) \>= 4 \& $(CPP_MINOR) \>= 7)" "1" - CFLAGS += -Wno-delete-non-virtual-dtor -endif - -# OS is Linux and not using clang -ifeq "$(shell expr $(OS) \= Linux \& $(IS_CLANG) \= 0)" "1" - LINK += -static-libgcc -endif - -OBJ_BIN := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) - -# This will break if we include other Makefiles, but is fine for now. It allows -# us to make a copy of this file that uses altered paths (ie. Makefile.mine) -# or other changes without mucking up the original. -MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)) - -$(BIN_DIR)/%.o: %.cpp - $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< - -all: check - mkdir -p $(BIN_DIR) - ln -sf ../smsdk_ext.cpp - if [ "$(USEMETA)" = "true" ]; then \ - ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX); \ - ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX); \ - fi - $(MAKE) -f $(MAKEFILE_NAME) extension - -check: - if [ "$(USEMETA)" = "true" ] && [ "$(ENGSET)" = "false" ]; then \ - echo "You must supply one of the following values for ENGINE:"; \ - echo "csgo, left4dead2, left4dead, css, orangeboxvalve, orangebox, or original"; \ - exit 1; \ - fi - -extension: check $(OBJ_BIN) - $(CPP) $(INCLUDE) $(OBJ_BIN) $(LINK) -o $(BIN_DIR)/$(BINARY) - -debug: - $(MAKE) -f $(MAKEFILE_NAME) all DEBUG=true - -default: all - -clean: check - rm -rf $(BIN_DIR)/*.o - rm -rf $(BIN_DIR)/$(BINARY) - diff --git a/PackageScript b/PackageScript deleted file mode 100644 index f81aea3..0000000 --- a/PackageScript +++ /dev/null @@ -1,52 +0,0 @@ -# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python: -import os - -# This is where the files will be output to -# package is the default -builder.SetBuildFolder('package') - -# Add any folders you need to this list -folder_list = [ - 'addons/sourcemod/extensions', - 'addons/sourcemod/scripting/include', - 'addons/sourcemod/gamedata', -] - -if 'x86_64' in SM.target_archs: - folder_list.extend([ - 'addons/sourcemod/extensions/x64', - ]) - -# Create the distribution folder hierarchy. -folder_map = {} -for folder in folder_list: - norm_folder = os.path.normpath(folder) - folder_map[folder] = builder.AddFolder(norm_folder) - -# Copy binaries. -for cxx_task in SM.extensions: - if cxx_task.target.arch == 'x86_64': - builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions/x64']) - else: - builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions']) - -# Do all straight-up file copies from the source tree. -def CopyFiles(src, dest, files): - if not dest: - dest = src - dest_entry = folder_map[dest] - for source_file in files: - source_path = os.path.join(builder.sourcePath, src, source_file) - dest_path = os.path.join(dest_entry.path, source_file) - if not os.path.isfile(str(dest_path)): - builder.AddCopy(source_path, dest_entry) - -# Include files -CopyFiles('addons/sourcemod/scripting/include', 'addons/sourcemod/scripting/include', - [ 'Voice.inc', ] -) - -# Gamedata files -CopyFiles('addons/sourcemod/gamedata', 'addons/sourcemod/gamedata', - [ 'voice.games.txt', ] -) diff --git a/configure.py b/configure.py deleted file mode 100755 index bdf5816..0000000 --- a/configure.py +++ /dev/null @@ -1,43 +0,0 @@ -# vim: set ts=2 sw=2 tw=99 noet: -import sys -try: - from ambuild2 import run, util -except: - try: - import ambuild - sys.stderr.write('It looks like you have AMBuild 1 installed, but this project uses AMBuild 2.\n') - sys.stderr.write('Upgrade to the latest version of AMBuild to continue.\n') - except: - sys.stderr.write('AMBuild must be installed to build this project.\n') - sys.stderr.write('http://www.alliedmods.net/ambuild\n') - sys.exit(1) - -# Hack to show a decent upgrade message, which wasn't done until 2.2. -ambuild_version = getattr(run, 'CURRENT_API', '2.1') -if ambuild_version.startswith('2.1'): - sys.stderr.write("AMBuild 2.2 or higher is required; please update\n") - sys.exit(1) - -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('--protobuf-valve-path', type=str, dest='protobuf_valve_path', default=None, - help='Path to valve protobuf') -parser.options.add_argument('--protobuf-path', type=str, dest='protobuf_path', default=None, - help='Path to protobuf') -parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug', - help='Enable debugging symbols') -parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt', - help='Enable optimization') -parser.options.add_argument('-s', '--sdks', default='all', dest='sdks', - help='Build against specified SDKs; valid args are "all", "present", or ' - 'comma-delimited list of engine names (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() diff --git a/extension.h b/extension.h deleted file mode 100644 index bbb16ab..0000000 --- a/extension.h +++ /dev/null @@ -1,189 +0,0 @@ -/** - * vim: set ts=4 : - * ============================================================================= - * SourceMod Sample Extension - * 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_PROPER_H_ -#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ - -#include -#include "smsdk_ext.h" -#include "celt_header.h" -#include "ringbuffer.h" - -#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_INSURGENCY -#include "csgo/netmessages.pb.h" -#endif - -/** - * @file extension.h - * @brief Sample extension code header. - */ - -#define MAX_CLIENTS 16 - -#ifdef _WIN32 -typedef __int64 int64; -#else -typedef long long int64; -#endif - -class CDetour; -class IClient; - -/** - * @brief Sample implementation of the SDK Extension. - * Note: Uncomment one of the pre-defined virtual functions in order to use it. - */ -class CVoice : - 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 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. - * Note: It is is a good idea to add natives here, if any are provided. - */ - virtual void SDK_OnAllLoaded(); - - /** - * @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 maxlength); -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 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: // IConCommandBaseAccessor - virtual bool RegisterConCommandBase(ConCommandBase *pVar); - -public: - CVoice(); - void OnGameFrame(bool simulating); - bool OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data); - - void ListenSocket(); - -private: - int m_ListenSocket; - - struct CClient - { - int m_Socket; - size_t m_BufferWriteIndex; - size_t m_LastLength; - double m_LastValidData; - bool m_New; - bool m_UnEven; - unsigned char m_Remainder; - } m_aClients[MAX_CLIENTS]; - - struct pollfd m_aPollFds[1 + MAX_CLIENTS]; - int m_PollFds; - - CRingBuffer m_Buffer; - - double m_AvailableTime; - - struct CEncoderSettings - { - celt_int32 SampleRate_Hz; - celt_int32 TargetBitRate_Kbps; - celt_int32 FrameSize; - celt_int32 PacketSize; - celt_int32 Complexity; - double FrameTime; - } m_EncoderSettings; - - CELTMode *m_pMode; - CELTEncoder *m_pCodec; - - CDetour *m_VoiceDetour; - - void HandleNetwork(); - void OnDataReceived(CClient *pClient, int16_t *pData, size_t Samples); - void HandleVoiceData(); - void BroadcastVoiceData(IClient *pClient, size_t nBytes, unsigned char *pData); -}; - -#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/addons/sourcemod/gamedata/voice.games.txt b/package/addons/sourcemod/gamedata/voice.games.txt similarity index 100% rename from addons/sourcemod/gamedata/voice.games.txt rename to package/addons/sourcemod/gamedata/voice.games.txt diff --git a/addons/sourcemod/scripting/include/Voice.inc b/package/addons/sourcemod/scripting/include/Voice.inc similarity index 100% rename from addons/sourcemod/scripting/include/Voice.inc rename to package/addons/sourcemod/scripting/include/Voice.inc diff --git a/product.version b/product.version new file mode 100644 index 0000000..38f77a6 --- /dev/null +++ b/product.version @@ -0,0 +1 @@ +2.0.1 diff --git a/sm-ext-common b/sm-ext-common new file mode 160000 index 0000000..2adde8c --- /dev/null +++ b/sm-ext-common @@ -0,0 +1 @@ +Subproject commit 2adde8cc6fdb3e32beee27349af1beb1769a5872 diff --git a/src/AMBuilder b/src/AMBuilder new file mode 100644 index 0000000..aac612c --- /dev/null +++ b/src/AMBuilder @@ -0,0 +1,52 @@ +# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: +import os + +projectName = 'Voice' + +project = builder.LibraryProject(projectName) +project.sources += [ + os.path.join(Extension.ext_root, 'src', 'extension.cpp'), + os.path.join(Extension.ext_root, 'src', 'ringbuffer.cpp'), + os.path.join(Extension.sm_root, 'public', 'smsdk_ext.cpp') +] + +for sdk_name in Extension.sdks: + sdk = Extension.sdks[sdk_name] + if sdk['name'] in ['mock']: + continue + + for cxx in builder.targets: + if not cxx.target.arch in sdk['platforms'][cxx.target.platform]: + continue + + binary = Extension.HL2ExtConfig(project, builder, cxx, projectName + '.ext.' + sdk['extension'], sdk) + + Extension.AddCDetour(binary) + + if sdk['name'] in ['csgo']: + binary.compiler.cxxincludes += [ + os.path.join(Extension.protobuf_root, 'include'), + os.path.join(Extension.protobuf_valve_root), + ] + binary.compiler.postlink += [ + '-L' + os.path.join(Extension.protobuf_root, 'lib'), + '-lprotobuf' + ] + + binary.sources += [ + os.path.join(Extension.protobuf_valve_root, 'csgo', 'netmessages.pb.cc'), + ] + + binary.compiler.cxxincludes += [ + os.path.join(Extension.ext_root, 'src', 'celt') + ] + # TODO: add proper linux support for x64 + if cxx.target.arch in ['x86'] and cxx.target.platform in ['linux']: + binary.compiler.linkflags += [ + os.path.join(Extension.ext_root, 'src', 'celt', 'libcelt0.a') + ] + # TODO: add proper windows support for celt + if cxx.target.platform in ['windows']: + binary.compiler.linkflags += ['/FORCE:UNRESOLVED'] + +Extension.extensions += builder.Add(project) diff --git a/celt/celt.h b/src/celt/celt.h similarity index 100% rename from celt/celt.h rename to src/celt/celt.h diff --git a/celt/celt_header.h b/src/celt/celt_header.h similarity index 100% rename from celt/celt_header.h rename to src/celt/celt_header.h diff --git a/celt/celt_types.h b/src/celt/celt_types.h similarity index 100% rename from celt/celt_types.h rename to src/celt/celt_types.h diff --git a/celt/libcelt0.a b/src/celt/libcelt0.a similarity index 100% rename from celt/libcelt0.a rename to src/celt/libcelt0.a diff --git a/extension.cpp b/src/extension.cpp similarity index 81% rename from extension.cpp rename to src/extension.cpp index 9665383..4522675 100644 --- a/extension.cpp +++ b/src/extension.cpp @@ -32,13 +32,22 @@ #include #include #include -#include -#include -#include -#include -#include #include -#include +#include + +#ifdef _WIN32 + #include + #include + typedef SOCKET socket_t; +#else + #include + #include + #include + #include + #include + #include + typedef int socket_t; +#endif #include #include @@ -51,7 +60,7 @@ #include "CDetour/detours.h" #include "extension.h" -#include "extensionHelper.h" +#include "convarhelper.h" // voice packets are sent over unreliable netchannel //#define NET_MAX_DATAGRAM_PAYLOAD 4000 // = maximum unreliable payload size @@ -79,7 +88,12 @@ ConVar *g_SvTestDataHex = CreateConVar("sm_voice_debug_celt_data", "", FCVAR_NOT * @brief Implement extension code here. */ -template inline T min(T a, T b) { return a +typedef SSIZE_T ssize_t; +#endif + +template inline T min_ext(T a, T b) { return a(count.QuadPart) / static_cast(freq.QuadPart); } +#else +double getTime() { + struct timespec tv; + if (clock_gettime(CLOCK_REALTIME, &tv) != 0) { + return 0.0; + } + return tv.tv_sec + tv.tv_nsec / 1e9; +} +#endif + void OnGameFrame(bool simulating) { g_Interface.OnGameFrame(simulating); @@ -319,22 +347,22 @@ bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late) g_pSM->LogMessage(myself, "== Voice Encoder Settings =="); g_pSM->LogMessage(myself, "SampleRateHertzKbps: %d", g_SvSampleRateHz->GetInt()); g_pSM->LogMessage(myself, "BitRate: %d", g_SvBitRateKbps->GetInt()); - g_pSM->LogMessage(myself, "FrameSize: %d", g_SvFrameSize->GetInt()); - g_pSM->LogMessage(myself, "PacketSize: %d", g_SvPacketSize->GetInt()); - g_pSM->LogMessage(myself, "Complexity: %d", g_SvComplexity->GetInt()); + g_pSM->LogMessage(myself, "frameSize: %d", g_SvFrameSize->GetInt()); + g_pSM->LogMessage(myself, "packetSize: %d", g_SvPacketSize->GetInt()); + g_pSM->LogMessage(myself, "complexity: %d", g_SvComplexity->GetInt()); } // Encoder settings - m_EncoderSettings.SampleRate_Hz = g_SvSampleRateHz->GetInt(); - m_EncoderSettings.TargetBitRate_Kbps = g_SvBitRateKbps->GetInt(); - m_EncoderSettings.FrameSize = g_SvFrameSize->GetInt(); // samples - m_EncoderSettings.PacketSize = g_SvPacketSize->GetInt(); - m_EncoderSettings.Complexity = g_SvComplexity->GetInt(); // 0 - 10 - m_EncoderSettings.FrameTime = (double)m_EncoderSettings.FrameSize / (double)m_EncoderSettings.SampleRate_Hz; + m_EncoderSettings.sampleRateHz = g_SvSampleRateHz->GetInt(); + m_EncoderSettings.targetBitRateKBPS = g_SvBitRateKbps->GetInt(); + m_EncoderSettings.frameSize = g_SvFrameSize->GetInt(); // samples + m_EncoderSettings.packetSize = g_SvPacketSize->GetInt(); + m_EncoderSettings.complexity = g_SvComplexity->GetInt(); // 0 - 10 + m_EncoderSettings.frameTime = (double)m_EncoderSettings.frameSize / (double)m_EncoderSettings.sampleRateHz; // Init CELT encoder int theError; - m_pMode = celt_mode_create(m_EncoderSettings.SampleRate_Hz, m_EncoderSettings.FrameSize, &theError); + m_pMode = celt_mode_create(m_EncoderSettings.sampleRateHz, m_EncoderSettings.frameSize, &theError); if(!m_pMode) { g_SMAPI->Format(error, maxlength, "celt_mode_create error: %d", theError); @@ -351,8 +379,8 @@ bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late) } celt_encoder_ctl(m_pCodec, CELT_RESET_STATE_REQUEST, NULL); - celt_encoder_ctl(m_pCodec, CELT_SET_BITRATE(m_EncoderSettings.TargetBitRate_Kbps * 1000)); - celt_encoder_ctl(m_pCodec, CELT_SET_COMPLEXITY(m_EncoderSettings.Complexity)); + celt_encoder_ctl(m_pCodec, CELT_SET_BITRATE(m_EncoderSettings.targetBitRateKBPS * 1000)); + celt_encoder_ctl(m_pCodec, CELT_SET_COMPLEXITY(m_EncoderSettings.complexity)); return true; } @@ -436,7 +464,7 @@ void CVoice::SDK_OnAllLoaded() } int yes = 1; - if(setsockopt(m_ListenSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) + if(setsockopt(m_ListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(yes)) < 0) { smutils->LogError(myself, "Failed setting SO_REUSEADDR on socket."); SDK_OnUnload(); @@ -447,6 +475,45 @@ void CVoice::SDK_OnAllLoaded() smutils->AddFrameAction(ListenSocketAction, this); } + +bool convert_ip(const char *ip, struct in_addr *addr) +{ +#ifdef _WIN32 + return InetPton(AF_INET, ip, addr) == 1; +#else + return inet_aton(ip, addr) != 0; +#endif +} + +void close_socket(int sock) +{ +#ifdef _WIN32 + closesocket(sock); +#else + close(sock); +#endif +} + +int my_poll(struct pollfd *fds, int nfds, int timeout) +{ +#ifdef _WIN32 + // Define nfds_t on Windows if needed + typedef int nfds_t; + return WSAPoll(fds, nfds, timeout); +#else + return poll(fds, nfds, timeout); +#endif +} + +int my_ioctl(socket_t sockfd, long cmd, size_t *argp) +{ +#ifdef _WIN32 + return ioctlsocket(sockfd, cmd, reinterpret_cast(argp)); // Windows version +#else + return ioctl(sockfd, cmd, argp); // Linux/macOS version +#endif +} + void CVoice::ListenSocket() { if(m_PollFds > 0) @@ -455,7 +522,12 @@ void CVoice::ListenSocket() sockaddr_in bindAddr; memset(&bindAddr, 0, sizeof(bindAddr)); bindAddr.sin_family = AF_INET; - inet_aton(g_SmVoiceAddr->GetString(), &bindAddr.sin_addr); + if (!convert_ip(g_SmVoiceAddr->GetString(), &bindAddr.sin_addr)) + { + smutils->LogError(myself, "Failed to convert ip."); + SDK_OnUnload(); + return; + } bindAddr.sin_port = htons(g_SmVoicePort->GetInt()); smutils->LogMessage(myself, "Binding to %s:%d!\n", g_SmVoiceAddr->GetString(), g_SmVoicePort->GetInt()); @@ -493,7 +565,7 @@ void CVoice::SDK_OnUnload() if(m_ListenSocket != -1) { - close(m_ListenSocket); + close_socket(m_ListenSocket); m_ListenSocket = -1; } @@ -501,7 +573,7 @@ void CVoice::SDK_OnUnload() { if(m_aClients[Client].m_Socket != -1) { - close(m_aClients[Client].m_Socket); + close_socket(m_aClients[Client].m_Socket); m_aClients[Client].m_Socket = -1; } } @@ -528,7 +600,7 @@ void CVoice::OnGameFrame(bool simulating) memset(g_aFrameVoiceBytes, 0, sizeof(g_aFrameVoiceBytes)); } -bool CVoice::OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data) +bool CVoice::OnBroadcastVoiceData(IClient *pClient, size_t nBytes, char *data) { // Reject empty packets if(nBytes < 1) @@ -538,7 +610,8 @@ bool CVoice::OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data) // Reject voice packet if we'd send more than NET_MAX_VOICE_BYTES_FRAME voice bytes from this client in the current frame. // 5 = SVC_VoiceData header/overhead - g_aFrameVoiceBytes[client] += 5 + nBytes; + size_t voice_data_header = 5; + g_aFrameVoiceBytes[client] += voice_data_header + nBytes; #if SOURCE_ENGINE != SE_CSGO && SOURCE_ENGINE == SE_INSURGENCY if (g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME) @@ -563,7 +636,7 @@ void CVoice::HandleNetwork() if(m_ListenSocket == -1) return; - int PollRes = poll(m_aPollFds, m_PollFds, 0); + int PollRes = my_poll(m_aPollFds, m_PollFds, 0); if(PollRes <= 0) return; @@ -582,7 +655,7 @@ void CVoice::HandleNetwork() if(Client != MAX_CLIENTS) { sockaddr_in addr; - size_t size = sizeof(sockaddr_in); + socklen_t size = sizeof(sockaddr_in); int Socket = accept(m_ListenSocket, (sockaddr *)&addr, &size); m_aClients[Client].m_Socket = Socket; @@ -621,7 +694,7 @@ void CVoice::HandleNetwork() if(m_aPollFds[PollFds].revents & POLLHUP) { if (pClient->m_Socket != -1) - close(pClient->m_Socket); + close_socket(pClient->m_Socket); pClient->m_Socket = -1; m_aPollFds[PollFds].fd = -1; @@ -636,7 +709,7 @@ void CVoice::HandleNetwork() continue; size_t BytesAvailable; - if(ioctl(pClient->m_Socket, FIONREAD, &BytesAvailable) == -1) + if(my_ioctl(pClient->m_Socket, FIONREAD, &BytesAvailable) == -1) continue; if(pClient->m_New) @@ -648,8 +721,8 @@ void CVoice::HandleNetwork() m_Buffer.SetWriteIndex(pClient->m_BufferWriteIndex); // Don't recv() when we can't fit data into the ringbuffer - unsigned char aBuf[32768]; - if(min(BytesAvailable, sizeof(aBuf)) > m_Buffer.CurrentFree() * sizeof(int16_t)) + char aBuf[32768]; + if(min_ext(BytesAvailable, sizeof(aBuf)) > m_Buffer.CurrentFree() * sizeof(int16_t)) continue; // Edge case: previously received data is uneven and last recv'd byte has to be prepended @@ -666,7 +739,7 @@ void CVoice::HandleNetwork() if(Bytes <= 0) { if (pClient->m_Socket != -1) - close(pClient->m_Socket); + close_socket(pClient->m_Socket); pClient->m_Socket = -1; m_aPollFds[PollFds].fd = -1; @@ -746,10 +819,10 @@ void CVoice::OnDataReceived(CClient *pClient, int16_t *pData, size_t Samples) void CVoice::HandleVoiceData() { - int SamplesPerFrame = m_EncoderSettings.FrameSize; - int PacketSize = m_EncoderSettings.PacketSize; - int FramesAvailable = m_Buffer.TotalLength() / SamplesPerFrame; - float TimeAvailable = (float)m_Buffer.TotalLength() / (float)m_EncoderSettings.SampleRate_Hz; + int SamplesPerFrame = m_EncoderSettings.frameSize; + int packetSize = m_EncoderSettings.packetSize; + size_t FramesAvailable = m_Buffer.TotalLength() / SamplesPerFrame; + float TimeAvailable = (float)m_Buffer.TotalLength() / (float)m_EncoderSettings.sampleRateHz; if(!FramesAvailable) return; @@ -763,7 +836,8 @@ void CVoice::HandleVoiceData() return; // 5 = max frames per packet - FramesAvailable = min(FramesAvailable, 5); + size_t max_frames = 5; + FramesAvailable = min_ext(FramesAvailable, max_frames); // Get SourceTV Index if (!hltv) @@ -786,10 +860,10 @@ void CVoice::HandleVoiceData() return; } - for(int Frame = 0; Frame < FramesAvailable; Frame++) + for(size_t Frame = 0; Frame < FramesAvailable; Frame++) { // Get data into buffer from ringbuffer. - int16_t aBuffer[SamplesPerFrame]; + int16_t *aBuffer = new int16_t[SamplesPerFrame]; size_t OldReadIdx = m_Buffer.m_ReadIndex; size_t OldCurLength = m_Buffer.CurrentLength(); @@ -797,17 +871,17 @@ void CVoice::HandleVoiceData() if(!m_Buffer.Pop(aBuffer, SamplesPerFrame)) { - printf("Buffer pop failed!!! Samples: %u, Length: %u\n", SamplesPerFrame, m_Buffer.TotalLength()); + printf("Buffer pop failed!!! Samples: %u, Length: %zu\n", SamplesPerFrame, m_Buffer.TotalLength()); return; } // Encode it! - unsigned char aFinal[PacketSize]; + unsigned char *aFinal = new unsigned char[packetSize]; int FinalSize = 0; if (m_pCodec) { - FinalSize = celt_encode(m_pCodec, aBuffer, SamplesPerFrame, aFinal, sizeof(aFinal)); + FinalSize = celt_encode(m_pCodec, aBuffer, SamplesPerFrame, aFinal, packetSize); if(FinalSize <= 0) { @@ -839,12 +913,15 @@ void CVoice::HandleVoiceData() } BroadcastVoiceData(pClient, FinalSize, aFinal); + + delete[] aBuffer; + delete[] aFinal; } if(m_AvailableTime < getTime()) m_AvailableTime = getTime(); - m_AvailableTime += (double)FramesAvailable * m_EncoderSettings.FrameTime; + m_AvailableTime += (double)FramesAvailable * m_EncoderSettings.frameTime; } void CVoice::BroadcastVoiceData(IClient *pClient, size_t nBytes, unsigned char *pData) @@ -888,7 +965,7 @@ void CVoice::BroadcastVoiceData(IClient *pClient, size_t nBytes, unsigned char * msg.set_data(testing.c_str(), testing.size()); } - uncompressed_sample_offset += m_EncoderSettings.FrameSize; + uncompressed_sample_offset += m_EncoderSettings.frameSize; msg.set_format(VOICEDATA_FORMAT_ENGINE); msg.set_sequence_bytes(sequence_bytes); @@ -905,12 +982,16 @@ void CVoice::BroadcastVoiceData(IClient *pClient, size_t nBytes, unsigned char * #endif #else #ifdef _WIN32 + #ifndef WIN64 __asm mov ecx, pClient; __asm mov edx, nBytes; + #endif - DETOUR_STATIC_CALL(SV_BroadcastVoiceData_LTCG)((char *)pData, 0); + if (g_SvCallOriginalBroadcast->GetInt()) + DETOUR_STATIC_CALL(SV_BroadcastVoiceData_LTCG)((char *)pData, 0); #else - DETOUR_STATIC_CALL(SV_BroadcastVoiceData)(pClient, nBytes, (char *)pData, 0); + if (g_SvCallOriginalBroadcast->GetInt()) + DETOUR_STATIC_CALL(SV_BroadcastVoiceData)(pClient, nBytes, (char *)pData, 0); #endif #endif -} +} \ No newline at end of file diff --git a/src/extension.h b/src/extension.h new file mode 100644 index 0000000..1dbd990 --- /dev/null +++ b/src/extension.h @@ -0,0 +1,198 @@ +/** +* vim: set ts=4 : +* ============================================================================= +* SourceMod Sample Extension +* 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_PROPER_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ + +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +#include "smsdk_ext.h" +#ifdef EXPORT +#undef EXPORT +#include "celt_header.h" +#endif +#include "ringbuffer.h" + +#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_INSURGENCY +#include "csgo/netmessages.pb.h" +#endif + +/** +* @file extension.h +* @brief Sample extension code header. +*/ + +#define MAX_CLIENTS 16 + +#ifdef _WIN32 +typedef __int64 int64; +#else +typedef long long int64; +#endif + +class CDetour; +class IClient; + +/** +* @brief Sample implementation of the SDK Extension. +* Note: Uncomment one of the pre-defined virtual functions in order to use it. +*/ +class CVoice : + 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 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. + * Note: It is is a good idea to add natives here, if any are provided. + */ + virtual void SDK_OnAllLoaded(); + + /** + * @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 maxlength); +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 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: // IConCommandBaseAccessor + virtual bool RegisterConCommandBase(ConCommandBase *pVar); + +public: + CVoice(); + void OnGameFrame(bool simulating); + bool OnBroadcastVoiceData(IClient *pClient, size_t nBytes, char *data); + + void ListenSocket(); + +private: + int m_ListenSocket; + + struct CClient + { + int m_Socket; + size_t m_BufferWriteIndex; + size_t m_LastLength; + double m_LastValidData; + bool m_New; + bool m_UnEven; + unsigned char m_Remainder; + } m_aClients[MAX_CLIENTS]; + + struct pollfd m_aPollFds[1 + MAX_CLIENTS]; + int m_PollFds; + + CRingBuffer m_Buffer; + + double m_AvailableTime; + + struct CEncoderSettings + { + celt_int32 sampleRateHz; + celt_int32 targetBitRateKBPS; + celt_int32 frameSize; + celt_int32 packetSize; + celt_int32 complexity; + double frameTime; + } m_EncoderSettings; + + CELTMode *m_pMode; + CELTEncoder *m_pCodec; + + CDetour *m_VoiceDetour; + + void HandleNetwork(); + void OnDataReceived(CClient *pClient, int16_t *pData, size_t Samples); + void HandleVoiceData(); + void BroadcastVoiceData(IClient *pClient, size_t nBytes, unsigned char *pData); +}; + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ \ No newline at end of file diff --git a/ringbuffer.cpp b/src/ringbuffer.cpp similarity index 93% rename from ringbuffer.cpp rename to src/ringbuffer.cpp index 2df026c..845003a 100644 --- a/ringbuffer.cpp +++ b/src/ringbuffer.cpp @@ -5,7 +5,12 @@ #undef NDEBUG #include -template inline T min(T a, T b) { return a +typedef SSIZE_T ssize_t; +#endif + +template inline T min_ext(T a, T b) { return a m_BufferSize) { diff --git a/ringbuffer.h b/src/ringbuffer.h similarity index 100% rename from ringbuffer.h rename to src/ringbuffer.h diff --git a/smsdk_config.h b/src/smsdk_config.h similarity index 95% rename from smsdk_config.h rename to src/smsdk_config.h index ef84fb5..12dca7d 100644 --- a/smsdk_config.h +++ b/src/smsdk_config.h @@ -37,10 +37,12 @@ * @brief Contains macros for configuring basic extension information. */ +#include "version.h" + /* Basic information exposed publicly */ #define SMEXT_CONF_NAME "Voice" #define SMEXT_CONF_DESCRIPTION "Inject voice data over existing clients" -#define SMEXT_CONF_VERSION "2.0" +#define SMEXT_CONF_VERSION SM_FULL_VERSION #define SMEXT_CONF_AUTHOR "BotoX, maxime1907" #define SMEXT_CONF_URL "" #define SMEXT_CONF_LOGTAG "VOICE" diff --git a/version.rc b/version.rc deleted file mode 100644 index d45a0c7..0000000 --- a/version.rc +++ /dev/null @@ -1,103 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -//#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -#include - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION SM_VERSION_FILE - PRODUCTVERSION SM_VERSION_FILE - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "Comments", "SourceMod Extension" - VALUE "FileDescription", "SourceMod Extension" - VALUE "FileVersion", SM_VERSION_STRING - VALUE "InternalName", "SourceMod Extension" - VALUE "LegalCopyright", "Copyright (c) 2004-2022, AlliedModders LLC" - VALUE "OriginalFilename", BINARY_NAME - VALUE "ProductName", "SourceMod Extension" - VALUE "ProductVersion", SM_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED