Author SHA1 Message Date
jenz 420a56c8c4 adding extra logging messages as a delay mechanism so nosteamers netaddress have enough time to be ready 2026-08-28 11:07:43 +01:00
jenz 5e262c573a copy pasting the password from the forward back to the connect extension so that the webclient can have it be used 2026-07-24 10:01:37 +01:00
jenz df4b1b0aa7 did not need this any more 2026-07-23 15:00:35 +01:00
jenz dfc25da57a moved webclient name generation over to the connect extension. fixed pending steam ID. name is tracked with cvar value. name also sets the steamID 2026-07-23 14:58:45 +01:00
jenz 4c7ec14d52 finally removed the logging and removed the duplicate case from begin auth session hook. probably fine 2026-06-25 14:32:41 +01:00
jenz 0aab8e0bd6 adding support for switching steamID for the nosteam webclients 2026-06-05 23:54:25 +01:00
jenz 86c714fb1b updated gamedata and updated extension to kick dead left over sessions that would be caused by being blocked by ISP on first connect to to server and then on second connect using a VPN instead. also changes how nosteamers attempting to spoof are handled so that a nosteamer could change IP address on a reconnect and still be allowed in 2026-03-19 15:38:02 +00:00
jenz 3a126db081 re-applying beginauthsession and endauthsession 2026-02-16 14:14:42 +00:00
jenz 0b5306f689 i am still keeping the log messages enabled for now. this extra begin auth session check should still work for nosteamers while being able to re-authenticate steam players with steam 2026-02-15 18:37:52 +00:00
jenz 00c4ee1521 to hell with it, committing the log messages 2026-01-27 23:27:50 +00:00
jenz aa115c645e adding a few infos in readme 2026-01-26 13:42:57 +00:00
jenz 723d6e07b9 actual changes applied 2026-01-26 07:54:21 +00:00
dependabot[bot] 8d83d5ecca Bump actions/cache from 4 to 5 (#59)
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 01:55:49 +00:00
dependabot[bot] 58a4c9df84 Bump actions/upload-artifact from 5 to 6 (#58)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-15 01:55:24 +00:00
dependabot[bot] ddf6e96660 Bump actions/upload-artifact from 4 to 5 (#55) 2025-11-25 10:32:13 +01:00
dependabot[bot] 2711a463a2 Bump actions/checkout from 4 to 6 (#57) 2025-11-25 10:19:08 +01:00
rtldg 736afc5d1f Rework the CI to build inside the valve sniper sdk container thing (#56) 2025-11-22 13:48:24 +01:00
dependabot[bot] 9aa1fb0474 Bump actions/setup-python from 5 to 6 (#54)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-30 23:29:14 +01:00
rtldg 670c7c5b02 fix offset usage for BeginAuthSession from #45 (resolves #49) (#52) 2025-05-23 19:07:06 -04:00
sappho a1fd39932a Update for May 2025 tf2 updates 2025-05-15 23:12:03 -04:00
sappho db47788db9 Update README.md 2025-05-15 22:54:42 -04:00
sappho 1c172cbfc7 Create README.md 2025-05-15 22:51:23 -04:00
rtldg caf6adddca Remove old & duplicate gamedata section missed in #33 (#48) 2025-05-12 12:34:13 +00:00
rtldg 0fbbba2d30 Use Ubuntu 22.04 runners & clang 11 (#47) 2025-05-12 12:32:09 +00:00
BenoistandKenzzer e494127fcb Remove RejectConnection detour + unused signature (#45)
* Remove RejectConnection detour + unused signature

* Readd rejectconnection signature

* Remove offset redefinition

* Remove unused variable

---------

Co-authored-by: Kenzzer <[email protected]>
2025-04-07 13:39:13 -04:00
dependabot[bot] 70eaa69d6b Change actions/upload-artifact from 4.6.1 to 4 (#44) 2025-03-24 10:01:29 +01:00
rtldg 7da1fa5ba6 Support windows64 and unify gamedata after source-sdk-2013 (2025) update (#33) 2025-03-03 14:16:44 -05:00
dependabot[bot] 84f3da6fd9 Bump actions/upload-artifact from 4.3.2 to 4.6.1 (#39)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.2 to 4.6.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.3.2...v4.6.1)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 02:01:36 +01:00
dependabot[bot] bd37cefe89 Bump actions/setup-python from 4 to 5 (#38)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 02:01:20 +01:00
dependabot[bot] 19aca45ce0 Bump actions/checkout from 3 to 4 (#37)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 02:01:01 +01:00
dependabot[bot] 9d02f9bc46 Bump actions/cache from 3 to 4 (#36)
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-02 02:00:34 +01:00
Benoist 703c293653 Fix broken CI 2025-03-02 01:55:38 +01:00
Benoist 06ceb89957 Update ci.yml 2025-03-02 01:48:41 +01:00
Benoist c4e6d2fe38 Enabled dependabot (#28) 2025-03-02 01:40:29 +01:00
Maxime Leroy d2a4e156fc feat: update sdks, builders, ci (#31) 2025-02-22 14:23:43 -05:00
maxime1907 71a12389c2 chore(ci): enable dependabot 2025-02-01 09:34:03 +01:00
sappho 406e0211a7 Knock linux build down to ubuntu 20.04 for glibc bcompat 2024-05-02 18:51:46 -04:00
sappho 6b361db6de Update ci, only run ubuntu-latest / windows-latest, but lock them to … (#26)
* Update ci, only run ubuntu-latest / windows-latest, but lock them to specific versions, and only upload when we're on master
2024-05-02 18:45:04 -04:00
sappho 1a9472480c Update product.version
#24
2024-05-02 17:59:35 -04:00
BenoistandKenzzer 51fe0dbac6 Fix extension rejecting valid auth tickets (#24)
* Fix extension rejecting valid auth tickets

* don't get origin val twice

* Review changes

---------

Co-authored-by: Kenzzer <[email protected]>
2024-05-02 17:58:15 -04:00
Natanel Shitrit b563b80bae Fix: 2024/04/18 update (#21)
* Fix signatures

* Use offset instead off midfunc signature

* Split signature + offset for games
2024-04-23 13:48:58 -04:00
sappho 3c2c79cb07 Merge pull request #23 from asherkin/dbg
fix up actions not giving artifacts
2024-04-20 18:54:19 -04:00
stephanie sappho lenzo 27173dc97c revert 4525781 2024-04-20 18:53:07 -04:00
sappho 4b40d377c1 Update windows artifacts 2024-04-20 18:07:12 -04:00
sappho d3f4a8f156 cleaner artifact names! 2024-04-20 17:25:47 -04:00
sappho a4cfc99114 this is so ugly 2024-04-20 17:23:52 -04:00
sappho a41c4f90cc always pkg release... 2024-04-20 17:20:13 -04:00
sappho 56e2ca1748 last ditch effort to update path before i get out the pwd and tree 2024-04-20 17:18:01 -04:00
sappho 7c3f42a2ec working-directory doesn't work with upload artifact action... 2024-04-20 17:12:56 -04:00
sappho 3f586f0ff9 working-directory 2024-04-20 17:11:17 -04:00
sappho b90ef97c58 Try making ci upload artifacts... 2024-04-20 17:09:35 -04:00
stephanie sappho lenzo 4525781cf5 attempt to add connect_debug macro 2024-04-20 16:58:29 -04:00
sappho 7768517f4a Merge pull request #22 from asherkin/fix-win-compiles
remove machine x86 to fix compile on win32
2024-04-19 18:25:49 -04:00
sappho 46b16e20b2 remove machine x86 to fix compile on win32 2024-04-19 18:22:46 -04:00
sappho 7fc53679f0 Merge pull request #15 from Kenzzer/ambuild2.2
Bring build scripts to AMBuild 2.2
2024-04-19 18:11:27 -04:00
Kenzzer 7cc832efc8 two oopsies 2024-02-09 23:18:45 +01:00
Kenzzer fa6bf9c44c Add x64 support 2024-02-08 23:09:08 +01:00
Benoist 5d90d5269a Setup action build & upload 2023-02-25 02:53:16 +01:00
Kenzzer 2824a307e4 Bring build scripts to AMBuild 2.2 2023-02-18 23:39:16 +01:00
Asher Baker 0c6274058e Fix tf2 gamedata not being used
When this was split out from the legacy obv gamedata in 5678c55 the new
block accidentally used the engine name for tf2 instead of the gamedir
in a gamedir match. Change it to use the same #supported rules as the
others to fix the gamedata loading and avoid future confusion.
2022-06-22 08:41:22 +00:00
Asher Baker 2dffbea59e Revert "Fix tf2 gamedata section name (#13)"
"tf" is the gamedir name, but "tf2" is the correct engine name.

This reverts commit cec180bf4b.
2022-06-22 08:39:30 +00:00
Batfoxkid cec180bf4b Fix tf2 gamedata section name (#13)
tf2 is tf, surprised this wasn't catched before.
2022-06-22 08:38:48 +00:00
Batfoxkid 9bc02f244d Update GameData for TF2 Update 6/21/2022 (#12) 2022-06-22 04:03:23 +00:00
sapphonie 0d9e80e474 Finish updating to newdecls (#9)
* newdecls for ext struct

* Update connect.sp

* spaces2tabs
2021-10-23 21:51:38 +00:00
Nick Hastings b307ee9e5e Revert CheckChallengeType sig for non-TF2 as well. 2021-10-23 17:22:56 -04:00
Nick Hastings 5678c55a25 Revert latest gamedata changes for non-TF2. 2021-10-23 16:18:06 -05:00
sapphonie 8a2e980817 Update syntax to transitional 2021-10-23 16:17:25 -05:00
Natanel Shitrit 9a1f4dd63c Update connect.games.txt (#7) 2021-10-11 19:37:14 +01:00
sapphonie 11a61d99c9 9/17/21 tf2 update 2021-09-21 08:41:47 +01:00
Ruben Gonzalez a612a5a352 Update connect.games.txt 2018-06-26 20:10:40 -04:00
Asher Baker 4c3335f31a Fix Windows build and update gamedata 2017-10-26 14:11:23 +01:00
Asher Baker 3b9e6208ea Fix linux compile with latest SDK
This needs some cleanup still for non-TF2
2017-10-26 13:57:38 +01:00
Asher Baker f557476d6b Fix compat with TF2 after Jungle Inferno update 2017-10-26 13:57:09 +01:00
Asher Baker 444e68b5ee Updated gamedata. 2014-05-16 02:03:39 +01:00
Asher Baker 25ecb99323 Pushbuild. 2013-05-04 17:50:14 +01:00
Asher Baker 14ad23a8c5 Fixed CS:S build. 2013-05-04 16:48:32 +01:00
Asher Baker 5c67e6a460 Updated build scipts. 2013-05-04 16:45:51 +01:00
Asher Baker 0014b4f2ad The linux buildslave needs to know where the CS:S SDK is, as it can't read the environment variables. 2012-11-05 16:11:38 +00:00
Asher Baker 7175b44357 GCC is never appeased the first try. 2012-11-05 16:04:12 +00:00
Asher Baker fe52823b62 Overhaul of many things. 2012-11-05 16:00:51 +00:00
Asher Baker 504d6befd2 Restructured directory structure. 2012-11-05 15:25:18 +00:00
Asher Baker 252b9d3581 Merge 2012-10-29 19:56:06 +00:00
Asher Baker e1237c1b38 Fixed EndAuthSession not being called in certain cases.
If Source ever become threaded this will be hell.
2012-10-29 19:55:17 +00:00
Asher Baker 661bed2c6e NOPE NOPE NOPE. 2012-10-27 00:13:53 +01:00
Asher Baker 716e944584 Added css engine. 2012-09-21 18:13:06 +01:00
Asher Baker c775f1908d Hopefully fixed blocking SourceTV clients. 2012-08-30 22:08:23 +01:00
Asher Baker 6633597413 Backed out changeset: 01646de6879f 2012-08-19 04:51:16 +01:00
Asher Baker 0cde327c1e Update gamedata. (Russianeer) 2012-08-16 13:13:57 +01:00
Asher Baker df28dab8c3 Updated gamedata. 2012-08-03 14:17:19 +01:00
Asher Baker 8f418a2634 Forgot to update buildbot version. 2012-06-29 11:09:11 +01:00
Asher Baker 0857956c40 Changed forward name to OnClientPreConnectEx. 2012-06-29 11:05:49 +01:00
Asher Baker 1bb2e369e0 Fixed another python path... 2012-05-31 12:24:55 +01:00
Asher Baker 9682460a56 Fixed path to version file. 2012-05-31 12:21:43 +01:00
Asher Baker 576529e60c Fixed whitespace (wtf python?) 2012-05-31 12:20:15 +01:00
Asher Baker 93dd6d47aa Hopefully added clang support, going to need to resync scripts against SM soon. 2012-05-31 12:13:04 +01:00
Asher Baker 376bf28f76 Switched to SourceMod 1.4 2012-05-31 12:04:24 +01:00
Asher Baker bb63c358ec Forgot to update the other 2 paths... 2012-05-31 12:01:51 +01:00
Asher Baker dafafea795 Let's try that again... 2012-05-31 12:00:35 +01:00
Asher Baker cc80b61c5f Try not specifying SDK paths... 2012-05-31 11:54:00 +01:00
Asher Baker 4397bc57ca Mac build fix. 2012-05-31 11:49:54 +01:00
Asher Baker 8e31675395 Updated gamedata, take 2. 2012-04-19 00:59:46 +01:00
Asher Baker d42fd3d3c2 Mac sux 2012-04-18 23:08:50 +01:00
Asher Baker 6ae9d8c6ec Build fix, please? 2012-04-18 23:03:07 +01:00
Asher Baker c6bd83858c Updated gamedata. 2012-04-18 22:57:15 +01:00
Asher Baker 06070d811e Updated gamedata. 2011-10-14 18:53:01 +01:00
Asher Baker 8d719caa2e Backed out changeset: 8919d426ee7a 2011-09-17 20:24:46 +01:00
Asher Baker fbaa45eca4 Dont ask. 2011-09-17 20:23:40 +01:00
Asher Baker beefabbf4f Updated gamedata. 2011-08-16 02:51:52 +01:00
Asher Baker 2d39ab840d Added mac gamedata. 2011-07-19 18:53:28 +01:00
Asher Baker 491c995393 Added mac support to CDetour. 2011-07-19 18:48:39 +01:00
Asher Baker 4e27d991b5 Fixed package name. 2011-07-19 17:33:46 +01:00
Asher Baker 08fedf43ee Removed -werror. 2011-07-19 17:29:06 +01:00
Asher Baker a67ef4d482 Initial commit. 2011-07-19 17:07:38 +01:00
32 changed files with 2324 additions and 2327 deletions
+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
+24
View File
@@ -0,0 +1,24 @@
#!/bin/bash
set -euxo pipefail
cd "$(dirname $0)/../.."
if [[ $PLATFORM == Linux* ]]; then
$CC --version
$CXX --version
apt install -y python3-pip
# buildbot/generate_header.py is ran by ambuild and we want git to not fail due to user-perms (because docker)
git config --global --add safe.directory $PWD
else
python -m pip install --upgrade pip setuptools wheel
fi
python -m pip install $CACHE_PATH/ambuild
mkdir build
cd build
python ../configure.py --enable-auto-versioning --enable-optimize --sdks="$SDKS" --mms-path="$CACHE_PATH/metamod-source" --hl2sdk-root="$CACHE_PATH" --sm-path="$CACHE_PATH/sourcemod"
ambuild
+173
View File
@@ -0,0 +1,173 @@
name: Extension builder
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
strategy:
matrix:
python-version: ['3.14']
os: [ubuntu-latest, windows-2022]
include:
- os: ubuntu-latest
cc: clang-11
cxx: clang++-11
- os: windows-2022
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.12'
SOURCEMOD_VERSION: '1.12'
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
- uses: actions/setup-python@v6
if: startsWith(matrix.os, 'windows-')
name: Setup Python ${{ matrix.python-version }}
with:
python-version: ${{ matrix.python-version }}
- uses: actions/checkout@v6
name: Repository checkout
with:
fetch-depth: 0
path: extension
- uses: actions/cache@v5
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 submodule deinit --all --force
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: Build
shell: bash
working-directory: extension
run: |
export PLATFORM="${{ runner.os }}"
if [[ $PLATFORM == Linux* ]]; then
# docker instead of podman because:
# - we don't need a job to `sudo apt install podman`
# - `sudo apt install -y python3-pip` didn't work inside podman for me?
docker run \
-e PLATFORM="$PLATFORM" \
-e PROJECT=${{ env.PROJECT }} \
-e SDKS="${{ env.SDKS }}" \
-e MMSOURCE_VERSION=${{ env.MMSOURCE_VERSION }} \
-e SOURCEMOD_VERSION=${{ env.MMSOURCE_SOURCEMOD_VERSION }} \
-e CACHE_PATH=${{ env.CACHE_PATH }} \
-e SDKS_KEY=${{ env.SDKS_KEY }} \
-e CC=${{ matrix.cc }} \
-e CXX=${{ matrix.cxx }} \
--mount type=bind,source=${{ env.CACHE_PATH }},target=${{ env.CACHE_PATH }} \
--mount type=bind,source=$PWD,target=$PWD \
"registry.gitlab.steamos.cloud/steamrt/sniper/sdk:latest" \
"$PWD/.github/workflows/build.sh"
# need to fix the owner because docker root-ed stuff?
sudo chown -R $USER .
else
bash ./.github/workflows/build.sh
fi
FILENAME="$(cat build/includes/filename_versioning.txt)"
ZIP_FILENAME="${{ env.PROJECT }}-${FILENAME}-${PLATFORM,}.zip"
echo "ZIP_FILENAME=${ZIP_FILENAME}" >> $GITHUB_ENV
# if: github.event_name == 'push' && github.ref == 'refs/heads/action' &&
- name: Package release - Windows
if: startsWith(matrix.os, 'windows-')
working-directory: extension/build/package
run: |
Compress-Archive -Path * -Destination ${{ env.ZIP_FILENAME }}
Copy-Item -Path ${{ env.ZIP_FILENAME }} -Destination ${{ matrix.os }}_${{ matrix.cc }}_${{ env.ZIP_FILENAME }}
- name: Package release - Linux
if: startsWith(matrix.os, 'ubuntu-')
working-directory: extension/build/package
run: |
zip -r "${{ env.ZIP_FILENAME }}" .
cp "${{ env.ZIP_FILENAME }}" "${{ matrix.os }}_${{ matrix.cc }}_${{ env.ZIP_FILENAME }}"
- name: Upload release
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
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 }}&filename=${{ env.ZIP_FILENAME }}")
if test ${HTTP_CODE} -ne 200; then
exit ${HTTP_CODE}
fi
echo "Upload successful!"
- name: Upload a Build Artifact
uses: actions/upload-artifact@v6
with:
# Artifact name
name: ${{ matrix.os }}_${{ matrix.cc }}_${{ env.ZIP_FILENAME }}
# optional, default is artifact
# A file, directory or wildcard pattern that describes what to upload
path: ${{ github.workspace }}/extension/build/package/${{ matrix.os }}_${{ matrix.cc }}_${{ env.ZIP_FILENAME }}
# The desired behavior if no files are found using the provided path.
if-no-files-found: error
# Duration after which artifact will expire in days. 0 means using default retention.
retention-days: 14
+6 -2
View File
@@ -1,2 +1,6 @@
*build/ build
*vs Containerfile
.venv
safetyhook
.env
secret.h
-3
View File
@@ -1,3 +0,0 @@
[submodule "hl2sdk-manifests"]
path = hl2sdk-manifests
url = https://github.com/alliedmodders/hl2sdk-manifests
+376 -137
View File
@@ -1,5 +1,75 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python: # vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os import os, sys, shutil
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
WinLinux = ['windows', 'linux']
CSS = {
'windows': ['x86', 'x86_64'],
'linux': ['x86', 'x86_64']
}
HL2DM = {
'windows': ['x86', 'x86_64'],
'linux': ['x86', 'x86_64']
}
DODS = {
'windows': ['x86', 'x86_64'],
'linux': ['x86', 'x86_64']
}
TF2 = {
'windows': ['x86', 'x86_64'],
'linux': ['x86', 'x86_64']
}
CSGO = {
'windows': ['x86'],
'linux': ['x86', 'x86_64']
}
PossibleSDKs = {
# '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', CSS, 'css'),
'hl2dm': SDK('HL2SDKHL2DM', '2.hl2dm', '7', 'HL2DM', HL2DM, 'hl2dm'),
'dods': SDK('HL2SDKDODS', '2.dods', '8', 'DODS', DODS, 'dods'),
'sdk2013': SDK('HL2SDK2013', '2.sdk2013', '9', 'SDK2013', WinLinux, 'sdk2013'),
# 'bms': SDK('HL2SDKBMS', '2.bms', '11', 'BMS', WinLinux, 'bms'),
'tf2': SDK('HL2SDKTF2', '2.tf2', '12', 'TF2', TF2, 'tf2'),
'l4d': SDK('HL2SDKL4D', '2.l4d', '13', 'LEFT4DEAD', WinLinux, 'l4d'),
# 'nucleardawn': SDK('HL2SDKND', '2.nd', '14', 'NUCLEARDAWN', WinLinuxMac, 'nucleardawn'),
# 'contagion': SDK('HL2SDKCONTAGION', '2.contagion', '15', 'CONTAGION', WinOnly, 'contagion'),
'l4d2': SDK('HL2SDKL4D2', '2.l4d2', '16', 'LEFT4DEAD2', WinLinux, 'l4d2'),
# 'swarm': SDK('HL2SDK-SWARM', '2.swarm', '17', 'ALIENSWARM', WinOnly, 'swarm'),
# 'portal2': SDK('HL2SDKPORTAL2', '2.portal2', '18', 'PORTAL2', [], 'portal2'),
# 'insurgency': SDK('HL2SDKINSURGENCY', '2.insurgency', '19', 'INSURGENCY', WinLinuxMac, 'insurgency'),
# 'blade': SDK('HL2SDKBLADE', '2.blade', '21', 'BLADE', WinLinux, 'blade'),
'csgo': SDK('HL2SDKCSGO', '2.csgo', '23', 'CSGO', CSGO, 'csgo'),
}
def ResolveEnvPath(env, folder): def ResolveEnvPath(env, folder):
if env in os.environ: if env in os.environ:
@@ -30,31 +100,10 @@ def SetArchFlags(compiler):
if compiler.target.arch == 'x86_64': if compiler.target.arch == 'x86_64':
compiler.defines += ['WIN64'] compiler.defines += ['WIN64']
hl2sdk_manifests_path = None
# First we check if the manifest exists in the current path
hl2sdk_manifests_path = os.path.join(builder.sourcePath, 'hl2sdk-manifests/SdkHelpers.ambuild')
if not os.path.exists(hl2sdk_manifests_path):
# manifests does not exists in the project file, use the path from --hl2sdk-manifest-path
if not builder.options.hl2sdk_manifest:
raise Exception('HL2SDK Manifest root path not set! (--hl2sdk-manifest-path)')
else:
hl2sdk_manifests_path = os.path.join(builder.options.hl2sdk_manifest, 'SdkHelpers.ambuild')
if not os.path.exists(hl2sdk_manifests_path):
raise Exception('Could not find SdkHelpers.ambuild in the given HL2SDK Manifest path!')
SdkHelpers = builder.Eval(hl2sdk_manifests_path, {
'Project': 'sm-extension'
})
class ExtensionConfig(object): class ExtensionConfig(object):
def __init__(self): def __init__(self):
self.sdk_manifests = []
self.sdks = {} self.sdks = {}
self.sdk_targets = [] self.binaries = []
self.extensions = [] self.extensions = []
self.generated_headers = None self.generated_headers = None
self.mms_root = None self.mms_root = None
@@ -84,36 +133,81 @@ class ExtensionConfig(object):
raise Exception('No suitable C/C++ compiler was found.') raise Exception('No suitable C/C++ compiler was found.')
def use_auto_versioning(self): def use_auto_versioning(self):
if builder.backend != 'amb2':
return False
return not getattr(builder.options, 'disable_auto_versioning', False) 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 @property
def tag(self): def tag(self):
if builder.options.debug == '1': if builder.options.debug == '1':
return 'Debug' return 'Debug'
return 'Release' return 'Release'
def findSdkPath(self, sdk_name): def detectProductVersion(self):
dir_name = 'hl2sdk-{}'.format(sdk_name) builder.AddConfigureFile('product.version')
if builder.options.hl2sdk_root:
sdk_path = os.path.join(builder.options.hl2sdk_root, dir_name)
if os.path.exists(sdk_path):
return sdk_path
return ResolveEnvPath('HL2SDK{}'.format(sdk_name.upper()), dir_name)
def shouldIncludeSdk(self, sdk): # For OS X dylib versioning
return not sdk.get('source2', False) 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): def detectSDKs(self):
sdk_list = [s for s in builder.options.sdks.split(',') if s] sdk_list = builder.options.sdks.split(' ')
SdkHelpers.sdk_filter = self.shouldIncludeSdk use_none = sdk_list[0] == 'none'
SdkHelpers.find_sdk_path = self.findSdkPath use_all = sdk_list[0] == 'all'
SdkHelpers.findSdks(builder, self.all_targets, sdk_list) use_present = sdk_list[0] == 'present'
self.sdks = SdkHelpers.sdks for sdk_name in PossibleSDKs:
self.sdk_manifests = SdkHelpers.sdk_manifests sdk = PossibleSDKs[sdk_name]
self.sdk_targets = SdkHelpers.sdk_targets 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 = os.path.realpath(builder.options.sm_path)
else:
self.sm_root = ResolveEnvPath('SOURCEMOD112', 'sourcemod-1.12')
if not self.sm_root:
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: if builder.options.mms_path:
self.mms_root = builder.options.mms_path self.mms_root = builder.options.mms_path
@@ -121,8 +215,6 @@ class ExtensionConfig(object):
self.mms_root = ResolveEnvPath('MMSOURCE112', 'mmsource-1.12') self.mms_root = ResolveEnvPath('MMSOURCE112', 'mmsource-1.12')
if not self.mms_root: if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source') self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'metamod-source')
if not self.mms_root: if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central') self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
@@ -130,26 +222,8 @@ class ExtensionConfig(object):
raise Exception('Could not find a source copy of Metamod:Source') raise Exception('Could not find a source copy of Metamod:Source')
self.mms_root = Normalize(self.mms_root) self.mms_root = Normalize(self.mms_root)
if builder.options.sm_path:
self.sm_root = builder.options.sm_path
else:
self.sm_root = ResolveEnvPath('SOURCEMOD112', 'sourcemod-1.12')
if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod')
if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD_DEV', '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)
def configure(self): def configure(self):
if not set(self.target_archs).issubset(['x86', 'x86_64']):
allowed_archs = ['x86','x86_64']
if not set(self.target_archs).issubset(allowed_archs):
raise Exception('Unknown target architecture: {0}'.format(self.target_archs)) raise Exception('Unknown target architecture: {0}'.format(self.target_archs))
for cxx in self.all_targets: for cxx in self.all_targets:
@@ -160,8 +234,8 @@ class ExtensionConfig(object):
if cxx.version < 1914 and builder.options.generator != 'vs': if cxx.version < 1914 and builder.options.generator != 'vs':
raise Exception(f'Only MSVC 2017 15.7 and later are supported, full C++17 support is required. ({str(cxx.version)} < 1914)') raise Exception(f'Only MSVC 2017 15.7 and later are supported, full C++17 support is required. ({str(cxx.version)} < 1914)')
elif cxx.family == 'gcc': elif cxx.family == 'gcc':
if cxx.version < 'gcc-8': if cxx.version < 'gcc-9':
raise Exception('Only GCC versions 8 or later are supported, full C++17 support is required.') raise Exception('Only GCC versions 9 or later are supported, full C++17 support is required.')
elif cxx.family == 'clang': elif cxx.family == 'clang':
if cxx.version < 'clang-5': if cxx.version < 'clang-5':
raise Exception('Only clang versions 5 or later are supported, full C++17 support is required.') raise Exception('Only clang versions 5 or later are supported, full C++17 support is required.')
@@ -171,7 +245,7 @@ class ExtensionConfig(object):
elif cxx.family == 'msvc': elif cxx.family == 'msvc':
self.configure_msvc(cxx) self.configure_msvc(cxx)
# Optimization # Optimizaiton
if builder.options.opt == '1': if builder.options.opt == '1':
cxx.defines += ['NDEBUG'] cxx.defines += ['NDEBUG']
@@ -187,6 +261,16 @@ class ExtensionConfig(object):
elif cxx.target.platform == 'windows': elif cxx.target.platform == 'windows':
self.configure_windows(cxx) 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): def configure_gcc(self, cxx):
cxx.defines += [ cxx.defines += [
'stricmp=strcasecmp', 'stricmp=strcasecmp',
@@ -204,28 +288,46 @@ class ExtensionConfig(object):
'-Wno-unused', '-Wno-unused',
'-Wno-switch', '-Wno-switch',
'-Wno-array-bounds', '-Wno-array-bounds',
'-msse',
'-Wno-unknown-pragmas',
'-Wno-dangling-else',
'-fvisibility=hidden', '-fvisibility=hidden',
] ]
if cxx.target.arch in ['x86', 'x86_64']:
cxx.cflags += ['-msse']
cxx.cxxflags += [ cxx.cxxflags += [
'-std=c++17',
'-fno-threadsafe-statics', '-fno-threadsafe-statics',
'-Wno-non-virtual-dtor', '-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual', '-Wno-overloaded-virtual',
'-Wno-register', '-Wno-register',
'-fvisibility-inlines-hidden', '-fvisibility-inlines-hidden',
'-std=c++17',
] ]
have_gcc = cxx.family == 'gcc' have_gcc = cxx.family == 'gcc'
have_clang = cxx.family == 'clang' have_clang = cxx.family == 'clang'
if cxx.version >= 'clang-3.9' or cxx.version == 'clang-3.4' or cxx.version > 'apple-clang-6.0':
# Work around errors from smsdk_ext.cpp 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: if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch'] cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
cxx.cxxflags += ['-Wno-deprecated-register']
else:
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']
# Work around SDK warnings. # Work around SDK warnings.
if cxx.version >= 'clang-10.0' or cxx.version >= 'apple-clang-12.0': if cxx.version >= 'clang-10.0' or cxx.version >= 'apple-clang-12.0':
@@ -241,11 +343,7 @@ class ExtensionConfig(object):
if builder.options.opt == '1': if builder.options.opt == '1':
cxx.cflags += ['-O3'] cxx.cflags += ['-O3']
# Don't omit the frame pointer.
cxx.cflags += ['-fno-omit-frame-pointer']
def configure_msvc(self, cxx): def configure_msvc(self, cxx):
if builder.options.debug == '1': if builder.options.debug == '1':
cxx.cflags += ['/MTd'] cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt'] cxx.linkflags += ['/NODEFAULTLIB:libcmt']
@@ -299,13 +397,12 @@ class ExtensionConfig(object):
cxx.linkflags += ['-static-libgcc'] cxx.linkflags += ['-static-libgcc']
elif cxx.family == 'clang': elif cxx.family == 'clang':
cxx.linkflags += ['-lgcc_eh'] cxx.linkflags += ['-lgcc_eh']
cxx.linkflags += ['-static-libstdc++']
def configure_mac(self, cxx): def configure_mac(self, cxx):
cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL'] cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
cxx.cflags += ['-mmacosx-version-min=10.15'] cxx.cflags += ['-mmacosx-version-min=10.7']
cxx.linkflags += [ cxx.linkflags += [
'-mmacosx-version-min=10.15', '-mmacosx-version-min=10.7',
'-stdlib=libc++', '-stdlib=libc++',
'-lc++', '-lc++',
] ]
@@ -314,19 +411,6 @@ class ExtensionConfig(object):
def configure_windows(self, cxx): def configure_windows(self, cxx):
cxx.defines += ['WIN32', '_WINDOWS'] cxx.defines += ['WIN32', '_WINDOWS']
def LibraryBuilder(self, compiler, name):
binary = compiler.Library(name)
self.AddVersioning(binary)
if binary.compiler.like('msvc'):
binary.compiler.linkflags += ['/SUBSYSTEM:WINDOWS']
self.AddCxxCompat(binary)
return binary
def Library(self, context, compiler, name):
compiler = compiler.clone()
SetArchFlags(compiler)
return self.LibraryBuilder(compiler, name)
def ConfigureForExtension(self, context, compiler): def ConfigureForExtension(self, context, compiler):
compiler.cxxincludes += [ compiler.cxxincludes += [
os.path.join(context.currentSourcePath), os.path.join(context.currentSourcePath),
@@ -339,37 +423,6 @@ class ExtensionConfig(object):
] ]
return compiler return compiler
def AddCDetour(self, binary):
public_path = os.path.join(self.sm_root, 'public')
binary.sources += [
os.path.join(public_path, 'CDetour', 'detours.cpp'),
os.path.join(public_path, 'safetyhook', 'src', 'allocator.cpp'),
os.path.join(public_path, 'safetyhook', 'src', 'easy.cpp'),
os.path.join(public_path, 'safetyhook', 'src', 'inline_hook.cpp'),
os.path.join(public_path, 'safetyhook', 'src', 'mid_hook.cpp'),
os.path.join(public_path, 'safetyhook', 'src', 'os.linux.cpp'),
os.path.join(public_path, 'safetyhook', 'src', 'utility.cpp'),
os.path.join(public_path, 'safetyhook', 'src', 'vmt_hook.cpp'),
os.path.join(public_path, 'safetyhook', 'zydis', 'Zydis.c')
]
binary.compiler.includes += [
os.path.join(public_path, 'safetyhook', 'include'),
os.path.join(public_path, 'safetyhook', 'zydis'),
]
def ExtLibrary(self, context, compiler, name):
binary = self.Library(context, compiler, name)
SetArchFlags(compiler)
self.ConfigureForExtension(context, binary.compiler)
return binary
def AddCxxCompat(self, binary):
if binary.compiler.target.platform == 'linux':
binary.sources += [
os.path.join(self.sm_root, 'public', 'amtl', 'compat', 'stdcxx.cpp'),
]
def ConfigureForHL2(self, context, binary, sdk): def ConfigureForHL2(self, context, binary, sdk):
compiler = binary.compiler compiler = binary.compiler
SetArchFlags(compiler) SetArchFlags(compiler)
@@ -379,44 +432,230 @@ class ExtensionConfig(object):
os.path.join(self.mms_root, 'core', 'sourcehook'), os.path.join(self.mms_root, 'core', 'sourcehook'),
] ]
for other_sdk in self.sdk_manifests: defines = ['RAD_TELEMETRY_DISABLED']
compiler.defines += ['SE_{}={}'.format(other_sdk['define'], other_sdk['code'])] defines += ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
compiler.defines += defines
SdkHelpers.configureCxx(context, binary, sdk) 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', 'css', 'tf2', 'dods', 'hl2dm'] 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.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':
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux64')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux64')
else:
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux')
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':
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2']:
lib_path = os.path.join(sdk.path, 'lib', 'public', 'x86', lib) + '.lib'
else:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
elif compiler.target.arch == 'x86_64':
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2']:
lib_path = os.path.join(sdk.path, 'lib', 'public', 'x64', lib) + '.lib'
else:
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 return binary
def HL2Library(self, context, compiler, name, sdk): def AddCDetour(self, binary):
binary = self.Library(context, compiler, name) sm_public_path = os.path.join(self.sm_root, 'public')
self.ConfigureForExtension(context, binary.compiler)
return self.ConfigureForHL2(context, binary, sdk) if os.path.exists(os.path.join(sm_public_path, 'safetyhook')):
binary.sources += [ os.path.join(sm_public_path, 'CDetour', 'detours.cpp') ]
binary.compiler.cxxincludes += [ os.path.join(builder.sourcePath, 'safetyhook', 'include') ]
for task in self.libsafetyhook:
if task.target.arch == binary.compiler.target.arch:
binary.compiler.linkflags += [task.binary]
return
raise Exception('No suitable build of safetyhook was found.')
else:
binary.sources += [
os.path.join(sm_public_path, 'CDetour', 'detours.cpp'),
os.path.join(sm_public_path, 'asm', 'asm.c'),
]
# sm1.10+
libudis_folder = os.path.join(sm_public_path, 'libudis86')
if os.path.isdir(libudis_folder):
binary.compiler.defines += ['HAVE_STRING_H']
binary.sources += [
os.path.join(libudis_folder, 'decode.c'),
os.path.join(libudis_folder, 'itab.c'),
os.path.join(libudis_folder, 'syn-att.c'),
os.path.join(libudis_folder, 'syn-intel.c'),
os.path.join(libudis_folder, 'syn.c'),
os.path.join(libudis_folder, 'udis86.c'),
]
def HL2Config(self, project, context, compiler, name, sdk): def HL2Config(self, project, context, compiler, name, sdk):
binary = project.Configure(compiler, name, binary = project.Configure(compiler, name,
'{0} - {1} {2}'.format(self.tag, sdk['name'], compiler.target.arch)) '{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch))
self.AddCxxCompat(binary) self.AddVersioning(binary)
return self.ConfigureForHL2(context, binary, sdk) return self.ConfigureForHL2(context, binary, sdk)
def HL2ExtConfig(self, project, context, compiler, name, sdk): def HL2ExtConfig(self, project, context, compiler, name, sdk):
binary = project.Configure(compiler, name, binary = project.Configure(compiler, name,
'{0} - {1} {2}'.format(self.tag, sdk['name'], compiler.target.arch)) '{0} - {1} {2}'.format(self.tag, sdk.name, compiler.target.arch))
self.AddCxxCompat(binary) self.AddVersioning(binary)
self.ConfigureForHL2(context, binary, sdk) self.ConfigureForHL2(context, binary, sdk)
self.ConfigureForExtension(context, binary.compiler) self.ConfigureForExtension(context, binary.compiler)
return binary return binary
class SafetyHookShim(object):
def __init__(self):
self.all_targets = {}
self.libsafetyhook = {}
if getattr(builder, 'target', None) is not None:
sys.stderr.write("Your output folder was configured for AMBuild 2.1.\n")
sys.stderr.write("Please remove your output folder and reconfigure to continue.\n")
os._exit(1)
Extension = ExtensionConfig() Extension = ExtensionConfig()
Extension.detectProductVersion()
Extension.detectSDKs() Extension.detectSDKs()
Extension.configure() Extension.configure()
if Extension.use_auto_versioning():
Extension.generated_headers = builder.Build('buildbot/Versioning')
if os.path.exists(os.path.join(Extension.sm_root, 'public', 'safetyhook')):
# we need to pull safetyhook in locally because ambuild does not take kindly to outside relpaths
safetyhook_dest = Normalize(builder.sourcePath + '/safetyhook/')
shutil.copytree(os.path.join(Extension.sm_root, 'public', 'safetyhook'), safetyhook_dest, dirs_exist_ok=True)
SafetyHook = SafetyHookShim()
SafetyHook.all_targets = Extension.all_targets
builder.Build('safetyhook/AMBuilder', {'SafetyHook': SafetyHook })
Extension.libsafetyhook = SafetyHook.libsafetyhook
# This will clone the list and each cxx object as we recurse, preventing child # This will clone the list and each cxx object as we recurse, preventing child
# scripts from messing up global state. # scripts from messing up global state.
builder.targets = builder.CloneableList(Extension.all_targets) builder.targets = builder.CloneableList(Extension.all_targets)
# Add additional buildscripts here
BuildScripts = [ BuildScripts = [
'AMBuilder', 'extension/AMBuilder',
'PackageScript', 'buildbot/PackageScript',
'buildbot/BreakpadSymbols'
] ]
builder.Build(BuildScripts, { 'Extension': Extension }) builder.Build(BuildScripts, { 'Extension': Extension })
-36
View File
@@ -1,36 +0,0 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
if not "SM" in globals():
SM = Extension
projectName = 'connect'
project = builder.LibraryProject(projectName)
project.sources += [
'extension.cpp',
os.path.join(SM.sm_root, 'public', 'smsdk_ext.cpp')
]
for sdk_name in SM.sdks:
sdk = SM.sdks[sdk_name]
if sdk['name'] in ['mock']:
continue
for cxx in builder.targets:
cxx.defines += ['HAVE_STRING_H'];
if not cxx.target.arch in sdk['platforms'][cxx.target.platform]:
continue
binary = Extension.HL2ExtConfig(project, builder, cxx, projectName + '.ext.' + sdk['extension'], sdk)
SM.AddCDetour(binary)
binary.compiler.cxxflags += [
'-Wno-dangling-else',
'-Wno-unknown-pragmas',
'-Wno-unused-result',
'-Wno-sign-compare',
]
SM.extensions += builder.Add(project)
-233
View File
@@ -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)
-50
View File
@@ -1,50 +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 Extension.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)
# 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)
builder.AddCopy(source_path, dest_entry)
# Include files
CopyFiles('include', 'addons/sourcemod/scripting/include',
[ 'connect.inc', ]
)
# Gamedata (custom so updater doesn't replace it)
CopyFiles('gamedata', 'addons/sourcemod/gamedata',
[ 'connect2.games.txt' ]
)
# Copy binaries.
for cxx_task in Extension.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'])
+42 -9
View File
@@ -1,11 +1,44 @@
AMBuildScript needs '-std=c++14', instead of '-std=c++11', # Connect - A safer OnClientPreConnect forward
def configure_linux(self, cxx): This extension provides a OnClientPreConnect forward (similar to CBaseServer's), but does proper checking to prevent malicious people spoofing SteamIDs.
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 += ['--static-libgcc']
remember to use that instead of cxx.linkflags += ['-static-libgcc'] and cxx.linkflags += ['-lgcc_eh'] If you are currently using CBaseServer for reserved slots, it's possible for a client to spoof an admin's SteamID and cause someone to be kicked from the server (although they would be later denied, so they couldn't actually join the game).
This extension does these checks before OnClientPreConnect is fired, so this isn't possible.
There are some additional features such as being able to change the password provided before it's checked (see included example plugin) and the ability to reject the client with a reason (like SourceMod's later OnClientConnect forward).
Only the Source 2009 engine is supported, as it's the only one that's been updated to use the new authentication system.
# Provided forwards
```
public bool OnClientPreConnectEx
(
const char[] name,
char password[255],
const char[] ip,
const char[] steamID,
char rejectReason[255]
)
{
// ...
}
```
`return false;` to disallow the client from joining, and change `rejectReason` to what you want them to be shown when denied.
Note that this function is called before the client has a client index on the server.
# [Builds](https://builds.limetech.io/?project=connect)
# helpful commands for building on the unloze machine
## the environment
export PATH=":/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin:/usr/X11/bin:/home/gameservers/.local/bin":/sbin:/bin:
export SOURCEMOD=/home/gameservers/automate/sourcemod_1.13.0.7207
export MMSOURCE=/home/gameservers/automate/mmsource-1.13
## building
rm -r -f build; mkdir build; cd build; python ../configure.py --sdks css --targets=x86 --enable-optimize; ambuild; cd ..
+7
View File
@@ -0,0 +1,7 @@
mkdir build
cd build
call "%VS100COMNTOOLS%\vsvars32.bat"
..\configure.py
build.py
pause
cd ..
+39
View File
@@ -0,0 +1,39 @@
# vim: set ts=2 sw=2 tw=99 noet ft=python:
import os, sys
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']
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]
)
+47
View File
@@ -0,0 +1,47 @@
# vim: set ts=2 sw=2 tw=99 noet ft=python:
import os
import shutil
import ambuild.osutil as osutil
from ambuild.command import Command
builder.SetBuildFolder('package')
def CreateFolders(folders):
dict = {}
for folder in folders:
path = os.path.normpath(folder)
dict[folder] = builder.AddFolder(path)
return dict
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 = CreateFolders(['addons/sourcemod/extensions', 'addons/sourcemod/extensions/x64', 'addons/sourcemod/gamedata', 'addons/sourcemod/scripting', 'addons/sourcemod/scripting/include'])
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('connect2.games.txt', folders['addons/sourcemod/gamedata'])
CopyFiles('connect.inc', folders['addons/sourcemod/scripting/include'])
CopyFiles('connect.sp', folders['addons/sourcemod/scripting'])
debug_info = []
+50
View File
@@ -0,0 +1,50 @@
# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python:
import os, sys
import re
builder.SetBuildFolder('/')
includes = builder.AddFolder('includes')
argv = [
sys.executable,
os.path.join(builder.sourcePath, 'buildbot', 'generate_header.py'),
os.path.join(builder.sourcePath),
os.path.join(builder.buildPath, 'includes'),
]
outputs = [
os.path.join(builder.buildFolder, 'includes', 'version_auto.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')
sources = [
os.path.join(builder.sourcePath, 'product.version'),
repo_head_path,
argv[1]
]
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
+61
View File
@@ -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 <source_path> <output_folder>\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()
+1
View File
@@ -0,0 +1 @@
Lemons.
Executable → Regular
+8 -9
View File
@@ -5,23 +5,22 @@ from ambuild2 import run
# Simple extensions do not need to modify this file. # Simple extensions do not need to modify this file.
parser = run.BuildParser(sourcePath = sys.path[0], api='2.2') parser = run.BuildParser(sourcePath = sys.path[0], api='2.2')
parser.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None, parser.options.add_argument('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
help='Root search folder for HL2SDKs') help='Root search folder for HL2SDKs')
parser.options.add_argument('--hl2sdk-manifest-path', type=str, dest='hl2sdk_manifest', default=None,
help='Path to HL2SDK Manifests')
parser.options.add_argument('--sm-path', type=str, dest='sm_path', default=None,
help='Path to SourceMod')
parser.options.add_argument('--mms-path', type=str, dest='mms_path', default=None, parser.options.add_argument('--mms-path', type=str, dest='mms_path', default=None,
help='Path to Metamod:Source') 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', parser.options.add_argument('--enable-debug', action='store_const', const='1', dest='debug',
help='Enable debugging symbols') help='Enable debugging symbols')
parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt', parser.options.add_argument('--enable-optimize', action='store_const', const='1', dest='opt',
help='Enable optimization') help='Enable optimization')
parser.options.add_argument('-s', '--sdks', default='present', dest='sdks', parser.options.add_argument('--enable-auto-versioning', action='store_false', dest='disable_auto_versioning',
help='Build against specified SDKs; valid args are "none", "all", "present",' default=True, help='Enables the auto versioning script')
' or comma-delimited list of engine names') 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)s)')
parser.options.add_argument('--targets', type=str, dest='targets', default=None, parser.options.add_argument('--targets', type=str, dest='targets', default=None,
help="Override the target architecture (use commas to separate multiple targets).") help="Override the target architecture (use commas to separate multiple targets).")
parser.Configure() parser.Configure()
+5 -14
View File
@@ -1,7 +1,8 @@
#if defined _Connect_Included #if defined _connect_included
#endinput #endinput
#endif #endif
#define _Connect_Included
#define _connect_included
enum EConnect enum EConnect
{ {
@@ -10,15 +11,12 @@ enum EConnect
k_OnClientPreConnectEx_Async = -1 k_OnClientPreConnectEx_Async = -1
}; };
forward EConnect OnClientPreConnectEx(const char[] sName, char sPassword[255], const char[] sIP, const char[] sSteam32ID, char sRejectReason[255]);
forward bool OnClientPreConnectEx(const char[] name, char password[255], const char[] ip, const char[] steamID, char rejectReason[255]);
native bool ClientPreConnectEx(const char[] sSteam32ID, EConnect RetVal, char sRejectReason[255]); native bool ClientPreConnectEx(const char[] sSteam32ID, EConnect RetVal, char sRejectReason[255]);
native bool SteamClientAuthenticated(const char[] sSteam32ID); native bool SteamClientAuthenticated(const char[] sSteam32ID);
/** public Extension __ext_Connect =
* Do not edit below this line!
*/
public Extension __ext_connect =
{ {
name = "Connect", name = "Connect",
file = "connect.ext", file = "connect.ext",
@@ -32,11 +30,4 @@ public Extension __ext_connect =
#else #else
required = 0, required = 0,
#endif #endif
};
#if !defined REQUIRE_EXTENSIONS
public __ext_connect_SetNTVOptional()
{
MarkNativeAsOptional("ClientPreConnectEx");
} }
#endif
+25
View File
@@ -0,0 +1,25 @@
#pragma semicolon 1 // Force strict semicolon mode.
#pragma newdecls required // Force new syntax
#include <sourcemod>
#define REQUIRE_EXTENSIONS
#include <connect>
public bool OnClientPreConnectEx(const char[] name, char password[255], const char[] ip, const char[] steamID, char rejectReason[255])
{
PrintToServer("----------------\nName: %s\nPassword: %s\nIP: %s\nSteamID: %s\n----------------", name, password, ip, steamID);
AdminId admin = FindAdminByIdentity(AUTHMETHOD_STEAM, steamID);
if (admin == INVALID_ADMIN_ID)
{
return true;
}
if (GetAdminFlag(admin, Admin_Root))
{
GetConVarString(FindConVar("sv_password"), password, 255);
}
return true;
}
+85
View File
@@ -0,0 +1,85 @@
"Games"
{
"#default"
{
"#supported"
{
"engine" "dods"
"engine" "css"
"engine" "hl2dm"
"engine" "tf2"
}
"Offsets"
{
"ISteamGameServer__BeginAuthSession"
{
"linux" "26"
"linux64" "26"
"windows" "26"
"windows64" "26"
}
"ISteamGameServer__EndAuthSession"
{
"linux" "27"
"linux64" "27"
"windows" "27"
"windows64" "27"
}
"CheckMasterServerRequestRestart_Steam3ServerFuncOffset"
{
"windows" "240"
"windows64" "299"
}
}
"Signatures"
{
"Steam3Server"
{
"library" "engine"
"linux" "@_Z12Steam3Serverv"
"linux64" "@_Z12Steam3Serverv"
}
"CBaseServer__ConnectClient"
{
"library" "engine"
"linux" "@_ZN11CBaseServer13ConnectClientER8netadr_siiiiPKcS3_S3_i"
"linux64" "@_ZN11CBaseServer13ConnectClientER8netadr_siiiiPKcS3_S3_i"
"windows" "\x55\x8B\xEC\x81\xEC\x24\x05\x00\x00\x53\x56\x57\x68\x2A\x2A\x2A\x2A"
"windows64" "\x48\x89\x5C\x24\x2A\x44\x89\x4C\x24\x2A\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x81\xEC\x80\x05\x00\x00"
}
"CBaseServer__RejectConnection"
{
"library" "engine"
"linux" "@_ZN11CBaseServer16RejectConnectionERK8netadr_siPKc"
"linux64" "@_ZN11CBaseServer16RejectConnectionERK8netadr_siPKc"
"windows" "\x55\x8B\xEC\x81\xEC\x04\x05\x00\x00\x57"
"windows64" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x48\x89\x74\x24\x2A\x57\x48\x81\xEC\x50\x05\x00\x00"
}
"CBaseServer__CheckMasterServerRequestRestart"
{
"library" "engine"
"windows" "\x55\x8B\xEC\x83\xEC\x1C\x53\x57\x33\xD2"
"windows64" "\x4C\x8B\xDC\x49\x89\x5B\x2A\x49\x89\x6B\x2A\x56\x57\x41\x54\x41\x56\x41\x57\x48\x83\xEC\x60\x48\x8B\x05\x2A\x2A\x2A\x2A\x48\x8D\x1D"
}
"CSteam3Server__OnValidateAuthTicketResponse"
{
"library" "engine"
"linux" "@_ZN13CSteam3Server28OnValidateAuthTicketResponseEP28ValidateAuthTicketResponse_t"
}
"CBaseClient__SetSteamID"
{
"library" "engine"
"linux" "@_ZN11CBaseClient10SetSteamIDERK8CSteamID"
}
}
}
}
-1377
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os, sys
projectname = 'connect'
project = builder.LibraryProject(projectname + '.ext')
project.sources = [
'extension.cpp',
os.path.join(Extension.sm_root, 'public', 'smsdk_ext.cpp'),
]
for sdk_name in Extension.sdks:
sdk = Extension.sdks[sdk_name]
for cxx in builder.targets:
if not cxx.target.arch in sdk.platformSpec[cxx.target.platform]:
continue
binary = Extension.HL2ExtConfig(project, builder, cxx, projectname + '.ext.' + sdk.ext, sdk)
Extension.AddCDetour(binary)
Extension.extensions = builder.Add(project)
+949
View File
@@ -0,0 +1,949 @@
/*
* =============================================================================
* 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 <http://www.gnu.org/licenses/>.
*/
#include "extension.h"
#include "CDetour/detours.h"
#include "sm_namehashset.h"
#include "steam/steamclientpublic.h"
#include "steam/isteamclient.h"
#include <iclient.h>
#include <ISDKTools.h>
#include <iserver.h>
#include "secret.h"
#include <string>
Connect g_connect;
SMEXT_LINK(&g_connect);
ConVar connectVersion("connect_version", SMEXT_CONF_VERSION, FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY, SMEXT_CONF_DESCRIPTION " Version");
ConVar g_SvLogging("sv_connect_logging", "0", FCVAR_NOTIFY, "Log connection checks.");
ConVar g_SvNoSteam("sv_nosteam", "0", FCVAR_NOTIFY, "Disable steam validation and force steam authentication.");
ConVar g_SvForceSteam("sv_forcesteam", "0", FCVAR_NOTIFY, "Force steam authentication.");
ConVar g_SvGameDesc("sv_gamedesc_override", "default", FCVAR_NOTIFY, "Overwrite the default game description. Set to 'default' to keep default description.");
ConVar g_SvMapName("sv_mapname_override", "default", FCVAR_NOTIFY, "Overwrite the map name. Set to 'default' to keep default name.");
ConVar g_SvSetSteamIDIPS("sv_set_steam_id_ips", "default", FCVAR_NOTIFY, "IP's allowed for webclient nosteamers");
ConVar g_SvWebclientName("sv_webclient_name", "", FCVAR_NOTIFY, "Generated name for the currently connecting webclient player.");
IGameConfig *g_pGameConf = NULL;
IForward *g_pConnectForward = NULL;
IServer *iserver = NULL;
ISDKTools *g_pSDKTools = NULL;
class IClient;
class CBaseServer;
typedef enum EAuthProtocol
{
k_EAuthProtocolWONCertificate = 1,
k_EAuthProtocolHashedCDKey = 2,
k_EAuthProtocolSteam = 3,
} EAuthProtocol;
/*
k_EBeginAuthSessionResultOK = 0, // Ticket is valid for this game and this steamID.
k_EBeginAuthSessionResultInvalidTicket = 1, // Ticket is not valid.
k_EBeginAuthSessionResultDuplicateRequest = 2, // A ticket has already been submitted for this steamID
k_EBeginAuthSessionResultInvalidVersion = 3, // Ticket is from an incompatible interface version
k_EBeginAuthSessionResultGameMismatch = 4, // Ticket is not for this game
k_EBeginAuthSessionResultExpiredTicket = 5, // Ticket has expired
*/
const char *CSteamID::Render() const
{
static char szSteamID[64];
V_snprintf(szSteamID, sizeof(szSteamID), "STEAM_0:%u:%u", this->GetAccountID() & 1, this->GetAccountID() >> 1);
return szSteamID;
}
class ISteamGameServer;
class CSteam3Server
{
public:
void *m_pSteamClient;
ISteamGameServer* m_pSteamGameServer;
void *m_pSteamGameServerUtils;
void *m_pSteamGameServerNetworking;
void *m_pSteamGameServerStats;
void *m_pSteamHTTP;
void *m_pSteamInventory;
void *m_pSteamUGC;
void *m_pSteamApps;
} *g_pSteam3Server;
typedef CSteam3Server *(*Steam3ServerFunc)();
class FEmptyClass {};
template<typename classcall, typename RetType, typename... Args>
union MFPHack {
private:
void* addr;
public:
MFPHack(void* addr)
{
this->addr = addr;
}
template<typename randomclass>
MFPHack(RetType (randomclass::*mfp)(Args...))
{
union
{
RetType (randomclass::*ptr)(Args...);
struct
{
void* addr;
#ifdef __linux__
intptr_t adjustor;
#endif
} details;
} u;
u.ptr = mfp;
this->addr = u.details.addr;
}
void SetAddress(void* addr)
{
this->addr = addr;
}
void* GetAddress()
{
return this->addr;
}
RetType operator()(classcall* ptrThis, Args... args)
{
union
{
RetType (FEmptyClass::*ptr)(Args...);
struct
{
void* addr;
#ifdef __linux__
intptr_t adjustor;
#endif
} details;
} u;
u.details.addr = addr;
#ifdef __linux__
u.details.adjustor = 0;
#endif
return (((FEmptyClass*)ptrThis)->*u.ptr)(args...);
}
};
CDetour* detourCBaseServer__ConnectClient = nullptr;
CDetour *g_Detour_CSteam3Server__OnValidateAuthTicketResponse = NULL;
CDetour *g_Detour_CBaseClient__SetSteamID = NULL;
char passwordBuffer[255];
Steam3ServerFunc g_pSteam3ServerFunc = nullptr;
MFPHack<CBaseServer, void, const netadr_t &, int, const char *> g_pRejectConnectionFunc(nullptr);
MFPHack<ISteamGameServer, EBeginAuthSessionResult, const void*, int, CSteamID> g_pBeginAuthSession(nullptr);
MFPHack<ISteamGameServer, void, CSteamID> g_pEndAuthSession(nullptr);
CSteam3Server *Steam3Server()
{
if (!g_pSteam3ServerFunc)
return NULL;
return g_pSteam3ServerFunc();
}
struct ValidateAuthTicketResponse_t
{
enum { k_iCallback = k_iSteamUserCallbacks + 43 };
CSteamID m_SteamID;
EAuthSessionResponse m_eAuthSessionResponse;
CSteamID m_OwnerSteamID; // different from m_SteamID if borrowed
//in dewey voice "can a nigga borrow a m_SteamID?"
//the teacher "How is a nigga gonna borrow a m_SteamID? nigga is you gonna give it back?"
};
class ConnectClientStorage
{
public:
void* pThis;
netadr_t address;
int nProtocol;
int iChallenge;
int iClientChallenge;
int nAuthProtocol;
char pchName[256];
char pchPassword[256];
char pCookie[256];
int cbCookie;
IClient *pClient;
uint64 ullSteamID;
ValidateAuthTicketResponse_t ValidateAuthTicketResponse;
bool GotValidateAuthTicketResponse;
bool SteamLegal;
bool SteamAuthFailed;
bool ManualRetry;
bool Webclient;
bool SuppressBeginAuthSession;
void *pvTicket;
int cbTicket;
ConnectClientStorage() { }
ConnectClientStorage(netadr_t address, int nProtocol, int iChallenge, int iClientChallenge, int nAuthProtocol, const char *pchName, const char *pchPassword, const char *pCookie, int cbCookie)
{
this->address = address;
this->nProtocol = nProtocol;
this->iChallenge = iChallenge;
this->iClientChallenge = iClientChallenge;
this->nAuthProtocol = nAuthProtocol;
V_strncpy(this->pchName, pchName, 255);
V_strncpy(this->pchPassword, pchPassword, 255);
memcpy(this->pCookie, pCookie, cbCookie);
this->cbCookie = cbCookie;
this->pClient = NULL;
this->GotValidateAuthTicketResponse = false;
this->SteamLegal = false;
this->SteamAuthFailed = false;
this->ManualRetry = false;
this->Webclient = false;
this->SuppressBeginAuthSession = false;
// Calculate and store the ticket pointer
this->pvTicket = (void *)((intptr_t)this->pCookie + sizeof(uint64));
this->cbTicket = cbCookie - sizeof(uint64);
}
};
StringHashMap<ConnectClientStorage> g_ConnectClientStorage;
SH_DECL_MANUALHOOK3(MHook_BeginAuthSession, 0, 0, 0, EBeginAuthSessionResult, const void *, int, CSteamID);
EBeginAuthSessionResult Hook_BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, CSteamID steamID)
{
ConnectClientStorage Storage;
g_ConnectClientStorage.retrieve(steamID.Render(), &Storage);
if (!Storage.SuppressBeginAuthSession)
{
//g_pSM->LogMessage(myself, "inside Hook_ BeginAuthSession 1. %s", steamID.Render());
RETURN_META_VALUE(MRES_IGNORED, k_EBeginAuthSessionResultOK);
}
Storage.SuppressBeginAuthSession = false;
g_ConnectClientStorage.replace(steamID.Render(), Storage);
//g_pSM->LogMessage(myself, "inside Hook_ BeginAuthSession 2. %s", steamID.Render());
RETURN_META_VALUE(MRES_SUPERCEDE, k_EBeginAuthSessionResultOK);
}
//ai generated function
uint64 GenerateSteamIDFromName(const char *pchName)
{
uint64 hash = 14695981039346656037ULL;
for (const char *p = pchName; *p; p++)
{
hash ^= (uint64)(unsigned char)*p;
hash *= 1099511628211ULL;
}
uint32 W = hash & 1;
// Range within existing Steam accounts: 1 to 700,000,000
uint32 Z = 1 + (uint32)((hash >> 1) % 699999999);
uint64 steamID64 = 0x0110000100000000ULL | ((uint64)Z << 1) | W;
return steamID64;
}
//AI generated function
static uint32_t HashString(const char *str)
{
uint32_t hash = 5381;
while (*str)
{
hash = ((hash << 5) + hash) + (unsigned char)*str;
hash = hash & 0x7fffffff;
str++;
}
return hash;
}
//AI generated function
void GenerateNickNameFromPassword(const char *pchPassword, const char *salt, char *outName, size_t outSize)
{
static const char *adjectives[] = {
"Fast","Slow","Red","Blue","Green","Dark","Bright","Wild",
"Cool","Hot","Big","Small","Sharp","Brave","Swift","Bold"
};
static const char *nouns[] = {
"Wolf","Eagle","Tiger","Bear","Fox","Lion","Hawk","Shark",
"Snake","Raven","Storm","Rock","Fire","Ice","Wind","Steel"
};
char salted[256];
V_snprintf(salted, sizeof(salted), "%s%s", pchPassword, salt);
uint32_t h1 = HashString(salted);
char salted1[256];
V_snprintf(salted1, sizeof(salted1), "%s1", salted);
uint32_t h2 = HashString(salted1);
char salted2[256];
V_snprintf(salted2, sizeof(salted2), "%s2", salted);
uint32_t h3 = HashString(salted2);
V_snprintf(outName, outSize, "%s %s %u",
adjectives[h1 % 16],
nouns[h2 % 16],
h3 % 9999
);
}
DETOUR_DECL_MEMBER1(CBaseClient__SetSteamID, void, const CSteamID &, steamID)
{
char aSteamID[32];
V_strncpy(aSteamID, steamID.Render(), 32);
ConnectClientStorage storage;
if (g_ConnectClientStorage.retrieve(aSteamID, &storage))
{
if (storage.SteamAuthFailed)
{
char IpsAllowed[255];
V_strncpy(IpsAllowed, g_SvSetSteamIDIPS.GetString(), 255);
char ipString[30];
V_snprintf(ipString, sizeof(ipString), "%u.%u.%u.%u", storage.address.ip[0], storage.address.ip[1], storage.address.ip[2], storage.address.ip[3]);
if (g_SvLogging.GetInt())
smutils->LogMessage(myself, "inside SetSteamID steamAuthFailed. IpsAllowed: %s. ipString: %s", IpsAllowed, ipString);
//connects from the IP's designated for the webclients.
if (strcmp(IpsAllowed, ipString) == 0)
{
//changes the storages pchName
GenerateNickNameFromPassword(storage.pchPassword, NAME_SALT, storage.pchName, sizeof(storage.pchName));
uint64 steamID64 = GenerateSteamIDFromName(storage.pchName);
CSteamID newSteamID = CSteamID(steamID64);
//smutils->LogMessage(myself, "Generated SteamID64: %llu for name: %s", steamID64, storage.pchName);
//smutils->LogMessage(myself, "SteamID render: %s. password. %s", newSteamID.Render(), storage.pchPassword);
storage.ullSteamID = steamID64;
storage.Webclient = true;
g_ConnectClientStorage.replace(aSteamID, storage);
DETOUR_MEMBER_CALL(CBaseClient__SetSteamID)(newSteamID);
return;
}
}
}
DETOUR_MEMBER_CALL(CBaseClient__SetSteamID)(steamID);
}
DETOUR_DECL_MEMBER1(CSteam3Server__OnValidateAuthTicketResponse, int, ValidateAuthTicketResponse_t *, pResponse)
{
char aSteamID[32];
V_strncpy(aSteamID, pResponse->m_SteamID.Render(), 32);
bool SteamLegal = pResponse->m_eAuthSessionResponse == k_EAuthSessionResponseOK;
bool force = g_SvNoSteam.GetInt() || g_SvForceSteam.GetInt();
if(!SteamLegal && force)
{
pResponse->m_eAuthSessionResponse = k_EAuthSessionResponseOK;
}
ConnectClientStorage Storage;
if (g_ConnectClientStorage.retrieve(aSteamID, &Storage))
{
if(!Storage.GotValidateAuthTicketResponse)
{
Storage.GotValidateAuthTicketResponse = true;
Storage.ValidateAuthTicketResponse = *pResponse;
Storage.SteamLegal = SteamLegal;
g_ConnectClientStorage.replace(aSteamID, Storage);
}
//2026 march 17th: resolve (STEAM UserID [xxxxxx] is already in use on this server)
//we handle it here in the detour before CheckForDuplicateSteamID() is called.
//confirm that this client actually did a manual retry
if (Storage.ManualRetry)
{
if (!Storage.pClient || !Storage.pClient->IsConnected())
{
return DETOUR_MEMBER_CALL(CSteam3Server__OnValidateAuthTicketResponse)(pResponse);
}
USERID_t clientID = Storage.pClient->GetNetworkID();
//two scenarios related to nosteam trying to spoof steam players.
//1: nosteamer trying to spoof active steam player on the server. should already be handled by MEMBER9 function comparing IP address and rejecting if nosteam
//2: nosteamer trying to spoof steam player not on the server right now. handled by PlayerManager_Connection kicking nosteamers with message "Trying to join with a legitimate steamid while not authenticated with steam."
for (int i = 0; i < iserver->GetClientCount(); i++)
{
IClient* pSlot = iserver->GetClient(i);
if (pSlot && pSlot->IsConnected() && pSlot != Storage.pClient)
{
USERID_t slotID = pSlot->GetNetworkID();
if (slotID.idtype == IDTYPE_STEAM && clientID.idtype == IDTYPE_STEAM)
{
if (slotID.steamid == clientID.steamid)
{
//g_pSM->LogMessage(myself, "Disconnecting idle left over session for steamID: %s", aSteamID);
pSlot->Disconnect("Disconnecting dead left over session.");
break;
}
}
}
}
}
}
return DETOUR_MEMBER_CALL(CSteam3Server__OnValidateAuthTicketResponse)(pResponse);
}
void *g_pLastHookedSteamGameServer = NULL;
int g_nBeginAuthSessionOffset = 0;
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)
{
// This is likely a SourceTV client, we don't want to interfere here.
return DETOUR_MEMBER_CALL(CBaseServer__ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie);
}
//g_pSM->LogMessage(myself, "entered MEMBER9");
if (g_pSteam3Server->m_pSteamGameServer != g_pLastHookedSteamGameServer)
{
//the hook tends to die, hence its reapplied whenever needed. thats probably very dumb.
//does however seem to stop "S3: Client connected with invalid ticket:" for nosteamers.
//g_pSM->LogMessage(myself, "Steam GameServer pointer changed! Old: %p, New: %p", g_pLastHookedSteamGameServer, g_pSteam3Server->m_pSteamGameServer);
if (g_pLastHookedSteamGameServer != NULL)
{
// Remove old hook if it exists
SH_REMOVE_MANUALHOOK(MHook_BeginAuthSession, g_pLastHookedSteamGameServer, SH_STATIC(Hook_BeginAuthSession), true);
}
// Add hook to the new object
SH_MANUALHOOK_RECONFIGURE(MHook_BeginAuthSession, g_nBeginAuthSessionOffset, 0, 0);
SH_ADD_MANUALHOOK(MHook_BeginAuthSession, g_pSteam3Server->m_pSteamGameServer, SH_STATIC(Hook_BeginAuthSession), true);
void** vtable = *((void***)g_pSteam3Server->m_pSteamGameServer);
g_pBeginAuthSession.SetAddress(vtable[g_nBeginAuthSessionOffset]);
int endAuthOffset = 0;
if (g_pGameConf->GetOffset("ISteamGameServer__EndAuthSession", &endAuthOffset))
{
g_pEndAuthSession.SetAddress(vtable[endAuthOffset]);
}
g_pLastHookedSteamGameServer = g_pSteam3Server->m_pSteamGameServer;
}
if (pCookie == NULL || (size_t)cbCookie < sizeof(uint64))
{
g_pRejectConnectionFunc((CBaseServer*)this, address, iClientChallenge, "#GameUI_ServerRejectInvalidSteamCertLen");
return NULL;
}
auto steamGameServer = Steam3Server()->m_pSteamGameServer;
char ipString[30];
V_snprintf(ipString, sizeof(ipString), "%u.%u.%u.%u", address.ip[0], address.ip[1], address.ip[2], address.ip[3]);
char IpsAllowed[255];
V_strncpy(IpsAllowed, g_SvSetSteamIDIPS.GetString(), 255);
//you think i am kidding but without this extra log message will ipString end up being empty for nosteamers.
//probably because of netadr_t& address not being processed yet as is. So these logging messages add enough delay.
smutils->LogMessage(myself, "IpsAllowed: %s. ipString: %s", IpsAllowed, ipString);
smutils->LogMessage(myself, "IpsAllowed: %s. ipString: %s", IpsAllowed, ipString);
smutils->LogMessage(myself, "IpsAllowed: %s. ipString: %s", IpsAllowed, ipString);
V_strncpy(passwordBuffer, pchPassword, 255);
uint64 ullSteamID = *(uint64 *)pCookie;
CSteamID ClientSteamID = CSteamID(ullSteamID);
char aSteamID[32];
V_strncpy(aSteamID, ClientSteamID.Render(), 32);
// If client is in async state remove the old object and fake an async retVal
// This can happen if the async ClientPreConnectEx takes too long to be called
// and the client auto-retries.
bool AsyncWaiting = false;
bool ExistingSteamid = false;
EBeginAuthSessionResult result;
ConnectClientStorage Storage(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie);
if (g_ConnectClientStorage.retrieve(aSteamID, &Storage))
{
//g_pSM->LogMessage(myself, "entered has clientstorage. %s", aSteamID);
ExistingSteamid = true;
g_ConnectClientStorage.remove(aSteamID);
// Only wait for async on auto-retry, manual retries should go through the full chain
// Don't want to leave the client waiting forever if something breaks in the async forward
if (Storage.iClientChallenge == iClientChallenge)
{
//g_pSM->LogMessage(myself, "entered async retry. %s", aSteamID);
AsyncWaiting = true;
//reject async nosteamers or async steam player who is not authenticated
if (Storage.SteamAuthFailed)
{
//we are only here in async state when server is 64/64.
g_pRejectConnectionFunc((CBaseServer*)this, address, iClientChallenge, "No slots for nosteamers. server is full");
return NULL;
}
//async steam player with a clientstorage, use the ticket from the previous clientstorage.
result = g_pBeginAuthSession(steamGameServer, Storage.pvTicket, Storage.cbTicket, ClientSteamID);
}
else
{
//client did a manual retry,
//create new auth storage with fresh ticket and challenge
Storage = ConnectClientStorage(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie);
//g_pSM->LogMessage(myself, "entered manual retry. %s", aSteamID);
result = g_pBeginAuthSession(steamGameServer, Storage.pvTicket, Storage.cbTicket, ClientSteamID);
}
}
else
{
result = g_pBeginAuthSession(steamGameServer, Storage.pvTicket, Storage.cbTicket, ClientSteamID);
//g_pSM->LogMessage(myself, "without client storage after beginauth session. %s", aSteamID);
}
//g_pSM->LogMessage(myself, "about to do endAuthSession. %s", aSteamID);
g_pEndAuthSession(steamGameServer, ClientSteamID); //xen said engine might start its own authsession, so end ours here.
bool NoSteam = g_SvNoSteam.GetInt();
bool SteamAuthFailed = false;
//g_pSM->LogMessage(myself, "g_pBeginAuthSession result: %d. %s", result, aSteamID);
if (result != k_EBeginAuthSessionResultOK)
{
if (!NoSteam)
{
g_pRejectConnectionFunc((CBaseServer*)this, address, iClientChallenge, "#GameUI_ServerRejectSteam");
return NULL;
}
Storage.SteamAuthFailed = SteamAuthFailed = true;
}
if(ExistingSteamid && !AsyncWaiting)
{
Storage.ManualRetry = true;
// Another player trying to spoof a Steam ID or game crashed?
if(memcmp(address.ip, Storage.address.ip, sizeof(address.ip)) != 0)
{
// Is a nosteam player
if(SteamAuthFailed)
{
//if the nosteam player is trying to spoof a steam player reject the nosteamer.
if (!Storage.SteamAuthFailed)
{
//g_pSM->LogMessage(myself, "about to do rejectconnection 1. %s", aSteamID);
g_pRejectConnectionFunc((CBaseServer*)this, address, iClientChallenge, "Steam ID already in use.");
return NULL;
}
//a nosteamer connecting the first time could be blocked by their ISP and then on the second connect be using a VPN
//so if the original nosteamer is not connected and ingame we allow the nosteamer to take over the spot
//a nosteamer spoofing another nosteamer that is not ingame is fine too.
if (Storage.pClient && Storage.pClient->IsConnected() && Storage.pClient->IsActive())
{
//g_pSM->LogMessage(myself, "about to do rejectconnection 2. %s", aSteamID);
g_pRejectConnectionFunc((CBaseServer*)this, address, iClientChallenge, "Steam ID already in use.");
return NULL;
}
}
// Kick existing player
if(Storage.pClient)
{
//g_pSM->LogMessage(myself, "about to do disconnect. %s", aSteamID);
Storage.pClient->Disconnect("Same Steam ID connected.");
}
else
{
//g_pSM->LogMessage(myself, "about to do rejectconnection 3. %s", aSteamID);
g_pRejectConnectionFunc((CBaseServer*)this, address, iClientChallenge, "Please try again later.");
return NULL;
}
}
}
char rejectReason[255];
cell_t retVal = 1;
if(AsyncWaiting)
{
retVal = -1; // Fake async return code when waiting for async call
}
else
{
g_pConnectForward->PushString(pchName);
g_pConnectForward->PushStringEx(passwordBuffer, 255, SM_PARAM_STRING_UTF8 | SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
g_pConnectForward->PushString(ipString);
g_pConnectForward->PushString(ClientSteamID.Render());
g_pConnectForward->PushStringEx(rejectReason, 255, SM_PARAM_STRING_UTF8 | SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
g_pConnectForward->Execute(&retVal);
}
pchPassword = passwordBuffer;
//overwrite it to the storage so the webclient can use its value assigned by nosteam celt plugin inside the SetSteamID detour.
V_strncpy(Storage.pchPassword, passwordBuffer, sizeof(Storage.pchPassword));
// k_OnClientPreConnectEx_Reject
if (retVal == 0)
{
g_ConnectClientStorage.remove(aSteamID);
if (!Storage.SteamAuthFailed)
{
//calling this on nosteamers does sometimes cause a server explosion.
//but not when creating a nosteamer with their first ticket
//g_pSM->LogMessage(myself, "k_OnClientPreConnectEx_Reject reached about to do endAuthSession. steamID: %s", aSteamID);
g_pEndAuthSession(steamGameServer, ClientSteamID);
}
//g_pSM->LogMessage(myself, "k_OnClientPreConnectEx_Reject reached about to do g_pRejectConnectionFunc. steamID: %s", aSteamID);
g_pRejectConnectionFunc((CBaseServer*)this, address, iClientChallenge, rejectReason);
return NULL;
}
Storage.pThis = this;
Storage.ullSteamID = ullSteamID;
Storage.SteamAuthFailed = SteamAuthFailed;
//puts the storage in the StringHashMap
if(!g_ConnectClientStorage.replace(aSteamID, Storage))
{
g_pRejectConnectionFunc((CBaseServer*)this, address, iClientChallenge, "Internal error.");
return NULL;
}
// k_OnClientPreConnectEx_Async
if (retVal == -1)
{
return NULL;
}
// k_OnClientPreConnectEx_Accept
//g_pSM->LogMessage(myself, "about to do DETOUR_MEMBER_CALL. %s", aSteamID);
Storage.SuppressBeginAuthSession = true;
g_ConnectClientStorage.replace(aSteamID, Storage);
auto client = DETOUR_MEMBER_CALL(CBaseServer__ConnectClient)(address, nProtocol, iChallenge, iClientChallenge, nAuthProtocol, pchName, pchPassword, pCookie, cbCookie);
//g_pSM->LogMessage(myself, "finished DETOUR_MEMBER_CALL. %s", aSteamID);
//doing another retrieve in case of SetSteamID for webclient.
ConnectClientStorage storage_setSteamID;
g_ConnectClientStorage.retrieve(aSteamID, &storage_setSteamID);
if (storage_setSteamID.Webclient)
{
storage_setSteamID.SuppressBeginAuthSession = false;
CSteamID newSteamID = CSteamID(storage_setSteamID.ullSteamID);
//smutils->LogMessage(myself, "Generated name after webclient check: %s", storage_setSteamID.pchName);
g_SvWebclientName.SetValue(storage_setSteamID.pchName);
storage_setSteamID.pClient = client;
//smutils->LogMessage(myself, "SteamID render after webclient check: %s", newSteamID.Render());
g_ConnectClientStorage.replace(newSteamID.Render(), storage_setSteamID);
g_ConnectClientStorage.remove(aSteamID);
if (client) //webclient is always nosteamer.
{
ValidateAuthTicketResponse_t Response;
Response.m_SteamID = newSteamID;
Response.m_eAuthSessionResponse = k_EAuthSessionResponseAuthTicketInvalid; //nosteamer monkeys
Response.m_OwnerSteamID = Response.m_SteamID;
//g_pSM->LogMessage(myself, "about to do OnValidateAuthTicketResponse webclient. %s", newSteamID.Render());
DETOUR_MEMBER_MCALL_CALLBACK(CSteam3Server__OnValidateAuthTicketResponse, g_pSteam3Server)(&Response);
}
}
else
{
Storage.SuppressBeginAuthSession = false;
Storage.pClient = client;
g_ConnectClientStorage.replace(aSteamID, Storage);
if (client && SteamAuthFailed)
{
ValidateAuthTicketResponse_t Response;
Response.m_SteamID = ClientSteamID;
Response.m_eAuthSessionResponse = k_EAuthSessionResponseAuthTicketInvalid; //nosteamer monkeys
Response.m_OwnerSteamID = Response.m_SteamID;
//g_pSM->LogMessage(myself, "about to do OnValidateAuthTicketResponse. %s", aSteamID);
DETOUR_MEMBER_MCALL_CALLBACK(CSteam3Server__OnValidateAuthTicketResponse, g_pSteam3Server)(&Response);
}
}
//g_pSM->LogMessage(myself, "MEMBER 9 end. %s", aSteamID);
return client;
}
bool Connect::SDK_OnLoad(char *error, size_t maxlen, bool late)
{
char conf_error[255] = "";
if (!gameconfs->LoadGameConfigFile("connect2.games", &g_pGameConf, conf_error, sizeof(conf_error)))
{
if (conf_error[0])
{
snprintf(error, maxlen, "Could not read connect2.games.txt: %s\n", conf_error);
}
return false;
}
void* addr;
if (!g_pGameConf->GetMemSig("CBaseServer__RejectConnection", &addr) || addr == nullptr)
{
snprintf(error, maxlen, "Failed to find CBaseServer__RejectConnection function.\n");
return false;
}
g_pRejectConnectionFunc.SetAddress(addr);
#ifndef WIN32
if (!g_pGameConf->GetMemSig("Steam3Server", (void **)(&g_pSteam3ServerFunc)) || !g_pSteam3ServerFunc)
{
snprintf(error, maxlen, "Failed to find Steam3Server function.\n");
return false;
}
#else
void *address;
if (!g_pGameConf->GetMemSig("CBaseServer__CheckMasterServerRequestRestart", &address) || !address)
{
snprintf(error, maxlen, "Failed to find CBaseServer__CheckMasterServerRequestRestart function.\n");
return false;
}
int steam3ServerFuncOffset = 0;
if (!g_pGameConf->GetOffset("CheckMasterServerRequestRestart_Steam3ServerFuncOffset", &steam3ServerFuncOffset) || steam3ServerFuncOffset == 0)
{
snprintf(error, maxlen, "Failed to find CheckMasterServerRequestRestart_Steam3ServerFuncOffset offset.\n");
return false;
}
//META_CONPRINTF("CheckMasterServerRequestRestart: %p\n", address);
address = (void *)((intptr_t)address + steam3ServerFuncOffset);
g_pSteam3ServerFunc = (Steam3ServerFunc)((intptr_t)address + *((int32_t *)address) + sizeof(int32_t));
//META_CONPRINTF("Steam3Server: %p\n", g_pSteam3ServerFunc);
#endif
g_pSteam3Server = Steam3Server();
if (!g_pSteam3Server)
{
snprintf(error, maxlen, "Unable to get Steam3Server singleton.\n");
return false;
}
if (!g_pSteam3Server->m_pSteamGameServer)
{
snprintf(error, maxlen, "Unable to get Steam Game Server.\n");
return false;
}
void** vtable = *((void***)g_pSteam3Server->m_pSteamGameServer);
if (!g_pGameConf->GetOffset("ISteamGameServer__BeginAuthSession", &g_nBeginAuthSessionOffset) || g_nBeginAuthSessionOffset == 0)
{
snprintf(error, maxlen, "Failed to find ISteamGameServer__BeginAuthSession offset.\n");
return false;
}
g_pBeginAuthSession.SetAddress(vtable[g_nBeginAuthSessionOffset]);
SH_MANUALHOOK_RECONFIGURE(MHook_BeginAuthSession, g_nBeginAuthSessionOffset, 0, 0);
if (SH_ADD_MANUALHOOK(MHook_BeginAuthSession, g_pSteam3Server->m_pSteamGameServer, SH_STATIC(Hook_BeginAuthSession), true) == 0)
{
snprintf(error, maxlen, "Failed to setup ISteamGameServer__BeginAuthSession hook.\n");
return false;
}
g_pLastHookedSteamGameServer = g_pSteam3Server->m_pSteamGameServer;
int offset = 0;
if (!g_pGameConf->GetOffset("ISteamGameServer__EndAuthSession", &offset) || offset == 0)
{
snprintf(error, maxlen, "Failed to find ISteamGameServer__EndAuthSession offset.\n");
return false;
}
g_pEndAuthSession.SetAddress(vtable[offset]);
CDetourManager::Init(g_pSM->GetScriptingEngine(), g_pGameConf);
detourCBaseServer__ConnectClient = DETOUR_CREATE_MEMBER(CBaseServer__ConnectClient, "CBaseServer__ConnectClient");
if (detourCBaseServer__ConnectClient == nullptr)
{
snprintf(error, maxlen, "Failed to create CBaseServer__ConnectClient detour.\n");
return false;
}
detourCBaseServer__ConnectClient->EnableDetour();
g_Detour_CSteam3Server__OnValidateAuthTicketResponse = DETOUR_CREATE_MEMBER(CSteam3Server__OnValidateAuthTicketResponse, "CSteam3Server__OnValidateAuthTicketResponse");
if(!g_Detour_CSteam3Server__OnValidateAuthTicketResponse)
{
snprintf(error, maxlen, "Failed to detour CSteam3Server__OnValidateAuthTicketResponse.\n");
return false;
}
g_Detour_CSteam3Server__OnValidateAuthTicketResponse->EnableDetour();
g_Detour_CBaseClient__SetSteamID = DETOUR_CREATE_MEMBER(CBaseClient__SetSteamID, "CBaseClient__SetSteamID");
if(!g_Detour_CBaseClient__SetSteamID)
{
snprintf(error, maxlen, "Failed to detour CBaseClient__SetSteamID.\n");
return false;
}
g_Detour_CBaseClient__SetSteamID->EnableDetour();
g_pConnectForward = g_pForwards->CreateForward("OnClientPreConnectEx", ET_LowEvent, 5, NULL, Param_String, Param_String, Param_String, Param_String, Param_String);
return true;
}
bool Connect::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late)
{
GET_V_IFACE_CURRENT(GetEngineFactory, g_pCVar, ICvar, CVAR_INTERFACE_VERSION);
ConVar_Register(0, this);
return true;
}
void Connect::SDK_OnUnload()
{
g_pForwards->ReleaseForward(g_pConnectForward);
gameconfs->CloseGameConfigFile(g_pGameConf);
}
bool Connect::SDK_OnMetamodUnload(char *error, size_t maxlen)
{
if (detourCBaseServer__ConnectClient)
{
detourCBaseServer__ConnectClient->DisableDetour();
delete detourCBaseServer__ConnectClient;
}
if (g_Detour_CSteam3Server__OnValidateAuthTicketResponse)
{
g_Detour_CSteam3Server__OnValidateAuthTicketResponse->DisableDetour();
delete g_Detour_CSteam3Server__OnValidateAuthTicketResponse;
}
if (g_Detour_CBaseClient__SetSteamID)
{
g_Detour_CBaseClient__SetSteamID->DisableDetour();
delete g_Detour_CBaseClient__SetSteamID;
}
return true;
}
bool Connect::RegisterConCommandBase(ConCommandBase *pCommand)
{
META_REGCVAR(pCommand);
return true;
}
cell_t SteamClientAuthenticated(IPluginContext *pContext, const cell_t *params)
{
char *pSteamID;
pContext->LocalToString(params[1], &pSteamID);
ConnectClientStorage Storage;
if(g_ConnectClientStorage.retrieve(pSteamID, &Storage))
{
if (g_SvLogging.GetInt())
g_pSM->LogMessage(myself, "%s SteamClientAuthenticated: %d", pSteamID, Storage.SteamLegal);
return Storage.SteamLegal;
}
if (g_SvLogging.GetInt())
g_pSM->LogMessage(myself, "%s SteamClientAuthenticated: FALSE!", pSteamID);
return false;
}
cell_t ClientPreConnectEx(IPluginContext *pContext, const cell_t *params)
{
char *pSteamID;
pContext->LocalToString(params[1], &pSteamID);
int retVal = params[2];
char *rejectReason;
pContext->LocalToString(params[3], &rejectReason);
ConnectClientStorage Storage;
if(!g_ConnectClientStorage.retrieve(pSteamID, &Storage))
{
return 1;
}
if(retVal == 0)
{
g_pSM->LogMessage(myself, "inside ClientPreConnectEx return 0. steamID: %s", pSteamID);
g_pRejectConnectionFunc((CBaseServer*)Storage.pThis, Storage.address, Storage.iClientChallenge, rejectReason);
return 0;
}
auto *pClient = DETOUR_MEMBER_MCALL_ORIGINAL(CBaseServer__ConnectClient, Storage.pThis)(Storage.address, Storage.nProtocol, Storage.iChallenge, Storage.iClientChallenge, Storage.nAuthProtocol, Storage.pchName, Storage.pchPassword, Storage.pCookie, Storage.cbCookie);
if(!pClient)
{
return 1;
}
bool force = g_SvNoSteam.GetInt() || g_SvForceSteam.GetInt();
if(Storage.SteamAuthFailed && force && !Storage.GotValidateAuthTicketResponse)
{
if (g_SvLogging.GetInt())
g_pSM->LogMessage(myself, "%s Force ValidateAuthTicketResponse", pSteamID);
Storage.ValidateAuthTicketResponse.m_SteamID = CSteamID(Storage.ullSteamID);
Storage.ValidateAuthTicketResponse.m_eAuthSessionResponse = k_EAuthSessionResponseOK;
Storage.ValidateAuthTicketResponse.m_OwnerSteamID = Storage.ValidateAuthTicketResponse.m_SteamID;
Storage.GotValidateAuthTicketResponse = true;
}
// Make sure this is always called in order to verify the client on the server
if(Storage.GotValidateAuthTicketResponse)
{
if (g_SvLogging.GetInt())
g_pSM->LogMessage(myself, "%s Replay ValidateAuthTicketResponse", pSteamID);
DETOUR_MEMBER_MCALL_ORIGINAL(CSteam3Server__OnValidateAuthTicketResponse, g_pSteam3Server)(&Storage.ValidateAuthTicketResponse);
}
return 0;
}
const sp_nativeinfo_t MyNatives[] =
{
{ "ClientPreConnectEx", ClientPreConnectEx },
{ "SteamClientAuthenticated", SteamClientAuthenticated },
{ NULL, NULL }
};
void Connect::SDK_OnAllLoaded()
{
SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
iserver = g_pSDKTools->GetIServer();
if (!iserver) {
smutils->LogError(myself, "Failed to get IServer interface from SDKTools!");
return;
}
sharesys->AddNatives(myself, MyNatives);
}
+28 -53
View File
@@ -1,8 +1,7 @@
/** /**
* vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod Sample Extension * TF2 Items Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * 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 * This program is free software; you can redistribute it and/or modify it under
@@ -17,37 +16,23 @@
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
* *
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ #ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ #define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
/** /**
* @file extension.h * @file extension.hpp
* @brief Sample extension code header. * @brief Connect extension code header.
*/ */
#include "smsdk_ext.h" #include "smsdk_ext.h"
#include <igameevents.h>
/** /**
* @brief Sample implementation of the SDK Extension. * @brief Sample implementation of the SDK Extension.
* Note: Uncomment one of the pre-defined virtual functions in order to use it. * Note: Uncomment one of the pre-defined virtual functions in order to use it.
*/ */
class Connect : class Connect : public SDKExtension, public IConCommandBaseAccessor
public SDKExtension,
public IConCommandBaseAccessor,
public IClientListener
{ {
public: public:
/** /**
@@ -58,23 +43,24 @@ public:
* @param late Whether or not the module was loaded after map load. * @param late Whether or not the module was loaded after map load.
* @return True to succeed loading, false to fail. * @return True to succeed loading, false to fail.
*/ */
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late); virtual bool SDK_OnLoad(char *error, size_t maxlen, bool late);
/** /**
* @brief This is called right before the extension is unloaded. * @brief This is called right before the extension is unloaded.
*/ */
virtual void SDK_OnUnload(); virtual void SDK_OnUnload();
/**
* @brief Called when the pause state is changed.
*/
//virtual void SDK_OnPauseChange(bool paused);
/** /**
* @brief This is called once all known extensions have been loaded. * @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. * Note: It is is a good idea to add natives here, if any are provided.
*/ */
virtual void SDK_OnAllLoaded(); 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. * @brief this is called when Core wants to know if your extension is working.
@@ -83,7 +69,7 @@ public:
* @param maxlength Size of error message buffer. * @param maxlength Size of error message buffer.
* @return True if working, false otherwise. * @return True if working, false otherwise.
*/ */
//virtual bool QueryRunning(char *error, size_t maxlength); //virtual bool QueryRunning(char *error, size_t maxlen);
public: public:
#if defined SMEXT_CONF_METAMOD #if defined SMEXT_CONF_METAMOD
/** /**
@@ -94,7 +80,7 @@ public:
* @param late Whether or not Metamod considers this a late load. * @param late Whether or not Metamod considers this a late load.
* @return True to succeed, false to fail. * @return True to succeed, false to fail.
*/ */
virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late); 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. * @brief Called when Metamod is detaching, after the extension version is called.
@@ -104,7 +90,7 @@ public:
* @param maxlength Maximum size of error buffer. * @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail. * @return True to succeed, false to fail.
*/ */
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength); virtual bool SDK_OnMetamodUnload(char *error, size_t maxlen);
/** /**
* @brief Called when Metamod's pause state is changing. * @brief Called when Metamod's pause state is changing.
@@ -115,35 +101,12 @@ public:
* @param maxlength Maximum size of error buffer. * @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail. * @return True to succeed, false to fail.
*/ */
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlen);
#endif #endif
public: //IConCommandBaseAccessor public: //IConCommandBaseAccessor
virtual bool RegisterConCommandBase(ConCommandBase *pVar); bool RegisterConCommandBase(ConCommandBase *pCommand);
public: // IClientListener
virtual void OnClientSettingsChanged(int client);
virtual void OnClientPutInServer(int client);
public:
void OnTimer();
}; };
class ConnectEvents : public IGameEventListener2
{
public:
virtual void FireGameEvent( IGameEvent *event );
};
class ConnectTimer : public ITimedEvent
{
public:
virtual ResultType OnTimer(ITimer *pTimer, void *pData);
virtual void OnTimerEnd(ITimer *pTimer, void *pData);
};
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
// custom detour macros
#define DETOUR_DECL_MEMBER9(name, ret, p1type, p1name, p2type, p2name, p3type, p3name, p4type, p4name, p5type, p5name, p6type, p6name, p7type, p7name, p8type, p8name, p9type, p9name) \ #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 \ class name##Class \
{ \ { \
@@ -158,3 +121,15 @@ ret name##Class::name(p1type p1name, p2type p2name, p3type p3name, p4type p4name
((name##Class *)classptr->*(&name##Class::name)) ((name##Class *)classptr->*(&name##Class::name))
#define DETOUR_MEMBER_MCALL_ORIGINAL(name, classptr) \ #define DETOUR_MEMBER_MCALL_ORIGINAL(name, classptr) \
((name##Class *)classptr->*(name##Class::name##_Actual)) ((name##Class *)classptr->*(name##Class::name##_Actual))
struct mfpDetails {
void *addr;
intptr_t adjustor;
void Init(void* addr, intptr_t adj = 0) {
this->addr = addr;
this->adjustor = adj;
}
};
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
+2
View File
@@ -0,0 +1,2 @@
#pragma once
#define NAME_SALT "your-salt-here"
+11 -12
View File
@@ -1,8 +1,7 @@
/** /**
* vim: set ts=4 :
* ============================================================================= * =============================================================================
* SourceMod Sample Extension * connect Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. * Copyright (C) 2011 Asher Baker (asherkin). All rights reserved.
* ============================================================================= * =============================================================================
* *
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
@@ -25,24 +24,24 @@
* this exception to all derivative works. AlliedModders LLC defines further * this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>. * or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/ */
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ #ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ #define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
/** /**
* @file smsdk_config.h * @file smsdk_config.hpp
* @brief Contains macros for configuring basic extension information. * @brief Contains macros for configuring basic extension information.
*/ */
#include "version.h" // SM_FULL_VERSION
/* Basic information exposed publicly */ /* Basic information exposed publicly */
#define SMEXT_CONF_NAME "Connect" #define SMEXT_CONF_NAME "Connect"
#define SMEXT_CONF_DESCRIPTION "Forward for early connection" #define SMEXT_CONF_DESCRIPTION "Forward for early connection"
#define SMEXT_CONF_VERSION "2.6-SANITY-CHECK" #define SMEXT_CONF_VERSION SM_FULL_VERSION
#define SMEXT_CONF_AUTHOR "Asher \"asherkin\" Baker + BotoX + Neon" #define SMEXT_CONF_AUTHOR "Asher \"asherkin\" Baker + jenz + zacade"
#define SMEXT_CONF_URL "https://github.com/CSSZombieEscape/sm-ext-connect" #define SMEXT_CONF_URL "https://git.unloze.com/UNLOZE/sm-ext-connect"
#define SMEXT_CONF_LOGTAG "CONNECT" #define SMEXT_CONF_LOGTAG "CONNECT"
#define SMEXT_CONF_LICENSE "GPL" #define SMEXT_CONF_LICENSE "GPL"
#define SMEXT_CONF_DATESTRING __DATE__ #define SMEXT_CONF_DATESTRING __DATE__
@@ -61,12 +60,12 @@
/** Enable interfaces you want to use here by uncommenting lines */ /** Enable interfaces you want to use here by uncommenting lines */
#define SMEXT_ENABLE_FORWARDSYS #define SMEXT_ENABLE_FORWARDSYS
//#define SMEXT_ENABLE_HANDLESYS //#define SMEXT_ENABLE_HANDLESYS
#define SMEXT_ENABLE_PLAYERHELPERS //#define SMEXT_ENABLE_PLAYERHELPERS
//#define SMEXT_ENABLE_DBMANAGER //#define SMEXT_ENABLE_DBMANAGER
#define SMEXT_ENABLE_GAMECONF #define SMEXT_ENABLE_GAMECONF
//#define SMEXT_ENABLE_MEMUTILS //#define SMEXT_ENABLE_MEMUTILS
//#define SMEXT_ENABLE_GAMEHELPERS //#define SMEXT_ENABLE_GAMEHELPERS
#define SMEXT_ENABLE_TIMERSYS //#define SMEXT_ENABLE_TIMERSYS
//#define SMEXT_ENABLE_THREADER //#define SMEXT_ENABLE_THREADER
//#define SMEXT_ENABLE_LIBSYS //#define SMEXT_ENABLE_LIBSYS
//#define SMEXT_ENABLE_MENUS //#define SMEXT_ENABLE_MENUS
@@ -76,6 +75,6 @@
//#define SMEXT_ENABLE_TEXTPARSERS //#define SMEXT_ENABLE_TEXTPARSERS
//#define SMEXT_ENABLE_USERMSGS //#define SMEXT_ENABLE_USERMSGS
//#define SMEXT_ENABLE_TRANSLATOR //#define SMEXT_ENABLE_TRANSLATOR
//#define SMEXT_ENABLE_ROOTCONSOLEMENU //#define SMEXT_ENABLE_NINVOKE
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ #endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
+27
View File
@@ -0,0 +1,27 @@
#ifndef _INCLUDE_VERSION_INFORMATION_H_
#define _INCLUDE_VERSION_INFORMATION_H_
/**
* @file Contains version information.
* @brief This file will redirect to an autogenerated version if being compiled via
* the build scripts.
*/
#if defined SM_GENERATED_BUILD
#include "version_auto.h"
#else
#ifndef SM_GENERATED_BUILD
#undef BINARY_NAME
#define BINARY_NAME "connect.ext.dll\0"
#endif
#define SM_BUILD_TAG "-manual"
#define SM_BUILD_UNIQUEID "[MANUAL BUILD]"
#define SM_VERSION "1.2.0"
#define SM_FULL_VERSION SM_VERSION SM_BUILD_TAG
#define SM_FILE_VERSION 1,2,0,0
#endif
#endif /* _INCLUDE_VERSION_INFORMATION_H_ */
+45
View File
@@ -0,0 +1,45 @@
#include "winres.h"
#include <version.h>
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif
#ifndef SM_GENERATED_BUILD
#define BINARY_NAME "connect.ext.dll\0"
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION SM_FILE_VERSION
PRODUCTVERSION SM_FILE_VERSION
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "Connect Extension"
VALUE "FileDescription", "SourceMod Connect Extension"
VALUE "FileVersion", SM_BUILD_UNIQUEID
VALUE "InternalName", "Connect"
VALUE "LegalCopyright", "Copyright (c) 2012, Asher Baker"
VALUE "OriginalFilename", BINARY_NAME
VALUE "ProductName", "Connect Extension"
VALUE "ProductVersion", SM_FULL_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 0x04B0
END
END
-178
View File
@@ -1,178 +0,0 @@
"Games"
{
"#default"
{
"#supported"
{
"engine" "dods"
"engine" "css"
"engine" "hl2dm"
"engine" "tf2"
}
"Offsets"
{
"ISteamGameServer__BeginAuthSession"
{
"linux" "29"
"linux64" "29"
"windows" "29"
}
"ISteamGameServer__EndAuthSession"
{
"linux" "30"
"linux64" "30"
"windows" "30"
}
}
"Signatures"
{
"Steam3Server"
{
"library" "engine"
"linux" "@_Z12Steam3Serverv"
"linux64" "@_Z12Steam3Serverv"
}
}
}
"#default"
{
"#supported"
{
"engine" "dods"
"engine" "css"
"engine" "hl2dm"
"engine" "tf2"
}
"Offsets"
{
"ISteamGameServer__BeginAuthSession"
{
"linux" "26"
"linux64" "26"
"windows" "26"
"windows64" "26"
}
"ISteamGameServer__EndAuthSession"
{
"linux" "27"
"linux64" "27"
"windows" "27"
"windows64" "27"
}
"CheckMasterServerRequestRestart_Steam3ServerFuncOffset"
{
"windows" "240"
"windows64" "299"
}
}
"Signatures"
{
"CBaseServer__ConnectClient"
{
"library" "engine"
"linux" "@_ZN11CBaseServer13ConnectClientER8netadr_siiiiPKcS3_S3_i"
"linux64" "@_ZN11CBaseServer13ConnectClientER8netadr_siiiiPKcS3_S3_i"
"windows" "\x55\x8B\xEC\x81\xEC\x24\x05\x00\x00\x53\x56\x57\x68\x2A\x2A\x2A\x2A"
"windows64" "\x48\x89\x5C\x24\x2A\x44\x89\x4C\x24\x2A\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x81\xEC\x80\x05\x00\x00"
}
"CBaseServer__CheckChallengeType"
{
"library" "engine"
"linux" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii"
"mac" "@_ZN11CBaseServer18CheckChallengeTypeEP11CBaseClientiR8netadr_siPKcii"
"windows" "\x55\x8B\xEC\x83\xEC\x14\x56\x57\x8B\x7D\x14\x8B\xF1"
}
"CBaseServer__RejectConnection"
{
"library" "engine"
"linux" "@_ZN11CBaseServer16RejectConnectionERK8netadr_siPKc"
"linux64" "@_ZN11CBaseServer16RejectConnectionERK8netadr_siPKc"
"windows" "\x55\x8B\xEC\x81\xEC\x04\x05\x00\x00\x57"
"windows64" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x48\x89\x74\x24\x2A\x57\x48\x81\xEC\x50\x05\x00\x00"
}
"CBaseClient__SetSteamID"
{
"library" "engine"
"linux" "@_ZN11CBaseClient10SetSteamIDERK8CSteamID"
"linux64" "@_ZN11CBaseClient10SetSteamIDERK8CSteamID"
"windows" "\x55\x8B\xEC\x56\x8B\xF1\x57\x8B\x7D\x08\x8D\x4E\x04"
"windows64" "\x48\x89\x5C\x24\x2A\x57\x48\x83\xEC\x20\x48\x8B\x02\x48\x8B\xD9\x48\x89\x41"
}
"CBaseServer__CheckMasterServerRequestRestart"
{
"library" "engine"
"windows" "\x55\x8B\xEC\x83\xEC\x1C\x53\x57\x33\xD2"
"windows64" "\x4C\x8B\xDC\x49\x89\x5B\x2A\x49\x89\x6B\x2A\x56\x57\x41\x54\x41\x56\x41\x57\x48\x83\xEC\x60\x48\x8B\x05\x2A\x2A\x2A\x2A\x48\x8D\x1D"
}
"NET_SendPacket"
{
"library" "engine"
"linux" "@_Z14NET_SendPacketP11INetChanneliRK8netadr_sPKhiP8bf_writeb"
}
"NET_CheckCleanupFakeIPConnection"
{
"library" "engine"
"linux" "@_Z32NET_CheckCleanupFakeIPConnectioniRK8netadr_s"
}
"CSteam3Server__OnValidateAuthTicketResponse"
{
"library" "engine"
"linux" "@_ZN13CSteam3Server28OnValidateAuthTicketResponseEP28ValidateAuthTicketResponse_t"
}
"s_queryRateChecker"
{
"library" "engine"
"linux" "@_ZL18s_queryRateChecker"
}
"CIPRateLimit__CheckIP"
{
"library" "engine"
"linux" "@_ZN12CIPRateLimit7CheckIPE8netadr_s"
}
"CBaseServer__ValidChallenge"
{
"library" "engine"
"linux" "@_ZN11CBaseServer14ValidChallengeER8netadr_si"
}
"CBaseServer__InactivateClients"
{
"library" "engine"
"linux" "@_ZN11CBaseServer17InactivateClientsEv"
}
"net_sockets"
{
"library" "engine"
"linux" "@_ZL11net_sockets"
}
"hltv"
{
"library" "engine"
"linux" "@hltv"
}
"net_time"
{
"library" "engine"
"linux" "@net_time"
}
}
}
}
+1
View File
@@ -0,0 +1 @@
1.4.0
+71
View File
@@ -0,0 +1,71 @@
import re, os, sys
import subprocess
import zipfile
import ftplib
platform = 'unknown'
if sys.platform.startswith('linux'):
platform = 'linux'
elif sys.platform.startswith('win32'):
platform = 'windows'
elif sys.platform.startswith('darwin'):
platform = 'mac'
def HGVersion():
p = subprocess.Popen(['hg', 'identify', '-n'], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
(stdout, stderr) = p.communicate()
stdout = stdout.decode('UTF-8')
return stdout.rstrip('+\r\n')
def ReleaseVersion():
productFile = open('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()
return '.'.join([major, minor, release])
filename = '-'.join(['connect', ReleaseVersion(), 'hg' + HGVersion(), platform])
debug_build = os.environ.get('is_debug_build', False) == "1"
if debug_build:
filename += '-debug'
filename += '.zip'
zip = zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED)
for base, dirs, files in os.walk('package'):
for file in files:
fn = os.path.join(base, file)
fns = fn[(len('package') + 1):]
zip.write(fn, fns)
print("%-33s %-10s %21s %12s" % ("File Name", "CRC32", "Modified ", "Size"))
for zinfo in zip.infolist():
date = "%d-%02d-%02d %02d:%02d:%02d" % zinfo.date_time[:6]
print("%-33s %-10d %21s %12d" % (zinfo.filename, zinfo.CRC, date, zinfo.file_size))
zip.close()
if 'ftp_hostname' in os.environ:
print('')
ftp = ftplib.FTP(os.environ['ftp_hostname'], os.environ['ftp_username'], os.environ['ftp_password'])
print('Connected to server, uploading build...')
ftp.cwd(os.environ['ftp_directory'])
print(ftp.storbinary('STOR ' + filename, open(filename, 'rb')))
ftp.quit()
print('Uploaded as \'' + filename + '\'')
os.unlink(filename)